wmaker: Fix compiler warnings about pointer <--> integer conversion
[wmaker-crm.git] / WINGs / wfilepanel.c
blobe5565eb2a00b20f0ed2b6fd8c8890615b8ba1e0c
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>
11 #include <stdint.h>
13 #ifndef PATH_MAX
14 #define PATH_MAX 1024
15 #endif
18 typedef struct W_FilePanel {
19 WMWindow *win;
21 WMLabel *iconLabel;
22 WMLabel *titleLabel;
24 WMFrame *line;
26 WMLabel *nameLabel;
27 WMBrowser *browser;
29 WMButton *okButton;
30 WMButton *cancelButton;
32 WMButton *homeButton;
33 WMButton *trashcanButton;
34 WMButton *createDirButton;
35 WMButton *disketteButton;
36 WMButton *unmountButton;
38 WMView *accessoryView;
40 WMTextField *fileField;
42 char **fileTypes;
44 struct {
45 unsigned int canExit:1;
46 unsigned int canceled:1; /* clicked on cancel */
47 unsigned int filtered:1;
48 unsigned int canChooseFiles:1;
49 unsigned int canChooseDirectories:1;
50 unsigned int autoCompletion:1;
51 unsigned int showAllFiles:1;
52 unsigned int canFreeFileTypes:1;
53 unsigned int fileMustExist:1;
54 unsigned int panelType:1;
55 } flags;
56 } W_FilePanel;
59 /* Type of panel */
60 #define WP_OPEN 0
61 #define WP_SAVE 1
63 #define PWIDTH 330
64 #define PHEIGHT 360
66 static void listDirectoryOnColumn(WMFilePanel *panel, int column, char *path);
67 static void browserClick();
68 static void browserDClick();
70 static void fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column,
71 WMList *list);
73 static void deleteFile();
75 static void createDir();
77 static void goHome();
79 static void goFloppy();
81 static void goUnmount();
83 static void buttonClick();
85 static char *getCurrentFileName(WMFilePanel *panel);
87 static void handleEvents(XEvent *event, void *data);
91 static WMBrowserDelegate browserDelegate = {
92 NULL, /* data */
93 fillColumn, /* createRowsForColumn */
94 NULL, /* titleOfColumn */
95 NULL, /* didScroll */
96 NULL /* willScroll */
100 static int
101 closestListItem(WMList *list, char *text, Bool exact)
103 WMListItem *item;
104 WMArray *items = WMGetListItems(list);
105 int i, len = strlen(text);
107 if (len==0)
108 return -1;
110 for(i=0; i<WMGetArrayItemCount(items); i++) {
111 item = WMGetFromArray(items, i);
112 if (strlen(item->text) >= len &&
113 ((exact && strcmp(item->text, text)==0) ||
114 (!exact && strncmp(item->text, text, len)==0))) {
115 return i;
119 return -1;
123 static void
124 textChangedObserver(void *observerData, WMNotification *notification)
126 W_FilePanel *panel = (W_FilePanel*)observerData;
127 char *text;
128 WMList *list;
129 int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
130 int i, textEvent;
132 if (!(list = WMGetBrowserListInColumn(panel->browser, col)))
133 return;
135 text = WMGetTextFieldText(panel->fileField);
136 textEvent = (int)(uintptr_t)WMGetNotificationClientData(notification);
138 if (panel->flags.autoCompletion && textEvent!=WMDeleteTextEvent)
139 i = closestListItem(list, text, False);
140 else
141 i = closestListItem(list, text, True);
143 WMSelectListItem(list, i);
144 if (i>=0 && panel->flags.autoCompletion) {
145 WMListItem *item = WMGetListItem(list, i);
146 int textLen = strlen(text), itemTextLen = strlen(item->text);
147 int visibleItems = WMWidgetHeight(list)/WMGetListItemHeight(list);
149 WMSetListPosition(list, i - visibleItems/2);
151 if (textEvent!=WMDeleteTextEvent) {
152 WMRange range;
154 WMInsertTextFieldText(panel->fileField, &item->text[textLen],
155 textLen);
156 range.position = textLen;
157 range.count = itemTextLen - textLen;
158 WMSelectTextFieldRange(panel->fileField, range);
159 /*WMSetTextFieldCursorPosition(panel->fileField, itemTextLen);*/
163 wfree(text);
167 static void
168 textEditedObserver(void *observerData, WMNotification *notification)
170 W_FilePanel *panel = (W_FilePanel*)observerData;
172 if ((int)(uintptr_t)WMGetNotificationClientData(notification)==WMReturnTextMovement) {
173 WMPerformButtonClick(panel->okButton);
179 static WMFilePanel*
180 makeFilePanel(WMScreen *scrPtr, char *name, char *title)
182 WMFilePanel *fPtr;
183 WMFont *largeFont;
184 WMPixmap *icon;
186 fPtr = wmalloc(sizeof(WMFilePanel));
187 memset(fPtr, 0, sizeof(WMFilePanel));
189 fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask
190 |WMResizableWindowMask);
191 WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
192 WMSetWindowTitle(fPtr->win, "");
194 WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask,
195 handleEvents, fPtr);
196 WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT);
199 fPtr->iconLabel = WMCreateLabel(fPtr->win);
200 WMResizeWidget(fPtr->iconLabel, 64, 64);
201 WMMoveWidget(fPtr->iconLabel, 0, 0);
202 WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
203 icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor*)NULL);
204 if (icon) {
205 WMSetLabelImage(fPtr->iconLabel, icon);
206 WMReleasePixmap(icon);
207 } else {
208 WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIconPixmap);
211 fPtr->titleLabel = WMCreateLabel(fPtr->win);
212 WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64);
213 WMMoveWidget(fPtr->titleLabel, 64, 0);
214 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
215 WMSetLabelFont(fPtr->titleLabel, largeFont);
216 WMReleaseFont(largeFont);
217 WMSetLabelText(fPtr->titleLabel, title);
219 fPtr->line = WMCreateFrame(fPtr->win);
220 WMMoveWidget(fPtr->line, 0, 64);
221 WMResizeWidget(fPtr->line, PWIDTH, 2);
222 WMSetFrameRelief(fPtr->line, WRGroove);
224 fPtr->browser = WMCreateBrowser(fPtr->win);
225 WMSetBrowserAllowEmptySelection(fPtr->browser, True);
226 WMSetBrowserDelegate(fPtr->browser, &browserDelegate);
227 WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
228 WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr);
229 WMMoveWidget(fPtr->browser, 7, 72);
230 WMResizeWidget(fPtr->browser, PWIDTH-14,200);
231 WMHangData(fPtr->browser, fPtr);
233 fPtr->nameLabel = WMCreateLabel(fPtr->win);
234 WMMoveWidget(fPtr->nameLabel, 7, 282);
235 WMResizeWidget(fPtr->nameLabel, 55, 14);
236 WMSetLabelText(fPtr->nameLabel, _("Name:"));
238 fPtr->fileField = WMCreateTextField(fPtr->win);
239 WMMoveWidget(fPtr->fileField, 60, 278);
240 WMResizeWidget(fPtr->fileField, PWIDTH-60-10, 24);
241 WMAddNotificationObserver(textEditedObserver, fPtr,
242 WMTextDidEndEditingNotification,
243 fPtr->fileField);
244 WMAddNotificationObserver(textChangedObserver, fPtr,
245 WMTextDidChangeNotification,
246 fPtr->fileField);
248 fPtr->okButton = WMCreateCommandButton(fPtr->win);
249 WMMoveWidget(fPtr->okButton, 245, 325);
250 WMResizeWidget(fPtr->okButton, 75, 28);
251 WMSetButtonText(fPtr->okButton, _("OK"));
252 WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
253 WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
254 WMSetButtonImagePosition(fPtr->okButton, WIPRight);
255 WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
257 fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
258 WMMoveWidget(fPtr->cancelButton, 165, 325);
259 WMResizeWidget(fPtr->cancelButton, 75, 28);
260 WMSetButtonText(fPtr->cancelButton, _("Cancel"));
261 WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
263 fPtr->trashcanButton = WMCreateCommandButton(fPtr->win);
264 WMMoveWidget(fPtr->trashcanButton, 7, 325);
265 WMResizeWidget(fPtr->trashcanButton, 28, 28);
266 WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly);
267 WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon);
268 WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon);
269 WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr);
271 fPtr->createDirButton = WMCreateCommandButton(fPtr->win);
272 WMMoveWidget(fPtr->createDirButton, 37, 325);
273 WMResizeWidget(fPtr->createDirButton, 28, 28);
274 WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly);
275 WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon);
276 WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon);
277 WMSetButtonAction(fPtr->createDirButton, createDir, fPtr);
279 fPtr->homeButton = WMCreateCommandButton(fPtr->win);
280 WMMoveWidget(fPtr->homeButton, 67, 325);
281 WMResizeWidget(fPtr->homeButton, 28, 28);
282 WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
283 WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
284 WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon);
285 WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
287 fPtr->disketteButton = WMCreateCommandButton(fPtr->win);
288 WMMoveWidget(fPtr->disketteButton, 97, 325);
289 WMResizeWidget(fPtr->disketteButton, 28, 28);
290 WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly);
291 WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon);
292 WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon);
293 WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr);
295 fPtr->unmountButton = WMCreateCommandButton(fPtr->win);
296 WMMoveWidget(fPtr->unmountButton, 127, 325);
297 WMResizeWidget(fPtr->unmountButton, 28, 28);
298 WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly);
299 WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon);
300 WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon);
301 WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr);
302 WMSetButtonEnabled(fPtr->unmountButton, False);
305 WMRealizeWidget(fPtr->win);
306 WMMapSubwidgets(fPtr->win);
308 WMSetFocusToWidget(fPtr->fileField);
309 WMSetTextFieldCursorPosition(fPtr->fileField, 0);
311 WMLoadBrowserColumnZero(fPtr->browser);
313 WMSetWindowInitialPosition(fPtr->win,
314 (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win))/2,
315 (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win))/2);
317 fPtr->flags.canChooseFiles = 1;
318 fPtr->flags.canChooseDirectories = 1;
319 fPtr->flags.autoCompletion = 1;
321 return fPtr;
325 WMOpenPanel*
326 WMGetOpenPanel(WMScreen *scrPtr)
328 WMFilePanel *panel;
330 if (scrPtr->sharedOpenPanel)
331 return scrPtr->sharedOpenPanel;
333 panel = makeFilePanel(scrPtr, "openFilePanel", _("Open"));
334 panel->flags.fileMustExist = 1;
335 panel->flags.panelType = WP_OPEN;
337 scrPtr->sharedOpenPanel = panel;
339 return panel;
343 WMSavePanel*
344 WMGetSavePanel(WMScreen *scrPtr)
346 WMFilePanel *panel;
348 if (scrPtr->sharedSavePanel)
349 return scrPtr->sharedSavePanel;
351 panel = makeFilePanel(scrPtr, "saveFilePanel", _("Save"));
352 panel->flags.fileMustExist = 0;
353 panel->flags.panelType = WP_SAVE;
355 scrPtr->sharedSavePanel = panel;
357 return panel;
361 void
362 WMFreeFilePanel(WMFilePanel *panel)
364 if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) {
365 WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
367 if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
368 WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
370 WMRemoveNotificationObserver(panel);
371 WMUnmapWidget(panel->win);
372 WMDestroyWidget(panel->win);
373 wfree(panel);
378 WMRunModalFilePanelForDirectory(WMFilePanel *panel, WMWindow *owner,
379 char *path, char *name, char **fileTypes)
381 WMScreen *scr = WMWidgetScreen(panel->win);
383 if (name && !owner) {
384 WMSetWindowTitle(panel->win, name);
387 WMChangePanelOwner(panel->win, owner);
389 WMSetFilePanelDirectory(panel, path);
391 switch(panel->flags.panelType) {
392 case WP_OPEN:
393 if (fileTypes)
394 panel->flags.filtered = 1;
395 panel->fileTypes = fileTypes;
396 if (name == NULL)
397 name = _("Open");
398 break;
399 case WP_SAVE:
400 panel->fileTypes = NULL;
401 panel->flags.filtered = 0;
402 if (name == NULL)
403 name = _("Save");
404 break;
405 default:
406 break;
409 WMSetLabelText(panel->titleLabel, name);
411 WMMapWidget(panel->win);
413 WMRunModalLoop(scr, W_VIEW(panel->win));
415 /* Must withdraw window because the next time we map
416 * it, it might have a different transient owner.
418 WMCloseWindow(panel->win);
420 return (panel->flags.canceled ? False : True);
426 void
427 WMSetFilePanelDirectory(WMFilePanel *panel, char *path)
429 WMList *list;
430 WMListItem *item;
431 int col;
432 char *rest;
434 rest = WMSetBrowserPath(panel->browser, path);
435 if (strcmp(path, "/")==0)
436 rest = NULL;
438 col = WMGetBrowserSelectedColumn(panel->browser);
439 list = WMGetBrowserListInColumn(panel->browser, col);
440 if (list && (item = WMGetListSelectedItem(list))) {
441 if (item->isBranch) {
442 WMSetTextFieldText(panel->fileField, rest);
443 } else {
444 WMSetTextFieldText(panel->fileField, item->text);
446 } else {
447 WMSetTextFieldText(panel->fileField, rest);
452 void
453 WMSetFilePanelCanChooseDirectories(WMFilePanel *panel, Bool flag)
455 panel->flags.canChooseDirectories = ((flag==0) ? 0 : 1);
458 void
459 WMSetFilePanelCanChooseFiles(WMFilePanel *panel, Bool flag)
461 panel->flags.canChooseFiles = ((flag==0) ? 0 : 1);
465 void
466 WMSetFilePanelAutoCompletion(WMFilePanel *panel, Bool flag)
468 panel->flags.autoCompletion = ((flag==0) ? 0 : 1);
472 char*
473 WMGetFilePanelFileName(WMFilePanel *panel)
475 return getCurrentFileName(panel);
479 void
480 WMSetFilePanelAccessoryView(WMFilePanel *panel, WMView *view)
482 WMView *v;
484 panel->accessoryView = view;
486 v = WMWidgetView(panel->win);
488 W_ReparentView(view, v, 0, 0);
490 W_MoveView(view, (v->size.width - v->size.width)/2, 300);
494 WMView*
495 WMGetFilePanelAccessoryView(WMFilePanel *panel)
497 return panel->accessoryView;
501 static char*
502 get_name_from_path(char *path)
504 int size;
506 assert(path!=NULL);
508 size = strlen(path);
510 /* remove trailing / */
511 while (size > 0 && path[size-1]=='/')
512 size--;
513 /* directory was root */
514 if (size == 0)
515 return wstrdup("/");
517 while (size > 0 && path[size-1] != '/')
518 size--;
520 return wstrdup(&(path[size]));
524 static int
525 filterFileName(WMFilePanel *panel, char *file, Bool isDirectory)
527 return True;
531 #define CAST(item) (*((WMListItem**)item))
532 static int
533 comparer(const void *a, const void *b)
535 if (CAST(a)->isBranch == CAST(b)->isBranch)
536 return (strcmp(CAST(a)->text, CAST(b)->text));
537 if (CAST(a)->isBranch)
538 return (-1);
539 return (1);
541 #undef CAST
544 static void
545 listDirectoryOnColumn(WMFilePanel *panel, int column, char *path)
547 WMBrowser *bPtr = panel->browser;
548 struct dirent *dentry;
549 DIR *dir;
550 struct stat stat_buf;
551 char pbuf[PATH_MAX+16];
552 char *name;
554 assert(column >= 0);
555 assert(path != NULL);
557 /* put directory name in the title */
558 name = get_name_from_path(path);
559 WMSetBrowserColumnTitle(bPtr, column, name);
560 wfree(name);
562 dir = opendir(path);
564 if (!dir) {
565 #ifdef VERBOSE
566 printf(_("WINGs: could not open directory %s\n"), path);
567 #endif
568 return;
571 /* list contents in the column */
572 while ((dentry = readdir(dir))) {
573 if (strcmp(dentry->d_name, ".")==0 ||
574 strcmp(dentry->d_name, "..")==0)
575 continue;
577 strcpy(pbuf, path);
578 if (strcmp(path, "/")!=0)
579 strcat(pbuf, "/");
580 strcat(pbuf, dentry->d_name);
582 if (stat(pbuf, &stat_buf)!=0) {
583 #ifdef VERBOSE
584 printf(_("WINGs: could not stat %s\n"), pbuf);
585 #endif
586 continue;
587 } else {
588 int isDirectory;
590 isDirectory = S_ISDIR(stat_buf.st_mode);
592 if (filterFileName(panel, dentry->d_name, isDirectory))
593 WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory);
596 WMSortBrowserColumnWithComparer(bPtr, column, comparer);
598 closedir(dir);
602 static void
603 fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column, WMList *list)
605 char *path;
606 WMFilePanel *panel;
608 if (column > 0) {
609 path = WMGetBrowserPathToColumn(bPtr, column-1);
610 } else {
611 path = wstrdup("/");
614 panel = WMGetHangedData(bPtr);
615 listDirectoryOnColumn(panel, column, path);
616 wfree(path);
620 static void
621 browserDClick(WMBrowser *bPtr, WMFilePanel *panel)
623 WMPerformButtonClick(panel->okButton);
626 static void
627 browserClick(WMBrowser *bPtr, WMFilePanel *panel)
629 int col = WMGetBrowserSelectedColumn(bPtr);
630 WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
632 if (!item || item->isBranch)
633 WMSetTextFieldText(panel->fileField, NULL);
634 else {
635 WMSetTextFieldText(panel->fileField, item->text);
640 static void
641 showError(WMScreen *scr, WMWindow *owner, char *s, char *file)
643 char *errStr;
645 if (file) {
646 errStr = wmalloc(strlen(file)+strlen(s));
647 sprintf(errStr, s, file);
648 } else {
649 errStr = wstrdup(s);
651 WMRunAlertPanel(scr, owner, _("Error"), errStr, _("OK"), NULL, NULL);
652 wfree(errStr);
656 static void
657 createDir(WMButton *bPre, WMFilePanel *panel)
659 char *dirName, *directory, *file, *s;
660 WMScreen *scr = WMWidgetScreen(panel->win);
662 dirName = WMRunInputPanel(scr, panel->win, _("Create Directory"),
663 _("Enter directory name"), "", _("OK"), _("Cancel"));
664 if (!dirName)
665 return;
667 directory = getCurrentFileName(panel);
668 s = strrchr(directory,'/');
669 if (s) s[1] = 0;
671 if (dirName[0] == '/') {
672 directory[0] = 0;
673 } else {
674 while ((s = strstr(directory,"//"))) {
675 int i;
676 for (i = 2;s[i] == '/';i++);
677 strcpy(s, &s[i-1]);
679 if ((s = strrchr(directory, '/')) && !s[1]) s[0] = 0;
681 while ((s = strstr(dirName,"//"))) {
682 int i;
683 for (i = 2;s[i] == '/';i++);
684 strcpy(s, &s[i-1]);
686 if ((s = strrchr(dirName, '/')) && !s[1]) s[0] = 0;
688 file = wmalloc(strlen(dirName)+strlen(directory)+4);
689 sprintf(file, "%s/%s", directory, dirName);
690 while ((s = strstr(file,"//"))) {
691 int i;
692 for (i = 2;s[i] == '/';i++);
693 strcpy(s, &s[i-1]);
696 if (mkdir(file,0xfff) != 0) {
697 switch (errno) {
698 case EACCES:
699 showError(scr, panel->win, _("Permission denied."), NULL);
700 break;
701 case EEXIST:
702 showError(scr, panel->win, _("'%s' already exists."), file);
703 break;
704 case ENOENT:
705 showError(scr, panel->win, _("Path does not exist."), NULL);
708 else WMSetFilePanelDirectory(panel, file);
710 wfree(dirName);
711 wfree(directory);
712 wfree(file);
715 static void
716 deleteFile(WMButton *bPre, WMFilePanel *panel)
718 char *file;
719 char *buffer, *s;
720 struct stat filestat;
721 WMScreen *scr = WMWidgetScreen(panel->win);
723 file = getCurrentFileName(panel);
725 while ((s = strstr(file,"//"))) {
726 int i;
727 for (i = 2;s[i] == '/';i++);
728 strcpy(s, &s[i-1]);
730 if (strlen(file) > 1 && (s = strrchr(file, '/')) && !s[1]) s[0] = 0;
732 if (stat(file,&filestat)) {
733 switch (errno) {
734 case ENOENT:
735 showError(scr, panel->win, _("'%s' does not exist."), file);
736 break;
737 case EACCES:
738 showError(scr, panel->win, _("Permission denied."), NULL);
739 break;
740 case ENOMEM:
741 showError(scr, panel->win,
742 _("Insufficient memory available."), NULL);
743 break;
744 case EROFS:
745 showError(scr, panel->win,
746 _("'%s' is on a read-only filesystem."), file);
747 break;
748 default:
749 showError(scr, panel->win, _("Can not delete '%s'."), file);
751 wfree(file);
752 return;
753 } else if (S_ISDIR(filestat.st_mode)) {
754 int len = strlen(file)+20;
755 buffer = wmalloc(len);
756 snprintf(buffer,len,_("Delete directory %s ?"),file);
757 } else {
758 int len = strlen(file)+15;
759 buffer = wmalloc(len);
760 snprintf(buffer,len,_("Delete file %s ?"),file);
763 if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
764 _("Warning"), buffer, _("OK"), _("Cancel"), NULL)) {
765 if (S_ISDIR(filestat.st_mode)) {
766 if (rmdir(file) != 0) {
767 switch (errno) {
768 case EACCES:
769 showError(scr, panel->win, _("Permission denied."), NULL);
770 break;
771 case ENOENT:
772 showError(scr, panel->win, _("Directory '%s' does not exist."), file);
773 break;
774 case ENOTEMPTY:
775 showError(scr, panel->win, _("Directory '%s' is not empty."), file);
776 break;
777 case EBUSY:
778 showError(scr, panel->win, _("Directory '%s' is busy."), file);
779 break;
780 default:
781 showError(scr, panel->win, _("Can not delete '%s'."), file);
783 } else {
784 char *s = strrchr(file,'/');
785 if (s) s[0] = 0;
786 WMSetFilePanelDirectory(panel, file);
788 } else if (remove(file) != 0) {
789 switch (errno) {
790 case EISDIR:
791 showError(scr, panel->win, _("'%s' is a directory."), file);
792 break;
793 case ENOENT:
794 showError(scr, panel->win, _("'%s' does not exist."), file);
795 break;
796 case EACCES:
797 showError(scr, panel->win, _("Permission denied."), NULL);
798 break;
799 case ENOMEM:
800 showError(scr, panel->win,
801 _("Insufficient memory available."), NULL);
802 break;
803 case EROFS:
804 showError(scr, panel->win,
805 _("'%s' is on a read-only filesystem."), file);
806 break;
807 default:
808 showError(scr, panel->win, _("Can not delete '%s'."), file);
810 } else {
811 char *s = strrchr(file,'/');
812 if (s) s[1] = 0;
813 WMSetFilePanelDirectory(panel, file);
816 wfree(buffer);
817 wfree(file);
820 static void
821 goUnmount(WMButton *bPtr, WMFilePanel *panel)
826 static void
827 goFloppy(WMButton *bPtr, WMFilePanel *panel)
829 struct stat filestat;
830 WMScreen *scr = WMWidgetScreen(panel->win);
832 if (stat(WINGsConfiguration.floppyPath, &filestat)) {
833 showError(scr, panel->win, _("An error occured browsing '%s'."),
834 WINGsConfiguration.floppyPath);
835 return;
836 } else if (!S_ISDIR(filestat.st_mode)) {
837 showError(scr, panel->win, _("'%s' is not a directory."),
838 WINGsConfiguration.floppyPath);
839 return;
842 WMSetFilePanelDirectory(panel, WINGsConfiguration.floppyPath);
846 static void
847 goHome(WMButton *bPtr, WMFilePanel *panel)
849 char *home;
851 /* home is statically allocated. Don't free it! */
852 home = wgethomedir();
853 if (!home)
854 return;
856 WMSetFilePanelDirectory(panel, home);
860 static void
861 handleEvents(XEvent *event, void *data)
863 W_FilePanel *pPtr = (W_FilePanel*)data;
864 W_View *view = WMWidgetView(pPtr->win);
866 if (event->type == ConfigureNotify) {
867 if (event->xconfigure.width != view->size.width
868 || event->xconfigure.height != view->size.height) {
869 unsigned int newWidth = event->xconfigure.width;
870 unsigned int newHeight = event->xconfigure.height;
871 int newColumnCount;
873 W_ResizeView(view, newWidth, newHeight);
874 WMResizeWidget(pPtr->line, newWidth, 2);
875 WMResizeWidget(pPtr->browser, newWidth-14,
876 newHeight-(PHEIGHT-200));
877 WMResizeWidget(pPtr->fileField, newWidth-60-10, 24);
878 WMMoveWidget(pPtr->nameLabel, 7, newHeight-(PHEIGHT-282));
879 WMMoveWidget(pPtr->fileField, 60, newHeight-(PHEIGHT-278));
880 WMMoveWidget(pPtr->okButton, newWidth-(PWIDTH-245),
881 newHeight-(PHEIGHT-325));
882 WMMoveWidget(pPtr->cancelButton, newWidth-(PWIDTH-165),
883 newHeight-(PHEIGHT-325));
885 WMMoveWidget(pPtr->trashcanButton, 7, newHeight-(PHEIGHT-325));
886 WMMoveWidget(pPtr->createDirButton, 37, newHeight-(PHEIGHT-325));
887 WMMoveWidget(pPtr->homeButton, 67, newHeight-(PHEIGHT-325));
888 WMMoveWidget(pPtr->disketteButton, 97, newHeight-(PHEIGHT-325));
889 WMMoveWidget(pPtr->unmountButton, 127, newHeight-(PHEIGHT-325));
891 newColumnCount = (newWidth - 14) / 140;
892 WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount);
898 static char*
899 getCurrentFileName(WMFilePanel *panel)
901 char *path;
902 char *file;
903 char *tmp;
904 int len;
906 path = WMGetBrowserPath(panel->browser);
908 len = strlen(path);
909 if (path[len-1]=='/') {
910 file = WMGetTextFieldText(panel->fileField);
911 tmp = wmalloc(strlen(path)+strlen(file)+8);
912 if (file[0]!='/') {
913 strcpy(tmp, path);
914 strcat(tmp, file);
915 } else
916 strcpy(tmp, file);
918 wfree(file);
919 wfree(path);
920 return tmp;
921 } else {
922 return path;
928 static Bool
929 validOpenFile(WMFilePanel *panel)
931 WMListItem *item;
932 int col, haveFile = 0;
933 char *file = WMGetTextFieldText(panel->fileField);
935 if (file[0] != '\0')
936 haveFile = 1;
937 wfree(file);
939 col = WMGetBrowserSelectedColumn(panel->browser);
940 item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
941 if (item) {
942 if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile)
943 return False;
944 else if (!item->isBranch && !panel->flags.canChooseFiles)
945 return False;
946 else
947 return True;
948 } else {
949 /* we compute for / here */
950 if (!panel->flags.canChooseDirectories && !haveFile)
951 return False;
952 else
953 return True;
955 return True;
960 static void
961 buttonClick(WMButton *bPtr, WMFilePanel *panel)
963 WMRange range;
965 if (bPtr == panel->okButton) {
966 if (!validOpenFile(panel))
967 return;
968 if (panel->flags.fileMustExist) {
969 char *file;
971 file = getCurrentFileName(panel);
972 if (access(file, F_OK)!=0) {
973 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
974 _("Error"), _("File does not exist."),
975 _("OK"), NULL, NULL);
976 wfree(file);
977 return;
979 wfree(file);
981 panel->flags.canceled = 0;
982 } else
983 panel->flags.canceled = 1;
985 range.count = range.position = 0;
986 WMSelectTextFieldRange(panel->fileField, range);
987 WMBreakModalLoop(WMWidgetScreen(bPtr));