aplied colorpanel fix patches
[wmaker-crm.git] / WINGs / wfilepanel.c
blob8535f3bd3c4461de64c2908bc716c0258902b30c
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
15 #ifndef FLOPPY_PATH
16 #define FLOPPY_PATH "/floppy"
17 #endif
19 typedef struct W_FilePanel {
20 WMWindow *win;
22 WMLabel *iconLabel;
23 WMLabel *titleLabel;
25 WMFrame *line;
27 WMLabel *nameLabel;
28 WMBrowser *browser;
30 WMButton *okButton;
31 WMButton *cancelButton;
33 WMButton *homeButton;
34 WMButton *trashcanButton;
35 WMButton *createDirButton;
36 WMButton *disketteButton;
37 WMButton *unmountButton;
39 WMView *accessoryView;
41 WMTextField *fileField;
43 char **fileTypes;
45 struct {
46 unsigned int canExit:1;
47 unsigned int canceled:1; /* clicked on cancel */
48 unsigned int done:1;
49 unsigned int filtered:1;
50 unsigned int canChooseFiles:1;
51 unsigned int canChooseDirectories:1;
52 unsigned int autoCompletion:1;
53 unsigned int showAllFiles:1;
54 unsigned int canFreeFileTypes:1;
55 unsigned int fileMustExist:1;
56 unsigned int panelType:1;
57 } flags;
58 } W_FilePanel;
61 /* Type of panel */
62 #define WP_OPEN 0
63 #define WP_SAVE 1
65 #define PWIDTH 330
66 #define PHEIGHT 360
68 static void listDirectoryOnColumn(WMFilePanel *panel, int column, char *path);
69 static void browserClick();
70 static void browserDClick();
72 static void fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column,
73 WMList *list);
75 static void deleteFile();
77 static void createDir();
79 static void goHome();
81 static void goFloppy();
83 static void goUnmount();
85 static void buttonClick();
87 static char *getCurrentFileName(WMFilePanel *panel);
89 static void handleEvents(XEvent *event, void *data);
93 static WMBrowserDelegate browserDelegate = {
94 NULL, /* data */
95 fillColumn, /* createRowsForColumn */
96 NULL, /* titleOfColumn */
97 NULL, /* didScroll */
98 NULL /* willScroll */
102 static int
103 closestListItem(WMList *list, char *text, Bool exact)
105 WMListItem *item;
106 WMBag *items = WMGetListItems(list);
107 int i;
108 int len = strlen(text);
110 if (len==0)
111 return -1;
113 for (i = 0; i < WMGetBagItemCount(items); i++) {
114 item = WMGetFromBag(items, i);
116 if (strlen(item->text) >= len &&
117 ((exact && strcmp(item->text, text)==0) ||
118 (!exact && strncmp(item->text, text, len)==0))) {
119 return i;
123 return -1;
127 static void
128 textChangedObserver(void *observerData, WMNotification *notification)
130 W_FilePanel *panel = (W_FilePanel*)observerData;
131 char *text;
132 WMList *list;
133 int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
134 int i, textEvent;
136 if (!(list = WMGetBrowserListInColumn(panel->browser, col)))
137 return;
139 text = WMGetTextFieldText(panel->fileField);
140 textEvent = (int)WMGetNotificationClientData(notification);
142 if (panel->flags.autoCompletion && textEvent!=WMDeleteTextEvent)
143 i = closestListItem(list, text, False);
144 else
145 i = closestListItem(list, text, True);
147 WMSelectListItem(list, i);
148 if (i>=0 && panel->flags.autoCompletion) {
149 WMListItem *item = WMGetListItem(list, i);
150 int textLen = strlen(text), itemTextLen = strlen(item->text);
151 int visibleItems = WMWidgetHeight(list)/WMGetListItemHeight(list);
153 WMSetListPosition(list, i - visibleItems/2);
155 if (textEvent!=WMDeleteTextEvent) {
156 WMRange range;
158 WMInsertTextFieldText(panel->fileField, &item->text[textLen],
159 textLen);
160 range.position = textLen;
161 range.count = itemTextLen - textLen;
162 WMSelectTextFieldRange(panel->fileField, range);
163 /*WMSetTextFieldCursorPosition(panel->fileField, itemTextLen);*/
167 wfree(text);
171 static void
172 textEditedObserver(void *observerData, WMNotification *notification)
174 W_FilePanel *panel = (W_FilePanel*)observerData;
176 if ((int)WMGetNotificationClientData(notification)==WMReturnTextMovement) {
177 WMPerformButtonClick(panel->okButton);
183 static WMFilePanel*
184 makeFilePanel(WMScreen *scrPtr, char *name, char *title)
186 WMFilePanel *fPtr;
187 WMFont *largeFont;
189 fPtr = wmalloc(sizeof(WMFilePanel));
190 memset(fPtr, 0, sizeof(WMFilePanel));
192 fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask
193 |WMResizableWindowMask);
194 WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
195 WMSetWindowTitle(fPtr->win, "");
197 WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask,
198 handleEvents, fPtr);
199 WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT);
202 fPtr->iconLabel = WMCreateLabel(fPtr->win);
203 WMResizeWidget(fPtr->iconLabel, 64, 64);
204 WMMoveWidget(fPtr->iconLabel, 0, 0);
205 WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
206 WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIcon);
208 fPtr->titleLabel = WMCreateLabel(fPtr->win);
209 WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64);
210 WMMoveWidget(fPtr->titleLabel, 64, 0);
211 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
212 WMSetLabelFont(fPtr->titleLabel, largeFont);
213 WMReleaseFont(largeFont);
214 WMSetLabelText(fPtr->titleLabel, title);
216 fPtr->line = WMCreateFrame(fPtr->win);
217 WMMoveWidget(fPtr->line, 0, 64);
218 WMResizeWidget(fPtr->line, PWIDTH, 2);
219 WMSetFrameRelief(fPtr->line, WRGroove);
221 fPtr->browser = WMCreateBrowser(fPtr->win);
222 WMSetBrowserDelegate(fPtr->browser, &browserDelegate);
223 WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
224 WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr);
225 WMMoveWidget(fPtr->browser, 7, 72);
226 WMResizeWidget(fPtr->browser, PWIDTH-14,200);
227 WMHangData(fPtr->browser, fPtr);
229 fPtr->nameLabel = WMCreateLabel(fPtr->win);
230 WMMoveWidget(fPtr->nameLabel, 7, 282);
231 WMResizeWidget(fPtr->nameLabel, 55, 14);
232 WMSetLabelText(fPtr->nameLabel, "Name:");
234 fPtr->fileField = WMCreateTextField(fPtr->win);
235 WMMoveWidget(fPtr->fileField, 60, 278);
236 WMResizeWidget(fPtr->fileField, PWIDTH-60-10, 24);
237 WMAddNotificationObserver(textEditedObserver, fPtr,
238 WMTextDidEndEditingNotification,
239 fPtr->fileField);
240 WMAddNotificationObserver(textChangedObserver, fPtr,
241 WMTextDidChangeNotification,
242 fPtr->fileField);
244 fPtr->okButton = WMCreateCommandButton(fPtr->win);
245 WMMoveWidget(fPtr->okButton, 245, 325);
246 WMResizeWidget(fPtr->okButton, 75, 28);
247 WMSetButtonText(fPtr->okButton, "OK");
248 WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
249 WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
250 WMSetButtonImagePosition(fPtr->okButton, WIPRight);
251 WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
253 fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
254 WMMoveWidget(fPtr->cancelButton, 165, 325);
255 WMResizeWidget(fPtr->cancelButton, 75, 28);
256 WMSetButtonText(fPtr->cancelButton, "Cancel");
257 WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
259 fPtr->trashcanButton = WMCreateCommandButton(fPtr->win);
260 WMMoveWidget(fPtr->trashcanButton, 7, 325);
261 WMResizeWidget(fPtr->trashcanButton, 28, 28);
262 WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly);
263 WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon);
264 WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon);
265 WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr);
267 fPtr->createDirButton = WMCreateCommandButton(fPtr->win);
268 WMMoveWidget(fPtr->createDirButton, 37, 325);
269 WMResizeWidget(fPtr->createDirButton, 28, 28);
270 WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly);
271 WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon);
272 WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon);
273 WMSetButtonAction(fPtr->createDirButton, createDir, fPtr);
275 fPtr->homeButton = WMCreateCommandButton(fPtr->win);
276 WMMoveWidget(fPtr->homeButton, 67, 325);
277 WMResizeWidget(fPtr->homeButton, 28, 28);
278 WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
279 WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
280 WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon);
281 WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
283 fPtr->disketteButton = WMCreateCommandButton(fPtr->win);
284 WMMoveWidget(fPtr->disketteButton, 97, 325);
285 WMResizeWidget(fPtr->disketteButton, 28, 28);
286 WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly);
287 WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon);
288 WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon);
289 WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr);
291 fPtr->unmountButton = WMCreateCommandButton(fPtr->win);
292 WMMoveWidget(fPtr->unmountButton, 127, 325);
293 WMResizeWidget(fPtr->unmountButton, 28, 28);
294 WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly);
295 WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon);
296 WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon);
297 WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr);
298 WMSetButtonEnabled(fPtr->unmountButton, False);
301 WMRealizeWidget(fPtr->win);
302 WMMapSubwidgets(fPtr->win);
304 WMSetFocusToWidget(fPtr->fileField);
305 WMSetTextFieldCursorPosition(fPtr->fileField, 0);
307 WMLoadBrowserColumnZero(fPtr->browser);
309 WMSetWindowInitialPosition(fPtr->win,
310 (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win))/2,
311 (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win))/2);
313 fPtr->flags.canChooseFiles = 1;
314 fPtr->flags.canChooseDirectories = 1;
315 fPtr->flags.autoCompletion = 1;
317 return fPtr;
321 WMOpenPanel*
322 WMGetOpenPanel(WMScreen *scrPtr)
324 WMFilePanel *panel;
326 if (scrPtr->sharedOpenPanel)
327 return scrPtr->sharedOpenPanel;
329 panel = makeFilePanel(scrPtr, "openFilePanel", "Open");
330 panel->flags.fileMustExist = 1;
331 panel->flags.panelType = WP_OPEN;
333 scrPtr->sharedOpenPanel = panel;
335 return panel;
339 WMSavePanel*
340 WMGetSavePanel(WMScreen *scrPtr)
342 WMFilePanel *panel;
344 if (scrPtr->sharedSavePanel)
345 return scrPtr->sharedSavePanel;
347 panel = makeFilePanel(scrPtr, "saveFilePanel", "Save");
348 panel->flags.fileMustExist = 0;
349 panel->flags.panelType = WP_SAVE;
351 scrPtr->sharedSavePanel = panel;
353 return panel;
357 void
358 WMFreeFilePanel(WMFilePanel *panel)
360 if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) {
361 WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
363 if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
364 WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
366 WMRemoveNotificationObserver(panel);
367 WMUnmapWidget(panel->win);
368 WMDestroyWidget(panel->win);
369 wfree(panel);
374 WMRunModalFilePanelForDirectory(WMFilePanel *panel, WMWindow *owner,
375 char *path, char *name, char **fileTypes)
377 WMScreen *scr = WMWidgetScreen(panel->win);
378 XEvent event;
380 if (name && !owner) {
381 WMSetWindowTitle(panel->win, name);
384 WMChangePanelOwner(panel->win, owner);
386 WMSetFilePanelDirectory(panel, path);
388 panel->flags.done = 0;
389 switch(panel->flags.panelType) {
390 case WP_OPEN:
391 if (fileTypes)
392 panel->flags.filtered = 1;
393 panel->fileTypes = fileTypes;
394 if (name == NULL)
395 name = "Open";
396 break;
397 case WP_SAVE:
398 panel->fileTypes = NULL;
399 panel->flags.filtered = 0;
400 if (name == NULL)
401 name = "Save";
402 break;
403 default:
404 break;
407 WMSetLabelText(panel->titleLabel, name);
409 scr->modalView = W_VIEW(panel->win);
410 WMMapWidget(panel->win);
412 scr->modal = 1;
413 while (!panel->flags.done) {
414 WMNextEvent(scr->display, &event);
415 WMHandleEvent(&event);
417 scr->modal = 0;
419 /* Must withdraw window because the next time we map
420 * it, it might have a different transient owner.
422 WMCloseWindow(panel->win);
424 return (panel->flags.canceled ? False : True);
430 void
431 WMSetFilePanelDirectory(WMFilePanel *panel, char *path)
433 WMList *list;
434 WMListItem *item;
435 int col;
436 char *rest;
438 rest = WMSetBrowserPath(panel->browser, path);
439 if (strcmp(path, "/")==0)
440 rest = NULL;
442 col = WMGetBrowserSelectedColumn(panel->browser);
443 list = WMGetBrowserListInColumn(panel->browser, col);
444 if (list && (item = WMGetListSelectedItem(list))) {
445 if (item->isBranch) {
446 WMSetTextFieldText(panel->fileField, rest);
447 } else {
448 WMSetTextFieldText(panel->fileField, item->text);
450 } else {
451 WMSetTextFieldText(panel->fileField, rest);
456 void
457 WMSetFilePanelCanChooseDirectories(WMFilePanel *panel, Bool flag)
459 panel->flags.canChooseDirectories = flag;
462 void
463 WMSetFilePanelCanChooseFiles(WMFilePanel *panel, Bool flag)
465 panel->flags.canChooseFiles = flag;
469 void
470 WMSetFilePanelAutoCompletion(WMFilePanel *panel, Bool flag)
472 panel->flags.autoCompletion = flag;
476 char*
477 WMGetFilePanelFileName(WMFilePanel *panel)
479 return getCurrentFileName(panel);
483 void
484 WMSetFilePanelAccessoryView(WMFilePanel *panel, WMView *view)
486 WMView *v;
488 panel->accessoryView = view;
490 v = WMWidgetView(panel->win);
492 W_ReparentView(view, v, 0, 0);
494 W_MoveView(view, (v->size.width - v->size.width)/2, 300);
498 WMView*
499 WMGetFilePanelAccessoryView(WMFilePanel *panel)
501 return panel->accessoryView;
505 static char*
506 get_name_from_path(char *path)
508 int size;
510 assert(path!=NULL);
512 size = strlen(path);
514 /* remove trailing / */
515 while (size > 0 && path[size-1]=='/')
516 size--;
517 /* directory was root */
518 if (size == 0)
519 return wstrdup("/");
521 while (size > 0 && path[size-1] != '/')
522 size--;
524 return wstrdup(&(path[size]));
528 static int
529 filterFileName(WMFilePanel *panel, char *file, Bool isDirectory)
531 return True;
535 #define CAST(item) (*((WMListItem**)item))
536 static int
537 comparer(const void *a, const void *b)
539 if (CAST(a)->isBranch == CAST(b)->isBranch)
540 return (strcmp(CAST(a)->text, CAST(b)->text));
541 if (CAST(a)->isBranch)
542 return (-1);
543 return (1);
545 #undef CAST
548 static void
549 listDirectoryOnColumn(WMFilePanel *panel, int column, char *path)
551 WMBrowser *bPtr = panel->browser;
552 struct dirent *dentry;
553 DIR *dir;
554 struct stat stat_buf;
555 char pbuf[PATH_MAX+16];
557 assert(column >= 0);
558 assert(path != NULL);
560 /* put directory name in the title */
561 WMSetBrowserColumnTitle(bPtr, column, get_name_from_path(path));
563 dir = opendir(path);
565 if (!dir) {
566 #ifdef VERBOSE
567 printf("WINGs: could not open directory %s\n", path);
568 #endif
569 return;
572 /* list contents in the column */
573 while ((dentry = readdir(dir))) {
574 if (strcmp(dentry->d_name, ".")==0 ||
575 strcmp(dentry->d_name, "..")==0)
576 continue;
578 strcpy(pbuf, path);
579 if (strcmp(path, "/")!=0)
580 strcat(pbuf, "/");
581 strcat(pbuf, dentry->d_name);
583 if (stat(pbuf, &stat_buf)!=0) {
584 #ifdef VERBOSE
585 printf("WINGs: could not stat %s\n", pbuf);
586 #endif
587 continue;
588 } else {
589 int isDirectory;
591 isDirectory = S_ISDIR(stat_buf.st_mode);
593 if (filterFileName(panel, dentry->d_name, isDirectory))
594 WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory);
597 WMSortBrowserColumnWithComparer(bPtr, column, comparer);
599 closedir(dir);
603 static void
604 fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column, WMList *list)
606 char *path;
607 WMFilePanel *panel;
609 if (column > 0) {
610 path = WMGetBrowserPathToColumn(bPtr, column-1);
611 } else {
612 path = wstrdup("/");
615 panel = WMGetHangedData(bPtr);
616 listDirectoryOnColumn(panel, column, path);
617 wfree(path);
621 static void
622 browserDClick(WMBrowser *bPtr, WMFilePanel *panel)
624 WMPerformButtonClick(panel->okButton);
627 static void
628 browserClick(WMBrowser *bPtr, WMFilePanel *panel)
630 int col = WMGetBrowserSelectedColumn(bPtr);
631 WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
633 if (!item || item->isBranch)
634 WMSetTextFieldText(panel->fileField, NULL);
635 else {
636 WMSetTextFieldText(panel->fileField, item->text);
641 static void
642 showError(WMScreen *scr, WMWindow *owner, char *s, char *file)
644 char *errStr;
646 if (file) {
647 errStr = wmalloc(strlen(file)+strlen(s));
648 sprintf(errStr, s, file);
649 } else {
650 errStr = wstrdup(s);
652 WMRunAlertPanel(scr, owner, "Error", errStr, "OK", NULL, NULL);
653 wfree(errStr);
657 static void
658 createDir(WMButton *bPre, WMFilePanel *panel)
660 char *directory_name;
661 char *directory;
662 char *file;
663 char *s;
664 WMScreen *scr = WMWidgetScreen(panel->win);
665 WMInputPanel *_panel;
667 _panel = WMCreateInputPanel(scr, panel->win,
668 "Create Directory", "Enter directory name", "", "OK", "Cancel");
669 scr->modalView = W_VIEW(_panel->win);
670 WMMapWidget(_panel->win);
671 scr->modal = 1;
672 while (!_panel->done || WMScreenPending(scr)) {
673 XEvent event;
674 WMNextEvent(scr->display, &event);
675 WMHandleEvent(&event);
677 scr->modal = 0;
679 if (_panel->result == WAPRDefault)
680 directory_name = WMGetTextFieldText(_panel->text);
681 else {
682 WMDestroyInputPanel(_panel);
683 return;
686 WMDestroyInputPanel(_panel);
688 directory = getCurrentFileName(panel);
690 char *s = strrchr(directory,'/');
691 if (s) s[1] = 0;
694 if (directory_name[0] == '/') {
695 directory[0] = 0;
696 } else {
697 while ((s = strstr(directory,"//"))) {
698 int i;
699 for (i = 2;s[i] == '/';i++);
700 strcpy(s, &s[i-1]);
702 if ((s = strrchr(directory, '/')) && !s[1]) s[0] = 0;
704 while ((s = strstr(directory_name,"//"))) {
705 int i;
706 for (i = 2;s[i] == '/';i++);
707 strcpy(s, &s[i-1]);
709 if ((s = strrchr(directory_name, '/')) && !s[1]) s[0] = 0;
711 file = wmalloc(strlen(directory_name)+strlen(directory)+1);
712 sprintf(file, "%s/%s", directory, directory_name);
713 while ((s = strstr(file,"//"))) {
714 int i;
715 for (i = 2;s[i] == '/';i++);
716 strcpy(s, &s[i-1]);
719 if (mkdir(file,0xfff) != 0) {
720 switch (errno) {
721 case EACCES:
722 showError(scr, panel->win, "Permission denied.", NULL);
723 break;
724 case EEXIST:
725 showError(scr, panel->win, "'%s' already existes.", file);
726 break;
727 case ENOENT:
728 showError(scr, panel->win, "Path does not exist.", NULL);
731 else WMSetFilePanelDirectory(panel, file);
733 wfree(directory_name);
734 wfree(directory);
735 wfree(file);
739 static void
740 deleteFile(WMButton *bPre, WMFilePanel *panel)
742 char *file;
743 char *buffer, *s;
744 struct stat filestat;
745 WMScreen *scr = WMWidgetScreen(panel->win);
747 file = getCurrentFileName(panel);
749 while ((s = strstr(file,"//"))) {
750 int i;
751 for (i = 2;s[i] == '/';i++);
752 strcpy(s, &s[i-1]);
754 if (strlen(file) > 1 && (s = strrchr(file, '/')) && !s[1]) s[0] = 0;
756 if (stat(file,&filestat)) {
757 switch (errno) {
758 case ENOENT:
759 showError(scr, panel->win, "'%s' does not exist.", file);
760 break;
761 case EACCES:
762 showError(scr, panel->win, "Permission denied.", NULL);
763 break;
764 case ENOMEM:
765 showError(scr, panel->win,
766 "Insufficient memory available.", NULL);
767 break;
768 case EROFS:
769 showError(scr, panel->win,
770 "'%s' is on a read-only filesystem.", file);
771 break;
772 default:
773 showError(scr, panel->win, "Can not delete '%s'.", file);
775 wfree(file);
776 return;
777 } else if (S_ISDIR(filestat.st_mode)) {
778 buffer = wmalloc(strlen(file)+20);
779 sprintf(buffer,"Delete directory %s ?",file);
780 } else {
781 buffer = wmalloc(strlen(file)+15);
782 sprintf(buffer,"Delete file %s ?",file);
785 if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
786 "Warning", buffer, "OK", "Cancel", NULL)) {
787 if (S_ISDIR(filestat.st_mode)) {
788 if (rmdir(file) != 0) {
789 switch (errno) {
790 case EACCES:
791 showError(scr, panel->win, "Permission denied.", NULL);
792 break;
793 case ENOENT:
794 showError(scr, panel->win, "Directory '%s' does not exist.", file);
795 break;
796 case ENOTEMPTY:
797 showError(scr, panel->win, "Directory '%s' is not empty.", file);
798 break;
799 case EBUSY:
800 showError(scr, panel->win, "Directory '%s' is busy.", file);
801 break;
802 default:
803 showError(scr, panel->win, "Can not delete '%s'.", file);
805 } else {
806 char *s = strrchr(file,'/');
807 if (s) s[0] = 0;
808 WMSetFilePanelDirectory(panel, file);
810 } else if (remove(file) != 0) {
811 switch (errno) {
812 case EISDIR:
813 showError(scr, panel->win, "'%s' is a directory.", file);
814 break;
815 case ENOENT:
816 showError(scr, panel->win, "'%s' does not exist.", file);
817 break;
818 case EACCES:
819 showError(scr, panel->win, "Permission denied.", NULL);
820 break;
821 case ENOMEM:
822 showError(scr, panel->win,
823 "Insufficient memory available.", NULL);
824 break;
825 case EROFS:
826 showError(scr, panel->win,
827 "'%s' is on a read-only filesystem.", file);
828 break;
829 default:
830 showError(scr, panel->win, "Can not delete '%s'.", file);
832 } else {
833 char *s = strrchr(file,'/');
834 if (s) s[1] = 0;
835 WMSetFilePanelDirectory(panel, file);
838 wfree(buffer);
839 wfree(file);
842 static void
843 goUnmount(WMButton *bPtr, WMFilePanel *panel)
848 static void
849 goFloppy(WMButton *bPtr, WMFilePanel *panel)
851 char *file;
852 struct stat filestat;
853 WMScreen *scr = WMWidgetScreen(panel->win);
855 file = FLOPPY_PATH;
856 if (stat(FLOPPY_PATH,&filestat)) {
857 showError(scr, panel->win, "An error occured browsing '%s'.", file);
858 return;
859 } else if (!S_ISDIR(filestat.st_mode)) {
860 showError(scr, panel->win, "'%s' is not a directory.", file);
861 return;
864 WMSetFilePanelDirectory(panel, FLOPPY_PATH);
868 static void
869 goHome(WMButton *bPtr, WMFilePanel *panel)
871 char *home;
873 /* home is statically allocated. Don't free it! */
874 home = wgethomedir();
875 if (!home)
876 return;
878 WMSetFilePanelDirectory(panel, home);
882 static void
883 handleEvents(XEvent *event, void *data)
885 W_FilePanel *pPtr = (W_FilePanel*)data;
886 W_View *view = WMWidgetView(pPtr->win);
888 if (event->type == ConfigureNotify) {
889 if (event->xconfigure.width != view->size.width
890 || event->xconfigure.height != view->size.height) {
891 unsigned int newWidth = event->xconfigure.width;
892 unsigned int newHeight = event->xconfigure.height;
893 int newColumnCount;
895 W_ResizeView(view, newWidth, newHeight);
896 WMResizeWidget(pPtr->line, newWidth, 2);
897 WMResizeWidget(pPtr->browser, newWidth-14,
898 newHeight-(PHEIGHT-200));
899 WMResizeWidget(pPtr->fileField, newWidth-60-10, 24);
900 WMMoveWidget(pPtr->nameLabel, 7, newHeight-(PHEIGHT-282));
901 WMMoveWidget(pPtr->fileField, 60, newHeight-(PHEIGHT-278));
902 WMMoveWidget(pPtr->okButton, newWidth-(PWIDTH-245),
903 newHeight-(PHEIGHT-325));
904 WMMoveWidget(pPtr->cancelButton, newWidth-(PWIDTH-165),
905 newHeight-(PHEIGHT-325));
907 WMMoveWidget(pPtr->trashcanButton, 7, newHeight-(PHEIGHT-325));
908 WMMoveWidget(pPtr->createDirButton, 37, newHeight-(PHEIGHT-325));
909 WMMoveWidget(pPtr->homeButton, 67, newHeight-(PHEIGHT-325));
910 WMMoveWidget(pPtr->disketteButton, 97, newHeight-(PHEIGHT-325));
911 WMMoveWidget(pPtr->unmountButton, 127, newHeight-(PHEIGHT-325));
913 newColumnCount = (newWidth - 14) / 140;
914 WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount);
920 static char*
921 getCurrentFileName(WMFilePanel *panel)
923 char *path;
924 char *file;
925 char *tmp;
926 int len;
928 path = WMGetBrowserPath(panel->browser);
930 len = strlen(path);
931 if (path[len-1]=='/') {
932 file = WMGetTextFieldText(panel->fileField);
933 tmp = wmalloc(strlen(path)+strlen(file)+8);
934 if (file[0]!='/') {
935 strcpy(tmp, path);
936 strcat(tmp, file);
937 } else
938 strcpy(tmp, file);
940 wfree(file);
941 wfree(path);
942 return tmp;
943 } else {
944 return path;
950 static Bool
951 validOpenFile(WMFilePanel *panel)
953 WMListItem *item;
954 int col, haveFile = 0;
955 char *file = WMGetTextFieldText(panel->fileField);
957 if (file[0] != '\0')
958 haveFile = 1;
959 wfree(file);
961 col = WMGetBrowserSelectedColumn(panel->browser);
962 item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
963 if (item) {
964 if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile)
965 return False;
966 else if (!item->isBranch && !panel->flags.canChooseFiles)
967 return False;
968 else
969 return True;
970 } else {
971 /* we compute for / here */
972 if (!panel->flags.canChooseDirectories && !haveFile)
973 return False;
974 else
975 return True;
977 return True;
982 static void
983 buttonClick(WMButton *bPtr, WMFilePanel *panel)
985 WMRange range;
987 if (bPtr == panel->okButton) {
988 if (!validOpenFile(panel))
989 return;
990 if (panel->flags.fileMustExist) {
991 char *file;
993 file = getCurrentFileName(panel);
994 if (access(file, F_OK)!=0) {
995 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
996 "Error", "File does not exist.",
997 "Ok", NULL, NULL);
998 wfree(file);
999 return;
1001 wfree(file);
1003 panel->flags.canceled = 0;
1004 } else
1005 panel->flags.canceled = 1;
1007 range.count = range.position = 0;
1008 WMSelectTextFieldRange(panel->fileField, range);
1009 panel->flags.done = 1;