changed indentation to use spaces only
[wmaker-crm.git] / WINGs / wfilepanel.c
blobb2ddea4eea549bb22b5c40bff20bb6a2049eb38b
2 #include "WINGsP.h"
3 #include "wconfig.h"
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include <dirent.h>
9 #include <limits.h>
10 #include <errno.h>
12 #ifndef PATH_MAX
13 #define PATH_MAX 1024
14 #endif
17 typedef struct W_FilePanel {
18 WMWindow *win;
20 WMLabel *iconLabel;
21 WMLabel *titleLabel;
23 WMFrame *line;
25 WMLabel *nameLabel;
26 WMBrowser *browser;
28 WMButton *okButton;
29 WMButton *cancelButton;
31 WMButton *homeButton;
32 WMButton *trashcanButton;
33 WMButton *createDirButton;
34 WMButton *disketteButton;
35 WMButton *unmountButton;
37 WMView *accessoryView;
39 WMTextField *fileField;
41 char **fileTypes;
43 struct {
44 unsigned int canExit:1;
45 unsigned int canceled:1; /* clicked on cancel */
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 WMArray *items = WMGetListItems(list);
104 int i, len = strlen(text);
106 if (len==0)
107 return -1;
109 for(i=0; i<WMGetArrayItemCount(items); i++) {
110 item = WMGetFromArray(items, i);
111 if (strlen(item->text) >= len &&
112 ((exact && strcmp(item->text, text)==0) ||
113 (!exact && strncmp(item->text, text, len)==0))) {
114 return 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;
183 WMPixmap *icon;
185 fPtr = wmalloc(sizeof(WMFilePanel));
186 memset(fPtr, 0, sizeof(WMFilePanel));
188 fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask
189 |WMResizableWindowMask);
190 WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
191 WMSetWindowTitle(fPtr->win, "");
193 WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask,
194 handleEvents, fPtr);
195 WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT);
198 fPtr->iconLabel = WMCreateLabel(fPtr->win);
199 WMResizeWidget(fPtr->iconLabel, 64, 64);
200 WMMoveWidget(fPtr->iconLabel, 0, 0);
201 WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
202 icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor*)NULL);
203 if (icon) {
204 WMSetLabelImage(fPtr->iconLabel, icon);
205 WMReleasePixmap(icon);
206 } else {
207 WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIconPixmap);
210 fPtr->titleLabel = WMCreateLabel(fPtr->win);
211 WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64);
212 WMMoveWidget(fPtr->titleLabel, 64, 0);
213 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
214 WMSetLabelFont(fPtr->titleLabel, largeFont);
215 WMReleaseFont(largeFont);
216 WMSetLabelText(fPtr->titleLabel, title);
218 fPtr->line = WMCreateFrame(fPtr->win);
219 WMMoveWidget(fPtr->line, 0, 64);
220 WMResizeWidget(fPtr->line, PWIDTH, 2);
221 WMSetFrameRelief(fPtr->line, WRGroove);
223 fPtr->browser = WMCreateBrowser(fPtr->win);
224 WMSetBrowserAllowEmptySelection(fPtr->browser, True);
225 WMSetBrowserDelegate(fPtr->browser, &browserDelegate);
226 WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
227 WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr);
228 WMMoveWidget(fPtr->browser, 7, 72);
229 WMResizeWidget(fPtr->browser, PWIDTH-14,200);
230 WMHangData(fPtr->browser, fPtr);
232 fPtr->nameLabel = WMCreateLabel(fPtr->win);
233 WMMoveWidget(fPtr->nameLabel, 7, 282);
234 WMResizeWidget(fPtr->nameLabel, 55, 14);
235 WMSetLabelText(fPtr->nameLabel, _("Name:"));
237 fPtr->fileField = WMCreateTextField(fPtr->win);
238 WMMoveWidget(fPtr->fileField, 60, 278);
239 WMResizeWidget(fPtr->fileField, PWIDTH-60-10, 24);
240 WMAddNotificationObserver(textEditedObserver, fPtr,
241 WMTextDidEndEditingNotification,
242 fPtr->fileField);
243 WMAddNotificationObserver(textChangedObserver, fPtr,
244 WMTextDidChangeNotification,
245 fPtr->fileField);
247 fPtr->okButton = WMCreateCommandButton(fPtr->win);
248 WMMoveWidget(fPtr->okButton, 245, 325);
249 WMResizeWidget(fPtr->okButton, 75, 28);
250 WMSetButtonText(fPtr->okButton, _("OK"));
251 WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
252 WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
253 WMSetButtonImagePosition(fPtr->okButton, WIPRight);
254 WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
256 fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
257 WMMoveWidget(fPtr->cancelButton, 165, 325);
258 WMResizeWidget(fPtr->cancelButton, 75, 28);
259 WMSetButtonText(fPtr->cancelButton, _("Cancel"));
260 WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
262 fPtr->trashcanButton = WMCreateCommandButton(fPtr->win);
263 WMMoveWidget(fPtr->trashcanButton, 7, 325);
264 WMResizeWidget(fPtr->trashcanButton, 28, 28);
265 WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly);
266 WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon);
267 WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon);
268 WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr);
270 fPtr->createDirButton = WMCreateCommandButton(fPtr->win);
271 WMMoveWidget(fPtr->createDirButton, 37, 325);
272 WMResizeWidget(fPtr->createDirButton, 28, 28);
273 WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly);
274 WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon);
275 WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon);
276 WMSetButtonAction(fPtr->createDirButton, createDir, fPtr);
278 fPtr->homeButton = WMCreateCommandButton(fPtr->win);
279 WMMoveWidget(fPtr->homeButton, 67, 325);
280 WMResizeWidget(fPtr->homeButton, 28, 28);
281 WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
282 WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
283 WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon);
284 WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
286 fPtr->disketteButton = WMCreateCommandButton(fPtr->win);
287 WMMoveWidget(fPtr->disketteButton, 97, 325);
288 WMResizeWidget(fPtr->disketteButton, 28, 28);
289 WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly);
290 WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon);
291 WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon);
292 WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr);
294 fPtr->unmountButton = WMCreateCommandButton(fPtr->win);
295 WMMoveWidget(fPtr->unmountButton, 127, 325);
296 WMResizeWidget(fPtr->unmountButton, 28, 28);
297 WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly);
298 WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon);
299 WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon);
300 WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr);
301 WMSetButtonEnabled(fPtr->unmountButton, False);
304 WMRealizeWidget(fPtr->win);
305 WMMapSubwidgets(fPtr->win);
307 WMSetFocusToWidget(fPtr->fileField);
308 WMSetTextFieldCursorPosition(fPtr->fileField, 0);
310 WMLoadBrowserColumnZero(fPtr->browser);
312 WMSetWindowInitialPosition(fPtr->win,
313 (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win))/2,
314 (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win))/2);
316 fPtr->flags.canChooseFiles = 1;
317 fPtr->flags.canChooseDirectories = 1;
318 fPtr->flags.autoCompletion = 1;
320 return fPtr;
324 WMOpenPanel*
325 WMGetOpenPanel(WMScreen *scrPtr)
327 WMFilePanel *panel;
329 if (scrPtr->sharedOpenPanel)
330 return scrPtr->sharedOpenPanel;
332 panel = makeFilePanel(scrPtr, "openFilePanel", _("Open"));
333 panel->flags.fileMustExist = 1;
334 panel->flags.panelType = WP_OPEN;
336 scrPtr->sharedOpenPanel = panel;
338 return panel;
342 WMSavePanel*
343 WMGetSavePanel(WMScreen *scrPtr)
345 WMFilePanel *panel;
347 if (scrPtr->sharedSavePanel)
348 return scrPtr->sharedSavePanel;
350 panel = makeFilePanel(scrPtr, "saveFilePanel", _("Save"));
351 panel->flags.fileMustExist = 0;
352 panel->flags.panelType = WP_SAVE;
354 scrPtr->sharedSavePanel = panel;
356 return panel;
360 void
361 WMFreeFilePanel(WMFilePanel *panel)
363 if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) {
364 WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
366 if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
367 WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
369 WMRemoveNotificationObserver(panel);
370 WMUnmapWidget(panel->win);
371 WMDestroyWidget(panel->win);
372 wfree(panel);
377 WMRunModalFilePanelForDirectory(WMFilePanel *panel, WMWindow *owner,
378 char *path, char *name, char **fileTypes)
380 WMScreen *scr = WMWidgetScreen(panel->win);
382 if (name && !owner) {
383 WMSetWindowTitle(panel->win, name);
386 WMChangePanelOwner(panel->win, owner);
388 WMSetFilePanelDirectory(panel, path);
390 switch(panel->flags.panelType) {
391 case WP_OPEN:
392 if (fileTypes)
393 panel->flags.filtered = 1;
394 panel->fileTypes = fileTypes;
395 if (name == NULL)
396 name = _("Open");
397 break;
398 case WP_SAVE:
399 panel->fileTypes = NULL;
400 panel->flags.filtered = 0;
401 if (name == NULL)
402 name = _("Save");
403 break;
404 default:
405 break;
408 WMSetLabelText(panel->titleLabel, name);
410 WMMapWidget(panel->win);
412 WMRunModalLoop(scr, W_VIEW(panel->win));
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==0) ? 0 : 1);
457 void
458 WMSetFilePanelCanChooseFiles(WMFilePanel *panel, Bool flag)
460 panel->flags.canChooseFiles = ((flag==0) ? 0 : 1);
464 void
465 WMSetFilePanelAutoCompletion(WMFilePanel *panel, Bool flag)
467 panel->flags.autoCompletion = ((flag==0) ? 0 : 1);
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];
551 char *name;
553 assert(column >= 0);
554 assert(path != NULL);
556 /* put directory name in the title */
557 name = get_name_from_path(path);
558 WMSetBrowserColumnTitle(bPtr, column, name);
559 wfree(name);
561 dir = opendir(path);
563 if (!dir) {
564 #ifdef VERBOSE
565 printf(_("WINGs: could not open directory %s\n"), path);
566 #endif
567 return;
570 /* list contents in the column */
571 while ((dentry = readdir(dir))) {
572 if (strcmp(dentry->d_name, ".")==0 ||
573 strcmp(dentry->d_name, "..")==0)
574 continue;
576 strcpy(pbuf, path);
577 if (strcmp(path, "/")!=0)
578 strcat(pbuf, "/");
579 strcat(pbuf, dentry->d_name);
581 if (stat(pbuf, &stat_buf)!=0) {
582 #ifdef VERBOSE
583 printf(_("WINGs: could not stat %s\n"), pbuf);
584 #endif
585 continue;
586 } else {
587 int isDirectory;
589 isDirectory = S_ISDIR(stat_buf.st_mode);
591 if (filterFileName(panel, dentry->d_name, isDirectory))
592 WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory);
595 WMSortBrowserColumnWithComparer(bPtr, column, comparer);
597 closedir(dir);
601 static void
602 fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column, WMList *list)
604 char *path;
605 WMFilePanel *panel;
607 if (column > 0) {
608 path = WMGetBrowserPathToColumn(bPtr, column-1);
609 } else {
610 path = wstrdup("/");
613 panel = WMGetHangedData(bPtr);
614 listDirectoryOnColumn(panel, column, path);
615 wfree(path);
619 static void
620 browserDClick(WMBrowser *bPtr, WMFilePanel *panel)
622 WMPerformButtonClick(panel->okButton);
625 static void
626 browserClick(WMBrowser *bPtr, WMFilePanel *panel)
628 int col = WMGetBrowserSelectedColumn(bPtr);
629 WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
631 if (!item || item->isBranch)
632 WMSetTextFieldText(panel->fileField, NULL);
633 else {
634 WMSetTextFieldText(panel->fileField, item->text);
639 static void
640 showError(WMScreen *scr, WMWindow *owner, char *s, char *file)
642 char *errStr;
644 if (file) {
645 errStr = wmalloc(strlen(file)+strlen(s));
646 sprintf(errStr, s, file);
647 } else {
648 errStr = wstrdup(s);
650 WMRunAlertPanel(scr, owner, _("Error"), errStr, _("OK"), NULL, NULL);
651 wfree(errStr);
655 static void
656 createDir(WMButton *bPre, WMFilePanel *panel)
658 char *dirName, *directory, *file, *s;
659 WMScreen *scr = WMWidgetScreen(panel->win);
661 dirName = WMRunInputPanel(scr, panel->win, _("Create Directory"),
662 _("Enter directory name"), "", _("OK"), _("Cancel"));
663 if (!dirName)
664 return;
666 directory = getCurrentFileName(panel);
667 s = strrchr(directory,'/');
668 if (s) s[1] = 0;
670 if (dirName[0] == '/') {
671 directory[0] = 0;
672 } else {
673 while ((s = strstr(directory,"//"))) {
674 int i;
675 for (i = 2;s[i] == '/';i++);
676 strcpy(s, &s[i-1]);
678 if ((s = strrchr(directory, '/')) && !s[1]) s[0] = 0;
680 while ((s = strstr(dirName,"//"))) {
681 int i;
682 for (i = 2;s[i] == '/';i++);
683 strcpy(s, &s[i-1]);
685 if ((s = strrchr(dirName, '/')) && !s[1]) s[0] = 0;
687 file = wmalloc(strlen(dirName)+strlen(directory)+4);
688 sprintf(file, "%s/%s", directory, dirName);
689 while ((s = strstr(file,"//"))) {
690 int i;
691 for (i = 2;s[i] == '/';i++);
692 strcpy(s, &s[i-1]);
695 if (mkdir(file,0xfff) != 0) {
696 switch (errno) {
697 case EACCES:
698 showError(scr, panel->win, _("Permission denied."), NULL);
699 break;
700 case EEXIST:
701 showError(scr, panel->win, _("'%s' already exists."), file);
702 break;
703 case ENOENT:
704 showError(scr, panel->win, _("Path does not exist."), NULL);
707 else WMSetFilePanelDirectory(panel, file);
709 wfree(dirName);
710 wfree(directory);
711 wfree(file);
714 static void
715 deleteFile(WMButton *bPre, WMFilePanel *panel)
717 char *file;
718 char *buffer, *s;
719 struct stat filestat;
720 WMScreen *scr = WMWidgetScreen(panel->win);
722 file = getCurrentFileName(panel);
724 while ((s = strstr(file,"//"))) {
725 int i;
726 for (i = 2;s[i] == '/';i++);
727 strcpy(s, &s[i-1]);
729 if (strlen(file) > 1 && (s = strrchr(file, '/')) && !s[1]) s[0] = 0;
731 if (stat(file,&filestat)) {
732 switch (errno) {
733 case ENOENT:
734 showError(scr, panel->win, _("'%s' does not exist."), file);
735 break;
736 case EACCES:
737 showError(scr, panel->win, _("Permission denied."), NULL);
738 break;
739 case ENOMEM:
740 showError(scr, panel->win,
741 _("Insufficient memory available."), NULL);
742 break;
743 case EROFS:
744 showError(scr, panel->win,
745 _("'%s' is on a read-only filesystem."), file);
746 break;
747 default:
748 showError(scr, panel->win, _("Can not delete '%s'."), file);
750 wfree(file);
751 return;
752 } else if (S_ISDIR(filestat.st_mode)) {
753 int len = strlen(file)+20;
754 buffer = wmalloc(len);
755 snprintf(buffer,len,_("Delete directory %s ?"),file);
756 } else {
757 int len = strlen(file)+15;
758 buffer = wmalloc(len);
759 snprintf(buffer,len,_("Delete file %s ?"),file);
762 if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
763 _("Warning"), buffer, _("OK"), _("Cancel"), NULL)) {
764 if (S_ISDIR(filestat.st_mode)) {
765 if (rmdir(file) != 0) {
766 switch (errno) {
767 case EACCES:
768 showError(scr, panel->win, _("Permission denied."), NULL);
769 break;
770 case ENOENT:
771 showError(scr, panel->win, _("Directory '%s' does not exist."), file);
772 break;
773 case ENOTEMPTY:
774 showError(scr, panel->win, _("Directory '%s' is not empty."), file);
775 break;
776 case EBUSY:
777 showError(scr, panel->win, _("Directory '%s' is busy."), file);
778 break;
779 default:
780 showError(scr, panel->win, _("Can not delete '%s'."), file);
782 } else {
783 char *s = strrchr(file,'/');
784 if (s) s[0] = 0;
785 WMSetFilePanelDirectory(panel, file);
787 } else if (remove(file) != 0) {
788 switch (errno) {
789 case EISDIR:
790 showError(scr, panel->win, _("'%s' is a directory."), file);
791 break;
792 case ENOENT:
793 showError(scr, panel->win, _("'%s' does not exist."), file);
794 break;
795 case EACCES:
796 showError(scr, panel->win, _("Permission denied."), NULL);
797 break;
798 case ENOMEM:
799 showError(scr, panel->win,
800 _("Insufficient memory available."), NULL);
801 break;
802 case EROFS:
803 showError(scr, panel->win,
804 _("'%s' is on a read-only filesystem."), file);
805 break;
806 default:
807 showError(scr, panel->win, _("Can not delete '%s'."), file);
809 } else {
810 char *s = strrchr(file,'/');
811 if (s) s[1] = 0;
812 WMSetFilePanelDirectory(panel, file);
815 wfree(buffer);
816 wfree(file);
819 static void
820 goUnmount(WMButton *bPtr, WMFilePanel *panel)
825 static void
826 goFloppy(WMButton *bPtr, WMFilePanel *panel)
828 struct stat filestat;
829 WMScreen *scr = WMWidgetScreen(panel->win);
831 if (stat(WINGsConfiguration.floppyPath, &filestat)) {
832 showError(scr, panel->win, _("An error occured browsing '%s'."),
833 WINGsConfiguration.floppyPath);
834 return;
835 } else if (!S_ISDIR(filestat.st_mode)) {
836 showError(scr, panel->win, _("'%s' is not a directory."),
837 WINGsConfiguration.floppyPath);
838 return;
841 WMSetFilePanelDirectory(panel, WINGsConfiguration.floppyPath);
845 static void
846 goHome(WMButton *bPtr, WMFilePanel *panel)
848 char *home;
850 /* home is statically allocated. Don't free it! */
851 home = wgethomedir();
852 if (!home)
853 return;
855 WMSetFilePanelDirectory(panel, home);
859 static void
860 handleEvents(XEvent *event, void *data)
862 W_FilePanel *pPtr = (W_FilePanel*)data;
863 W_View *view = WMWidgetView(pPtr->win);
865 if (event->type == ConfigureNotify) {
866 if (event->xconfigure.width != view->size.width
867 || event->xconfigure.height != view->size.height) {
868 unsigned int newWidth = event->xconfigure.width;
869 unsigned int newHeight = event->xconfigure.height;
870 int newColumnCount;
872 W_ResizeView(view, newWidth, newHeight);
873 WMResizeWidget(pPtr->line, newWidth, 2);
874 WMResizeWidget(pPtr->browser, newWidth-14,
875 newHeight-(PHEIGHT-200));
876 WMResizeWidget(pPtr->fileField, newWidth-60-10, 24);
877 WMMoveWidget(pPtr->nameLabel, 7, newHeight-(PHEIGHT-282));
878 WMMoveWidget(pPtr->fileField, 60, newHeight-(PHEIGHT-278));
879 WMMoveWidget(pPtr->okButton, newWidth-(PWIDTH-245),
880 newHeight-(PHEIGHT-325));
881 WMMoveWidget(pPtr->cancelButton, newWidth-(PWIDTH-165),
882 newHeight-(PHEIGHT-325));
884 WMMoveWidget(pPtr->trashcanButton, 7, newHeight-(PHEIGHT-325));
885 WMMoveWidget(pPtr->createDirButton, 37, newHeight-(PHEIGHT-325));
886 WMMoveWidget(pPtr->homeButton, 67, newHeight-(PHEIGHT-325));
887 WMMoveWidget(pPtr->disketteButton, 97, newHeight-(PHEIGHT-325));
888 WMMoveWidget(pPtr->unmountButton, 127, newHeight-(PHEIGHT-325));
890 newColumnCount = (newWidth - 14) / 140;
891 WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount);
897 static char*
898 getCurrentFileName(WMFilePanel *panel)
900 char *path;
901 char *file;
902 char *tmp;
903 int len;
905 path = WMGetBrowserPath(panel->browser);
907 len = strlen(path);
908 if (path[len-1]=='/') {
909 file = WMGetTextFieldText(panel->fileField);
910 tmp = wmalloc(strlen(path)+strlen(file)+8);
911 if (file[0]!='/') {
912 strcpy(tmp, path);
913 strcat(tmp, file);
914 } else
915 strcpy(tmp, file);
917 wfree(file);
918 wfree(path);
919 return tmp;
920 } else {
921 return path;
927 static Bool
928 validOpenFile(WMFilePanel *panel)
930 WMListItem *item;
931 int col, haveFile = 0;
932 char *file = WMGetTextFieldText(panel->fileField);
934 if (file[0] != '\0')
935 haveFile = 1;
936 wfree(file);
938 col = WMGetBrowserSelectedColumn(panel->browser);
939 item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
940 if (item) {
941 if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile)
942 return False;
943 else if (!item->isBranch && !panel->flags.canChooseFiles)
944 return False;
945 else
946 return True;
947 } else {
948 /* we compute for / here */
949 if (!panel->flags.canChooseDirectories && !haveFile)
950 return False;
951 else
952 return True;
954 return True;
959 static void
960 buttonClick(WMButton *bPtr, WMFilePanel *panel)
962 WMRange range;
964 if (bPtr == panel->okButton) {
965 if (!validOpenFile(panel))
966 return;
967 if (panel->flags.fileMustExist) {
968 char *file;
970 file = getCurrentFileName(panel);
971 if (access(file, F_OK)!=0) {
972 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
973 _("Error"), _("File does not exist."),
974 _("OK"), NULL, NULL);
975 wfree(file);
976 return;
978 wfree(file);
980 panel->flags.canceled = 0;
981 } else
982 panel->flags.canceled = 1;
984 range.count = range.position = 0;
985 WMSelectTextFieldRange(panel->fileField, range);
986 WMBreakModalLoop(WMWidgetScreen(bPtr));