Guess what? Yep, another wmtext update. Now this was all, please go to
[wmaker-crm.git] / WINGs / wfilepanel.c
blobce53974af8a8a1e1e952274b7b0bcdffa00752d2
2 #include "WINGsP.h"
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include <dirent.h>
8 #include <limits.h>
9 #include <errno.h>
11 #ifndef PATH_MAX
12 #define PATH_MAX 1024
13 #endif
16 typedef struct W_FilePanel {
17 WMWindow *win;
19 WMLabel *iconLabel;
20 WMLabel *titleLabel;
22 WMFrame *line;
24 WMLabel *nameLabel;
25 WMBrowser *browser;
27 WMButton *okButton;
28 WMButton *cancelButton;
30 WMButton *homeButton;
31 WMButton *trashcanButton;
32 WMButton *createDirButton;
33 WMButton *disketteButton;
34 WMButton *unmountButton;
36 WMView *accessoryView;
38 WMTextField *fileField;
40 char **fileTypes;
42 struct {
43 unsigned int canExit:1;
44 unsigned int canceled:1; /* clicked on cancel */
45 unsigned int done:1;
46 unsigned int filtered:1;
47 unsigned int canChooseFiles:1;
48 unsigned int canChooseDirectories:1;
49 unsigned int autoCompletion:1;
50 unsigned int showAllFiles:1;
51 unsigned int canFreeFileTypes:1;
52 unsigned int fileMustExist:1;
53 unsigned int panelType:1;
54 } flags;
55 } W_FilePanel;
58 /* Type of panel */
59 #define WP_OPEN 0
60 #define WP_SAVE 1
62 #define PWIDTH 330
63 #define PHEIGHT 360
65 static void listDirectoryOnColumn(WMFilePanel *panel, int column, char *path);
66 static void browserClick();
67 static void browserDClick();
69 static void fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column,
70 WMList *list);
72 static void deleteFile();
74 static void createDir();
76 static void goHome();
78 static void goFloppy();
80 static void goUnmount();
82 static void buttonClick();
84 static char *getCurrentFileName(WMFilePanel *panel);
86 static void handleEvents(XEvent *event, void *data);
90 static WMBrowserDelegate browserDelegate = {
91 NULL, /* data */
92 fillColumn, /* createRowsForColumn */
93 NULL, /* titleOfColumn */
94 NULL, /* didScroll */
95 NULL /* willScroll */
99 static int
100 closestListItem(WMList *list, char *text, Bool exact)
102 WMListItem *item;
103 WMBag *items = WMGetListItems(list);
104 WMBagIterator i;
105 int len = strlen(text);
107 if (len==0)
108 return -1;
110 WM_ITERATE_BAG(items, item, i) {
111 if (strlen(item->text) >= len &&
112 ((exact && strcmp(item->text, text)==0) ||
113 (!exact && strncmp(item->text, text, len)==0))) {
114 return WMBagIndexForIterator(items, i);
118 return -1;
122 static void
123 textChangedObserver(void *observerData, WMNotification *notification)
125 W_FilePanel *panel = (W_FilePanel*)observerData;
126 char *text;
127 WMList *list;
128 int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
129 int i, textEvent;
131 if (!(list = WMGetBrowserListInColumn(panel->browser, col)))
132 return;
134 text = WMGetTextFieldText(panel->fileField);
135 textEvent = (int)WMGetNotificationClientData(notification);
137 if (panel->flags.autoCompletion && textEvent!=WMDeleteTextEvent)
138 i = closestListItem(list, text, False);
139 else
140 i = closestListItem(list, text, True);
142 WMSelectListItem(list, i);
143 if (i>=0 && panel->flags.autoCompletion) {
144 WMListItem *item = WMGetListItem(list, i);
145 int textLen = strlen(text), itemTextLen = strlen(item->text);
146 int visibleItems = WMWidgetHeight(list)/WMGetListItemHeight(list);
148 WMSetListPosition(list, i - visibleItems/2);
150 if (textEvent!=WMDeleteTextEvent) {
151 WMRange range;
153 WMInsertTextFieldText(panel->fileField, &item->text[textLen],
154 textLen);
155 range.position = textLen;
156 range.count = itemTextLen - textLen;
157 WMSelectTextFieldRange(panel->fileField, range);
158 /*WMSetTextFieldCursorPosition(panel->fileField, itemTextLen);*/
162 wfree(text);
166 static void
167 textEditedObserver(void *observerData, WMNotification *notification)
169 W_FilePanel *panel = (W_FilePanel*)observerData;
171 if ((int)WMGetNotificationClientData(notification)==WMReturnTextMovement) {
172 WMPerformButtonClick(panel->okButton);
178 static WMFilePanel*
179 makeFilePanel(WMScreen *scrPtr, char *name, char *title)
181 WMFilePanel *fPtr;
182 WMFont *largeFont;
184 fPtr = wmalloc(sizeof(WMFilePanel));
185 memset(fPtr, 0, sizeof(WMFilePanel));
187 fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask
188 |WMResizableWindowMask);
189 WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
190 WMSetWindowTitle(fPtr->win, "");
192 WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask,
193 handleEvents, fPtr);
194 WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT);
197 fPtr->iconLabel = WMCreateLabel(fPtr->win);
198 WMResizeWidget(fPtr->iconLabel, 64, 64);
199 WMMoveWidget(fPtr->iconLabel, 0, 0);
200 WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
201 WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIcon);
203 fPtr->titleLabel = WMCreateLabel(fPtr->win);
204 WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64);
205 WMMoveWidget(fPtr->titleLabel, 64, 0);
206 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
207 WMSetLabelFont(fPtr->titleLabel, largeFont);
208 WMReleaseFont(largeFont);
209 WMSetLabelText(fPtr->titleLabel, title);
211 fPtr->line = WMCreateFrame(fPtr->win);
212 WMMoveWidget(fPtr->line, 0, 64);
213 WMResizeWidget(fPtr->line, PWIDTH, 2);
214 WMSetFrameRelief(fPtr->line, WRGroove);
216 fPtr->browser = WMCreateBrowser(fPtr->win);
217 WMSetBrowserDelegate(fPtr->browser, &browserDelegate);
218 WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
219 WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr);
220 WMMoveWidget(fPtr->browser, 7, 72);
221 WMResizeWidget(fPtr->browser, PWIDTH-14,200);
222 WMHangData(fPtr->browser, fPtr);
224 fPtr->nameLabel = WMCreateLabel(fPtr->win);
225 WMMoveWidget(fPtr->nameLabel, 7, 282);
226 WMResizeWidget(fPtr->nameLabel, 55, 14);
227 WMSetLabelText(fPtr->nameLabel, "Name:");
229 fPtr->fileField = WMCreateTextField(fPtr->win);
230 WMMoveWidget(fPtr->fileField, 60, 278);
231 WMResizeWidget(fPtr->fileField, PWIDTH-60-10, 24);
232 WMAddNotificationObserver(textEditedObserver, fPtr,
233 WMTextDidEndEditingNotification,
234 fPtr->fileField);
235 WMAddNotificationObserver(textChangedObserver, fPtr,
236 WMTextDidChangeNotification,
237 fPtr->fileField);
239 fPtr->okButton = WMCreateCommandButton(fPtr->win);
240 WMMoveWidget(fPtr->okButton, 245, 325);
241 WMResizeWidget(fPtr->okButton, 75, 28);
242 WMSetButtonText(fPtr->okButton, "OK");
243 WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
244 WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
245 WMSetButtonImagePosition(fPtr->okButton, WIPRight);
246 WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
248 fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
249 WMMoveWidget(fPtr->cancelButton, 165, 325);
250 WMResizeWidget(fPtr->cancelButton, 75, 28);
251 WMSetButtonText(fPtr->cancelButton, "Cancel");
252 WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
254 fPtr->trashcanButton = WMCreateCommandButton(fPtr->win);
255 WMMoveWidget(fPtr->trashcanButton, 7, 325);
256 WMResizeWidget(fPtr->trashcanButton, 28, 28);
257 WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly);
258 WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon);
259 WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon);
260 WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr);
262 fPtr->createDirButton = WMCreateCommandButton(fPtr->win);
263 WMMoveWidget(fPtr->createDirButton, 37, 325);
264 WMResizeWidget(fPtr->createDirButton, 28, 28);
265 WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly);
266 WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon);
267 WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon);
268 WMSetButtonAction(fPtr->createDirButton, createDir, fPtr);
270 fPtr->homeButton = WMCreateCommandButton(fPtr->win);
271 WMMoveWidget(fPtr->homeButton, 67, 325);
272 WMResizeWidget(fPtr->homeButton, 28, 28);
273 WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
274 WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
275 WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon);
276 WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
278 fPtr->disketteButton = WMCreateCommandButton(fPtr->win);
279 WMMoveWidget(fPtr->disketteButton, 97, 325);
280 WMResizeWidget(fPtr->disketteButton, 28, 28);
281 WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly);
282 WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon);
283 WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon);
284 WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr);
286 fPtr->unmountButton = WMCreateCommandButton(fPtr->win);
287 WMMoveWidget(fPtr->unmountButton, 127, 325);
288 WMResizeWidget(fPtr->unmountButton, 28, 28);
289 WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly);
290 WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon);
291 WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon);
292 WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr);
293 WMSetButtonEnabled(fPtr->unmountButton, False);
296 WMRealizeWidget(fPtr->win);
297 WMMapSubwidgets(fPtr->win);
299 WMSetFocusToWidget(fPtr->fileField);
300 WMSetTextFieldCursorPosition(fPtr->fileField, 0);
302 WMLoadBrowserColumnZero(fPtr->browser);
304 WMSetWindowInitialPosition(fPtr->win,
305 (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win))/2,
306 (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win))/2);
308 fPtr->flags.canChooseFiles = 1;
309 fPtr->flags.canChooseDirectories = 1;
310 fPtr->flags.autoCompletion = 1;
312 return fPtr;
316 WMOpenPanel*
317 WMGetOpenPanel(WMScreen *scrPtr)
319 WMFilePanel *panel;
321 if (scrPtr->sharedOpenPanel)
322 return scrPtr->sharedOpenPanel;
324 panel = makeFilePanel(scrPtr, "openFilePanel", "Open");
325 panel->flags.fileMustExist = 1;
326 panel->flags.panelType = WP_OPEN;
328 scrPtr->sharedOpenPanel = panel;
330 return panel;
334 WMSavePanel*
335 WMGetSavePanel(WMScreen *scrPtr)
337 WMFilePanel *panel;
339 if (scrPtr->sharedSavePanel)
340 return scrPtr->sharedSavePanel;
342 panel = makeFilePanel(scrPtr, "saveFilePanel", "Save");
343 panel->flags.fileMustExist = 0;
344 panel->flags.panelType = WP_SAVE;
346 scrPtr->sharedSavePanel = panel;
348 return panel;
352 void
353 WMFreeFilePanel(WMFilePanel *panel)
355 if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) {
356 WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
358 if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
359 WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
361 WMRemoveNotificationObserver(panel);
362 WMUnmapWidget(panel->win);
363 WMDestroyWidget(panel->win);
364 wfree(panel);
369 WMRunModalFilePanelForDirectory(WMFilePanel *panel, WMWindow *owner,
370 char *path, char *name, char **fileTypes)
372 WMScreen *scr = WMWidgetScreen(panel->win);
373 XEvent event;
375 if (name && !owner) {
376 WMSetWindowTitle(panel->win, name);
379 WMChangePanelOwner(panel->win, owner);
381 WMSetFilePanelDirectory(panel, path);
383 panel->flags.done = 0;
384 switch(panel->flags.panelType) {
385 case WP_OPEN:
386 if (fileTypes)
387 panel->flags.filtered = 1;
388 panel->fileTypes = fileTypes;
389 if (name == NULL)
390 name = "Open";
391 break;
392 case WP_SAVE:
393 panel->fileTypes = NULL;
394 panel->flags.filtered = 0;
395 if (name == NULL)
396 name = "Save";
397 break;
398 default:
399 break;
402 WMSetLabelText(panel->titleLabel, name);
404 scr->modalView = W_VIEW(panel->win);
405 WMMapWidget(panel->win);
407 scr->modal = 1;
408 while (!panel->flags.done) {
409 WMNextEvent(scr->display, &event);
410 WMHandleEvent(&event);
412 scr->modal = 0;
414 /* Must withdraw window because the next time we map
415 * it, it might have a different transient owner.
417 WMCloseWindow(panel->win);
419 return (panel->flags.canceled ? False : True);
425 void
426 WMSetFilePanelDirectory(WMFilePanel *panel, char *path)
428 WMList *list;
429 WMListItem *item;
430 int col;
431 char *rest;
433 rest = WMSetBrowserPath(panel->browser, path);
434 if (strcmp(path, "/")==0)
435 rest = NULL;
437 col = WMGetBrowserSelectedColumn(panel->browser);
438 list = WMGetBrowserListInColumn(panel->browser, col);
439 if (list && (item = WMGetListSelectedItem(list))) {
440 if (item->isBranch) {
441 WMSetTextFieldText(panel->fileField, rest);
442 } else {
443 WMSetTextFieldText(panel->fileField, item->text);
445 } else {
446 WMSetTextFieldText(panel->fileField, rest);
451 void
452 WMSetFilePanelCanChooseDirectories(WMFilePanel *panel, Bool flag)
454 panel->flags.canChooseDirectories = flag;
457 void
458 WMSetFilePanelCanChooseFiles(WMFilePanel *panel, Bool flag)
460 panel->flags.canChooseFiles = flag;
464 void
465 WMSetFilePanelAutoCompletion(WMFilePanel *panel, Bool flag)
467 panel->flags.autoCompletion = flag;
471 char*
472 WMGetFilePanelFileName(WMFilePanel *panel)
474 return getCurrentFileName(panel);
478 void
479 WMSetFilePanelAccessoryView(WMFilePanel *panel, WMView *view)
481 WMView *v;
483 panel->accessoryView = view;
485 v = WMWidgetView(panel->win);
487 W_ReparentView(view, v, 0, 0);
489 W_MoveView(view, (v->size.width - v->size.width)/2, 300);
493 WMView*
494 WMGetFilePanelAccessoryView(WMFilePanel *panel)
496 return panel->accessoryView;
500 static char*
501 get_name_from_path(char *path)
503 int size;
505 assert(path!=NULL);
507 size = strlen(path);
509 /* remove trailing / */
510 while (size > 0 && path[size-1]=='/')
511 size--;
512 /* directory was root */
513 if (size == 0)
514 return wstrdup("/");
516 while (size > 0 && path[size-1] != '/')
517 size--;
519 return wstrdup(&(path[size]));
523 static int
524 filterFileName(WMFilePanel *panel, char *file, Bool isDirectory)
526 return True;
530 #define CAST(item) (*((WMListItem**)item))
531 static int
532 comparer(const void *a, const void *b)
534 if (CAST(a)->isBranch == CAST(b)->isBranch)
535 return (strcmp(CAST(a)->text, CAST(b)->text));
536 if (CAST(a)->isBranch)
537 return (-1);
538 return (1);
540 #undef CAST
543 static void
544 listDirectoryOnColumn(WMFilePanel *panel, int column, char *path)
546 WMBrowser *bPtr = panel->browser;
547 struct dirent *dentry;
548 DIR *dir;
549 struct stat stat_buf;
550 char pbuf[PATH_MAX+16];
552 assert(column >= 0);
553 assert(path != NULL);
555 /* put directory name in the title */
556 WMSetBrowserColumnTitle(bPtr, column, get_name_from_path(path));
558 dir = opendir(path);
560 if (!dir) {
561 #ifdef VERBOSE
562 printf("WINGs: could not open directory %s\n", path);
563 #endif
564 return;
567 /* list contents in the column */
568 while ((dentry = readdir(dir))) {
569 if (strcmp(dentry->d_name, ".")==0 ||
570 strcmp(dentry->d_name, "..")==0)
571 continue;
573 strcpy(pbuf, path);
574 if (strcmp(path, "/")!=0)
575 strcat(pbuf, "/");
576 strcat(pbuf, dentry->d_name);
578 if (stat(pbuf, &stat_buf)!=0) {
579 #ifdef VERBOSE
580 printf("WINGs: could not stat %s\n", pbuf);
581 #endif
582 continue;
583 } else {
584 int isDirectory;
586 isDirectory = S_ISDIR(stat_buf.st_mode);
588 if (filterFileName(panel, dentry->d_name, isDirectory))
589 WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory);
592 WMSortBrowserColumnWithComparer(bPtr, column, comparer);
594 closedir(dir);
598 static void
599 fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column, WMList *list)
601 char *path;
602 WMFilePanel *panel;
604 if (column > 0) {
605 path = WMGetBrowserPathToColumn(bPtr, column-1);
606 } else {
607 path = wstrdup("/");
610 panel = WMGetHangedData(bPtr);
611 listDirectoryOnColumn(panel, column, path);
612 wfree(path);
616 static void
617 browserDClick(WMBrowser *bPtr, WMFilePanel *panel)
619 WMPerformButtonClick(panel->okButton);
622 static void
623 browserClick(WMBrowser *bPtr, WMFilePanel *panel)
625 int col = WMGetBrowserSelectedColumn(bPtr);
626 WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
628 if (!item || item->isBranch)
629 WMSetTextFieldText(panel->fileField, NULL);
630 else {
631 WMSetTextFieldText(panel->fileField, item->text);
636 static void
637 showError(WMScreen *scr, WMWindow *owner, char *s, char *file)
639 char *errStr;
641 if (file) {
642 errStr = wmalloc(strlen(file)+strlen(s));
643 sprintf(errStr, s, file);
644 } else {
645 errStr = wstrdup(s);
647 WMRunAlertPanel(scr, owner, "Error", errStr, "OK", NULL, NULL);
648 wfree(errStr);
652 static void
653 createDir(WMButton *bPre, WMFilePanel *panel)
655 char *directory_name;
656 char *directory;
657 char *file;
658 char *s;
659 WMScreen *scr = WMWidgetScreen(panel->win);
660 WMInputPanel *_panel;
662 _panel = WMCreateInputPanel(scr, panel->win,
663 "Create Directory", "Enter directory name", "", "OK", "Cancel");
664 scr->modalView = W_VIEW(_panel->win);
665 WMMapWidget(_panel->win);
666 scr->modal = 1;
667 while (!_panel->done || WMScreenPending(scr)) {
668 XEvent event;
669 WMNextEvent(scr->display, &event);
670 WMHandleEvent(&event);
672 scr->modal = 0;
674 if (_panel->result == WAPRDefault)
675 directory_name = WMGetTextFieldText(_panel->text);
676 else {
677 WMDestroyInputPanel(_panel);
678 return;
681 WMDestroyInputPanel(_panel);
683 directory = getCurrentFileName(panel);
685 char *s = strrchr(directory,'/');
686 if (s) s[1] = 0;
689 if (directory_name[0] == '/') {
690 directory[0] = 0;
691 } else {
692 while ((s = strstr(directory,"//"))) {
693 int i;
694 for (i = 2;s[i] == '/';i++);
695 strcpy(s, &s[i-1]);
697 if ((s = strrchr(directory, '/')) && !s[1]) s[0] = 0;
699 while ((s = strstr(directory_name,"//"))) {
700 int i;
701 for (i = 2;s[i] == '/';i++);
702 strcpy(s, &s[i-1]);
704 if ((s = strrchr(directory_name, '/')) && !s[1]) s[0] = 0;
706 file = wmalloc(strlen(directory_name)+strlen(directory)+1);
707 sprintf(file, "%s/%s", directory, directory_name);
708 while ((s = strstr(file,"//"))) {
709 int i;
710 for (i = 2;s[i] == '/';i++);
711 strcpy(s, &s[i-1]);
714 if (mkdir(file,0xfff) != 0) {
715 switch (errno) {
716 case EACCES:
717 showError(scr, panel->win, "Permission denied.", NULL);
718 break;
719 case EEXIST:
720 showError(scr, panel->win, "'%s' already existes.", file);
721 break;
722 case ENOENT:
723 showError(scr, panel->win, "Path does not exist.", NULL);
726 else WMSetFilePanelDirectory(panel, file);
728 wfree(directory_name);
729 wfree(directory);
730 wfree(file);
734 static void
735 deleteFile(WMButton *bPre, WMFilePanel *panel)
737 char *file;
738 char *buffer, *s;
739 struct stat filestat;
740 WMScreen *scr = WMWidgetScreen(panel->win);
742 file = getCurrentFileName(panel);
744 while ((s = strstr(file,"//"))) {
745 int i;
746 for (i = 2;s[i] == '/';i++);
747 strcpy(s, &s[i-1]);
749 if (strlen(file) > 1 && (s = strrchr(file, '/')) && !s[1]) s[0] = 0;
751 if (stat(file,&filestat)) {
752 switch (errno) {
753 case ENOENT:
754 showError(scr, panel->win, "'%s' does not exist.", file);
755 break;
756 case EACCES:
757 showError(scr, panel->win, "Permission denied.", NULL);
758 break;
759 case ENOMEM:
760 showError(scr, panel->win,
761 "Insufficient memory available.", NULL);
762 break;
763 case EROFS:
764 showError(scr, panel->win,
765 "'%s' is on a read-only filesystem.", file);
766 break;
767 default:
768 showError(scr, panel->win, "Can not delete '%s'.", file);
770 wfree(file);
771 return;
772 } else if (S_ISDIR(filestat.st_mode)) {
773 buffer = wmalloc(strlen(file)+20);
774 sprintf(buffer,"Delete directory %s ?",file);
775 } else {
776 buffer = wmalloc(strlen(file)+15);
777 sprintf(buffer,"Delete file %s ?",file);
780 if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
781 "Warning", buffer, "OK", "Cancel", NULL)) {
782 if (S_ISDIR(filestat.st_mode)) {
783 if (rmdir(file) != 0) {
784 switch (errno) {
785 case EACCES:
786 showError(scr, panel->win, "Permission denied.", NULL);
787 break;
788 case ENOENT:
789 showError(scr, panel->win, "Directory '%s' does not exist.", file);
790 break;
791 case ENOTEMPTY:
792 showError(scr, panel->win, "Directory '%s' is not empty.", file);
793 break;
794 case EBUSY:
795 showError(scr, panel->win, "Directory '%s' is busy.", file);
796 break;
797 default:
798 showError(scr, panel->win, "Can not delete '%s'.", file);
800 } else {
801 char *s = strrchr(file,'/');
802 if (s) s[0] = 0;
803 WMSetFilePanelDirectory(panel, file);
805 } else if (remove(file) != 0) {
806 switch (errno) {
807 case EISDIR:
808 showError(scr, panel->win, "'%s' is a directory.", file);
809 break;
810 case ENOENT:
811 showError(scr, panel->win, "'%s' does not exist.", file);
812 break;
813 case EACCES:
814 showError(scr, panel->win, "Permission denied.", NULL);
815 break;
816 case ENOMEM:
817 showError(scr, panel->win,
818 "Insufficient memory available.", NULL);
819 break;
820 case EROFS:
821 showError(scr, panel->win,
822 "'%s' is on a read-only filesystem.", file);
823 break;
824 default:
825 showError(scr, panel->win, "Can not delete '%s'.", file);
827 } else {
828 char *s = strrchr(file,'/');
829 if (s) s[1] = 0;
830 WMSetFilePanelDirectory(panel, file);
833 wfree(buffer);
834 wfree(file);
837 static void
838 goUnmount(WMButton *bPtr, WMFilePanel *panel)
843 static void
844 goFloppy(WMButton *bPtr, WMFilePanel *panel)
846 struct stat filestat;
847 WMScreen *scr = WMWidgetScreen(panel->win);
849 if (stat(WINGsConfiguration.floppyPath, &filestat)) {
850 showError(scr, panel->win, "An error occured browsing '%s'.",
851 WINGsConfiguration.floppyPath);
852 return;
853 } else if (!S_ISDIR(filestat.st_mode)) {
854 showError(scr, panel->win, "'%s' is not a directory.",
855 WINGsConfiguration.floppyPath);
856 return;
859 WMSetFilePanelDirectory(panel, WINGsConfiguration.floppyPath);
863 static void
864 goHome(WMButton *bPtr, WMFilePanel *panel)
866 char *home;
868 /* home is statically allocated. Don't free it! */
869 home = wgethomedir();
870 if (!home)
871 return;
873 WMSetFilePanelDirectory(panel, home);
877 static void
878 handleEvents(XEvent *event, void *data)
880 W_FilePanel *pPtr = (W_FilePanel*)data;
881 W_View *view = WMWidgetView(pPtr->win);
883 if (event->type == ConfigureNotify) {
884 if (event->xconfigure.width != view->size.width
885 || event->xconfigure.height != view->size.height) {
886 unsigned int newWidth = event->xconfigure.width;
887 unsigned int newHeight = event->xconfigure.height;
888 int newColumnCount;
890 W_ResizeView(view, newWidth, newHeight);
891 WMResizeWidget(pPtr->line, newWidth, 2);
892 WMResizeWidget(pPtr->browser, newWidth-14,
893 newHeight-(PHEIGHT-200));
894 WMResizeWidget(pPtr->fileField, newWidth-60-10, 24);
895 WMMoveWidget(pPtr->nameLabel, 7, newHeight-(PHEIGHT-282));
896 WMMoveWidget(pPtr->fileField, 60, newHeight-(PHEIGHT-278));
897 WMMoveWidget(pPtr->okButton, newWidth-(PWIDTH-245),
898 newHeight-(PHEIGHT-325));
899 WMMoveWidget(pPtr->cancelButton, newWidth-(PWIDTH-165),
900 newHeight-(PHEIGHT-325));
902 WMMoveWidget(pPtr->trashcanButton, 7, newHeight-(PHEIGHT-325));
903 WMMoveWidget(pPtr->createDirButton, 37, newHeight-(PHEIGHT-325));
904 WMMoveWidget(pPtr->homeButton, 67, newHeight-(PHEIGHT-325));
905 WMMoveWidget(pPtr->disketteButton, 97, newHeight-(PHEIGHT-325));
906 WMMoveWidget(pPtr->unmountButton, 127, newHeight-(PHEIGHT-325));
908 newColumnCount = (newWidth - 14) / 140;
909 WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount);
915 static char*
916 getCurrentFileName(WMFilePanel *panel)
918 char *path;
919 char *file;
920 char *tmp;
921 int len;
923 path = WMGetBrowserPath(panel->browser);
925 len = strlen(path);
926 if (path[len-1]=='/') {
927 file = WMGetTextFieldText(panel->fileField);
928 tmp = wmalloc(strlen(path)+strlen(file)+8);
929 if (file[0]!='/') {
930 strcpy(tmp, path);
931 strcat(tmp, file);
932 } else
933 strcpy(tmp, file);
935 wfree(file);
936 wfree(path);
937 return tmp;
938 } else {
939 return path;
945 static Bool
946 validOpenFile(WMFilePanel *panel)
948 WMListItem *item;
949 int col, haveFile = 0;
950 char *file = WMGetTextFieldText(panel->fileField);
952 if (file[0] != '\0')
953 haveFile = 1;
954 wfree(file);
956 col = WMGetBrowserSelectedColumn(panel->browser);
957 item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
958 if (item) {
959 if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile)
960 return False;
961 else if (!item->isBranch && !panel->flags.canChooseFiles)
962 return False;
963 else
964 return True;
965 } else {
966 /* we compute for / here */
967 if (!panel->flags.canChooseDirectories && !haveFile)
968 return False;
969 else
970 return True;
972 return True;
977 static void
978 buttonClick(WMButton *bPtr, WMFilePanel *panel)
980 WMRange range;
982 if (bPtr == panel->okButton) {
983 if (!validOpenFile(panel))
984 return;
985 if (panel->flags.fileMustExist) {
986 char *file;
988 file = getCurrentFileName(panel);
989 if (access(file, F_OK)!=0) {
990 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
991 "Error", "File does not exist.",
992 "Ok", NULL, NULL);
993 wfree(file);
994 return;
996 wfree(file);
998 panel->flags.canceled = 0;
999 } else
1000 panel->flags.canceled = 1;
1002 range.count = range.position = 0;
1003 WMSelectTextFieldRange(panel->fileField, range);
1004 panel->flags.done = 1;