Репозитории ALT
S: | 0.96.0-alt1 |
5.1: | 0.92.0-alt6 |
4.1: | 0.92.0-alt2 |
4.0: | 0.92.0-alt2 |
3.0: | 0.91.0-alt1 |
+backports: | 0.92.0-alt0.M30.1 |
Группа :: Графические оболочки/Window Maker
Пакет: WindowMaker
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: WindowMaker-0.92.0-alt-adialog.patch
Скачать
Скачать
src/WindowMaker.h | 1 +
src/defaults.c | 3 +
src/dialog.c | 322 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/dialog.h | 1 +
src/misc.c | 136 ++++++++--------------
5 files changed, 377 insertions(+), 86 deletions(-)
diff --git a/src/WindowMaker.h b/src/WindowMaker.h
index 6e10325..84d2856 100644
--- a/src/WindowMaker.h
+++ b/src/WindowMaker.h
@@ -491,6 +491,7 @@ typedef struct WPreferences {
char single_click;
int show_clip_title;
+ int history_lines;
struct {
unsigned int nodock:1; /* don't display the dock */
diff --git a/src/defaults.c b/src/defaults.c
index e874c94..b3b5f15 100644
--- a/src/defaults.c
+++ b/src/defaults.c
@@ -894,6 +894,9 @@ WDefaultEntry optionList[] = {
},
{"SelectCursor", "(builtin, cross)", (void*)WCUR_SELECT,
NULL, getCursor, setCursor
+ },
+ {"DialogHistoryLines", "500", NULL,
+ &wPreferences.history_lines, getInt, NULL
}
};
diff --git a/src/dialog.c b/src/dialog.c
index c71a896..cd43e14 100644
--- a/src/dialog.c
+++ b/src/dialog.c
@@ -178,6 +178,328 @@ wExitDialog(WScreen *scr, char *title, char *message,
return result;
}
+typedef struct _WMInputPanelWithHistory
+{
+ WMInputPanel *panel;
+ WMArray *history;
+ int histpos;
+ char *prefix;
+ char *suffix;
+ char *rest;
+ WMArray *variants;
+ int varpos;
+} WMInputPanelWithHistory;
+
+static char *
+HistoryFileName(char *name)
+{
+ char *filename = NULL;
+
+ filename = wstrdup(wusergnusteppath());
+ filename = wstrappend(filename, "/.AppInfo/WindowMaker/History");
+ if(name && strlen(name)) {
+ filename = wstrappend(filename, ".");
+ filename = wstrappend(filename, name);
+ }
+ return filename;
+}
+
+static int
+matchString(void *str1, void *str2)
+{
+ return (strcmp((char*)str1, (char*)str2)==0 ? 1 : 0);
+}
+
+static WMArray *
+LoadHistory(char *filename, int max)
+{
+ WMPropList *plhistory;
+ WMPropList *plitem;
+ WMArray *history;
+ int i, num;
+
+ history = WMCreateArrayWithDestructor(1, wfree);
+ WMAddToArray(history, wstrdup(""));
+
+ plhistory = WMReadPropListFromFile((char*)filename);
+
+ if(plhistory && WMIsPLArray(plhistory)) {
+ num = WMGetPropListItemCount(plhistory);
+ if(num > max) num = max;
+
+ for(i = 0; i < num; ++i) {
+ plitem = WMGetFromPLArray(plhistory, i);
+ if(WMIsPLString(plitem) && WMFindInArray(history, matchString,
+ WMGetFromPLString(plitem)) == WANotFound)
+ WMAddToArray(history, WMGetFromPLString(plitem));
+ }
+ }
+
+ return history;
+}
+
+static void
+SaveHistory(WMArray *history, char *filename)
+{
+ int i;
+ WMPropList *plhistory;
+
+ plhistory = WMCreatePLArray(NULL);
+
+ for(i = 0; i < WMGetArrayItemCount(history); ++i)
+ WMAddToPLArray(plhistory,
+ WMCreatePLString(WMGetFromArray(history, i)));
+
+ WMWritePropListToFile(plhistory, (char*)filename, False);
+ WMReleasePropList(plhistory);
+}
+
+static int
+strmatch(const char *str1, const char *str2)
+{
+ return !strcmp(str1, str2);
+}
+
+static int
+pstrcmp(const char **str1, const char **str2)
+{
+ return strcmp(*str1, *str2);
+}
+
+static void
+ScanFiles(const char *dir, const char *prefix, unsigned acceptmask,
+ unsigned declinemask, WMArray *result)
+{
+ int prefixlen;
+ DIR *d;
+ struct dirent *de;
+ struct stat sb;
+ char *fullfilename, *suffix;
+
+ prefixlen = strlen(prefix);
+ if((d = opendir(dir)) != NULL) {
+ while((de = readdir(d)) != NULL) {
+ if(strlen(de->d_name) > prefixlen &&
+ !strncmp(prefix, de->d_name, prefixlen) &&
+ strcmp(de->d_name, ".") != 0 &&
+ strcmp(de->d_name, "..")) {
+ fullfilename = wstrconcat((char*)dir, "/");
+ fullfilename = wstrappend(fullfilename, de->d_name);
+
+ if(stat(fullfilename, &sb) == 0 &&
+ (sb.st_mode & acceptmask) &&
+ !(sb.st_mode & declinemask) &&
+ WMFindInArray(result, (WMMatchDataProc*)strmatch,
+ de->d_name + prefixlen) == WANotFound) {
+ suffix = wstrdup(de->d_name + prefixlen);
+ WMAddToArray(result, suffix);
+ }
+ wfree(fullfilename);
+ }
+ }
+ closedir(d);
+ }
+}
+
+static WMArray *
+GenerateVariants(const char * complete)
+{
+ Bool firstWord = True;
+ WMArray *variants = NULL;
+ char *pos = NULL, *path = NULL, *tmp = NULL, *dir = NULL, *prefix = NULL;
+
+ variants = WMCreateArrayWithDestructor(0, wfree);
+
+ while(*complete == ' ') ++complete;
+
+ if((pos = strrchr(complete, ' ')) != NULL) {
+ complete = pos + 1;
+ firstWord = False;
+ }
+
+ if((pos = strrchr(complete, '/')) != NULL) {
+ tmp = wstrndup((char*)complete, pos - complete + 1);
+ if(*tmp == '~' && *(tmp+1) == '/' && getenv("HOME")) {
+ dir = wstrdup(getenv("HOME"));
+ dir = wstrappend(dir, tmp + 1);
+ wfree(tmp);
+ } else {
+ dir = tmp;
+ }
+ prefix = wstrdup(pos + 1);
+ ScanFiles(dir, prefix, (unsigned)-1, 0, variants);
+ wfree(dir);
+ wfree(prefix);
+ } else if(*complete == '~') {
+ WMAddToArray(variants, wstrdup("/"));
+ } else if(firstWord) {
+ path = getenv("PATH");
+ while(path) {
+ pos = strchr(path, ':');
+ if(pos) {
+ tmp = wstrndup(path, pos - path);
+ path = pos + 1;
+ } else if(*path != '\0') {
+ tmp = wstrdup(path);
+ path = NULL;
+ } else break;
+ ScanFiles(tmp, complete,
+ S_IXOTH | S_IXGRP | S_IXUSR, S_IFDIR, variants);
+ wfree(tmp);
+ }
+ }
+
+ WMSortArray(variants, (WMCompareDataProc*)pstrcmp);
+ return variants;
+}
+
+static void
+handleHistoryKeyPress(XEvent *event, void *clientData)
+{
+ char *text;
+ unsigned pos;
+ WMInputPanelWithHistory *p = (WMInputPanelWithHistory*)clientData;
+ KeySym ksym;
+
+ ksym = XLookupKeysym(&event->xkey, 0);
+
+ switch(ksym)
+ {
+ case XK_Up:
+ if(p->histpos < WMGetArrayItemCount(p->history) - 1) {
+ if(p->histpos == 0)
+ wfree(WMReplaceInArray(p->history,
+ 0, WMGetTextFieldText(p->panel->text)));
+ p->histpos++;
+ WMSetTextFieldText(p->panel->text,
+ WMGetFromArray(p->history, p->histpos));
+ }
+ break;
+ case XK_Down:
+ if(p->histpos > 0) {
+ p->histpos--;
+ WMSetTextFieldText(p->panel->text,
+ WMGetFromArray(p->history, p->histpos));
+ }
+ break;
+ case XK_Tab:
+ if(!p->variants) {
+ text = WMGetTextFieldText(p->panel->text);
+ pos = WMGetTextFieldCursorPosition(p->panel->text);
+ p->prefix = wstrndup(text, pos);
+ p->suffix = wstrdup(text + pos);
+ wfree(text);
+ p->variants = GenerateVariants(p->prefix);
+ p->varpos = 0;
+ if(!p->variants) {
+ wfree(p->prefix);
+ wfree(p->suffix);
+ p->prefix = NULL;
+ p->suffix = NULL;
+ }
+ }
+ if(p->variants && p->prefix && p->suffix) {
+ p->varpos++;
+ if(p->varpos > WMGetArrayItemCount(p->variants))
+ p->varpos = 0;
+ if(p->varpos > 0)
+ text = wstrconcat(p->prefix,
+ WMGetFromArray(p->variants, p->varpos - 1));
+ else
+ text = wstrdup(p->prefix);
+ pos = strlen(text);
+ text = wstrappend(text, p->suffix);
+ WMSetTextFieldText(p->panel->text, text);
+ WMSetTextFieldCursorPosition(p->panel->text, pos);
+ wfree(text);
+ }
+ break;
+ }
+ if(ksym != XK_Tab) {
+ if(p->prefix) {
+ wfree(p->prefix);
+ p->prefix = NULL;
+ }
+ if(p->suffix) {
+ wfree(p->suffix);
+ p->suffix = NULL;
+ }
+ if(p->variants) {
+ WMFreeArray(p->variants);
+ p->variants = NULL;
+ }
+ }
+}
+
+int
+wAdvancedInputDialog(WScreen *scr, char *title, char *message,
+ char *name, char **text)
+{
+ WWindow *wwin;
+ Window parent;
+ char *result;
+ WMPoint center;
+ WMInputPanelWithHistory *p;
+ char *filename;
+
+ filename = HistoryFileName(name);
+ p = wmalloc(sizeof(WMInputPanelWithHistory));
+ p->panel = WMCreateInputPanel(scr->wmscreen, NULL, title, message, *text,
+ _("OK"), _("Cancel"));
+ p->history = LoadHistory(filename, wPreferences.history_lines);
+ p->histpos = 0;
+ p->prefix = NULL;
+ p->suffix = NULL;
+ p->rest = NULL;
+ p->variants = NULL;
+ p->varpos = 0;
+ WMCreateEventHandler(WMWidgetView(p->panel->text), KeyPressMask,
+ handleHistoryKeyPress, p);
+
+ parent = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 320, 160, 0, 0, 0);
+ XSelectInput(dpy, parent, KeyPressMask|KeyReleaseMask);
+
+ XReparentWindow(dpy, WMWidgetXID(p->panel->win), parent, 0, 0);
+
+ center = getCenter(scr, 320, 160);
+ wwin = wManageInternalWindow(scr, parent, None, NULL, center.x, center.y,
+ 320, 160);
+
+ wwin->client_leader = WMWidgetXID(p->panel->win);
+
+ WMMapWidget(p->panel->win);
+
+ wWindowMap(wwin);
+
+ WMRunModalLoop(WMWidgetScreen(p->panel->win), WMWidgetView(p->panel->win));
+
+ if (p->panel->result == WAPRDefault) {
+ result = WMGetTextFieldText(p->panel->text);
+ wfree(WMReplaceInArray(p->history, 0, wstrdup(result)));
+ SaveHistory(p->history, filename);
+ }
+ else
+ result = NULL;
+
+ wUnmanageWindow(wwin, False, False);
+
+ WMDestroyInputPanel(p->panel);
+ WMFreeArray(p->history);
+ wfree(p);
+ wfree(filename);
+
+ XDestroyWindow(dpy, parent);
+
+ if (result==NULL)
+ return False;
+ else {
+ if (*text)
+ wfree(*text);
+ *text = result;
+
+ return True;
+ }
+}
int
wInputDialog(WScreen *scr, char *title, char *message, char **text)
diff --git a/src/dialog.h b/src/dialog.h
index 1c4af3b..61f842d 100644
--- a/src/dialog.h
+++ b/src/dialog.h
@@ -33,6 +33,7 @@ enum {
int wMessageDialog(WScreen *scr, char *title, char *message,
char *defBtn, char *altBtn, char *othBtn);
+int wAdvancedInputDialog(WScreen *scr, char *title, char *message, char *name, char **text);
int wInputDialog(WScreen *scr, char *title, char *message, char **text);
int wExitDialog(WScreen *scr, char *title, char *message, char *defBtn,
diff --git a/src/misc.c b/src/misc.c
index 31cb35a..93edfe5 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -607,97 +607,60 @@ getselection(WScreen *scr)
static char*
-getuserinput(WScreen *scr, char *line, int *ptr)
+parseuserinputpart(char *line, int *ptr, char *endchars)
{
- char *ret;
- char *title;
- char *prompt;
- int j, state;
- int begin = 0;
-#define BUFSIZE 512
- char tbuffer[BUFSIZE], pbuffer[BUFSIZE];
-
-
- title = _("Program Arguments");
- prompt = _("Enter command arguments:");
- ret = NULL;
-
-#define _STARTING 0
-#define _TITLE 1
-#define _PROMPT 2
-#define _DONE 3
-
- state = _STARTING;
- j = 0;
- for (; line[*ptr]!=0 && state!=_DONE; (*ptr)++) {
- switch (state) {
- case _STARTING:
- if (line[*ptr]=='(') {
- state = _TITLE;
- begin = *ptr+1;
- } else {
- state = _DONE;
- }
- break;
-
- case _TITLE:
- if (j <= 0 && line[*ptr]==',') {
-
- j = 0;
- if (*ptr > begin) {
- strncpy(tbuffer, &line[begin], WMIN(*ptr-begin, BUFSIZE));
- tbuffer[WMIN(*ptr-begin, BUFSIZE)] = 0;
- title = (char*)tbuffer;
- }
- begin = *ptr+1;
- state = _PROMPT;
-
- } else if (j <= 0 && line[*ptr]==')') {
-
- if (*ptr > begin) {
- strncpy(tbuffer, &line[begin], WMIN(*ptr-begin, BUFSIZE));
- tbuffer[WMIN(*ptr-begin, BUFSIZE)] = 0;
- title = (char*)tbuffer;
- }
- state = _DONE;
-
- } else if (line[*ptr]=='(') {
- j++;
- } else if (line[*ptr]==')') {
- j--;
- }
+ int depth = 0, begin;
+ char *value = NULL;
+ begin = ++*ptr;
+
+ while(line[*ptr] != '\0') {
+ if(line[*ptr] == '(') {
+ ++depth;
+ } else if(depth > 0 && line[*ptr] == ')') {
+ --depth;
+ } else if(depth == 0 && strchr(endchars, line[*ptr]) != NULL) {
+ value = wmalloc(*ptr - begin + 1);
+ strncpy(value, line + begin, *ptr - begin);
+ value[*ptr - begin] = '\0';
+ break;
+ }
+ ++*ptr;
+ }
+
+ return value;
+}
- break;
+static char*
+getuserinput(WScreen *scr, char *line, int *ptr, Bool advanced)
+{
+ char *ret = NULL, *title = NULL, *prompt = NULL, *name = NULL;
+ int rv;
+
+ if(line[*ptr] == '(')
+ title = parseuserinputpart(line, ptr, ",)");
+ if(title != NULL && line[*ptr] == ',')
+ prompt = parseuserinputpart(line, ptr, ",)");
+ if(prompt != NULL && line[*ptr] == ',')
+ name = parseuserinputpart(line, ptr, ")");
+
+ if(advanced)
+ rv = wAdvancedInputDialog(scr,
+ title ? gettext(title):_("Program Arguments"),
+ prompt ? gettext(prompt):_("Enter command arguments:"),
+ name, &ret);
+ else
+ rv = wInputDialog(scr,
+ title ? gettext(title):_("Program Arguments"),
+ prompt ? gettext(prompt):_("Enter command arguments:"),
+ &ret);
- case _PROMPT:
- if (line[*ptr]==')' && j==0) {
+ if(title) wfree(title);
+ if(prompt) wfree(prompt);
+ if(name) wfree(name);
- if (*ptr-begin > 1) {
- strncpy(pbuffer, &line[begin], WMIN(*ptr-begin, BUFSIZE));
- pbuffer[WMIN(*ptr-begin, BUFSIZE)] = 0;
- prompt = (char*)pbuffer;
- }
- state = _DONE;
- } else if (line[*ptr]=='(')
- j++;
- else if (line[*ptr]==')')
- j--;
- break;
- }
- }
- (*ptr)--;
-#undef _STARTING
-#undef _TITLE
-#undef _PROMPT
-#undef _DONE
-
- if (!wInputDialog(scr, title, prompt, &ret))
- return NULL;
- else
- return ret;
+ return rv ? ret : NULL;
}
-
#define S_NORMAL 0
#define S_ESCAPE 1
#define S_OPTION 2
@@ -814,8 +777,9 @@ ExpandOptions(WScreen *scr, char *cmdline)
break;
case 'a':
+ case 'A':
ptr++;
- user_input = getuserinput(scr, cmdline, &ptr);
+ user_input = getuserinput(scr, cmdline, &ptr, cmdline[ptr-1] == 'A');
if (user_input) {
slen = strlen(user_input);
olen += slen;