Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37514665
en ru br
Репозитории 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
www.altlinux.org/Changes

Группа :: Графические оболочки/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;
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin