2008 06 MiniCommander – własne dwa panele [Programowanie]


Programowanie
Arkusz kalkulacyjny i makra
MiniCommander 
własne dwa panele
Marek Sawerwain
Zarządzanie plikami to jedna z najważniejszych i zarazem najczęściej wykonywana czynność podczas
korzystania z systemu operacyjnego, czyli mówiąc wprost podczas korzystania z komputera. Dla
systemu Linux, powstało już wiele różnych wersji tego typu programów. Niewątpliwie najbardziej
popularny jest program o nazwie Midnight Commander. Wzorcem dla tego programu był Norton
Commander, który w czasach systemu DOS znacząco poprawiał komfort korzystania z systemu.
arto przypomnieć, iż Norton Commander Podstawowe informacje
nie był jedynym programem do zarządza- W naszym programie będą dostępne tylko podstawowe opcje,
nia plików. Drugim tego typu programem jednak mimo tych ograniczeń kod zródłowy liczy sobie 44kb.
Wo nieco innej filozofii pracy był program To naturalnie nadal niewielki program, ale koniecznie trzeba
XTree. Podobnie jak Norton Commander również posiadał za- przygotować diagram najważniejszych zdarzeń. Rysunek 1
gorzałych fanów. Kolejnym programem do zarządzania, który przedstawia taki schemat.
także cieszył się ogromną popularnością był Directory Opus. Pierwsze zdarzenie jakie pojawia się po uruchomieniu
Jednakże był on dostępny na komputery Amiga. Użytkownicy programu dotyczy obsługi trybu tekstowego. Musimy od-
Linuksa są w bardzo komfortowej sytuacji, ponieważ powstało powiednio uruchomić obsługę konsoli. Następnie nasz pro-
kilkanaście różnych programów do zarządzania plikami. Istnie- gram wchodzi w główną pętlę. W pętli sprawdzamy, które
ją odpowiedniki Norton Commandera, jak wspomniany Midni- klawisze zostały użyte przez użytkownika. Jeśli używane są
ght Commander oraz równie dobry - jeśli nie lepszy - Krusader. kursory, to na aktywnym panelu odpowiednio przesuwamy
Wersji programu naśladującego XTree jest kilkanaście, powstał kursor wskazujący na aktualny katalog bądz plik. Wciśnię-
nawet odpowiednik Directory Opusa - nazywa się Worker. cie klawisza TAB powoduje zmianę panelu ma przeciwny.
Natomiast naszym zadaniem będzie napisanie programu Obsługujemy także inne klawisze, jak np.: F7, czyli two-
podobnego do Midnight Commandera. Skupimy się tylko na rzenie katalogu. Po naciśnięciu tego klawisza wyświetlamy
najważniejszych opcjach. Jednak będziemy mieli na uwadze odpowiednie okno dialogowe. Obsługujemy także kombi-
fakt, aby nasz program był użyteczny, czyli potrafił kopiować nacje klawiszy, jak np.: CTRL-A - wciśnięcie tych klawiszy
pliki oraz tworzyć i kasować katalogi. Niestety nie jest możli- powoduje pojawienie się okna do zmiany atrybutów pliku
we nawet pobieżne przedstawienie wszystkich elementów ko- lub katalogu.
du zródłowego - jest on zbyt duży. Dlatego zostaną przedsta- Schemat z Rysunku 1 nie przedstawia wszystkich klawi-
wione tylko podstawowe elementy. szy, jednakże pozostałe klawisze są obsługiwane w podobny
56 czerwiec 2008
linux@software.com.pl
Programowanie
Arkusz kalkulacyjny i makra
sposób. Na koniec naturalnie trzeba zamknąć do katalogu. Naturalnie tylko wtedy, kiedy Listing 2. zawiera pełny kod zródłowy funk-
tryb tekstowy. mamy do tego prawo. Tę sytuację łatwo wy- cji kopiującej plik. Funkcja ta posiada cztery
Kod zródłowy naszego programu został kryć sprawdzając choćby, czy wartością funk- argumenty. Pierwsze dwa to ścieżka zródło-
podzielony na kilka części. Pliki fList.c oraz cji opendir jest wartość NULL. Jeśli tak jest, wa oraz ścieżka docelowa. Trzeci argument to
fList.h to implementacja dynamicznej listy może to oznaczać, iż nie mamy prawa dostę- wielkość kopiowanego pliku. W ostatnim ar-
dwukierunkowej, która pomaga w realizacji li- pu do katalogu. Gdy operacja się udała, za po- gumencie podajemy prawa pliku.
sty plików i katalogów wyświetlanych w pane- mocą wywołań readdir będziemy odczyty- Sam proces kopiowania polega na przepi-
lu. Obsługa okien dialogowych została umiesz- wać zawartość katalogu, element po elemen- sywaniu zawartości pliku małymi fragmenta-
czona w plikach dialogs.c oraz dialogs.h. Re- cie. Poszczególne elementy są typu struct mi. Jeden fragment to około 64kb. Dlatego na-
alizacja operacji na plikach i katalogach, np.: dirent. Struktura ta opisuje jeden wpis w ka- leży obliczyć ile bloków danych, czyli małych
usuwanie katalogu, to zadanie dla funkcji znaj- talogu. Zapisem do listy zajmuje się funkcja fragmentów, trzeba przegrać. Naturalnie trze-
dujących się plikach fs_oper.c oraz fs_oper.h. DecomposeDirent, która wydziela ze struktu- ba obliczyć resztę z dzielenia (ponieważ rzad-
Obsługa paneli, czyli ich rysowanie oraz ob- ry dirent poszczególne elementy, jak nazwę i ko bywa aby plik miał idealną długość po-
sługa klawiatury została umieszczona w pli- rodzaj wpisu: plik, katalog, link symbolicz- dzielną przez pewną wielkość):
kach workscr.c i workscr.h. Ostatnim plikiem ny. Odczytywane są także prawa dostępu oraz
jest maincode.c. W tym pliku znajduje się funk- czas modyfikacji. Te elementy są wyświetla- blocks=len / 65000
cja main, w której wykonujemy wszystkie nie- ne w panelu. Proces odczytywania zakończy remaing=len % 65000;
zbędne czynności, aby uruchomić nasz pro- się w momencie, gdy funkcja readdir zwróci
gram, czyli uruchamiamy tryb tekstowy, a po wartość NULL. Po tych obliczeniach w pętli kopiujemy blo-
wciśnięciu klawisza F10, kończącego pracę na- Odczytana zawartość katalogu niestety nie ki danych:
szego programu, w funkcji main wykonywane jest posortowana - jej kolejność jest zazwyczaj
są ostatnie czynności związane z zamknięciem określona przez datę utworzenia. My jednak for(i=0;itrybu tekstowego. będziemy sortować alfabetycznie: posortowa- le=read(f1, buf, 65000);
niem odczytanej zawartości zajmuje się funk- le=write(f2, buf, 65000);
Odczytanie zawartości katalogu cja SortList. }
Zanim poszczególne nazwy zostaną wyświe-
tlone w panelu, należy odczytać zawartość ka- Kopiowanie pliku Kopiowanie ostatniego fragmentu danych jest
talogu. Funkcja, która wykonuje to zadanie Tworzony przez nas program potrafi kopiować podobne, wykorzystujemy zmienną remaing,
jest dość krótka. Przedstawiona została na Li- pojedyncze pliki oraz całe katalogi. Najważ- w której mamy informacje ile danych trzeba
stingu 1. Odczyt zawartości wskazanego ka- niejszą funkcją jest funkcja kopiująca poje- przegrać, aby plik był kompletny.
talogu jest dość łatwy do zrealizowania. Wy- dynczy plik, ponieważ funkcja kopiowania re-
wołując funkcję opendir uzyskujemy dostęp kurencyjnego korzysta z opisywanej funkcji. le=read(f1, buf, remaing);
le=write(f2, buf, remaing);
START
Po przegraniu danych ustalamy jeszcze pra-
wa za pomocą polecenia fchmod. Zwróćmy
inicjalizacja
też uwagę (potwierdza to Listing 2.), iż jeśli
trybu tekstowego
plik jest mniejszy niż wielkość jednego bloku
odczyt aktualnego
danych, to kopiujemy jego zawartość jednym
katalogu
wywołaniem funkcji read oraz write.
TAK
Czy naciśnięto
zmiana panelu
klawisz TAB?
NIE
obsługa klawiatury Biblioteka S-Lang
TAK
Tworzenie
procedura
Biblioteka S-Lang oferuje funkcje do obsługi
katalogu?
tworzenia katalogu
konsoli, czyli ekranu oraz klawiatury. Funk-
TAK
Edycja
procedura
cje te pracują zarówno na niskim i wysokim
atrubutów
edycji atrybutów
poziomie, co oznacza, że jeśli stosujemy
NIE
funkcję wysokiego poziomu nie musimy się
...
martwić o detale związane z obsługą konso-
li. Mamy także dostęp do prostego edytora
NIE
koniec pracy
liniowego (Readline), co znacząco ułatwia
programu?
odbiór danych od użytkownika. Zaletą pa-
TAK
kietu S-Lang jest również wydajność. Pakiet
zamknięcie
ten oferuje również dostęp do interpretowa-
trybu tekstowego
nego języka programowania podobnego do
STOP
C. W naszym programie jednak nie korzy-
stamy z tej możliwości.
Rysunek 1. Schemat przepływu sterowania w projektowanej aplikacji
www.lpmagazine.org 57
Programowanie
Arkusz kalkulacyjny i makra
Lista plików i katalogów w panelu Listing wisze strzałek, wtedy przesuwany jest kursor,
Listing 1. Odczytanie zawartości katalogu
3. zawiera fragment z funkcji DisplayDirec- czyli zmienna cpos_left. Zmienne te są też
int ReadDirectory(char *path) { tory, która jest odpowiedzialna na wyświetla- modyfikowane, gdy naciskane są klawisze Pa-
DIR *dir=NULL; nie listy plików i katalogów w lewym panelu ge Up oraz Page Down. Obsługa klawiszy znaj-
struct dirent* idir = NULL; (wersja dla prawego jest naturalnie podobna). duje się w funkcji NavigateKey.
TDirItem tmp; Stosujemy pętlę for, która wykorzystuje zmien- Wyświetlanie informacji o plikach (zebra-
dir=opendir(path); ne ifrom_dir_left oraz ito_dir_left. W nych przez funkcję ReadDirectory) rozpoczy-
if(dir==NULL) { zmiennych tych zapisane są numery, od któ- namy od odczytania odpowiedniego elementu z
return -1; rego wpisu w katalogu należy rozpocząć wy- listy funkcją At0List. Następnie w zależności
} świetlanie i na którym należy zakończyć. Ilość
while(idir=readdir(dir)) { elementów jest wyliczana przez funkcję Cal- Listing 4. Odczytanie jednej linii tekstu, wykorzy-
DecomposeDirent(idir); culate. Funkcja ta, uwzględniając wielkość, a stując edytor Readline
} dokładniej wysokość konsoli, oblicza wielkość char* ReadLineText(int x, int y,
closedir(dir); okna podglądu. Zmienne ifrom_dir_left int w, char *txt) {
SortList(active_dir, IDirCmp, oraz ito_dir_left są również odpowiednio int n;
IDirAssign, &tmp); modyfikowane. Gdy użytkownik naciska kla- unsigned char *line;
return 0; rline_BUF[0]=0;
} Listing 3. Funkcja kopiująca plik init_slang_readline(x, y, w);
case PANEL_LEFT: if(txt != NULL) {
Listing 2. Funkcja kopiująca plik for(i=ifrom_dir_left; i<=ito_ SLrline_set_line( rline_RLI,
int copy_fi le(char *from, char *to, dir_left; i++) { txt);
int len, mode_t mode) { di=(TDirItem*)At0List(dir_ SLrline_set_point(rline_RLI,
int f1, f2, i, blocks, remaing, left, i); strlen(txt));
le; void *buf; switch(di->ft) { }
le=-1; case ft_DIR: line = SLrline_read_line( rline_
f1=open(from, O_RDONLY); sprintf(t,DISP_DIR, di->name, di- RLI, NULL, &len );
if(f1!=-1) { >mtime); break; strcpy( &rline_BUF[0], line);
f2=open(to, O_CREAT | O_TRUNC case ft_LNK: SLfree ( line );
| O_WRONLY); sprintf(t,DISP_LNK, di->name, di- SLrline_close ( rline_RLI );
if(f2==-1) { >mtime); break; return &rline_BUF[0];
le=close(f1); case ft_REG: }
return -1; sprintf(t,DISP_REG, di->name,
} IntToMB(di->size), di->mtime); Listing 5. Okno kasowania pliku
buf=(void*)malloc(65000); break; int DeleteDLG(char *path) {
if(len<65000) { default: sprintf(t, int x,y,c,l,le;
le=read(f1, buf, len); ""); l=strlen(path)+6+2;
le=write(f2, buf, len); } if(l<28) l=28;
le=fchmod(f2, mode); if(i==cpos_left) { x=SLtt_Screen_Rows/2;
} Slsmg_set_color(3); y=SLtt_Screen_Cols/2;
else { SLsmg_gotorc(rd++, 1); SLsmg_fi ll_region(x-2, y-l/2, 4,
blocks=len / 65000; Slsmg_printf("%s",t); l+2,' ');
remaing=len % 65000; /* dodatkowe informacje na SLsmg_draw_box(x-2, y-l/2, 4,
for(i=0;ile=read(f1, buf, Slsmg_set_color(5); SLsmg_gotorc(x-1, y-l/2+1);
65000); le=write(f2, buf, 65000); SLsmg_gotorc(SLtt_Screen_ SLsmg_printf("Delete \"%s\
} Rows-2, 2); "",path);
le=read(f1, buf, remaing); sprintf( t, ADD_INFO, SLsmg_gotorc(x, y-9);
le=write(f2, buf, remaing); di->name, ReturnMode(di->mode), DrawButton("OK");
le=fchmod(f2, mode); IntToMB(di->size)); SLsmg_gotorc(x, y);
} SLsmg_printf("%s", t); DrawButton("CANCEL");
free(buf); } Slsmg_refresh();
le=close(f2); le=close(f1); else { if(Select(x, y-9, y,"OK",
} SLsmg_set_color(5); "CANCEL")==0) {
else { SLsmg_gotorc(rd++, 1); le=recursive_del(path);
le=-1; Slsmg_printf("%s",t); if(le==-1)
} } AccessViolationDLG();
return le; } }
} break; }
58 czerwiec 2008
Programowanie
Arkusz kalkulacyjny i makra
od typu wpisu (plik, link, katalog) przygotowu- przez argument w. Natomiast w ostatnim argu- znaków, jak również znajdujemy współrzęd-
jemy poleceniem sprintf ciąg znaków. mencie o nazwie txt możemy podać tekst, któ- ne środka ekranu. Następnie za pomocą funkcji
Kolejny test to sprawdzenie, czy aktualna ry zostanie podany edycji. Zmieniony tekst lub SLsmg_fi ll_region wypełniamy pewien obszar
wartość zmiennej i jest równa wartości zmien- jego kopia, jeśli użytkownik nie zmieni treści, ekranu jednolitym kolorem, aby następną funk-
nej cpos_left. Jeśli tak jest, to dobierając od- staje się wynikiem działania funkcji ReadLine- cją narysować prostokąt. Wewnątrz tego prosto-
powiednie zmiany kolorów użytkownik nasze- Text. Funkcja ReadLineText choć dość krótka, kąta umieszczamy komunikat tekstowy. Rysuje-
go programu będzie widział kursor w panelu. składa się z trzech części. W pierwszej inicjali- my również dwa dodatkowe przyciski - OK oraz
Inaczej mówiąc, wiadomo będzie na jaki plik zujemy system Readline dostępny w bibliote- CANCEL. Po tych przygotowaniach możemy
bądz katalog aktualnie wskazujemy. Jeśli bę- ce S-Lang. Następnie sprawdzamy zawartość stosując funkcję Select pozwolić użytkowniko-
dzie to katalog, to naciśnięcie klawisza ENTER argumentu txt. Jeśli wartość tej zmiennej jest wi na wybór, czy chce skasować plik wybierając
spowoduje przejście do tego katalogu. Wybranie różna od NULL, to zawartość argumentu txt OK, czy też woli wycofać się z tej operacji po-
dwóch kropek, naturalnie, spowoduje przejście zostanie przepisana do edytora liniowego za przez wybór przycisku CANCEL. Jeśli użytkow-
katalog wyżej. pomocą funkcji Slrline_set_line. nik wybierze OK funkcja recursive_del usu-
Następny krok to edycja danych. Po wywo- nie wskazany plik bądz katalog. Jeśli nie mamy
Readline  obieranie łaniu funkcji SLrline_read_line użytkownik praw dostępu, to w zmiennej le znajdzie się war-
informacji od użytkownika może wpisać nowy tekst lub zmienić istniejący. tość -1. Możemy w ten sposób poinformować
Podczas tworzenia katalogu, przenoszenia pli- Proces edycji trwa do momentu wciśnięcia kla- użytkownika o braku praw dostępu.
ku oraz kopiowania, użytkownik ma możliwość wisza ENTER. Można też tak oprogramować
podania nazwy nowego katalogu lub zmianę na- obsługę Readline, aby klawiszem TAB można Podsumowanie
zwy kopiowanego pliku. Edycja jest możliwa było opuścić tryb edycji. Po zakończonej edycji Nie sposób opisać wszystkich detali związa-
dzięki zastosowaniu edytora liniowego. Biblio- celowo zawartość zmiennej line jest kopiowa- nych z naszym programem. Choć ograniczyli-
teka S-Lang daje możliwość skorzystania z pro- na do zmiennej globalnej rline_BUF, bowiem śmy liczbę możliwości, to jak widać nie jest to
stego edytora liniowego o nazwie Readline. W pamięć przydzielona do zmiennej line powinna już program do napisania w przysłowiowy jeden
naszym programie występują trzy funkcje: in- zostać zwolniona. Wywołaniem funkcji SLrli- wieczór. Jednakże w tym, bądz co bądz, niewiel-
it_slang_readline zajmująca się przygotowa- ne_close zamykamy proces edycji (pomijamy kim programie udało się zaimplementować pod-
niem odpowiednich zmiennych, druga ReadLi- wywołanie funkcji done_slang_readline). stawowe opcje, takie jak kopiowanie i usuwanie
neText, która zgodnie z nazwą odczytuje linię plików oraz katalogów. Swobodnie możemy się
tekstu oraz done_slang_readline zamykają- Okno kasowania pliku bądz katalogu także poruszać po strukturze katalogowej. Pro-
ca proces odczytu linii tekstu. Wszystkie naj- Listing 5. zawiera całą funkcję odpowie- gram oferuje także możliwość zmiany podsta-
ważniejsze czynności są wykonywane w funk- dzialną za narysowanie okna dialogowego z za- wowych atrybutów plików i katalogów. Wielką
cji ReadLineText. Jej kod zródłowy prezentu- pytaniem, czy skasować wskazany przez użyt- zaletą naszego programu jest też jego wielkość.
je Listing 4. Istotne są argumenty tej funkcji. kownika plik bądz katalog. Przed narysowaniem Nasz program to zaledwie kilkadziesiąt kilobaj-
Dwa pierwsze, x oraz y, określają współrzędne okna należy uzyskać kilka istotnych dla nas in- tów, choć wymagana jest dodatkowa bibliote-
na ekranie, w którym będzie znajdować się po- formacji. Obliczamy długość ścieżki (wielkość ka S-Lang. Jednakże, jak zostało to pokazane,
le edycyjne. Szerokość tego pola jest określona ta zostaje zapisana w zmiennej l), dodając osiem w dość prosty sposób możemy utworzyć wersję
statyczną naszego programu. Jej zaletą jest nie-
zależność od zainstalowanych bibliotek.
W naszym programie brakuje także kilku
Wersja statyczna programu
ważnych opcji. Wypadałoby zaimplementować
podgląd plików w postaci tekstowej. Oblicza-
Kompilacja omawianego programu przebiega w typowy sposób. Trzeba pamiętać, aby w
nie wielkości zajętego miejsca przez wskazany
systemie dostępna była biblioteka S-Lang. Poszczególne pliki programu możemy kompilo-
katalog także byłoby bardzo przydatną funkcją.
wać w następujący sposób (zakładamy, że pliki zródłowe znajdują się w podkatalogu src):
Nieco bardziej skomplikowaną funkcją były-
by dostęp do konsoli.Jednakże ta funkcja spo-
gcc -c ./src/fs_oper.c -I./src
wodowałaby, iż nasz program zyskałby bar-
dzo wiele na funkcjonalności. Wiele większych
Budowa wersji binarnej programu, sprowadza się do wydania polecenia:
oraz mniejszych funkcji można dodać do opisy-
gcc -o minicmd dialogs.o fList.o fs_oper.o mainfi le.o workscr.o -lslang
wanego programu, toteż zachęcam do wprowa-
dzania zmian i eksperymentowania z nim.
Jednak tak powstały program będzie wymagał w systemie obecności biblioteki S-Lang. W
dość prosty sposób możemy usunąć to ograniczenie, tworząc program z użyciem biblio-
tek statycznych. Jednakże oprócz biblioteki S-Lang trzeba także dołączyć bibliotekę Ncur-
ses, w następujący sposób:
O autorze
gcc -o minicmd_static dialogs.o fList.o fs_oper.o mainfi le.o workscr.o /usr/
Autor zajmuje się tworzeniem oprogramo-
lib/libslang.a /usr/lib/libncurses.a
wania dla WIN32 i Linuksa. Zainteresowa-
nia: teoria języków programowania oraz
Uzyskana wersja binarna jest znacznie większa niż wersja niestatyczna, ale program dzia-
dobra literatura.
ła poprawnie w systemach, gdzie nie ma zainstalowanej biblioteki S-Lang.
Kontakt z autorem: autorzy@linux.com.pl.
www.lpmagazine.org 59


Wyszukiwarka

Podobne podstrony:
2008 06 Scalix – poczta dla podróżujących [Programowanie]
2008 06 Programowanie grafiki [Programowanie]
2008 06 the Way of the Ray Enterprise Collaboration with Liferay
2008 06 Living Free Free Communications on the Freenet Network
2008 06 Czy boisz się Slackware [Poczatkujacy]
2008 06 teleinformatyk arkusz x
2008 06 Virtual machines [Consumer test]
2008 06 05 WHR B?instrukcja
2008 06 Tworzenie i edycja grafiki online [Grafika]
2008 06 Test CAPTCHA
2008 07 08 Serwis zdjęć z wakacji [Programowanie]
2008 11 Opensource owe platformy blogowe [Programowanie PHP]
ŚK 2008 06 Jak zacząć budowę makiety modułowej 3
2008 06 More Sun
2008 09 Wine Importer Running Windows Programs on Linux with Wine

więcej podobnych podstron