X-Git-Url: https://repo.or.cz/w/wmaker-crm.git/blobdiff_plain/59fc927dc9f183802621138534fa6eaafe5593ba..688a56e8ab67b56550e2874d9d7423f0d435bfd9:/WINGs/wfilepanel.c diff --git a/WINGs/wfilepanel.c b/WINGs/wfilepanel.c dissimilarity index 95% index e5565eb2..33e3dab5 100644 --- a/WINGs/wfilepanel.c +++ b/WINGs/wfilepanel.c @@ -1,990 +1,904 @@ - -#include "WINGsP.h" -#include "wconfig.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifndef PATH_MAX -#define PATH_MAX 1024 -#endif - - -typedef struct W_FilePanel { - WMWindow *win; - - WMLabel *iconLabel; - WMLabel *titleLabel; - - WMFrame *line; - - WMLabel *nameLabel; - WMBrowser *browser; - - WMButton *okButton; - WMButton *cancelButton; - - WMButton *homeButton; - WMButton *trashcanButton; - WMButton *createDirButton; - WMButton *disketteButton; - WMButton *unmountButton; - - WMView *accessoryView; - - WMTextField *fileField; - - char **fileTypes; - - struct { - unsigned int canExit:1; - unsigned int canceled:1; /* clicked on cancel */ - unsigned int filtered:1; - unsigned int canChooseFiles:1; - unsigned int canChooseDirectories:1; - unsigned int autoCompletion:1; - unsigned int showAllFiles:1; - unsigned int canFreeFileTypes:1; - unsigned int fileMustExist:1; - unsigned int panelType:1; - } flags; -} W_FilePanel; - - -/* Type of panel */ -#define WP_OPEN 0 -#define WP_SAVE 1 - -#define PWIDTH 330 -#define PHEIGHT 360 - -static void listDirectoryOnColumn(WMFilePanel *panel, int column, char *path); -static void browserClick(); -static void browserDClick(); - -static void fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column, - WMList *list); - -static void deleteFile(); - -static void createDir(); - -static void goHome(); - -static void goFloppy(); - -static void goUnmount(); - -static void buttonClick(); - -static char *getCurrentFileName(WMFilePanel *panel); - -static void handleEvents(XEvent *event, void *data); - - - -static WMBrowserDelegate browserDelegate = { - NULL, /* data */ - fillColumn, /* createRowsForColumn */ - NULL, /* titleOfColumn */ - NULL, /* didScroll */ - NULL /* willScroll */ -}; - - -static int -closestListItem(WMList *list, char *text, Bool exact) -{ - WMListItem *item; - WMArray *items = WMGetListItems(list); - int i, len = strlen(text); - - if (len==0) - return -1; - - for(i=0; itext) >= len && - ((exact && strcmp(item->text, text)==0) || - (!exact && strncmp(item->text, text, len)==0))) { - return i; - } - } - - return -1; -} - - -static void -textChangedObserver(void *observerData, WMNotification *notification) -{ - W_FilePanel *panel = (W_FilePanel*)observerData; - char *text; - WMList *list; - int col = WMGetBrowserNumberOfColumns(panel->browser) - 1; - int i, textEvent; - - if (!(list = WMGetBrowserListInColumn(panel->browser, col))) - return; - - text = WMGetTextFieldText(panel->fileField); - textEvent = (int)(uintptr_t)WMGetNotificationClientData(notification); - - if (panel->flags.autoCompletion && textEvent!=WMDeleteTextEvent) - i = closestListItem(list, text, False); - else - i = closestListItem(list, text, True); - - WMSelectListItem(list, i); - if (i>=0 && panel->flags.autoCompletion) { - WMListItem *item = WMGetListItem(list, i); - int textLen = strlen(text), itemTextLen = strlen(item->text); - int visibleItems = WMWidgetHeight(list)/WMGetListItemHeight(list); - - WMSetListPosition(list, i - visibleItems/2); - - if (textEvent!=WMDeleteTextEvent) { - WMRange range; - - WMInsertTextFieldText(panel->fileField, &item->text[textLen], - textLen); - range.position = textLen; - range.count = itemTextLen - textLen; - WMSelectTextFieldRange(panel->fileField, range); - /*WMSetTextFieldCursorPosition(panel->fileField, itemTextLen);*/ - } - } - - wfree(text); -} - - -static void -textEditedObserver(void *observerData, WMNotification *notification) -{ - W_FilePanel *panel = (W_FilePanel*)observerData; - - if ((int)(uintptr_t)WMGetNotificationClientData(notification)==WMReturnTextMovement) { - WMPerformButtonClick(panel->okButton); - } -} - - - -static WMFilePanel* -makeFilePanel(WMScreen *scrPtr, char *name, char *title) -{ - WMFilePanel *fPtr; - WMFont *largeFont; - WMPixmap *icon; - - fPtr = wmalloc(sizeof(WMFilePanel)); - memset(fPtr, 0, sizeof(WMFilePanel)); - - fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask - |WMResizableWindowMask); - WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT); - WMSetWindowTitle(fPtr->win, ""); - - WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask, - handleEvents, fPtr); - WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT); - - - fPtr->iconLabel = WMCreateLabel(fPtr->win); - WMResizeWidget(fPtr->iconLabel, 64, 64); - WMMoveWidget(fPtr->iconLabel, 0, 0); - WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly); - icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor*)NULL); - if (icon) { - WMSetLabelImage(fPtr->iconLabel, icon); - WMReleasePixmap(icon); - } else { - WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIconPixmap); - } - - fPtr->titleLabel = WMCreateLabel(fPtr->win); - WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64); - WMMoveWidget(fPtr->titleLabel, 64, 0); - largeFont = WMBoldSystemFontOfSize(scrPtr, 24); - WMSetLabelFont(fPtr->titleLabel, largeFont); - WMReleaseFont(largeFont); - WMSetLabelText(fPtr->titleLabel, title); - - fPtr->line = WMCreateFrame(fPtr->win); - WMMoveWidget(fPtr->line, 0, 64); - WMResizeWidget(fPtr->line, PWIDTH, 2); - WMSetFrameRelief(fPtr->line, WRGroove); - - fPtr->browser = WMCreateBrowser(fPtr->win); - WMSetBrowserAllowEmptySelection(fPtr->browser, True); - WMSetBrowserDelegate(fPtr->browser, &browserDelegate); - WMSetBrowserAction(fPtr->browser, browserClick, fPtr); - WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr); - WMMoveWidget(fPtr->browser, 7, 72); - WMResizeWidget(fPtr->browser, PWIDTH-14,200); - WMHangData(fPtr->browser, fPtr); - - fPtr->nameLabel = WMCreateLabel(fPtr->win); - WMMoveWidget(fPtr->nameLabel, 7, 282); - WMResizeWidget(fPtr->nameLabel, 55, 14); - WMSetLabelText(fPtr->nameLabel, _("Name:")); - - fPtr->fileField = WMCreateTextField(fPtr->win); - WMMoveWidget(fPtr->fileField, 60, 278); - WMResizeWidget(fPtr->fileField, PWIDTH-60-10, 24); - WMAddNotificationObserver(textEditedObserver, fPtr, - WMTextDidEndEditingNotification, - fPtr->fileField); - WMAddNotificationObserver(textChangedObserver, fPtr, - WMTextDidChangeNotification, - fPtr->fileField); - - fPtr->okButton = WMCreateCommandButton(fPtr->win); - WMMoveWidget(fPtr->okButton, 245, 325); - WMResizeWidget(fPtr->okButton, 75, 28); - WMSetButtonText(fPtr->okButton, _("OK")); - WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow); - WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow); - WMSetButtonImagePosition(fPtr->okButton, WIPRight); - WMSetButtonAction(fPtr->okButton, buttonClick, fPtr); - - fPtr->cancelButton = WMCreateCommandButton(fPtr->win); - WMMoveWidget(fPtr->cancelButton, 165, 325); - WMResizeWidget(fPtr->cancelButton, 75, 28); - WMSetButtonText(fPtr->cancelButton, _("Cancel")); - WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr); - - fPtr->trashcanButton = WMCreateCommandButton(fPtr->win); - WMMoveWidget(fPtr->trashcanButton, 7, 325); - WMResizeWidget(fPtr->trashcanButton, 28, 28); - WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly); - WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon); - WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon); - WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr); - - fPtr->createDirButton = WMCreateCommandButton(fPtr->win); - WMMoveWidget(fPtr->createDirButton, 37, 325); - WMResizeWidget(fPtr->createDirButton, 28, 28); - WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly); - WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon); - WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon); - WMSetButtonAction(fPtr->createDirButton, createDir, fPtr); - - fPtr->homeButton = WMCreateCommandButton(fPtr->win); - WMMoveWidget(fPtr->homeButton, 67, 325); - WMResizeWidget(fPtr->homeButton, 28, 28); - WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly); - WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon); - WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon); - WMSetButtonAction(fPtr->homeButton, goHome, fPtr); - - fPtr->disketteButton = WMCreateCommandButton(fPtr->win); - WMMoveWidget(fPtr->disketteButton, 97, 325); - WMResizeWidget(fPtr->disketteButton, 28, 28); - WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly); - WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon); - WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon); - WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr); - - fPtr->unmountButton = WMCreateCommandButton(fPtr->win); - WMMoveWidget(fPtr->unmountButton, 127, 325); - WMResizeWidget(fPtr->unmountButton, 28, 28); - WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly); - WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon); - WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon); - WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr); - WMSetButtonEnabled(fPtr->unmountButton, False); - - - WMRealizeWidget(fPtr->win); - WMMapSubwidgets(fPtr->win); - - WMSetFocusToWidget(fPtr->fileField); - WMSetTextFieldCursorPosition(fPtr->fileField, 0); - - WMLoadBrowserColumnZero(fPtr->browser); - - WMSetWindowInitialPosition(fPtr->win, - (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win))/2, - (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win))/2); - - fPtr->flags.canChooseFiles = 1; - fPtr->flags.canChooseDirectories = 1; - fPtr->flags.autoCompletion = 1; - - return fPtr; -} - - -WMOpenPanel* -WMGetOpenPanel(WMScreen *scrPtr) -{ - WMFilePanel *panel; - - if (scrPtr->sharedOpenPanel) - return scrPtr->sharedOpenPanel; - - panel = makeFilePanel(scrPtr, "openFilePanel", _("Open")); - panel->flags.fileMustExist = 1; - panel->flags.panelType = WP_OPEN; - - scrPtr->sharedOpenPanel = panel; - - return panel; -} - - -WMSavePanel* -WMGetSavePanel(WMScreen *scrPtr) -{ - WMFilePanel *panel; - - if (scrPtr->sharedSavePanel) - return scrPtr->sharedSavePanel; - - panel = makeFilePanel(scrPtr, "saveFilePanel", _("Save")); - panel->flags.fileMustExist = 0; - panel->flags.panelType = WP_SAVE; - - scrPtr->sharedSavePanel = panel; - - return panel; -} - - -void -WMFreeFilePanel(WMFilePanel *panel) -{ - if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) { - WMWidgetScreen(panel->win)->sharedSavePanel = NULL; - } - if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) { - WMWidgetScreen(panel->win)->sharedOpenPanel = NULL; - } - WMRemoveNotificationObserver(panel); - WMUnmapWidget(panel->win); - WMDestroyWidget(panel->win); - wfree(panel); -} - - -int -WMRunModalFilePanelForDirectory(WMFilePanel *panel, WMWindow *owner, - char *path, char *name, char **fileTypes) -{ - WMScreen *scr = WMWidgetScreen(panel->win); - - if (name && !owner) { - WMSetWindowTitle(panel->win, name); - } - - WMChangePanelOwner(panel->win, owner); - - WMSetFilePanelDirectory(panel, path); - - switch(panel->flags.panelType) { - case WP_OPEN: - if (fileTypes) - panel->flags.filtered = 1; - panel->fileTypes = fileTypes; - if (name == NULL) - name = _("Open"); - break; - case WP_SAVE: - panel->fileTypes = NULL; - panel->flags.filtered = 0; - if (name == NULL) - name = _("Save"); - break; - default: - break; - } - - WMSetLabelText(panel->titleLabel, name); - - WMMapWidget(panel->win); - - WMRunModalLoop(scr, W_VIEW(panel->win)); - - /* Must withdraw window because the next time we map - * it, it might have a different transient owner. - */ - WMCloseWindow(panel->win); - - return (panel->flags.canceled ? False : True); -} - - - - -void -WMSetFilePanelDirectory(WMFilePanel *panel, char *path) -{ - WMList *list; - WMListItem *item; - int col; - char *rest; - - rest = WMSetBrowserPath(panel->browser, path); - if (strcmp(path, "/")==0) - rest = NULL; - - col = WMGetBrowserSelectedColumn(panel->browser); - list = WMGetBrowserListInColumn(panel->browser, col); - if (list && (item = WMGetListSelectedItem(list))) { - if (item->isBranch) { - WMSetTextFieldText(panel->fileField, rest); - } else { - WMSetTextFieldText(panel->fileField, item->text); - } - } else { - WMSetTextFieldText(panel->fileField, rest); - } -} - - -void -WMSetFilePanelCanChooseDirectories(WMFilePanel *panel, Bool flag) -{ - panel->flags.canChooseDirectories = ((flag==0) ? 0 : 1); -} - -void -WMSetFilePanelCanChooseFiles(WMFilePanel *panel, Bool flag) -{ - panel->flags.canChooseFiles = ((flag==0) ? 0 : 1); -} - - -void -WMSetFilePanelAutoCompletion(WMFilePanel *panel, Bool flag) -{ - panel->flags.autoCompletion = ((flag==0) ? 0 : 1); -} - - -char* -WMGetFilePanelFileName(WMFilePanel *panel) -{ - return getCurrentFileName(panel); -} - - -void -WMSetFilePanelAccessoryView(WMFilePanel *panel, WMView *view) -{ - WMView *v; - - panel->accessoryView = view; - - v = WMWidgetView(panel->win); - - W_ReparentView(view, v, 0, 0); - - W_MoveView(view, (v->size.width - v->size.width)/2, 300); -} - - -WMView* -WMGetFilePanelAccessoryView(WMFilePanel *panel) -{ - return panel->accessoryView; -} - - -static char* -get_name_from_path(char *path) -{ - int size; - - assert(path!=NULL); - - size = strlen(path); - - /* remove trailing / */ - while (size > 0 && path[size-1]=='/') - size--; - /* directory was root */ - if (size == 0) - return wstrdup("/"); - - while (size > 0 && path[size-1] != '/') - size--; - - return wstrdup(&(path[size])); -} - - -static int -filterFileName(WMFilePanel *panel, char *file, Bool isDirectory) -{ - return True; -} - - -#define CAST(item) (*((WMListItem**)item)) -static int -comparer(const void *a, const void *b) -{ - if (CAST(a)->isBranch == CAST(b)->isBranch) - return (strcmp(CAST(a)->text, CAST(b)->text)); - if (CAST(a)->isBranch) - return (-1); - return (1); -} -#undef CAST - - -static void -listDirectoryOnColumn(WMFilePanel *panel, int column, char *path) -{ - WMBrowser *bPtr = panel->browser; - struct dirent *dentry; - DIR *dir; - struct stat stat_buf; - char pbuf[PATH_MAX+16]; - char *name; - - assert(column >= 0); - assert(path != NULL); - - /* put directory name in the title */ - name = get_name_from_path(path); - WMSetBrowserColumnTitle(bPtr, column, name); - wfree(name); - - dir = opendir(path); - - if (!dir) { -#ifdef VERBOSE - printf(_("WINGs: could not open directory %s\n"), path); -#endif - return; - } - - /* list contents in the column */ - while ((dentry = readdir(dir))) { - if (strcmp(dentry->d_name, ".")==0 || - strcmp(dentry->d_name, "..")==0) - continue; - - strcpy(pbuf, path); - if (strcmp(path, "/")!=0) - strcat(pbuf, "/"); - strcat(pbuf, dentry->d_name); - - if (stat(pbuf, &stat_buf)!=0) { -#ifdef VERBOSE - printf(_("WINGs: could not stat %s\n"), pbuf); -#endif - continue; - } else { - int isDirectory; - - isDirectory = S_ISDIR(stat_buf.st_mode); - - if (filterFileName(panel, dentry->d_name, isDirectory)) - WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory); - } - } - WMSortBrowserColumnWithComparer(bPtr, column, comparer); - - closedir(dir); -} - - -static void -fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column, WMList *list) -{ - char *path; - WMFilePanel *panel; - - if (column > 0) { - path = WMGetBrowserPathToColumn(bPtr, column-1); - } else { - path = wstrdup("/"); - } - - panel = WMGetHangedData(bPtr); - listDirectoryOnColumn(panel, column, path); - wfree(path); -} - - -static void -browserDClick(WMBrowser *bPtr, WMFilePanel *panel) -{ - WMPerformButtonClick(panel->okButton); -} - -static void -browserClick(WMBrowser *bPtr, WMFilePanel *panel) -{ - int col = WMGetBrowserSelectedColumn(bPtr); - WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col); - - if (!item || item->isBranch) - WMSetTextFieldText(panel->fileField, NULL); - else { - WMSetTextFieldText(panel->fileField, item->text); - } -} - - -static void -showError(WMScreen *scr, WMWindow *owner, char *s, char *file) -{ - char *errStr; - - if (file) { - errStr = wmalloc(strlen(file)+strlen(s)); - sprintf(errStr, s, file); - } else { - errStr = wstrdup(s); - } - WMRunAlertPanel(scr, owner, _("Error"), errStr, _("OK"), NULL, NULL); - wfree(errStr); -} - - -static void -createDir(WMButton *bPre, WMFilePanel *panel) -{ - char *dirName, *directory, *file, *s; - WMScreen *scr = WMWidgetScreen(panel->win); - - dirName = WMRunInputPanel(scr, panel->win, _("Create Directory"), - _("Enter directory name"), "", _("OK"), _("Cancel")); - if (!dirName) - return; - - directory = getCurrentFileName(panel); - s = strrchr(directory,'/'); - if (s) s[1] = 0; - - if (dirName[0] == '/') { - directory[0] = 0; - } else { - while ((s = strstr(directory,"//"))) { - int i; - for (i = 2;s[i] == '/';i++); - strcpy(s, &s[i-1]); - } - if ((s = strrchr(directory, '/')) && !s[1]) s[0] = 0; - } - while ((s = strstr(dirName,"//"))) { - int i; - for (i = 2;s[i] == '/';i++); - strcpy(s, &s[i-1]); - } - if ((s = strrchr(dirName, '/')) && !s[1]) s[0] = 0; - - file = wmalloc(strlen(dirName)+strlen(directory)+4); - sprintf(file, "%s/%s", directory, dirName); - while ((s = strstr(file,"//"))) { - int i; - for (i = 2;s[i] == '/';i++); - strcpy(s, &s[i-1]); - } - - if (mkdir(file,0xfff) != 0) { - switch (errno) { - case EACCES: - showError(scr, panel->win, _("Permission denied."), NULL); - break; - case EEXIST: - showError(scr, panel->win, _("'%s' already exists."), file); - break; - case ENOENT: - showError(scr, panel->win, _("Path does not exist."), NULL); - } - } - else WMSetFilePanelDirectory(panel, file); - - wfree(dirName); - wfree(directory); - wfree(file); -} - -static void -deleteFile(WMButton *bPre, WMFilePanel *panel) -{ - char *file; - char *buffer, *s; - struct stat filestat; - WMScreen *scr = WMWidgetScreen(panel->win); - - file = getCurrentFileName(panel); - - while ((s = strstr(file,"//"))) { - int i; - for (i = 2;s[i] == '/';i++); - strcpy(s, &s[i-1]); - } - if (strlen(file) > 1 && (s = strrchr(file, '/')) && !s[1]) s[0] = 0; - - if (stat(file,&filestat)) { - switch (errno) { - case ENOENT: - showError(scr, panel->win, _("'%s' does not exist."), file); - break; - case EACCES: - showError(scr, panel->win, _("Permission denied."), NULL); - break; - case ENOMEM: - showError(scr, panel->win, - _("Insufficient memory available."), NULL); - break; - case EROFS: - showError(scr, panel->win, - _("'%s' is on a read-only filesystem."), file); - break; - default: - showError(scr, panel->win, _("Can not delete '%s'."), file); - } - wfree(file); - return; - } else if (S_ISDIR(filestat.st_mode)) { - int len = strlen(file)+20; - buffer = wmalloc(len); - snprintf(buffer,len,_("Delete directory %s ?"),file); - } else { - int len = strlen(file)+15; - buffer = wmalloc(len); - snprintf(buffer,len,_("Delete file %s ?"),file); - } - - if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win, - _("Warning"), buffer, _("OK"), _("Cancel"), NULL)) { - if (S_ISDIR(filestat.st_mode)) { - if (rmdir(file) != 0) { - switch (errno) { - case EACCES: - showError(scr, panel->win, _("Permission denied."), NULL); - break; - case ENOENT: - showError(scr, panel->win, _("Directory '%s' does not exist."), file); - break; - case ENOTEMPTY: - showError(scr, panel->win, _("Directory '%s' is not empty."), file); - break; - case EBUSY: - showError(scr, panel->win, _("Directory '%s' is busy."), file); - break; - default: - showError(scr, panel->win, _("Can not delete '%s'."), file); - } - } else { - char *s = strrchr(file,'/'); - if (s) s[0] = 0; - WMSetFilePanelDirectory(panel, file); - } - } else if (remove(file) != 0) { - switch (errno) { - case EISDIR: - showError(scr, panel->win, _("'%s' is a directory."), file); - break; - case ENOENT: - showError(scr, panel->win, _("'%s' does not exist."), file); - break; - case EACCES: - showError(scr, panel->win, _("Permission denied."), NULL); - break; - case ENOMEM: - showError(scr, panel->win, - _("Insufficient memory available."), NULL); - break; - case EROFS: - showError(scr, panel->win, - _("'%s' is on a read-only filesystem."), file); - break; - default: - showError(scr, panel->win, _("Can not delete '%s'."), file); - } - } else { - char *s = strrchr(file,'/'); - if (s) s[1] = 0; - WMSetFilePanelDirectory(panel, file); - } - } - wfree(buffer); - wfree(file); -} - -static void -goUnmount(WMButton *bPtr, WMFilePanel *panel) -{ -} - - -static void -goFloppy(WMButton *bPtr, WMFilePanel *panel) -{ - struct stat filestat; - WMScreen *scr = WMWidgetScreen(panel->win); - - if (stat(WINGsConfiguration.floppyPath, &filestat)) { - showError(scr, panel->win, _("An error occured browsing '%s'."), - WINGsConfiguration.floppyPath); - return; - } else if (!S_ISDIR(filestat.st_mode)) { - showError(scr, panel->win, _("'%s' is not a directory."), - WINGsConfiguration.floppyPath); - return; - } - - WMSetFilePanelDirectory(panel, WINGsConfiguration.floppyPath); -} - - -static void -goHome(WMButton *bPtr, WMFilePanel *panel) -{ - char *home; - - /* home is statically allocated. Don't free it! */ - home = wgethomedir(); - if (!home) - return; - - WMSetFilePanelDirectory(panel, home); -} - - -static void -handleEvents(XEvent *event, void *data) -{ - W_FilePanel *pPtr = (W_FilePanel*)data; - W_View *view = WMWidgetView(pPtr->win); - - if (event->type == ConfigureNotify) { - if (event->xconfigure.width != view->size.width - || event->xconfigure.height != view->size.height) { - unsigned int newWidth = event->xconfigure.width; - unsigned int newHeight = event->xconfigure.height; - int newColumnCount; - - W_ResizeView(view, newWidth, newHeight); - WMResizeWidget(pPtr->line, newWidth, 2); - WMResizeWidget(pPtr->browser, newWidth-14, - newHeight-(PHEIGHT-200)); - WMResizeWidget(pPtr->fileField, newWidth-60-10, 24); - WMMoveWidget(pPtr->nameLabel, 7, newHeight-(PHEIGHT-282)); - WMMoveWidget(pPtr->fileField, 60, newHeight-(PHEIGHT-278)); - WMMoveWidget(pPtr->okButton, newWidth-(PWIDTH-245), - newHeight-(PHEIGHT-325)); - WMMoveWidget(pPtr->cancelButton, newWidth-(PWIDTH-165), - newHeight-(PHEIGHT-325)); - - WMMoveWidget(pPtr->trashcanButton, 7, newHeight-(PHEIGHT-325)); - WMMoveWidget(pPtr->createDirButton, 37, newHeight-(PHEIGHT-325)); - WMMoveWidget(pPtr->homeButton, 67, newHeight-(PHEIGHT-325)); - WMMoveWidget(pPtr->disketteButton, 97, newHeight-(PHEIGHT-325)); - WMMoveWidget(pPtr->unmountButton, 127, newHeight-(PHEIGHT-325)); - - newColumnCount = (newWidth - 14) / 140; - WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount); - } - } -} - - -static char* -getCurrentFileName(WMFilePanel *panel) -{ - char *path; - char *file; - char *tmp; - int len; - - path = WMGetBrowserPath(panel->browser); - - len = strlen(path); - if (path[len-1]=='/') { - file = WMGetTextFieldText(panel->fileField); - tmp = wmalloc(strlen(path)+strlen(file)+8); - if (file[0]!='/') { - strcpy(tmp, path); - strcat(tmp, file); - } else - strcpy(tmp, file); - - wfree(file); - wfree(path); - return tmp; - } else { - return path; - } -} - - - -static Bool -validOpenFile(WMFilePanel *panel) -{ - WMListItem *item; - int col, haveFile = 0; - char *file = WMGetTextFieldText(panel->fileField); - - if (file[0] != '\0') - haveFile = 1; - wfree(file); - - col = WMGetBrowserSelectedColumn(panel->browser); - item = WMGetBrowserSelectedItemInColumn(panel->browser, col); - if (item) { - if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile) - return False; - else if (!item->isBranch && !panel->flags.canChooseFiles) - return False; - else - return True; - } else { - /* we compute for / here */ - if (!panel->flags.canChooseDirectories && !haveFile) - return False; - else - return True; - } - return True; -} - - - -static void -buttonClick(WMButton *bPtr, WMFilePanel *panel) -{ - WMRange range; - - if (bPtr == panel->okButton) { - if (!validOpenFile(panel)) - return; - if (panel->flags.fileMustExist) { - char *file; - - file = getCurrentFileName(panel); - if (access(file, F_OK)!=0) { - WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win, - _("Error"), _("File does not exist."), - _("OK"), NULL, NULL); - wfree(file); - return; - } - wfree(file); - } - panel->flags.canceled = 0; - } else - panel->flags.canceled = 1; - - range.count = range.position = 0; - WMSelectTextFieldRange(panel->fileField, range); - WMBreakModalLoop(WMWidgetScreen(bPtr)); -} - - + +#include "WINGsP.h" +#include "wconfig.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +typedef struct W_FilePanel { + WMWindow *win; + + WMLabel *iconLabel; + WMLabel *titleLabel; + + WMFrame *line; + + WMLabel *nameLabel; + WMBrowser *browser; + + WMButton *okButton; + WMButton *cancelButton; + + WMButton *homeButton; + WMButton *trashcanButton; + WMButton *createDirButton; + WMButton *disketteButton; + WMButton *unmountButton; + + WMView *accessoryView; + + WMTextField *fileField; + + char **fileTypes; + + struct { + unsigned int canExit:1; + unsigned int canceled:1; /* clicked on cancel */ + unsigned int filtered:1; + unsigned int canChooseFiles:1; + unsigned int canChooseDirectories:1; + unsigned int autoCompletion:1; + unsigned int showAllFiles:1; + unsigned int canFreeFileTypes:1; + unsigned int fileMustExist:1; + unsigned int panelType:1; + } flags; +} W_FilePanel; + +/* Type of panel */ +#define WP_OPEN 0 +#define WP_SAVE 1 + +#define PWIDTH 330 +#define PHEIGHT 360 + +static void listDirectoryOnColumn(WMFilePanel * panel, int column, char *path); +static void browserClick(); +static void browserDClick(); + +static void fillColumn(WMBrowserDelegate * self, WMBrowser * bPtr, int column, WMList * list); + +static void deleteFile(); + +static void createDir(); + +static void goHome(); + +static void goFloppy(); + +static void goUnmount(); + +static void buttonClick(); + +static char *getCurrentFileName(WMFilePanel * panel); + +static void handleEvents(XEvent * event, void *data); + +static WMBrowserDelegate browserDelegate = { + NULL, /* data */ + fillColumn, /* createRowsForColumn */ + NULL, /* titleOfColumn */ + NULL, /* didScroll */ + NULL /* willScroll */ +}; + +static int closestListItem(WMList * list, char *text, Bool exact) +{ + WMListItem *item; + WMArray *items = WMGetListItems(list); + int i, len = strlen(text); + + if (len == 0) + return -1; + + for (i = 0; i < WMGetArrayItemCount(items); i++) { + item = WMGetFromArray(items, i); + if (strlen(item->text) >= len && + ((exact && strcmp(item->text, text) == 0) || + (!exact && strncmp(item->text, text, len) == 0))) { + return i; + } + } + + return -1; +} + +static void textChangedObserver(void *observerData, WMNotification * notification) +{ + W_FilePanel *panel = (W_FilePanel *) observerData; + char *text; + WMList *list; + int col = WMGetBrowserNumberOfColumns(panel->browser) - 1; + int i, textEvent; + + if (!(list = WMGetBrowserListInColumn(panel->browser, col))) + return; + + text = WMGetTextFieldText(panel->fileField); + textEvent = (int)(uintptr_t) WMGetNotificationClientData(notification); + + if (panel->flags.autoCompletion && textEvent != WMDeleteTextEvent) + i = closestListItem(list, text, False); + else + i = closestListItem(list, text, True); + + WMSelectListItem(list, i); + if (i >= 0 && panel->flags.autoCompletion) { + WMListItem *item = WMGetListItem(list, i); + int textLen = strlen(text), itemTextLen = strlen(item->text); + int visibleItems = WMWidgetHeight(list) / WMGetListItemHeight(list); + + WMSetListPosition(list, i - visibleItems / 2); + + if (textEvent != WMDeleteTextEvent) { + WMRange range; + + WMInsertTextFieldText(panel->fileField, &item->text[textLen], textLen); + range.position = textLen; + range.count = itemTextLen - textLen; + WMSelectTextFieldRange(panel->fileField, range); + /*WMSetTextFieldCursorPosition(panel->fileField, itemTextLen); */ + } + } + + wfree(text); +} + +static void textEditedObserver(void *observerData, WMNotification * notification) +{ + W_FilePanel *panel = (W_FilePanel *) observerData; + + if ((int)(uintptr_t) WMGetNotificationClientData(notification) == WMReturnTextMovement) { + WMPerformButtonClick(panel->okButton); + } +} + +static WMFilePanel *makeFilePanel(WMScreen * scrPtr, char *name, char *title) +{ + WMFilePanel *fPtr; + WMFont *largeFont; + WMPixmap *icon; + + fPtr = wmalloc(sizeof(WMFilePanel)); + memset(fPtr, 0, sizeof(WMFilePanel)); + + fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask | WMResizableWindowMask); + WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT); + WMSetWindowTitle(fPtr->win, ""); + + WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask, handleEvents, fPtr); + WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT); + + fPtr->iconLabel = WMCreateLabel(fPtr->win); + WMResizeWidget(fPtr->iconLabel, 64, 64); + WMMoveWidget(fPtr->iconLabel, 0, 0); + WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly); + icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor *) NULL); + if (icon) { + WMSetLabelImage(fPtr->iconLabel, icon); + WMReleasePixmap(icon); + } else { + WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIconPixmap); + } + + fPtr->titleLabel = WMCreateLabel(fPtr->win); + WMResizeWidget(fPtr->titleLabel, PWIDTH - 64, 64); + WMMoveWidget(fPtr->titleLabel, 64, 0); + largeFont = WMBoldSystemFontOfSize(scrPtr, 24); + WMSetLabelFont(fPtr->titleLabel, largeFont); + WMReleaseFont(largeFont); + WMSetLabelText(fPtr->titleLabel, title); + + fPtr->line = WMCreateFrame(fPtr->win); + WMMoveWidget(fPtr->line, 0, 64); + WMResizeWidget(fPtr->line, PWIDTH, 2); + WMSetFrameRelief(fPtr->line, WRGroove); + + fPtr->browser = WMCreateBrowser(fPtr->win); + WMSetBrowserAllowEmptySelection(fPtr->browser, True); + WMSetBrowserDelegate(fPtr->browser, &browserDelegate); + WMSetBrowserAction(fPtr->browser, browserClick, fPtr); + WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr); + WMMoveWidget(fPtr->browser, 7, 72); + WMResizeWidget(fPtr->browser, PWIDTH - 14, 200); + WMHangData(fPtr->browser, fPtr); + + fPtr->nameLabel = WMCreateLabel(fPtr->win); + WMMoveWidget(fPtr->nameLabel, 7, 282); + WMResizeWidget(fPtr->nameLabel, 55, 14); + WMSetLabelText(fPtr->nameLabel, _("Name:")); + + fPtr->fileField = WMCreateTextField(fPtr->win); + WMMoveWidget(fPtr->fileField, 60, 278); + WMResizeWidget(fPtr->fileField, PWIDTH - 60 - 10, 24); + WMAddNotificationObserver(textEditedObserver, fPtr, WMTextDidEndEditingNotification, fPtr->fileField); + WMAddNotificationObserver(textChangedObserver, fPtr, WMTextDidChangeNotification, fPtr->fileField); + + fPtr->okButton = WMCreateCommandButton(fPtr->win); + WMMoveWidget(fPtr->okButton, 245, 325); + WMResizeWidget(fPtr->okButton, 75, 28); + WMSetButtonText(fPtr->okButton, _("OK")); + WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow); + WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow); + WMSetButtonImagePosition(fPtr->okButton, WIPRight); + WMSetButtonAction(fPtr->okButton, buttonClick, fPtr); + + fPtr->cancelButton = WMCreateCommandButton(fPtr->win); + WMMoveWidget(fPtr->cancelButton, 165, 325); + WMResizeWidget(fPtr->cancelButton, 75, 28); + WMSetButtonText(fPtr->cancelButton, _("Cancel")); + WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr); + + fPtr->trashcanButton = WMCreateCommandButton(fPtr->win); + WMMoveWidget(fPtr->trashcanButton, 7, 325); + WMResizeWidget(fPtr->trashcanButton, 28, 28); + WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly); + WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon); + WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon); + WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr); + + fPtr->createDirButton = WMCreateCommandButton(fPtr->win); + WMMoveWidget(fPtr->createDirButton, 37, 325); + WMResizeWidget(fPtr->createDirButton, 28, 28); + WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly); + WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon); + WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon); + WMSetButtonAction(fPtr->createDirButton, createDir, fPtr); + + fPtr->homeButton = WMCreateCommandButton(fPtr->win); + WMMoveWidget(fPtr->homeButton, 67, 325); + WMResizeWidget(fPtr->homeButton, 28, 28); + WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly); + WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon); + WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon); + WMSetButtonAction(fPtr->homeButton, goHome, fPtr); + + fPtr->disketteButton = WMCreateCommandButton(fPtr->win); + WMMoveWidget(fPtr->disketteButton, 97, 325); + WMResizeWidget(fPtr->disketteButton, 28, 28); + WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly); + WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon); + WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon); + WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr); + + fPtr->unmountButton = WMCreateCommandButton(fPtr->win); + WMMoveWidget(fPtr->unmountButton, 127, 325); + WMResizeWidget(fPtr->unmountButton, 28, 28); + WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly); + WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon); + WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon); + WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr); + WMSetButtonEnabled(fPtr->unmountButton, False); + + WMRealizeWidget(fPtr->win); + WMMapSubwidgets(fPtr->win); + + WMSetFocusToWidget(fPtr->fileField); + WMSetTextFieldCursorPosition(fPtr->fileField, 0); + + WMLoadBrowserColumnZero(fPtr->browser); + + WMSetWindowInitialPosition(fPtr->win, + (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win)) / 2, + (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win)) / 2); + + fPtr->flags.canChooseFiles = 1; + fPtr->flags.canChooseDirectories = 1; + fPtr->flags.autoCompletion = 1; + + return fPtr; +} + +WMOpenPanel *WMGetOpenPanel(WMScreen * scrPtr) +{ + WMFilePanel *panel; + + if (scrPtr->sharedOpenPanel) + return scrPtr->sharedOpenPanel; + + panel = makeFilePanel(scrPtr, "openFilePanel", _("Open")); + panel->flags.fileMustExist = 1; + panel->flags.panelType = WP_OPEN; + + scrPtr->sharedOpenPanel = panel; + + return panel; +} + +WMSavePanel *WMGetSavePanel(WMScreen * scrPtr) +{ + WMFilePanel *panel; + + if (scrPtr->sharedSavePanel) + return scrPtr->sharedSavePanel; + + panel = makeFilePanel(scrPtr, "saveFilePanel", _("Save")); + panel->flags.fileMustExist = 0; + panel->flags.panelType = WP_SAVE; + + scrPtr->sharedSavePanel = panel; + + return panel; +} + +void WMFreeFilePanel(WMFilePanel * panel) +{ + if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) { + WMWidgetScreen(panel->win)->sharedSavePanel = NULL; + } + if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) { + WMWidgetScreen(panel->win)->sharedOpenPanel = NULL; + } + WMRemoveNotificationObserver(panel); + WMUnmapWidget(panel->win); + WMDestroyWidget(panel->win); + wfree(panel); +} + +int +WMRunModalFilePanelForDirectory(WMFilePanel * panel, WMWindow * owner, char *path, char *name, char **fileTypes) +{ + WMScreen *scr = WMWidgetScreen(panel->win); + + if (name && !owner) { + WMSetWindowTitle(panel->win, name); + } + + WMChangePanelOwner(panel->win, owner); + + WMSetFilePanelDirectory(panel, path); + + switch (panel->flags.panelType) { + case WP_OPEN: + if (fileTypes) + panel->flags.filtered = 1; + panel->fileTypes = fileTypes; + if (name == NULL) + name = _("Open"); + break; + case WP_SAVE: + panel->fileTypes = NULL; + panel->flags.filtered = 0; + if (name == NULL) + name = _("Save"); + break; + default: + break; + } + + WMSetLabelText(panel->titleLabel, name); + + WMMapWidget(panel->win); + + WMRunModalLoop(scr, W_VIEW(panel->win)); + + /* Must withdraw window because the next time we map + * it, it might have a different transient owner. + */ + WMCloseWindow(panel->win); + + return (panel->flags.canceled ? False : True); +} + +void WMSetFilePanelDirectory(WMFilePanel * panel, char *path) +{ + WMList *list; + WMListItem *item; + int col; + char *rest; + + rest = WMSetBrowserPath(panel->browser, path); + if (strcmp(path, "/") == 0) + rest = NULL; + + col = WMGetBrowserSelectedColumn(panel->browser); + list = WMGetBrowserListInColumn(panel->browser, col); + if (list && (item = WMGetListSelectedItem(list))) { + if (item->isBranch) { + WMSetTextFieldText(panel->fileField, rest); + } else { + WMSetTextFieldText(panel->fileField, item->text); + } + } else { + WMSetTextFieldText(panel->fileField, rest); + } +} + +void WMSetFilePanelCanChooseDirectories(WMFilePanel * panel, Bool flag) +{ + panel->flags.canChooseDirectories = ((flag == 0) ? 0 : 1); +} + +void WMSetFilePanelCanChooseFiles(WMFilePanel * panel, Bool flag) +{ + panel->flags.canChooseFiles = ((flag == 0) ? 0 : 1); +} + +void WMSetFilePanelAutoCompletion(WMFilePanel * panel, Bool flag) +{ + panel->flags.autoCompletion = ((flag == 0) ? 0 : 1); +} + +char *WMGetFilePanelFileName(WMFilePanel * panel) +{ + return getCurrentFileName(panel); +} + +void WMSetFilePanelAccessoryView(WMFilePanel * panel, WMView * view) +{ + WMView *v; + + panel->accessoryView = view; + + v = WMWidgetView(panel->win); + + W_ReparentView(view, v, 0, 0); + + W_MoveView(view, (v->size.width - v->size.width) / 2, 300); +} + +WMView *WMGetFilePanelAccessoryView(WMFilePanel * panel) +{ + return panel->accessoryView; +} + +static char *get_name_from_path(char *path) +{ + int size; + + assert(path != NULL); + + size = strlen(path); + + /* remove trailing / */ + while (size > 0 && path[size - 1] == '/') + size--; + /* directory was root */ + if (size == 0) + return wstrdup("/"); + + while (size > 0 && path[size - 1] != '/') + size--; + + return wstrdup(&(path[size])); +} + +static int filterFileName(WMFilePanel * panel, char *file, Bool isDirectory) +{ + return True; +} + +#define CAST(item) (*((WMListItem**)item)) +static int comparer(const void *a, const void *b) +{ + if (CAST(a)->isBranch == CAST(b)->isBranch) + return (strcmp(CAST(a)->text, CAST(b)->text)); + if (CAST(a)->isBranch) + return (-1); + return (1); +} + +#undef CAST + +static void listDirectoryOnColumn(WMFilePanel * panel, int column, char *path) +{ + WMBrowser *bPtr = panel->browser; + struct dirent *dentry; + DIR *dir; + struct stat stat_buf; + char pbuf[PATH_MAX + 16]; + char *name; + + assert(column >= 0); + assert(path != NULL); + + /* put directory name in the title */ + name = get_name_from_path(path); + WMSetBrowserColumnTitle(bPtr, column, name); + wfree(name); + + dir = opendir(path); + + if (!dir) { +#ifdef VERBOSE + printf(_("WINGs: could not open directory %s\n"), path); +#endif + return; + } + + /* list contents in the column */ + while ((dentry = readdir(dir))) { + if (strcmp(dentry->d_name, ".") == 0 || strcmp(dentry->d_name, "..") == 0) + continue; + + strcpy(pbuf, path); + if (strcmp(path, "/") != 0) + strcat(pbuf, "/"); + strcat(pbuf, dentry->d_name); + + if (stat(pbuf, &stat_buf) != 0) { +#ifdef VERBOSE + printf(_("WINGs: could not stat %s\n"), pbuf); +#endif + continue; + } else { + int isDirectory; + + isDirectory = S_ISDIR(stat_buf.st_mode); + + if (filterFileName(panel, dentry->d_name, isDirectory)) + WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory); + } + } + WMSortBrowserColumnWithComparer(bPtr, column, comparer); + + closedir(dir); +} + +static void fillColumn(WMBrowserDelegate * self, WMBrowser * bPtr, int column, WMList * list) +{ + char *path; + WMFilePanel *panel; + + if (column > 0) { + path = WMGetBrowserPathToColumn(bPtr, column - 1); + } else { + path = wstrdup("/"); + } + + panel = WMGetHangedData(bPtr); + listDirectoryOnColumn(panel, column, path); + wfree(path); +} + +static void browserDClick(WMBrowser * bPtr, WMFilePanel * panel) +{ + WMPerformButtonClick(panel->okButton); +} + +static void browserClick(WMBrowser * bPtr, WMFilePanel * panel) +{ + int col = WMGetBrowserSelectedColumn(bPtr); + WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col); + + if (!item || item->isBranch) + WMSetTextFieldText(panel->fileField, NULL); + else { + WMSetTextFieldText(panel->fileField, item->text); + } +} + +static void showError(WMScreen * scr, WMWindow * owner, char *s, char *file) +{ + char *errStr; + + if (file) { + errStr = wmalloc(strlen(file) + strlen(s)); + sprintf(errStr, s, file); + } else { + errStr = wstrdup(s); + } + WMRunAlertPanel(scr, owner, _("Error"), errStr, _("OK"), NULL, NULL); + wfree(errStr); +} + +static void createDir(WMButton * bPre, WMFilePanel * panel) +{ + char *dirName, *directory, *file, *s; + WMScreen *scr = WMWidgetScreen(panel->win); + + dirName = WMRunInputPanel(scr, panel->win, _("Create Directory"), + _("Enter directory name"), "", _("OK"), _("Cancel")); + if (!dirName) + return; + + directory = getCurrentFileName(panel); + s = strrchr(directory, '/'); + if (s) + s[1] = 0; + + if (dirName[0] == '/') { + directory[0] = 0; + } else { + while ((s = strstr(directory, "//"))) { + int i; + for (i = 2; s[i] == '/'; i++) ; + strcpy(s, &s[i - 1]); + } + if ((s = strrchr(directory, '/')) && !s[1]) + s[0] = 0; + } + while ((s = strstr(dirName, "//"))) { + int i; + for (i = 2; s[i] == '/'; i++) ; + strcpy(s, &s[i - 1]); + } + if ((s = strrchr(dirName, '/')) && !s[1]) + s[0] = 0; + + file = wmalloc(strlen(dirName) + strlen(directory) + 4); + sprintf(file, "%s/%s", directory, dirName); + while ((s = strstr(file, "//"))) { + int i; + for (i = 2; s[i] == '/'; i++) ; + strcpy(s, &s[i - 1]); + } + + if (mkdir(file, 0xfff) != 0) { + switch (errno) { + case EACCES: + showError(scr, panel->win, _("Permission denied."), NULL); + break; + case EEXIST: + showError(scr, panel->win, _("'%s' already exists."), file); + break; + case ENOENT: + showError(scr, panel->win, _("Path does not exist."), NULL); + } + } else + WMSetFilePanelDirectory(panel, file); + + wfree(dirName); + wfree(directory); + wfree(file); +} + +static void deleteFile(WMButton * bPre, WMFilePanel * panel) +{ + char *file; + char *buffer, *s; + struct stat filestat; + WMScreen *scr = WMWidgetScreen(panel->win); + + file = getCurrentFileName(panel); + + while ((s = strstr(file, "//"))) { + int i; + for (i = 2; s[i] == '/'; i++) ; + strcpy(s, &s[i - 1]); + } + if (strlen(file) > 1 && (s = strrchr(file, '/')) && !s[1]) + s[0] = 0; + + if (stat(file, &filestat)) { + switch (errno) { + case ENOENT: + showError(scr, panel->win, _("'%s' does not exist."), file); + break; + case EACCES: + showError(scr, panel->win, _("Permission denied."), NULL); + break; + case ENOMEM: + showError(scr, panel->win, _("Insufficient memory available."), NULL); + break; + case EROFS: + showError(scr, panel->win, _("'%s' is on a read-only filesystem."), file); + break; + default: + showError(scr, panel->win, _("Can not delete '%s'."), file); + } + wfree(file); + return; + } else if (S_ISDIR(filestat.st_mode)) { + int len = strlen(file) + 20; + buffer = wmalloc(len); + snprintf(buffer, len, _("Delete directory %s ?"), file); + } else { + int len = strlen(file) + 15; + buffer = wmalloc(len); + snprintf(buffer, len, _("Delete file %s ?"), file); + } + + if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win, + _("Warning"), buffer, _("OK"), _("Cancel"), NULL)) { + if (S_ISDIR(filestat.st_mode)) { + if (rmdir(file) != 0) { + switch (errno) { + case EACCES: + showError(scr, panel->win, _("Permission denied."), NULL); + break; + case ENOENT: + showError(scr, panel->win, _("Directory '%s' does not exist."), file); + break; + case ENOTEMPTY: + showError(scr, panel->win, _("Directory '%s' is not empty."), file); + break; + case EBUSY: + showError(scr, panel->win, _("Directory '%s' is busy."), file); + break; + default: + showError(scr, panel->win, _("Can not delete '%s'."), file); + } + } else { + char *s = strrchr(file, '/'); + if (s) + s[0] = 0; + WMSetFilePanelDirectory(panel, file); + } + } else if (remove(file) != 0) { + switch (errno) { + case EISDIR: + showError(scr, panel->win, _("'%s' is a directory."), file); + break; + case ENOENT: + showError(scr, panel->win, _("'%s' does not exist."), file); + break; + case EACCES: + showError(scr, panel->win, _("Permission denied."), NULL); + break; + case ENOMEM: + showError(scr, panel->win, _("Insufficient memory available."), NULL); + break; + case EROFS: + showError(scr, panel->win, _("'%s' is on a read-only filesystem."), file); + break; + default: + showError(scr, panel->win, _("Can not delete '%s'."), file); + } + } else { + char *s = strrchr(file, '/'); + if (s) + s[1] = 0; + WMSetFilePanelDirectory(panel, file); + } + } + wfree(buffer); + wfree(file); +} + +static void goUnmount(WMButton * bPtr, WMFilePanel * panel) +{ +} + +static void goFloppy(WMButton * bPtr, WMFilePanel * panel) +{ + struct stat filestat; + WMScreen *scr = WMWidgetScreen(panel->win); + + if (stat(WINGsConfiguration.floppyPath, &filestat)) { + showError(scr, panel->win, _("An error occured browsing '%s'."), WINGsConfiguration.floppyPath); + return; + } else if (!S_ISDIR(filestat.st_mode)) { + showError(scr, panel->win, _("'%s' is not a directory."), WINGsConfiguration.floppyPath); + return; + } + + WMSetFilePanelDirectory(panel, WINGsConfiguration.floppyPath); +} + +static void goHome(WMButton * bPtr, WMFilePanel * panel) +{ + char *home; + + /* home is statically allocated. Don't free it! */ + home = wgethomedir(); + if (!home) + return; + + WMSetFilePanelDirectory(panel, home); +} + +static void handleEvents(XEvent * event, void *data) +{ + W_FilePanel *pPtr = (W_FilePanel *) data; + W_View *view = WMWidgetView(pPtr->win); + + if (event->type == ConfigureNotify) { + if (event->xconfigure.width != view->size.width || event->xconfigure.height != view->size.height) { + unsigned int newWidth = event->xconfigure.width; + unsigned int newHeight = event->xconfigure.height; + int newColumnCount; + + W_ResizeView(view, newWidth, newHeight); + WMResizeWidget(pPtr->line, newWidth, 2); + WMResizeWidget(pPtr->browser, newWidth - 14, newHeight - (PHEIGHT - 200)); + WMResizeWidget(pPtr->fileField, newWidth - 60 - 10, 24); + WMMoveWidget(pPtr->nameLabel, 7, newHeight - (PHEIGHT - 282)); + WMMoveWidget(pPtr->fileField, 60, newHeight - (PHEIGHT - 278)); + WMMoveWidget(pPtr->okButton, newWidth - (PWIDTH - 245), newHeight - (PHEIGHT - 325)); + WMMoveWidget(pPtr->cancelButton, newWidth - (PWIDTH - 165), newHeight - (PHEIGHT - 325)); + + WMMoveWidget(pPtr->trashcanButton, 7, newHeight - (PHEIGHT - 325)); + WMMoveWidget(pPtr->createDirButton, 37, newHeight - (PHEIGHT - 325)); + WMMoveWidget(pPtr->homeButton, 67, newHeight - (PHEIGHT - 325)); + WMMoveWidget(pPtr->disketteButton, 97, newHeight - (PHEIGHT - 325)); + WMMoveWidget(pPtr->unmountButton, 127, newHeight - (PHEIGHT - 325)); + + newColumnCount = (newWidth - 14) / 140; + WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount); + } + } +} + +static char *getCurrentFileName(WMFilePanel * panel) +{ + char *path; + char *file; + char *tmp; + int len; + + path = WMGetBrowserPath(panel->browser); + + len = strlen(path); + if (path[len - 1] == '/') { + file = WMGetTextFieldText(panel->fileField); + tmp = wmalloc(strlen(path) + strlen(file) + 8); + if (file[0] != '/') { + strcpy(tmp, path); + strcat(tmp, file); + } else + strcpy(tmp, file); + + wfree(file); + wfree(path); + return tmp; + } else { + return path; + } +} + +static Bool validOpenFile(WMFilePanel * panel) +{ + WMListItem *item; + int col, haveFile = 0; + char *file = WMGetTextFieldText(panel->fileField); + + if (file[0] != '\0') + haveFile = 1; + wfree(file); + + col = WMGetBrowserSelectedColumn(panel->browser); + item = WMGetBrowserSelectedItemInColumn(panel->browser, col); + if (item) { + if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile) + return False; + else if (!item->isBranch && !panel->flags.canChooseFiles) + return False; + else + return True; + } else { + /* we compute for / here */ + if (!panel->flags.canChooseDirectories && !haveFile) + return False; + else + return True; + } + return True; +} + +static void buttonClick(WMButton * bPtr, WMFilePanel * panel) +{ + WMRange range; + + if (bPtr == panel->okButton) { + if (!validOpenFile(panel)) + return; + if (panel->flags.fileMustExist) { + char *file; + + file = getCurrentFileName(panel); + if (access(file, F_OK) != 0) { + WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win, + _("Error"), _("File does not exist."), _("OK"), NULL, NULL); + wfree(file); + return; + } + wfree(file); + } + panel->flags.canceled = 0; + } else + panel->flags.canceled = 1; + + range.count = range.position = 0; + WMSelectTextFieldRange(panel->fileField, range); + WMBreakModalLoop(WMWidgetScreen(bPtr)); +}