Fixed some problems in 0.60.0
[wmaker-crm.git] / WINGs / wfilepanel.c
blobb95b7492dda6cd25ca0296153ea812b2f6fe5850
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 typedef struct W_FilePanel {
16 WMWindow *win;
18 WMLabel *iconLabel;
19 WMLabel *titleLabel;
21 WMFrame *line;
23 WMLabel *nameLabel;
24 WMBrowser *browser;
26 WMButton *okButton;
27 WMButton *cancelButton;
29 WMButton *homeButton;
30 WMButton *trashcanButton;
31 WMButton *disketteButton;
33 WMView *accessoryView;
35 WMTextField *fileField;
37 char **fileTypes;
39 struct {
40 unsigned int canExit:1;
41 unsigned int canceled:1; /* clicked on cancel */
42 unsigned int done:1;
43 unsigned int filtered:1;
44 unsigned int canChooseFiles:1;
45 unsigned int canChooseDirectories:1;
46 unsigned int autoCompletion:1;
47 unsigned int showAllFiles:1;
48 unsigned int canFreeFileTypes:1;
49 unsigned int fileMustExist:1;
50 unsigned int panelType:1;
51 } flags;
52 } W_FilePanel;
55 /* Type of panel */
56 #define WP_OPEN 0
57 #define WP_SAVE 1
59 #define PWIDTH 320
60 #define PHEIGHT 360
62 static void listDirectoryOnColumn(WMFilePanel *panel, int column, char *path);
63 static void browserClick();
64 static void browserDClick();
66 static void fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column,
67 WMList *list);
69 static void deleteFile();
71 static void goHome();
73 static void goFloppy();
75 static void buttonClick();
77 static char *getCurrentFileName(WMFilePanel *panel);
79 static void handleEvents(XEvent *event, void *data);
83 static WMBrowserDelegate browserDelegate = {
84 NULL, /* data */
85 fillColumn, /* createRowsForColumn */
86 NULL, /* titleOfColumn */
87 NULL, /* didScroll */
88 NULL /* willScroll */
92 static int
93 closestListItem(WMList *list, char *text, Bool exact)
95 WMListItem *item = WMGetListItem(list, 0);
96 int i = 0;
97 int len = strlen(text);
99 if (len==0)
100 return -1;
102 while (item) {
103 if (strlen(item->text) >= len &&
104 ((exact && strcmp(item->text, text)==0) ||
105 (!exact && strncmp(item->text, text, len)==0))) {
106 return i;
108 item = item->nextPtr;
109 i++;
111 return -1;
115 static void
116 textChangedObserver(void *observerData, WMNotification *notification)
118 W_FilePanel *panel = (W_FilePanel*)observerData;
119 char *text;
120 WMList *list;
121 int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
122 int i, textEvent;
124 if (!(list = WMGetBrowserListInColumn(panel->browser, col)))
125 return;
127 text = WMGetTextFieldText(panel->fileField);
128 textEvent = (int)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],
147 textLen);
148 WMSetTextFieldCursorPosition(panel->fileField, itemTextLen);
149 range.position = textLen;
150 range.count = itemTextLen - textLen;
151 WMSelectTextFieldRange(panel->fileField, range);
155 free(text);
159 static void
160 textEditedObserver(void *observerData, WMNotification *notification)
162 W_FilePanel *panel = (W_FilePanel*)observerData;
164 if ((int)WMGetNotificationClientData(notification)==WMReturnTextMovement) {
165 WMPerformButtonClick(panel->okButton);
171 static WMFilePanel*
172 makeFilePanel(WMScreen *scrPtr, char *name, char *title)
174 WMFilePanel *fPtr;
175 WMFont *largeFont;
177 fPtr = wmalloc(sizeof(WMFilePanel));
178 memset(fPtr, 0, sizeof(WMFilePanel));
180 fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask
181 |WMResizableWindowMask);
182 WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
183 WMSetWindowTitle(fPtr->win, "");
185 WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask,
186 handleEvents, fPtr);
187 WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT);
190 fPtr->iconLabel = WMCreateLabel(fPtr->win);
191 WMResizeWidget(fPtr->iconLabel, 64, 64);
192 WMMoveWidget(fPtr->iconLabel, 0, 0);
193 WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
194 WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIcon);
196 fPtr->titleLabel = WMCreateLabel(fPtr->win);
197 WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64);
198 WMMoveWidget(fPtr->titleLabel, 64, 0);
199 largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
200 WMSetLabelFont(fPtr->titleLabel, largeFont);
201 WMReleaseFont(largeFont);
202 WMSetLabelText(fPtr->titleLabel, title);
204 fPtr->line = WMCreateFrame(fPtr->win);
205 WMMoveWidget(fPtr->line, 0, 64);
206 WMResizeWidget(fPtr->line, PWIDTH, 2);
207 WMSetFrameRelief(fPtr->line, WRGroove);
209 fPtr->browser = WMCreateBrowser(fPtr->win);
210 WMSetBrowserDelegate(fPtr->browser, &browserDelegate);
211 WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
212 WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr);
213 WMMoveWidget(fPtr->browser, 7, 72);
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,
225 WMTextDidEndEditingNotification,
226 fPtr->fileField);
227 WMAddNotificationObserver(textChangedObserver, fPtr,
228 WMTextDidChangeNotification,
229 fPtr->fileField);
231 fPtr->okButton = WMCreateCommandButton(fPtr->win);
232 WMMoveWidget(fPtr->okButton, 230, 325);
233 WMResizeWidget(fPtr->okButton, 80, 28);
234 WMSetButtonText(fPtr->okButton, "OK");
235 WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
236 WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
237 WMSetButtonImagePosition(fPtr->okButton, WIPRight);
238 WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
240 fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
241 WMMoveWidget(fPtr->cancelButton, 140, 325);
242 WMResizeWidget(fPtr->cancelButton, 80, 28);
243 WMSetButtonText(fPtr->cancelButton, "Cancel");
244 WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
246 fPtr->homeButton = WMCreateCommandButton(fPtr->win);
247 WMMoveWidget(fPtr->homeButton, 55, 325);
248 WMResizeWidget(fPtr->homeButton, 28, 28);
249 WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
250 WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
251 WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon);
252 WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
254 fPtr->trashcanButton = WMCreateCommandButton(fPtr->win);
255 WMMoveWidget(fPtr->trashcanButton, 25, 325);
256 WMResizeWidget(fPtr->trashcanButton, 28, 28);
257 WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly);
258 WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon);
259 WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon);
260 WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr);
262 fPtr->disketteButton = WMCreateCommandButton(fPtr->win);
263 WMMoveWidget(fPtr->disketteButton, 85, 325);
264 WMResizeWidget(fPtr->disketteButton, 28, 28);
265 WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly);
266 WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon);
267 WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon);
268 WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr);
270 /*xxxxxxxxxxxx***/
272 WMRealizeWidget(fPtr->win);
273 WMMapSubwidgets(fPtr->win);
275 WMSetFocusToWidget(fPtr->fileField);
276 WMSetTextFieldCursorPosition(fPtr->fileField, 0);
278 WMLoadBrowserColumnZero(fPtr->browser);
280 fPtr->flags.canChooseFiles = 1;
281 fPtr->flags.canChooseDirectories = 1;
282 fPtr->flags.autoCompletion = 1;
284 return fPtr;
288 WMOpenPanel*
289 WMGetOpenPanel(WMScreen *scrPtr)
291 WMFilePanel *panel;
293 if (scrPtr->sharedOpenPanel)
294 return scrPtr->sharedOpenPanel;
296 panel = makeFilePanel(scrPtr, "openFilePanel", "Open");
297 panel->flags.fileMustExist = 1;
298 panel->flags.panelType = WP_OPEN;
300 scrPtr->sharedOpenPanel = panel;
302 return panel;
306 WMSavePanel*
307 WMGetSavePanel(WMScreen *scrPtr)
309 WMFilePanel *panel;
311 if (scrPtr->sharedSavePanel)
312 return scrPtr->sharedSavePanel;
314 panel = makeFilePanel(scrPtr, "saveFilePanel", "Save");
315 panel->flags.fileMustExist = 0;
316 panel->flags.panelType = WP_SAVE;
318 scrPtr->sharedSavePanel = panel;
320 return panel;
324 void
325 WMFreeFilePanel(WMFilePanel *panel)
327 if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) {
328 WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
330 if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
331 WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
333 WMRemoveNotificationObserver(panel);
334 WMUnmapWidget(panel->win);
335 WMDestroyWidget(panel->win);
336 free(panel);
341 WMRunModalFilePanelForDirectory(WMFilePanel *panel, WMWindow *owner,
342 char *path, char *name, char **fileTypes)
344 WMScreen *scr = WMWidgetScreen(panel->win);
345 XEvent event;
347 if (name && !owner) {
348 WMSetWindowTitle(panel->win, name);
351 WMChangePanelOwner(panel->win, owner);
353 WMSetFilePanelDirectory(panel, path);
355 panel->flags.done = 0;
356 switch(panel->flags.panelType) {
357 case WP_OPEN:
358 if (fileTypes)
359 panel->flags.filtered = 1;
360 panel->fileTypes = fileTypes;
361 if (name == NULL)
362 name = "Open";
363 break;
364 case WP_SAVE:
365 panel->fileTypes = NULL;
366 panel->flags.filtered = 0;
367 if (name == NULL)
368 name = "Save";
369 break;
370 default:
371 break;
374 WMSetWindowUPosition(panel->win,
375 (scr->rootView->size.width - WMWidgetWidth(panel->win))/2,
376 (scr->rootView->size.height - WMWidgetHeight(panel->win))/2);
377 WMSetLabelText(panel->titleLabel, name);
379 scr->modalView = W_VIEW(panel->win);
380 WMMapWidget(panel->win);
382 scr->modal = 1;
383 while (!panel->flags.done) {
384 WMNextEvent(scr->display, &event);
385 WMHandleEvent(&event);
387 scr->modal = 0;
389 /* Must withdraw window because the next time we map
390 * it, it might have a different transient owner.
392 WMCloseWindow(panel->win);
394 return (panel->flags.canceled ? False : True);
400 void
401 WMSetFilePanelDirectory(WMFilePanel *panel, char *path)
403 WMList *list;
404 WMListItem *item;
405 int col;
406 char *rest;
408 rest = WMSetBrowserPath(panel->browser, path);
409 if (strcmp(path, "/")==0)
410 rest = NULL;
412 col = WMGetBrowserSelectedColumn(panel->browser);
413 list = WMGetBrowserListInColumn(panel->browser, col);
414 if (list && (item = WMGetListSelectedItem(list))) {
415 if (item->isBranch) {
416 WMSetTextFieldText(panel->fileField, rest);
417 } else {
418 WMSetTextFieldText(panel->fileField, item->text);
420 } else {
421 WMSetTextFieldText(panel->fileField, rest);
426 void
427 WMSetFilePanelCanChooseDirectories(WMFilePanel *panel, Bool flag)
429 panel->flags.canChooseDirectories = flag;
432 void
433 WMSetFilePanelCanChooseFiles(WMFilePanel *panel, Bool flag)
435 panel->flags.canChooseFiles = flag;
439 void
440 WMSetFilePanelAutoCompletion(WMFilePanel *panel, Bool flag)
442 panel->flags.autoCompletion = flag;
446 char*
447 WMGetFilePanelFileName(WMFilePanel *panel)
449 return getCurrentFileName(panel);
453 void
454 WMSetFilePanelAccessoryView(WMFilePanel *panel, WMView *view)
456 WMView *v;
458 panel->accessoryView = view;
460 v = WMWidgetView(panel->win);
462 W_ReparentView(view, v, 0, 0);
464 W_MoveView(view, (v->size.width - v->size.width)/2, 300);
468 WMView*
469 WMGetFilePanelAccessoryView(WMFilePanel *panel)
471 return panel->accessoryView;
475 static char*
476 get_name_from_path(char *path)
478 int size;
480 assert(path!=NULL);
482 size = strlen(path);
484 /* remove trailing / */
485 while (size > 0 && path[size-1]=='/')
486 size--;
487 /* directory was root */
488 if (size == 0)
489 return wstrdup("/");
491 while (size > 0 && path[size-1] != '/')
492 size--;
494 return wstrdup(&(path[size]));
498 static int
499 filterFileName(WMFilePanel *panel, char *file, Bool isDirectory)
501 return True;
505 static void
506 listDirectoryOnColumn(WMFilePanel *panel, int column, char *path)
508 WMBrowser *bPtr = panel->browser;
509 struct dirent *dentry;
510 DIR *dir;
511 struct stat stat_buf;
512 char pbuf[PATH_MAX+16];
514 assert(column >= 0);
515 assert(path != NULL);
517 /* put directory name in the title */
518 WMSetBrowserColumnTitle(bPtr, column, get_name_from_path(path));
520 dir = opendir(path);
522 if (!dir) {
523 #ifdef VERBOSE
524 printf("WINGs: could not open directory %s\n", path);
525 #endif
526 return;
529 /* list contents in the column */
530 while ((dentry = readdir(dir))) {
531 if (strcmp(dentry->d_name, ".")==0 ||
532 strcmp(dentry->d_name, "..")==0)
533 continue;
535 strcpy(pbuf, path);
536 if (strcmp(path, "/")!=0)
537 strcat(pbuf, "/");
538 strcat(pbuf, dentry->d_name);
540 if (stat(pbuf, &stat_buf)!=0) {
541 #ifdef VERBOSE
542 printf("WINGs: could not stat %s\n", pbuf);
543 #endif
544 continue;
545 } else {
546 int isDirectory;
548 isDirectory = S_ISDIR(stat_buf.st_mode);
550 if (filterFileName(panel, dentry->d_name, isDirectory))
551 WMAddSortedBrowserItem(bPtr, column, dentry->d_name,
552 isDirectory);
556 closedir(dir);
560 static void
561 fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column, WMList *list)
563 char *path;
564 WMFilePanel *panel;
566 if (column > 0) {
567 path = WMGetBrowserPathToColumn(bPtr, column-1);
568 } else {
569 path = wstrdup("/");
572 panel = WMGetHangedData(bPtr);
573 listDirectoryOnColumn(panel, column, path);
574 free(path);
578 static void
579 browserDClick(WMBrowser *bPtr, WMFilePanel *panel)
581 WMPerformButtonClick(panel->okButton);
584 static void
585 browserClick(WMBrowser *bPtr, WMFilePanel *panel)
587 int col = WMGetBrowserSelectedColumn(bPtr);
588 WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
590 if (!item || item->isBranch)
591 WMSetTextFieldText(panel->fileField, NULL);
592 else {
593 WMSetTextFieldText(panel->fileField, item->text);
598 static void
599 showError(WMScreen *scr, WMWindow *owner, char *s, char *file)
601 char *errStr;
603 if (file) {
604 errStr = wmalloc(strlen(file)+strlen(s));
605 sprintf(errStr, s, file);
606 } else {
607 errStr = wstrdup(s);
609 WMRunAlertPanel(scr, owner, "Error", errStr, "OK", NULL, NULL);
610 free(errStr);
614 static void
615 deleteFile(WMButton *bPre, WMFilePanel *panel)
617 WMScreen *scr = WMWidgetScreen(panel->win);
618 char *file;
619 char *buffer;
621 file = getCurrentFileName(panel);
622 if (file[strlen(file)-1] == '/') {
623 showError(scr, panel->win, "%s is a directory.", file);
624 free(file);
625 return;
627 buffer = wmalloc(strlen(file)+16);
628 sprintf(buffer,"Delete file %s ?",file);
629 if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
630 "Warning", buffer, "OK", "Cancel", NULL)) {
631 if (remove(file) != 0) {
632 switch (errno) {
633 case EISDIR:
634 showError(scr, panel->win, "'%s' is a directory.", file);
635 break;
636 case ENOENT:
637 showError(scr, panel->win, "'%s' does not exist.", file);
638 break;
639 case EACCES:
640 showError(scr, panel->win, "Permission denied.", NULL);
641 break;
642 case ENOMEM:
643 showError(scr, panel->win,
644 "Insufficient memory available.", NULL);
645 break;
646 case EROFS:
647 showError(scr, panel->win,
648 "'%s' is on a read-only filesystem.", file);
649 break;
650 default:
651 showError(scr, panel->win, "Can not delete '%s'.", file);
654 else {
655 char *s = strrchr(file, '/');
656 if (s) s[1] = 0;
657 WMSetFilePanelDirectory(panel, file);
660 free(buffer);
661 free(file);
665 static void
666 goFloppy(WMButton *bPtr, WMFilePanel *panel)
668 WMScreen *scr = WMWidgetScreen(panel->win);
669 struct stat filestat;
671 if (stat("/floppy", &filestat)) {
672 showError(scr, panel->win, "An error occured browsing /floppy.", NULL);
673 return;
674 } else if (!S_ISDIR(filestat.st_mode)) {
675 showError(scr, panel->win, "/floppy is not a directory.", NULL);
676 return;
679 WMSetFilePanelDirectory(panel, "/floppy/");
682 static void
683 goHome(WMButton *bPtr, WMFilePanel *panel)
685 char *home;
687 /* home is statically allocated. Don't free it! */
688 home = wgethomedir();
689 if (!home)
690 return;
692 WMSetFilePanelDirectory(panel, home);
696 static void
697 handleEvents(XEvent *event, void *data)
699 W_FilePanel *pPtr = (W_FilePanel*)data;
700 W_View *view = WMWidgetView(pPtr->win);
702 if (event->type == ConfigureNotify) {
703 if (event->xconfigure.width != view->size.width
704 || event->xconfigure.height != view->size.height) {
705 unsigned int newWidth = event->xconfigure.width;
706 unsigned int newHeight = event->xconfigure.height;
707 int newColumnCount;
709 W_ResizeView(view, newWidth, newHeight);
710 WMResizeWidget(pPtr->line, newWidth, 2);
711 WMResizeWidget(pPtr->browser, newWidth-14,
712 newHeight-(PHEIGHT-200));
713 WMResizeWidget(pPtr->fileField, newWidth-60-10, 24);
714 WMMoveWidget(pPtr->nameLabel, 7, newHeight-(PHEIGHT-282));
715 WMMoveWidget(pPtr->fileField, 60, newHeight-(PHEIGHT-278));
716 WMMoveWidget(pPtr->okButton, newWidth-(PWIDTH-230),
717 newHeight-(PHEIGHT-325));
718 WMMoveWidget(pPtr->cancelButton, newWidth-(PWIDTH-140),
719 newHeight-(PHEIGHT-325));
720 WMMoveWidget(pPtr->homeButton, 55, newHeight-(PHEIGHT-325));
721 WMMoveWidget(pPtr->trashcanButton, 25, newHeight-(PHEIGHT-325));
723 newColumnCount = (newWidth - 14) / 140;
724 WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount);
730 static char*
731 getCurrentFileName(WMFilePanel *panel)
733 char *path;
734 char *file;
735 char *tmp;
736 int len;
738 path = WMGetBrowserPath(panel->browser);
740 len = strlen(path);
741 if (path[len-1]=='/') {
742 file = WMGetTextFieldText(panel->fileField);
743 tmp = wmalloc(strlen(path)+strlen(file)+8);
744 if (file[0]!='/') {
745 strcpy(tmp, path);
746 strcat(tmp, file);
747 } else
748 strcpy(tmp, file);
750 free(file);
751 free(path);
752 return tmp;
753 } else {
754 return path;
760 static Bool
761 validOpenFile(WMFilePanel *panel)
763 WMListItem *item;
764 int col, haveFile = 0;
765 char *file = WMGetTextFieldText(panel->fileField);
767 if (file[0] != '\0')
768 haveFile = 1;
769 free(file);
771 col = WMGetBrowserSelectedColumn(panel->browser);
772 item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
773 if (item) {
774 if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile)
775 return False;
776 else if (!item->isBranch && !panel->flags.canChooseFiles)
777 return False;
778 else
779 return True;
780 } else {
781 /* we compute for / here */
782 if (!panel->flags.canChooseDirectories && !haveFile)
783 return False;
784 else
785 return True;
787 return True;
792 static void
793 buttonClick(WMButton *bPtr, WMFilePanel *panel)
795 WMRange range;
797 if (bPtr == panel->okButton) {
798 if (!validOpenFile(panel))
799 return;
800 if (panel->flags.fileMustExist) {
801 char *file;
803 file = getCurrentFileName(panel);
804 if (access(file, F_OK)!=0) {
805 WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
806 "Error", "File does not exist.",
807 "Ok", NULL, NULL);
808 free(file);
809 return;
811 free(file);
813 panel->flags.canceled = 0;
814 } else
815 panel->flags.canceled = 1;
817 range.count = range.position = 0;
818 WMSelectTextFieldRange(panel->fileField, range);
819 panel->flags.done = 1;