mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-18 03:50:30 +01:00
Update all the callers in our code to deal with the const qualifier where the compiler reports an issue.
897 lines
23 KiB
C
897 lines
23 KiB
C
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
#include <dirent.h>
|
|
#include <limits.h>
|
|
#include <errno.h>
|
|
#include <stdint.h>
|
|
|
|
#include "WINGsP.h"
|
|
#include "wconfig.h"
|
|
|
|
#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, const char *path);
|
|
static void browserClick(WMWidget *widget, void *p_panel);
|
|
static void browserDClick(WMWidget *widget, void *p_panel);
|
|
|
|
static void fillColumn(WMBrowserDelegate * self, WMBrowser * bPtr, int column, WMList * list);
|
|
|
|
static void normalizePath(char *s);
|
|
|
|
static void deleteFile(WMWidget *widget, void *p_panel);
|
|
static void createDir(WMWidget *widget, void *p_panel);
|
|
static void goHome(WMWidget *widget, void *p_panel);
|
|
static void goFloppy(WMWidget *widget, void *p_panel);
|
|
static void goUnmount(WMWidget *widget, void *p_panel);
|
|
static void buttonClick(WMWidget *widget, void *p_panel);
|
|
|
|
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, const char *text, Bool exact)
|
|
{
|
|
WMListItem *item;
|
|
WMArray *items = WMGetListItems(list);
|
|
int i, nb_item, len = strlen(text);
|
|
|
|
if (len == 0)
|
|
return -1;
|
|
|
|
nb_item = WMGetArrayItemCount(items);
|
|
for (i = 0; i < nb_item; i++) {
|
|
item = WMGetFromArray(items, i);
|
|
if ((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;
|
|
uintptr_t textEvent;
|
|
|
|
if (!(list = WMGetBrowserListInColumn(panel->browser, col)))
|
|
return;
|
|
|
|
text = WMGetTextFieldText(panel->fileField);
|
|
textEvent = (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 ((uintptr_t)WMGetNotificationClientData(notification) == WMReturnTextMovement) {
|
|
WMPerformButtonClick(panel->okButton);
|
|
}
|
|
}
|
|
|
|
static WMFilePanel *makeFilePanel(WMScreen * scrPtr, const char *name, const char *title)
|
|
{
|
|
WMFilePanel *fPtr;
|
|
WMFont *largeFont;
|
|
WMPixmap *icon;
|
|
|
|
fPtr = wmalloc(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, const char *path, const 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, const char *path)
|
|
{
|
|
WMList *list;
|
|
WMListItem *item;
|
|
int col;
|
|
const 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(const 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]));
|
|
}
|
|
|
|
#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, const 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;
|
|
|
|
if (wstrlcpy(pbuf, path, sizeof(pbuf)) >= sizeof(pbuf))
|
|
goto out;
|
|
if (strcmp(path, "/") != 0 &&
|
|
wstrlcat(pbuf, "/", sizeof(pbuf)) >= sizeof(pbuf))
|
|
goto out;
|
|
if (wstrlcat(pbuf, dentry->d_name, sizeof(pbuf)) >= sizeof(pbuf))
|
|
goto out;
|
|
|
|
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);
|
|
WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory);
|
|
}
|
|
}
|
|
WMSortBrowserColumnWithComparer(bPtr, column, comparer);
|
|
|
|
out:
|
|
closedir(dir);
|
|
}
|
|
|
|
static void fillColumn(WMBrowserDelegate * self, WMBrowser * bPtr, int column, WMList * list)
|
|
{
|
|
char *path;
|
|
WMFilePanel *panel;
|
|
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) self;
|
|
(void) list;
|
|
|
|
if (column > 0) {
|
|
path = WMGetBrowserPathToColumn(bPtr, column - 1);
|
|
} else {
|
|
path = wstrdup("/");
|
|
}
|
|
|
|
panel = WMGetHangedData(bPtr);
|
|
listDirectoryOnColumn(panel, column, path);
|
|
wfree(path);
|
|
}
|
|
|
|
static void browserDClick(WMWidget *widget, void *p_panel)
|
|
{
|
|
WMFilePanel *panel = p_panel;
|
|
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) widget;
|
|
|
|
WMPerformButtonClick(panel->okButton);
|
|
}
|
|
|
|
static void browserClick(WMWidget *widget, void *p_panel)
|
|
{
|
|
WMBrowser *bPtr = (WMBrowser *) widget;
|
|
WMFilePanel *panel = p_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, const char *s, const char *file)
|
|
{
|
|
char *errStr;
|
|
|
|
if (file) {
|
|
errStr = wmalloc(strlen(file) + strlen(s) + 1);
|
|
sprintf(errStr, s, file);
|
|
} else {
|
|
errStr = wstrdup(s);
|
|
}
|
|
WMRunAlertPanel(scr, owner, _("Error"), errStr, _("OK"), NULL, NULL);
|
|
wfree(errStr);
|
|
}
|
|
|
|
static void createDir(WMWidget *widget, void *p_panel)
|
|
{
|
|
WMFilePanel *panel = p_panel;
|
|
char *dirName, *directory, *file;
|
|
size_t slen;
|
|
WMScreen *scr = WMWidgetScreen(panel->win);
|
|
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) widget;
|
|
|
|
dirName = WMRunInputPanel(scr, panel->win, _("Create Directory"),
|
|
_("Enter directory name"), "", _("OK"), _("Cancel"));
|
|
if (!dirName)
|
|
return;
|
|
|
|
/* if `dirName' is an absolute path, don't mind `directory'.
|
|
* normalize as needed (possibly not needed at all?) */
|
|
normalizePath(dirName);
|
|
if (*dirName != '/') {
|
|
directory = getCurrentFileName(panel);
|
|
normalizePath(directory);
|
|
} else {
|
|
directory = NULL;
|
|
}
|
|
|
|
slen = strlen(dirName) + (directory ? strlen(directory) + 1 /* "/" */ : 0) + 1 /* NULL */;
|
|
file = wmalloc(slen);
|
|
|
|
if (directory &&
|
|
(wstrlcat(file, directory, slen) >= slen ||
|
|
wstrlcat(file, "/", slen) >= slen))
|
|
goto out;
|
|
|
|
if (wstrlcat(file, dirName, slen) >= slen)
|
|
goto out;
|
|
|
|
if (mkdir(file, 00777) != 0) {
|
|
#define __msgbufsize__ 512
|
|
char *buffer = wmalloc(__msgbufsize__);
|
|
snprintf(buffer, __msgbufsize__, _("Can not create %s: %s"), file, strerror(errno));
|
|
showError(scr, panel->win, buffer, NULL);
|
|
wfree(buffer);
|
|
#undef __msgbufsize__
|
|
} else {
|
|
WMSetFilePanelDirectory(panel, file);
|
|
}
|
|
|
|
out:
|
|
if (dirName)
|
|
wfree(dirName);
|
|
if (directory)
|
|
wfree(directory);
|
|
if (file)
|
|
wfree(file);
|
|
}
|
|
|
|
/*
|
|
*----------------------------------------------------------------------
|
|
* normalizePath--
|
|
* Remove multiple consecutive and any trailing slashes from
|
|
* a path.
|
|
*----------------------------------------------------------------------
|
|
*/
|
|
static void normalizePath(char *s)
|
|
{
|
|
int i, j, found;
|
|
|
|
found = 0;
|
|
for (i = 0; s[i]; (void)(!found && i++)) {
|
|
found = 0;
|
|
if (s[i] == '/' && s[i+1] == '/') {
|
|
int nslash = 1;
|
|
found = 1;
|
|
i++;
|
|
while (s[i+nslash] == '/')
|
|
nslash++;
|
|
for (j = 0; s[i+j+nslash]; j++)
|
|
s[i+j] = s[i+j+nslash];
|
|
s[i+j] = '\0';
|
|
}
|
|
}
|
|
if (i > 1 && s[--i] == '/')
|
|
s[i] = '\0';
|
|
}
|
|
|
|
|
|
static void deleteFile(WMWidget *widget, void *p_panel)
|
|
{
|
|
WMFilePanel *panel = p_panel;
|
|
char *file;
|
|
char buffer[512];
|
|
struct stat filestat;
|
|
WMScreen *scr = WMWidgetScreen(panel->win);
|
|
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) widget;
|
|
|
|
file = getCurrentFileName(panel);
|
|
if (file == NULL)
|
|
return;
|
|
|
|
normalizePath(file);
|
|
|
|
if (stat(file, &filestat) == -1) {
|
|
snprintf(buffer, sizeof(buffer),
|
|
_("Can not find %s: %s"),
|
|
file, strerror(errno));
|
|
showError(scr, panel->win, buffer, NULL);
|
|
goto out;
|
|
}
|
|
|
|
snprintf(buffer, sizeof(buffer), _("Delete %s %s?"),
|
|
S_ISDIR(filestat.st_mode) ? _("directory") : _("file"), file);
|
|
|
|
if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
|
|
_("Warning"), buffer, _("OK"), _("Cancel"), NULL)) {
|
|
|
|
if (remove(file) == -1) {
|
|
snprintf(buffer, sizeof(buffer),
|
|
_("Removing %s failed: %s"),
|
|
file, strerror(errno));
|
|
showError(scr, panel->win, buffer, NULL);
|
|
} else {
|
|
char *s = strrchr(file, '/');
|
|
if (s)
|
|
s[0] = 0;
|
|
WMSetFilePanelDirectory(panel, file);
|
|
}
|
|
|
|
}
|
|
out:
|
|
wfree(file);
|
|
}
|
|
|
|
static void goUnmount(WMWidget *widget, void *p_panel)
|
|
{
|
|
/* Not implemented yet */
|
|
(void) widget;
|
|
(void) p_panel;
|
|
}
|
|
|
|
static void goFloppy(WMWidget *widget, void *p_panel)
|
|
{
|
|
WMFilePanel *panel = p_panel;
|
|
struct stat filestat;
|
|
WMScreen *scr = WMWidgetScreen(panel->win);
|
|
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) widget;
|
|
|
|
if (stat(WINGsConfiguration.floppyPath, &filestat)) {
|
|
showError(scr, panel->win, _("An error occurred 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(WMWidget *widget, void *p_panel)
|
|
{
|
|
WMFilePanel *panel = p_panel;
|
|
const char *home;
|
|
|
|
/* Parameter not used, but tell the compiler that it is ok */
|
|
(void) widget;
|
|
|
|
/* 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 *ret;
|
|
size_t slen;
|
|
|
|
path = WMGetBrowserPath(panel->browser);
|
|
|
|
if (!path)
|
|
return NULL;
|
|
|
|
if (path[strlen(path) -1] != '/')
|
|
return path;
|
|
|
|
file = WMGetTextFieldText(panel->fileField);
|
|
slen = strlen(path) + strlen(file) + 1;
|
|
ret = wmalloc(slen);
|
|
|
|
if (file[0] != '/')
|
|
strcpy(ret, path);
|
|
|
|
strcat(ret, file);
|
|
|
|
wfree(file);
|
|
wfree(path);
|
|
return ret;
|
|
}
|
|
|
|
|
|
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(WMWidget *widget, void *p_panel)
|
|
{
|
|
WMButton *bPtr = (WMButton *) widget;
|
|
WMFilePanel *panel = p_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));
|
|
}
|