Update German translation
[wmaker-crm.git] / WINGs / wfilepanel.c
blob29de7b5e16acb551a34c20b052fbb9e2f8c8403c
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
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;
57 /* Type of panel */
58 #define WP_OPEN 0
59 #define WP_SAVE 1
61 #define PWIDTH 330
62 #define PHEIGHT 360
64 static void listDirectoryOnColumn(WMFilePanel * panel, int column, char *path);
65 static void browserClick();
66 static void browserDClick();
68 static void fillColumn(WMBrowserDelegate * self, WMBrowser * bPtr, int column, WMList * list);
70 static void deleteFile();
72 static void createDir();
74 static void goHome();
76 static void goFloppy();
78 static void goUnmount();
80 static void buttonClick();
82 static char *getCurrentFileName(WMFilePanel * panel);
84 static void handleEvents(XEvent * event, void *data);
86 static WMBrowserDelegate browserDelegate = {
87 NULL, /* data */
88 fillColumn, /* createRowsForColumn */
89 NULL, /* titleOfColumn */
90 NULL, /* didScroll */
91 NULL /* willScroll */
94 static int closestListItem(WMList * list, char *text, Bool exact)
96 WMListItem *item;
97 WMArray *items = WMGetListItems(list);
98 int i, len = strlen(text);
100 if (len == 0)
101 return -1;
103 for (i = 0; i < WMGetArrayItemCount(items); i++) {
104 item = WMGetFromArray(items, i);
105 if (strlen(item->text) >= len &&
106 ((exact && strcmp(item->text, text) == 0) ||
107 (!exact && strncmp(item->text, text, len) == 0))) {
108 return i;
112 return -1;
115 static void textChangedObserver(void *observerData, WMNotification * notification)
117 W_FilePanel *panel = (W_FilePanel *) observerData;
118 char *text;
119 WMList *list;
120 int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
121 int i;
122 uintptr_t textEvent;
124 if (!(list = WMGetBrowserListInColumn(panel->browser, col)))
125 return;
127 text = WMGetTextFieldText(panel->fileField);
128 textEvent = (uintptr_t)WMGetNotificationClientData(notification);
130 if (panel->flags.autoCompletion && textEvent != WMDeleteTextEvent)
131 i = closestListItem(list, text, False);
132 else
133 i = closestListItem(list, text, True);
135 WMSelectListItem(list, i);
136 if (i >= 0 && panel->flags.autoCompletion) {
137 WMListItem *item = WMGetListItem(list, i);
138 int textLen = strlen(text), itemTextLen = strlen(item->text);
139 int visibleItems = WMWidgetHeight(list) / WMGetListItemHeight(list);
141 WMSetListPosition(list, i - visibleItems / 2);
143 if (textEvent != WMDeleteTextEvent) {
144 WMRange range;
146 WMInsertTextFieldText(panel->fileField, &item->text[textLen], textLen);
147 range.position = textLen;
148 range.count = itemTextLen - textLen;
149 WMSelectTextFieldRange(panel->fileField, range);
150 /*WMSetTextFieldCursorPosition(panel->fileField, itemTextLen); */
154 wfree(text);
157 static void textEditedObserver(void *observerData, WMNotification * notification)
159 W_FilePanel *panel = (W_FilePanel *) observerData;
161 if ((uintptr_t)WMGetNotificationClientData(notification) == WMReturnTextMovement) {
162 WMPerformButtonClick(panel->okButton);
166 static WMFilePanel *makeFilePanel(WMScreen * scrPtr, char *name, char *title)
168 WMFilePanel *fPtr;
169 WMFont *largeFont;
170 WMPixmap *icon;
172 fPtr = wmalloc(sizeof(WMFilePanel));
173 memset(fPtr, 0, sizeof(WMFilePanel));
175 fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask | WMResizableWindowMask);
176 WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
177 WMSetWindowTitle(fPtr->win, "");
179 WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask, handleEvents, fPtr);
180 WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT);
182 fPtr->iconLabel = WMCreateLabel(fPtr->win);
183 WMResizeWidget(fPtr->iconLabel, 64, 64);
184 WMMoveWidget(fPtr->iconLabel, 0, 0);
185 WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
186 icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor *) NULL);
187 if (icon) {
188 WMSetLabelImage(fPtr->iconLabel, icon);
189 WMReleasePixmap(icon);
190 } else {
191 WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIconPixmap);
194 fPtr->titleLabel = WMCreateLabel(fPtr->win);
195 WMResizeWidget(fPtr->titleLabel, PWIDTH - 64, 64);
196 WMMoveWidget(fPtr->titleLabel, 64, 0);
197 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
198 WMSetLabelFont(fPtr->titleLabel, largeFont);
199 WMReleaseFont(largeFont);
200 WMSetLabelText(fPtr->titleLabel, title);
202 fPtr->line = WMCreateFrame(fPtr->win);
203 WMMoveWidget(fPtr->line, 0, 64);
204 WMResizeWidget(fPtr->line, PWIDTH, 2);
205 WMSetFrameRelief(fPtr->line, WRGroove);
207 fPtr->browser = WMCreateBrowser(fPtr->win);
208 WMSetBrowserAllowEmptySelection(fPtr->browser, True);
209 WMSetBrowserDelegate(fPtr->browser, &browserDelegate);
210 WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
211 WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr);
212 WMMoveWidget(fPtr->browser, 7, 72);
213 WMResizeWidget(fPtr->browser, PWIDTH - 14, 200);
214 WMHangData(fPtr->browser, fPtr);
216 fPtr->nameLabel = WMCreateLabel(fPtr->win);
217 WMMoveWidget(fPtr->nameLabel, 7, 282);
218 WMResizeWidget(fPtr->nameLabel, 55, 14);
219 WMSetLabelText(fPtr->nameLabel, _("Name:"));
221 fPtr->fileField = WMCreateTextField(fPtr->win);
222 WMMoveWidget(fPtr->fileField, 60, 278);
223 WMResizeWidget(fPtr->fileField, PWIDTH - 60 - 10, 24);
224 WMAddNotificationObserver(textEditedObserver, fPtr, WMTextDidEndEditingNotification, fPtr->fileField);
225 WMAddNotificationObserver(textChangedObserver, fPtr, WMTextDidChangeNotification, fPtr->fileField);
227 fPtr->okButton = WMCreateCommandButton(fPtr->win);
228 WMMoveWidget(fPtr->okButton, 245, 325);
229 WMResizeWidget(fPtr->okButton, 75, 28);
230 WMSetButtonText(fPtr->okButton, _("OK"));
231 WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
232 WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
233 WMSetButtonImagePosition(fPtr->okButton, WIPRight);
234 WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
236 fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
237 WMMoveWidget(fPtr->cancelButton, 165, 325);
238 WMResizeWidget(fPtr->cancelButton, 75, 28);
239 WMSetButtonText(fPtr->cancelButton, _("Cancel"));
240 WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
242 fPtr->trashcanButton = WMCreateCommandButton(fPtr->win);
243 WMMoveWidget(fPtr->trashcanButton, 7, 325);
244 WMResizeWidget(fPtr->trashcanButton, 28, 28);
245 WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly);
246 WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon);
247 WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon);
248 WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr);
250 fPtr->createDirButton = WMCreateCommandButton(fPtr->win);
251 WMMoveWidget(fPtr->createDirButton, 37, 325);
252 WMResizeWidget(fPtr->createDirButton, 28, 28);
253 WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly);
254 WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon);
255 WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon);
256 WMSetButtonAction(fPtr->createDirButton, createDir, fPtr);
258 fPtr->homeButton = WMCreateCommandButton(fPtr->win);
259 WMMoveWidget(fPtr->homeButton, 67, 325);
260 WMResizeWidget(fPtr->homeButton, 28, 28);
261 WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
262 WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
263 WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon);
264 WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
266 fPtr->disketteButton = WMCreateCommandButton(fPtr->win);
267 WMMoveWidget(fPtr->disketteButton, 97, 325);
268 WMResizeWidget(fPtr->disketteButton, 28, 28);
269 WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly);
270 WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon);
271 WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon);
272 WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr);
274 fPtr->unmountButton = WMCreateCommandButton(fPtr->win);
275 WMMoveWidget(fPtr->unmountButton, 127, 325);
276 WMResizeWidget(fPtr->unmountButton, 28, 28);
277 WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly);
278 WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon);
279 WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon);
280 WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr);
281 WMSetButtonEnabled(fPtr->unmountButton, False);
283 WMRealizeWidget(fPtr->win);
284 WMMapSubwidgets(fPtr->win);
286 WMSetFocusToWidget(fPtr->fileField);
287 WMSetTextFieldCursorPosition(fPtr->fileField, 0);
289 WMLoadBrowserColumnZero(fPtr->browser);
291 WMSetWindowInitialPosition(fPtr->win,
292 (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win)) / 2,
293 (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win)) / 2);
295 fPtr->flags.canChooseFiles = 1;
296 fPtr->flags.canChooseDirectories = 1;
297 fPtr->flags.autoCompletion = 1;
299 return fPtr;
302 WMOpenPanel *WMGetOpenPanel(WMScreen * scrPtr)
304 WMFilePanel *panel;
306 if (scrPtr->sharedOpenPanel)
307 return scrPtr->sharedOpenPanel;
309 panel = makeFilePanel(scrPtr, "openFilePanel", _("Open"));
310 panel->flags.fileMustExist = 1;
311 panel->flags.panelType = WP_OPEN;
313 scrPtr->sharedOpenPanel = panel;
315 return panel;
318 WMSavePanel *WMGetSavePanel(WMScreen * scrPtr)
320 WMFilePanel *panel;
322 if (scrPtr->sharedSavePanel)
323 return scrPtr->sharedSavePanel;
325 panel = makeFilePanel(scrPtr, "saveFilePanel", _("Save"));
326 panel->flags.fileMustExist = 0;
327 panel->flags.panelType = WP_SAVE;
329 scrPtr->sharedSavePanel = panel;
331 return panel;
334 void WMFreeFilePanel(WMFilePanel * panel)
336 if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) {
337 WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
339 if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
340 WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
342 WMRemoveNotificationObserver(panel);
343 WMUnmapWidget(panel->win);
344 WMDestroyWidget(panel->win);
345 wfree(panel);
349 WMRunModalFilePanelForDirectory(WMFilePanel * panel, WMWindow * owner, char *path, char *name, char **fileTypes)
351 WMScreen *scr = WMWidgetScreen(panel->win);
353 if (name && !owner) {
354 WMSetWindowTitle(panel->win, name);
357 WMChangePanelOwner(panel->win, owner);
359 WMSetFilePanelDirectory(panel, path);
361 switch (panel->flags.panelType) {
362 case WP_OPEN:
363 if (fileTypes)
364 panel->flags.filtered = 1;
365 panel->fileTypes = fileTypes;
366 if (name == NULL)
367 name = _("Open");
368 break;
369 case WP_SAVE:
370 panel->fileTypes = NULL;
371 panel->flags.filtered = 0;
372 if (name == NULL)
373 name = _("Save");
374 break;
375 default:
376 break;
379 WMSetLabelText(panel->titleLabel, name);
381 WMMapWidget(panel->win);
383 WMRunModalLoop(scr, W_VIEW(panel->win));
385 /* Must withdraw window because the next time we map
386 * it, it might have a different transient owner.
388 WMCloseWindow(panel->win);
390 return (panel->flags.canceled ? False : True);
393 void WMSetFilePanelDirectory(WMFilePanel * panel, char *path)
395 WMList *list;
396 WMListItem *item;
397 int col;
398 char *rest;
400 rest = WMSetBrowserPath(panel->browser, path);
401 if (strcmp(path, "/") == 0)
402 rest = NULL;
404 col = WMGetBrowserSelectedColumn(panel->browser);
405 list = WMGetBrowserListInColumn(panel->browser, col);
406 if (list && (item = WMGetListSelectedItem(list))) {
407 if (item->isBranch) {
408 WMSetTextFieldText(panel->fileField, rest);
409 } else {
410 WMSetTextFieldText(panel->fileField, item->text);
412 } else {
413 WMSetTextFieldText(panel->fileField, rest);
417 void WMSetFilePanelCanChooseDirectories(WMFilePanel * panel, Bool flag)
419 panel->flags.canChooseDirectories = ((flag == 0) ? 0 : 1);
422 void WMSetFilePanelCanChooseFiles(WMFilePanel * panel, Bool flag)
424 panel->flags.canChooseFiles = ((flag == 0) ? 0 : 1);
427 void WMSetFilePanelAutoCompletion(WMFilePanel * panel, Bool flag)
429 panel->flags.autoCompletion = ((flag == 0) ? 0 : 1);
432 char *WMGetFilePanelFileName(WMFilePanel * panel)
434 return getCurrentFileName(panel);
437 void WMSetFilePanelAccessoryView(WMFilePanel * panel, WMView * view)
439 WMView *v;
441 panel->accessoryView = view;
443 v = WMWidgetView(panel->win);
445 W_ReparentView(view, v, 0, 0);
447 W_MoveView(view, (v->size.width - v->size.width) / 2, 300);
450 WMView *WMGetFilePanelAccessoryView(WMFilePanel * panel)
452 return panel->accessoryView;
455 static char *get_name_from_path(char *path)
457 int size;
459 assert(path != NULL);
461 size = strlen(path);
463 /* remove trailing / */
464 while (size > 0 && path[size - 1] == '/')
465 size--;
466 /* directory was root */
467 if (size == 0)
468 return wstrdup("/");
470 while (size > 0 && path[size - 1] != '/')
471 size--;
473 return wstrdup(&(path[size]));
476 static int filterFileName(WMFilePanel * panel, char *file, Bool isDirectory)
478 return True;
481 #define CAST(item) (*((WMListItem**)item))
482 static int comparer(const void *a, const void *b)
484 if (CAST(a)->isBranch == CAST(b)->isBranch)
485 return (strcmp(CAST(a)->text, CAST(b)->text));
486 if (CAST(a)->isBranch)
487 return (-1);
488 return (1);
491 #undef CAST
493 static void listDirectoryOnColumn(WMFilePanel * panel, int column, char *path)
495 WMBrowser *bPtr = panel->browser;
496 struct dirent *dentry;
497 DIR *dir;
498 struct stat stat_buf;
499 char pbuf[PATH_MAX + 16];
500 char *name;
502 assert(column >= 0);
503 assert(path != NULL);
505 /* put directory name in the title */
506 name = get_name_from_path(path);
507 WMSetBrowserColumnTitle(bPtr, column, name);
508 wfree(name);
510 dir = opendir(path);
512 if (!dir) {
513 #ifdef VERBOSE
514 printf(_("WINGs: could not open directory %s\n"), path);
515 #endif
516 return;
519 /* list contents in the column */
520 while ((dentry = readdir(dir))) {
521 if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0)
522 continue;
524 strcpy(pbuf, path);
525 if (strcmp(path, "/") != 0)
526 strcat(pbuf, "/");
527 strcat(pbuf, dentry->d_name);
529 if (stat(pbuf, &stat_buf) != 0) {
530 #ifdef VERBOSE
531 printf(_("WINGs: could not stat %s\n"), pbuf);
532 #endif
533 continue;
534 } else {
535 int isDirectory;
537 isDirectory = S_ISDIR(stat_buf.st_mode);
539 if (filterFileName(panel, dentry->d_name, isDirectory))
540 WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory);
543 WMSortBrowserColumnWithComparer(bPtr, column, comparer);
545 closedir(dir);
548 static void fillColumn(WMBrowserDelegate * self, WMBrowser * bPtr, int column, WMList * list)
550 char *path;
551 WMFilePanel *panel;
553 if (column > 0) {
554 path = WMGetBrowserPathToColumn(bPtr, column - 1);
555 } else {
556 path = wstrdup("/");
559 panel = WMGetHangedData(bPtr);
560 listDirectoryOnColumn(panel, column, path);
561 wfree(path);
564 static void browserDClick(WMBrowser * bPtr, WMFilePanel * panel)
566 WMPerformButtonClick(panel->okButton);
569 static void browserClick(WMBrowser * bPtr, WMFilePanel * panel)
571 int col = WMGetBrowserSelectedColumn(bPtr);
572 WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
574 if (!item || item->isBranch)
575 WMSetTextFieldText(panel->fileField, NULL);
576 else {
577 WMSetTextFieldText(panel->fileField, item->text);
581 static void showError(WMScreen * scr, WMWindow * owner, char *s, char *file)
583 char *errStr;
585 if (file) {
586 errStr = wmalloc(strlen(file) + strlen(s));
587 sprintf(errStr, s, file);
588 } else {
589 errStr = wstrdup(s);
591 WMRunAlertPanel(scr, owner, _("Error"), errStr, _("OK"), NULL, NULL);
592 wfree(errStr);
595 static void createDir(WMButton * bPre, WMFilePanel * panel)
597 char *dirName, *directory, *file, *s;
598 WMScreen *scr = WMWidgetScreen(panel->win);
600 dirName = WMRunInputPanel(scr, panel->win, _("Create Directory"),
601 _("Enter directory name"), "", _("OK"), _("Cancel"));
602 if (!dirName)
603 return;
605 directory = getCurrentFileName(panel);
606 s = strrchr(directory, '/');
607 if (s)
608 s[1] = 0;
610 if (dirName[0] == '/') {
611 directory[0] = 0;
612 } else {
613 while ((s = strstr(directory, "//"))) {
614 int i;
615 for (i = 2; s[i] == '/'; i++) ;
616 strcpy(s, &s[i - 1]);
618 if ((s = strrchr(directory, '/')) && !s[1])
619 s[0] = 0;
621 while ((s = strstr(dirName, "//"))) {
622 int i;
623 for (i = 2; s[i] == '/'; i++) ;
624 strcpy(s, &s[i - 1]);
626 if ((s = strrchr(dirName, '/')) && !s[1])
627 s[0] = 0;
629 file = wmalloc(strlen(dirName) + strlen(directory) + 4);
630 sprintf(file, "%s/%s", directory, dirName);
631 while ((s = strstr(file, "//"))) {
632 int i;
633 for (i = 2; s[i] == '/'; i++) ;
634 strcpy(s, &s[i - 1]);
637 if (mkdir(file, 0xfff) != 0) {
638 switch (errno) {
639 case EACCES:
640 showError(scr, panel->win, _("Permission denied."), NULL);
641 break;
642 case EEXIST:
643 showError(scr, panel->win, _("'%s' already exists."), file);
644 break;
645 case ENOENT:
646 showError(scr, panel->win, _("Path does not exist."), NULL);
648 } else
649 WMSetFilePanelDirectory(panel, file);
651 wfree(dirName);
652 wfree(directory);
653 wfree(file);
656 static void deleteFile(WMButton * bPre, WMFilePanel * panel)
658 char *file;
659 char *buffer, *s;
660 struct stat filestat;
661 WMScreen *scr = WMWidgetScreen(panel->win);
663 file = getCurrentFileName(panel);
665 while ((s = strstr(file, "//"))) {
666 int i;
667 for (i = 2; s[i] == '/'; i++) ;
668 strcpy(s, &s[i - 1]);
670 if (strlen(file) > 1 && (s = strrchr(file, '/')) && !s[1])
671 s[0] = 0;
673 if (stat(file, &filestat)) {
674 switch (errno) {
675 case ENOENT:
676 showError(scr, panel->win, _("'%s' does not exist."), file);
677 break;
678 case EACCES:
679 showError(scr, panel->win, _("Permission denied."), NULL);
680 break;
681 case ENOMEM:
682 showError(scr, panel->win, _("Insufficient memory available."), NULL);
683 break;
684 case EROFS:
685 showError(scr, panel->win, _("'%s' is on a read-only filesystem."), file);
686 break;
687 default:
688 showError(scr, panel->win, _("Can not delete '%s'."), file);
690 wfree(file);
691 return;
692 } else if (S_ISDIR(filestat.st_mode)) {
693 int len = strlen(file) + 20;
694 buffer = wmalloc(len);
695 snprintf(buffer, len, _("Delete directory %s ?"), file);
696 } else {
697 int len = strlen(file) + 15;
698 buffer = wmalloc(len);
699 snprintf(buffer, len, _("Delete file %s ?"), file);
702 if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
703 _("Warning"), buffer, _("OK"), _("Cancel"), NULL)) {
704 if (S_ISDIR(filestat.st_mode)) {
705 if (rmdir(file) != 0) {
706 switch (errno) {
707 case EACCES:
708 showError(scr, panel->win, _("Permission denied."), NULL);
709 break;
710 case ENOENT:
711 showError(scr, panel->win, _("Directory '%s' does not exist."), file);
712 break;
713 case ENOTEMPTY:
714 showError(scr, panel->win, _("Directory '%s' is not empty."), file);
715 break;
716 case EBUSY:
717 showError(scr, panel->win, _("Directory '%s' is busy."), file);
718 break;
719 default:
720 showError(scr, panel->win, _("Can not delete '%s'."), file);
722 } else {
723 char *s = strrchr(file, '/');
724 if (s)
725 s[0] = 0;
726 WMSetFilePanelDirectory(panel, file);
728 } else if (remove(file) != 0) {
729 switch (errno) {
730 case EISDIR:
731 showError(scr, panel->win, _("'%s' is a directory."), file);
732 break;
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, _("Insufficient memory available."), NULL);
741 break;
742 case EROFS:
743 showError(scr, panel->win, _("'%s' is on a read-only filesystem."), file);
744 break;
745 default:
746 showError(scr, panel->win, _("Can not delete '%s'."), file);
748 } else {
749 char *s = strrchr(file, '/');
750 if (s)
751 s[1] = 0;
752 WMSetFilePanelDirectory(panel, file);
755 wfree(buffer);
756 wfree(file);
759 static void goUnmount(WMButton * bPtr, WMFilePanel * panel)
763 static void goFloppy(WMButton * bPtr, WMFilePanel * panel)
765 struct stat filestat;
766 WMScreen *scr = WMWidgetScreen(panel->win);
768 if (stat(WINGsConfiguration.floppyPath, &filestat)) {
769 showError(scr, panel->win, _("An error occured browsing '%s'."), WINGsConfiguration.floppyPath);
770 return;
771 } else if (!S_ISDIR(filestat.st_mode)) {
772 showError(scr, panel->win, _("'%s' is not a directory."), WINGsConfiguration.floppyPath);
773 return;
776 WMSetFilePanelDirectory(panel, WINGsConfiguration.floppyPath);
779 static void goHome(WMButton * bPtr, WMFilePanel * panel)
781 char *home;
783 /* home is statically allocated. Don't free it! */
784 home = wgethomedir();
785 if (!home)
786 return;
788 WMSetFilePanelDirectory(panel, home);
791 static void handleEvents(XEvent * event, void *data)
793 W_FilePanel *pPtr = (W_FilePanel *) data;
794 W_View *view = WMWidgetView(pPtr->win);
796 if (event->type == ConfigureNotify) {
797 if (event->xconfigure.width != view->size.width || event->xconfigure.height != view->size.height) {
798 unsigned int newWidth = event->xconfigure.width;
799 unsigned int newHeight = event->xconfigure.height;
800 int newColumnCount;
802 W_ResizeView(view, newWidth, newHeight);
803 WMResizeWidget(pPtr->line, newWidth, 2);
804 WMResizeWidget(pPtr->browser, newWidth - 14, newHeight - (PHEIGHT - 200));
805 WMResizeWidget(pPtr->fileField, newWidth - 60 - 10, 24);
806 WMMoveWidget(pPtr->nameLabel, 7, newHeight - (PHEIGHT - 282));
807 WMMoveWidget(pPtr->fileField, 60, newHeight - (PHEIGHT - 278));
808 WMMoveWidget(pPtr->okButton, newWidth - (PWIDTH - 245), newHeight - (PHEIGHT - 325));
809 WMMoveWidget(pPtr->cancelButton, newWidth - (PWIDTH - 165), newHeight - (PHEIGHT - 325));
811 WMMoveWidget(pPtr->trashcanButton, 7, newHeight - (PHEIGHT - 325));
812 WMMoveWidget(pPtr->createDirButton, 37, newHeight - (PHEIGHT - 325));
813 WMMoveWidget(pPtr->homeButton, 67, newHeight - (PHEIGHT - 325));
814 WMMoveWidget(pPtr->disketteButton, 97, newHeight - (PHEIGHT - 325));
815 WMMoveWidget(pPtr->unmountButton, 127, newHeight - (PHEIGHT - 325));
817 newColumnCount = (newWidth - 14) / 140;
818 WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount);
823 static char *getCurrentFileName(WMFilePanel * panel)
825 char *path;
826 char *file;
827 char *tmp;
828 int len;
830 path = WMGetBrowserPath(panel->browser);
832 len = strlen(path);
833 if (path[len - 1] == '/') {
834 file = WMGetTextFieldText(panel->fileField);
835 tmp = wmalloc(strlen(path) + strlen(file) + 8);
836 if (file[0] != '/') {
837 strcpy(tmp, path);
838 strcat(tmp, file);
839 } else
840 strcpy(tmp, file);
842 wfree(file);
843 wfree(path);
844 return tmp;
845 } else {
846 return path;
850 static Bool validOpenFile(WMFilePanel * panel)
852 WMListItem *item;
853 int col, haveFile = 0;
854 char *file = WMGetTextFieldText(panel->fileField);
856 if (file[0] != '\0')
857 haveFile = 1;
858 wfree(file);
860 col = WMGetBrowserSelectedColumn(panel->browser);
861 item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
862 if (item) {
863 if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile)
864 return False;
865 else if (!item->isBranch && !panel->flags.canChooseFiles)
866 return False;
867 else
868 return True;
869 } else {
870 /* we compute for / here */
871 if (!panel->flags.canChooseDirectories && !haveFile)
872 return False;
873 else
874 return True;
876 return True;
879 static void buttonClick(WMButton * bPtr, WMFilePanel * panel)
881 WMRange range;
883 if (bPtr == panel->okButton) {
884 if (!validOpenFile(panel))
885 return;
886 if (panel->flags.fileMustExist) {
887 char *file;
889 file = getCurrentFileName(panel);
890 if (access(file, F_OK) != 0) {
891 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
892 _("Error"), _("File does not exist."), _("OK"), NULL, NULL);
893 wfree(file);
894 return;
896 wfree(file);
898 panel->flags.canceled = 0;
899 } else
900 panel->flags.canceled = 1;
902 range.count = range.position = 0;
903 WMSelectTextFieldRange(panel->fileField, range);
904 WMBreakModalLoop(WMWidgetScreen(bPtr));