Rename libwutil1 to libwutil2
[wmaker-crm.git] / WINGs / wfilepanel.c
blobcf0af451a1cc35d3e6ebfe2467a5a0764525d283
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 normalizePath(char *s);
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);
88 static WMBrowserDelegate browserDelegate = {
89 NULL, /* data */
90 fillColumn, /* createRowsForColumn */
91 NULL, /* titleOfColumn */
92 NULL, /* didScroll */
93 NULL /* willScroll */
96 static int closestListItem(WMList * list, char *text, Bool exact)
98 WMListItem *item;
99 WMArray *items = WMGetListItems(list);
100 int i, len = strlen(text);
102 if (len == 0)
103 return -1;
105 for (i = 0; i < WMGetArrayItemCount(items); i++) {
106 item = WMGetFromArray(items, i);
107 if (strlen(item->text) >= len &&
108 ((exact && strcmp(item->text, text) == 0) ||
109 (!exact && strncmp(item->text, text, len) == 0))) {
110 return i;
114 return -1;
117 static void textChangedObserver(void *observerData, WMNotification * notification)
119 W_FilePanel *panel = (W_FilePanel *) observerData;
120 char *text;
121 WMList *list;
122 int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
123 int i;
124 uintptr_t textEvent;
126 if (!(list = WMGetBrowserListInColumn(panel->browser, col)))
127 return;
129 text = WMGetTextFieldText(panel->fileField);
130 textEvent = (uintptr_t)WMGetNotificationClientData(notification);
132 if (panel->flags.autoCompletion && textEvent != WMDeleteTextEvent)
133 i = closestListItem(list, text, False);
134 else
135 i = closestListItem(list, text, True);
137 WMSelectListItem(list, i);
138 if (i >= 0 && panel->flags.autoCompletion) {
139 WMListItem *item = WMGetListItem(list, i);
140 int textLen = strlen(text), itemTextLen = strlen(item->text);
141 int visibleItems = WMWidgetHeight(list) / WMGetListItemHeight(list);
143 WMSetListPosition(list, i - visibleItems / 2);
145 if (textEvent != WMDeleteTextEvent) {
146 WMRange range;
148 WMInsertTextFieldText(panel->fileField, &item->text[textLen], textLen);
149 range.position = textLen;
150 range.count = itemTextLen - textLen;
151 WMSelectTextFieldRange(panel->fileField, range);
152 /*WMSetTextFieldCursorPosition(panel->fileField, itemTextLen); */
156 wfree(text);
159 static void textEditedObserver(void *observerData, WMNotification * notification)
161 W_FilePanel *panel = (W_FilePanel *) observerData;
163 if ((uintptr_t)WMGetNotificationClientData(notification) == WMReturnTextMovement) {
164 WMPerformButtonClick(panel->okButton);
168 static WMFilePanel *makeFilePanel(WMScreen * scrPtr, char *name, char *title)
170 WMFilePanel *fPtr;
171 WMFont *largeFont;
172 WMPixmap *icon;
174 fPtr = wmalloc(sizeof(WMFilePanel));
176 fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask | WMResizableWindowMask);
177 WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
178 WMSetWindowTitle(fPtr->win, "");
180 WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask, handleEvents, fPtr);
181 WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT);
183 fPtr->iconLabel = WMCreateLabel(fPtr->win);
184 WMResizeWidget(fPtr->iconLabel, 64, 64);
185 WMMoveWidget(fPtr->iconLabel, 0, 0);
186 WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
187 icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor *) NULL);
188 if (icon) {
189 WMSetLabelImage(fPtr->iconLabel, icon);
190 WMReleasePixmap(icon);
191 } else {
192 WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIconPixmap);
195 fPtr->titleLabel = WMCreateLabel(fPtr->win);
196 WMResizeWidget(fPtr->titleLabel, PWIDTH - 64, 64);
197 WMMoveWidget(fPtr->titleLabel, 64, 0);
198 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
199 WMSetLabelFont(fPtr->titleLabel, largeFont);
200 WMReleaseFont(largeFont);
201 WMSetLabelText(fPtr->titleLabel, title);
203 fPtr->line = WMCreateFrame(fPtr->win);
204 WMMoveWidget(fPtr->line, 0, 64);
205 WMResizeWidget(fPtr->line, PWIDTH, 2);
206 WMSetFrameRelief(fPtr->line, WRGroove);
208 fPtr->browser = WMCreateBrowser(fPtr->win);
209 WMSetBrowserAllowEmptySelection(fPtr->browser, True);
210 WMSetBrowserDelegate(fPtr->browser, &browserDelegate);
211 WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
212 WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr);
213 WMMoveWidget(fPtr->browser, 7, 72);
214 WMResizeWidget(fPtr->browser, PWIDTH - 14, 200);
215 WMHangData(fPtr->browser, fPtr);
217 fPtr->nameLabel = WMCreateLabel(fPtr->win);
218 WMMoveWidget(fPtr->nameLabel, 7, 282);
219 WMResizeWidget(fPtr->nameLabel, 55, 14);
220 WMSetLabelText(fPtr->nameLabel, _("Name:"));
222 fPtr->fileField = WMCreateTextField(fPtr->win);
223 WMMoveWidget(fPtr->fileField, 60, 278);
224 WMResizeWidget(fPtr->fileField, PWIDTH - 60 - 10, 24);
225 WMAddNotificationObserver(textEditedObserver, fPtr, WMTextDidEndEditingNotification, fPtr->fileField);
226 WMAddNotificationObserver(textChangedObserver, fPtr, WMTextDidChangeNotification, fPtr->fileField);
228 fPtr->okButton = WMCreateCommandButton(fPtr->win);
229 WMMoveWidget(fPtr->okButton, 245, 325);
230 WMResizeWidget(fPtr->okButton, 75, 28);
231 WMSetButtonText(fPtr->okButton, _("OK"));
232 WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
233 WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
234 WMSetButtonImagePosition(fPtr->okButton, WIPRight);
235 WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
237 fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
238 WMMoveWidget(fPtr->cancelButton, 165, 325);
239 WMResizeWidget(fPtr->cancelButton, 75, 28);
240 WMSetButtonText(fPtr->cancelButton, _("Cancel"));
241 WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
243 fPtr->trashcanButton = WMCreateCommandButton(fPtr->win);
244 WMMoveWidget(fPtr->trashcanButton, 7, 325);
245 WMResizeWidget(fPtr->trashcanButton, 28, 28);
246 WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly);
247 WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon);
248 WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon);
249 WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr);
251 fPtr->createDirButton = WMCreateCommandButton(fPtr->win);
252 WMMoveWidget(fPtr->createDirButton, 37, 325);
253 WMResizeWidget(fPtr->createDirButton, 28, 28);
254 WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly);
255 WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon);
256 WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon);
257 WMSetButtonAction(fPtr->createDirButton, createDir, fPtr);
259 fPtr->homeButton = WMCreateCommandButton(fPtr->win);
260 WMMoveWidget(fPtr->homeButton, 67, 325);
261 WMResizeWidget(fPtr->homeButton, 28, 28);
262 WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
263 WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
264 WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon);
265 WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
267 fPtr->disketteButton = WMCreateCommandButton(fPtr->win);
268 WMMoveWidget(fPtr->disketteButton, 97, 325);
269 WMResizeWidget(fPtr->disketteButton, 28, 28);
270 WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly);
271 WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon);
272 WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon);
273 WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr);
275 fPtr->unmountButton = WMCreateCommandButton(fPtr->win);
276 WMMoveWidget(fPtr->unmountButton, 127, 325);
277 WMResizeWidget(fPtr->unmountButton, 28, 28);
278 WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly);
279 WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon);
280 WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon);
281 WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr);
282 WMSetButtonEnabled(fPtr->unmountButton, False);
284 WMRealizeWidget(fPtr->win);
285 WMMapSubwidgets(fPtr->win);
287 WMSetFocusToWidget(fPtr->fileField);
288 WMSetTextFieldCursorPosition(fPtr->fileField, 0);
290 WMLoadBrowserColumnZero(fPtr->browser);
292 WMSetWindowInitialPosition(fPtr->win,
293 (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win)) / 2,
294 (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win)) / 2);
296 fPtr->flags.canChooseFiles = 1;
297 fPtr->flags.canChooseDirectories = 1;
298 fPtr->flags.autoCompletion = 1;
300 return fPtr;
303 WMOpenPanel *WMGetOpenPanel(WMScreen * scrPtr)
305 WMFilePanel *panel;
307 if (scrPtr->sharedOpenPanel)
308 return scrPtr->sharedOpenPanel;
310 panel = makeFilePanel(scrPtr, "openFilePanel", _("Open"));
311 panel->flags.fileMustExist = 1;
312 panel->flags.panelType = WP_OPEN;
314 scrPtr->sharedOpenPanel = panel;
316 return panel;
319 WMSavePanel *WMGetSavePanel(WMScreen * scrPtr)
321 WMFilePanel *panel;
323 if (scrPtr->sharedSavePanel)
324 return scrPtr->sharedSavePanel;
326 panel = makeFilePanel(scrPtr, "saveFilePanel", _("Save"));
327 panel->flags.fileMustExist = 0;
328 panel->flags.panelType = WP_SAVE;
330 scrPtr->sharedSavePanel = panel;
332 return panel;
335 void WMFreeFilePanel(WMFilePanel * panel)
337 if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) {
338 WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
340 if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
341 WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
343 WMRemoveNotificationObserver(panel);
344 WMUnmapWidget(panel->win);
345 WMDestroyWidget(panel->win);
346 wfree(panel);
350 WMRunModalFilePanelForDirectory(WMFilePanel * panel, WMWindow * owner, char *path, char *name, char **fileTypes)
352 WMScreen *scr = WMWidgetScreen(panel->win);
354 if (name && !owner) {
355 WMSetWindowTitle(panel->win, name);
358 WMChangePanelOwner(panel->win, owner);
360 WMSetFilePanelDirectory(panel, path);
362 switch (panel->flags.panelType) {
363 case WP_OPEN:
364 if (fileTypes)
365 panel->flags.filtered = 1;
366 panel->fileTypes = fileTypes;
367 if (name == NULL)
368 name = _("Open");
369 break;
370 case WP_SAVE:
371 panel->fileTypes = NULL;
372 panel->flags.filtered = 0;
373 if (name == NULL)
374 name = _("Save");
375 break;
376 default:
377 break;
380 WMSetLabelText(panel->titleLabel, name);
382 WMMapWidget(panel->win);
384 WMRunModalLoop(scr, W_VIEW(panel->win));
386 /* Must withdraw window because the next time we map
387 * it, it might have a different transient owner.
389 WMCloseWindow(panel->win);
391 return (panel->flags.canceled ? False : True);
394 void WMSetFilePanelDirectory(WMFilePanel * panel, char *path)
396 WMList *list;
397 WMListItem *item;
398 int col;
399 char *rest;
401 rest = WMSetBrowserPath(panel->browser, path);
402 if (strcmp(path, "/") == 0)
403 rest = NULL;
405 col = WMGetBrowserSelectedColumn(panel->browser);
406 list = WMGetBrowserListInColumn(panel->browser, col);
407 if (list && (item = WMGetListSelectedItem(list))) {
408 if (item->isBranch) {
409 WMSetTextFieldText(panel->fileField, rest);
410 } else {
411 WMSetTextFieldText(panel->fileField, item->text);
413 } else {
414 WMSetTextFieldText(panel->fileField, rest);
418 void WMSetFilePanelCanChooseDirectories(WMFilePanel * panel, Bool flag)
420 panel->flags.canChooseDirectories = ((flag == 0) ? 0 : 1);
423 void WMSetFilePanelCanChooseFiles(WMFilePanel * panel, Bool flag)
425 panel->flags.canChooseFiles = ((flag == 0) ? 0 : 1);
428 void WMSetFilePanelAutoCompletion(WMFilePanel * panel, Bool flag)
430 panel->flags.autoCompletion = ((flag == 0) ? 0 : 1);
433 char *WMGetFilePanelFileName(WMFilePanel * panel)
435 return getCurrentFileName(panel);
438 void WMSetFilePanelAccessoryView(WMFilePanel * panel, WMView * view)
440 WMView *v;
442 panel->accessoryView = view;
444 v = WMWidgetView(panel->win);
446 W_ReparentView(view, v, 0, 0);
448 W_MoveView(view, (v->size.width - v->size.width) / 2, 300);
451 WMView *WMGetFilePanelAccessoryView(WMFilePanel * panel)
453 return panel->accessoryView;
456 static char *get_name_from_path(char *path)
458 int size;
460 assert(path != NULL);
462 size = strlen(path);
464 /* remove trailing / */
465 while (size > 0 && path[size - 1] == '/')
466 size--;
467 /* directory was root */
468 if (size == 0)
469 return wstrdup("/");
471 while (size > 0 && path[size - 1] != '/')
472 size--;
474 return wstrdup(&(path[size]));
477 static int filterFileName(WMFilePanel * panel, char *file, Bool isDirectory)
479 return True;
482 #define CAST(item) (*((WMListItem**)item))
483 static int comparer(const void *a, const void *b)
485 if (CAST(a)->isBranch == CAST(b)->isBranch)
486 return (strcmp(CAST(a)->text, CAST(b)->text));
487 if (CAST(a)->isBranch)
488 return (-1);
489 return (1);
492 #undef CAST
494 static void listDirectoryOnColumn(WMFilePanel * panel, int column, char *path)
496 WMBrowser *bPtr = panel->browser;
497 struct dirent *dentry;
498 DIR *dir;
499 struct stat stat_buf;
500 char pbuf[PATH_MAX + 16];
501 char *name;
503 assert(column >= 0);
504 assert(path != NULL);
506 /* put directory name in the title */
507 name = get_name_from_path(path);
508 WMSetBrowserColumnTitle(bPtr, column, name);
509 wfree(name);
511 dir = opendir(path);
513 if (!dir) {
514 #ifdef VERBOSE
515 printf(_("WINGs: could not open directory %s\n"), path);
516 #endif
517 return;
520 /* list contents in the column */
521 while ((dentry = readdir(dir))) {
522 if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0)
523 continue;
525 strcpy(pbuf, path);
526 if (strcmp(path, "/") != 0)
527 strcat(pbuf, "/");
528 strcat(pbuf, dentry->d_name);
530 if (stat(pbuf, &stat_buf) != 0) {
531 #ifdef VERBOSE
532 printf(_("WINGs: could not stat %s\n"), pbuf);
533 #endif
534 continue;
535 } else {
536 int isDirectory;
538 isDirectory = S_ISDIR(stat_buf.st_mode);
540 if (filterFileName(panel, dentry->d_name, isDirectory))
541 WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory);
544 WMSortBrowserColumnWithComparer(bPtr, column, comparer);
546 closedir(dir);
549 static void fillColumn(WMBrowserDelegate * self, WMBrowser * bPtr, int column, WMList * list)
551 char *path;
552 WMFilePanel *panel;
554 if (column > 0) {
555 path = WMGetBrowserPathToColumn(bPtr, column - 1);
556 } else {
557 path = wstrdup("/");
560 panel = WMGetHangedData(bPtr);
561 listDirectoryOnColumn(panel, column, path);
562 wfree(path);
565 static void browserDClick(WMBrowser * bPtr, WMFilePanel * panel)
567 WMPerformButtonClick(panel->okButton);
570 static void browserClick(WMBrowser * bPtr, WMFilePanel * panel)
572 int col = WMGetBrowserSelectedColumn(bPtr);
573 WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
575 if (!item || item->isBranch)
576 WMSetTextFieldText(panel->fileField, NULL);
577 else {
578 WMSetTextFieldText(panel->fileField, item->text);
582 static void showError(WMScreen * scr, WMWindow * owner, char *s, char *file)
584 char *errStr;
586 if (file) {
587 errStr = wmalloc(strlen(file) + strlen(s));
588 sprintf(errStr, s, file);
589 } else {
590 errStr = wstrdup(s);
592 WMRunAlertPanel(scr, owner, _("Error"), errStr, _("OK"), NULL, NULL);
593 wfree(errStr);
596 static void createDir(WMButton * bPre, WMFilePanel * panel)
598 char *dirName, *directory, *file;
599 size_t slen;
600 WMScreen *scr = WMWidgetScreen(panel->win);
602 dirName = WMRunInputPanel(scr, panel->win, _("Create Directory"),
603 _("Enter directory name"), "", _("OK"), _("Cancel"));
604 if (!dirName)
605 return;
607 /* if `dirName' is an absolute path, don't mind `directory'.
608 * normalize as needed (possibly not needed at all?) */
609 normalizePath(dirName);
610 if (*dirName != '/') {
611 directory = getCurrentFileName(panel);
612 normalizePath(directory);
613 } else {
614 directory = NULL;
617 slen = strlen(dirName) + (directory ? strlen(directory) + 1 /* "/" */ : 0) + 1 /* NULL */;
618 file = wmalloc(slen);
620 if (directory) {
621 strncpy(file, directory, slen - 1);
622 strncat(file, "/", slen - strlen(file));
625 strncat(file, dirName, slen - strlen(file));
627 if (mkdir(file, 00777) != 0) {
628 #define __msgbufsize__ 512
629 char *buffer = wmalloc(__msgbufsize__);
630 snprintf(buffer, __msgbufsize__, _("Can not create %s: %s"), file, strerror(errno));
631 showError(scr, panel->win, buffer, NULL);
632 wfree(buffer);
633 #undef __msgbufsize__
634 } else {
635 WMSetFilePanelDirectory(panel, file);
638 if (dirName)
639 wfree(dirName);
640 if (directory)
641 wfree(directory);
642 if (file)
643 wfree(file);
647 *----------------------------------------------------------------------
648 * normalizePath--
649 * Remove multiple consecutive and any trailing slashes from
650 * a path.
651 *----------------------------------------------------------------------
653 static void normalizePath(char *s)
655 int i, j, found;
657 found = 0;
658 for (i = 0; s[i]; !found && i++) {
659 found = 0;
660 if (s[i] == '/' && s[i+1] == '/') {
661 int nslash = 1;
662 found = 1;
663 i++;
664 while (s[i+nslash] == '/')
665 nslash++;
666 for (j = 0; s[i+j+nslash]; j++)
667 s[i+j] = s[i+j+nslash];
668 s[i+j] = '\0';
671 if (i > 1 && s[--i] == '/')
672 s[i] = '\0';
676 static void deleteFile(WMButton * bPre, WMFilePanel * panel)
678 char *file, *buffer;
679 struct stat filestat;
680 WMScreen *scr = WMWidgetScreen(panel->win);
681 #define __msgbufsize__ 512
683 buffer = wmalloc(__msgbufsize__);
684 file = getCurrentFileName(panel);
685 normalizePath(file);
687 if (stat(file, &filestat) == -1) {
688 snprintf(buffer, __msgbufsize__, _("Can not find %s: %s"), file, strerror(errno));
689 showError(scr, panel->win, buffer, NULL);
690 goto out;
693 snprintf(buffer, __msgbufsize__, _("Delete %s %s?"),
694 S_ISDIR(filestat.st_mode) ? _("directory") : _("file"), file);
696 if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
697 _("Warning"), buffer, _("OK"), _("Cancel"), NULL)) {
699 if (remove(file) == -1) {
700 snprintf(buffer, __msgbufsize__, _("Removing %s failed: %s"), file, strerror(errno));
701 showError(scr, panel->win, buffer, NULL);
702 } else {
703 char *s = strrchr(file, '/');
704 if (s)
705 s[0] = 0;
706 WMSetFilePanelDirectory(panel, file);
710 out:
711 if (buffer)
712 wfree(buffer);
713 if (file)
714 wfree(file);
715 #undef __msgbufsize__
718 static void goUnmount(WMButton * bPtr, WMFilePanel * panel)
722 static void goFloppy(WMButton * bPtr, WMFilePanel * panel)
724 struct stat filestat;
725 WMScreen *scr = WMWidgetScreen(panel->win);
727 if (stat(WINGsConfiguration.floppyPath, &filestat)) {
728 showError(scr, panel->win, _("An error occured browsing '%s'."), WINGsConfiguration.floppyPath);
729 return;
730 } else if (!S_ISDIR(filestat.st_mode)) {
731 showError(scr, panel->win, _("'%s' is not a directory."), WINGsConfiguration.floppyPath);
732 return;
735 WMSetFilePanelDirectory(panel, WINGsConfiguration.floppyPath);
738 static void goHome(WMButton * bPtr, WMFilePanel * panel)
740 char *home;
742 /* home is statically allocated. Don't free it! */
743 home = wgethomedir();
744 if (!home)
745 return;
747 WMSetFilePanelDirectory(panel, home);
750 static void handleEvents(XEvent * event, void *data)
752 W_FilePanel *pPtr = (W_FilePanel *) data;
753 W_View *view = WMWidgetView(pPtr->win);
755 if (event->type == ConfigureNotify) {
756 if (event->xconfigure.width != view->size.width || event->xconfigure.height != view->size.height) {
757 unsigned int newWidth = event->xconfigure.width;
758 unsigned int newHeight = event->xconfigure.height;
759 int newColumnCount;
761 W_ResizeView(view, newWidth, newHeight);
762 WMResizeWidget(pPtr->line, newWidth, 2);
763 WMResizeWidget(pPtr->browser, newWidth - 14, newHeight - (PHEIGHT - 200));
764 WMResizeWidget(pPtr->fileField, newWidth - 60 - 10, 24);
765 WMMoveWidget(pPtr->nameLabel, 7, newHeight - (PHEIGHT - 282));
766 WMMoveWidget(pPtr->fileField, 60, newHeight - (PHEIGHT - 278));
767 WMMoveWidget(pPtr->okButton, newWidth - (PWIDTH - 245), newHeight - (PHEIGHT - 325));
768 WMMoveWidget(pPtr->cancelButton, newWidth - (PWIDTH - 165), newHeight - (PHEIGHT - 325));
770 WMMoveWidget(pPtr->trashcanButton, 7, newHeight - (PHEIGHT - 325));
771 WMMoveWidget(pPtr->createDirButton, 37, newHeight - (PHEIGHT - 325));
772 WMMoveWidget(pPtr->homeButton, 67, newHeight - (PHEIGHT - 325));
773 WMMoveWidget(pPtr->disketteButton, 97, newHeight - (PHEIGHT - 325));
774 WMMoveWidget(pPtr->unmountButton, 127, newHeight - (PHEIGHT - 325));
776 newColumnCount = (newWidth - 14) / 140;
777 WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount);
782 static char *getCurrentFileName(WMFilePanel * panel)
784 char *path;
785 char *file;
786 char *tmp;
787 int len;
789 path = WMGetBrowserPath(panel->browser);
791 len = strlen(path);
792 if (path[len - 1] == '/') {
793 file = WMGetTextFieldText(panel->fileField);
794 tmp = wmalloc(strlen(path) + strlen(file) + 8);
795 if (file[0] != '/') {
796 strcpy(tmp, path);
797 strcat(tmp, file);
798 } else
799 strcpy(tmp, file);
801 wfree(file);
802 wfree(path);
803 return tmp;
804 } else {
805 return path;
809 static Bool validOpenFile(WMFilePanel * panel)
811 WMListItem *item;
812 int col, haveFile = 0;
813 char *file = WMGetTextFieldText(panel->fileField);
815 if (file[0] != '\0')
816 haveFile = 1;
817 wfree(file);
819 col = WMGetBrowserSelectedColumn(panel->browser);
820 item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
821 if (item) {
822 if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile)
823 return False;
824 else if (!item->isBranch && !panel->flags.canChooseFiles)
825 return False;
826 else
827 return True;
828 } else {
829 /* we compute for / here */
830 if (!panel->flags.canChooseDirectories && !haveFile)
831 return False;
832 else
833 return True;
835 return True;
838 static void buttonClick(WMButton * bPtr, WMFilePanel * panel)
840 WMRange range;
842 if (bPtr == panel->okButton) {
843 if (!validOpenFile(panel))
844 return;
845 if (panel->flags.fileMustExist) {
846 char *file;
848 file = getCurrentFileName(panel);
849 if (access(file, F_OK) != 0) {
850 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
851 _("Error"), _("File does not exist."), _("OK"), NULL, NULL);
852 wfree(file);
853 return;
855 wfree(file);
857 panel->flags.canceled = 0;
858 } else
859 panel->flags.canceled = 1;
861 range.count = range.position = 0;
862 WMSelectTextFieldRange(panel->fileField, range);
863 WMBreakModalLoop(WMWidgetScreen(bPtr));