Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37841901
en ru br
ALT Linux repos
S:3.4.2-alt1
5.0: 1.2.36-alt2.1
4.1: 1.2.35-alt2.1
4.0: 1.2.32-alt2.1
3.0: 1.2.23-alt1
+backports:1.2.30-alt1.M30.1

Group :: Graphical desktop/Icewm
RPM: icewm

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: icewm-alt-readline.patch
Download


 icewm/configure.in       |   16 ++++
 icewm/src/aaddressbar.cc |  173 ++++++++++++++++++++++++++++++++++++++++++++++
 icewm/src/config.h.in    |    3 +
 icewm/src/yinput.cc      |    2 +-
 4 files changed, 193 insertions(+), 1 deletions(-)
diff --git a/icewm/configure.in b/icewm/configure.in
index 58f248e..6a9ea8e 100644
--- a/icewm/configure.in
+++ b/icewm/configure.in
@@ -482,6 +482,22 @@ AC_ARG_ENABLE(xfreetype,
     features="${features} corefonts"
   fi
 
+dnl =================================================== Support for readline ===
+dnl
+AC_ARG_ENABLE(readline,
+  [  --with-readline         Enable readline & history support])
+  if test "$with_readline" != "no"; then
+    AC_CHECK_LIB(history, using_history,
+      CORE_LIBS="${CORE_LIBS} -lhistory -lreadline"
+      features="${features} readline"
+      [ AC_DEFINE(HAVE_READLINE, 1, [Enable readline & history support]) ],
+      [ AC_MSG_ERROR([Unable to find history library])])
+    AC_CHECK_LIB(ncurses, copywin,
+      CORE_LIBS="${CORE_LIBS} -lncurses"
+      [ ],
+      [ AC_MSG_ERROR([Unable to find ncurses library])])
+  fi
+
 dnl ============================================================= GUI Events ===
 dnl
 AC_ARG_ENABLE(guievents,
diff --git a/icewm/src/aaddressbar.cc b/icewm/src/aaddressbar.cc
index 31c5e83..1767031 100644
--- a/icewm/src/aaddressbar.cc
+++ b/icewm/src/aaddressbar.cc
@@ -15,8 +15,144 @@
 #include "sysdep.h"
 #include "default.h"
 
+#ifdef HAVE_READLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+
+char *extract_colon_unit (char *string, int *p_index)
+{
+  int i, start, len;
+  char *value = NULL;
+
+  if (string == 0)
+    return (string);
+
+  len = strlen (string);
+  if (*p_index >= len)
+    return ((char *)NULL);
+
+  i = *p_index;
+
+  if (i && string[i] == ':')
+    i++;
+
+  for (start = i; string[i] && string[i] != ':'; i++)
+    ;
+
+  *p_index = i;
+
+  if (i == start)
+    {
+      if (string[i])
+	(*p_index)++;
+      /* Return "" in the case of a trailing `:'. */
+      value = new char[1];
+      value[0] = '\0';
+    }
+  else
+    {
+      int len = i-start;
+      value = new char[len+1];
+      strncpy(value, string+start,len);
+      value[len] = '\0';
+    }
+
+  return (value);
+}
+
+char *find_completion(const char *text,int *state) {
+    char *path = getenv("PATH");
+    char *current_path;
+    char **matches = NULL;
+    char *filename = NULL;
+    char *found = NULL;
+    int path_index, text_len = strlen(text), found_len = 0, path_len = 0;
+    struct stat st;
+
+    *state = 0;
+    path_index = 0;
+    if (text[0] != '/' && text[0] != '~') {
+	while (path && path[path_index]) {
+	    current_path = extract_colon_unit(path, &path_index);
+	    if (current_path && *current_path) {
+		filename = new char[2+strlen(current_path)+text_len];
+		sprintf(filename,"%s/%s",current_path,text);
+		path_len = strlen(current_path)+1;
+		free(current_path);
+		matches = rl_completion_matches(filename, rl_filename_completion_function);
+		if (matches) {
+		    //if (!matches[1]) {
+			char *f = *matches+path_len;
+			int len = strlen(f);
+			if (len < found_len) {
+			    free(found);
+			    found = strdup(f);
+			    found_len = len;
+			    *state = 3;
+			} else if (*state) {
+			    *state = 2;
+			    if (found) {
+				free(found);
+				found = NULL;
+			    }
+			} else {
+			    found = strdup(*matches+path_len);
+			    found_len = strlen(found);
+			    if (matches[1])
+				*state = 3;
+			    else
+				*state = 1;
+			}
+		    //} else {
+		//	*state = 2;
+		//    }
+		}
+		if (*state == 2)
+		    return NULL;
+	    }
+	}
+    } else {
+	const char *wtilde = NULL;
+	int len = -1;
+	if (text[0] == '~') {
+	    wtilde = text;
+	    text = tilde_expand(text);
+	    len = strlen(text);
+	}
+        matches = rl_completion_matches(text, rl_filename_completion_function);
+	if (matches) {
+	    stat(*matches,&st);
+	    if (len > 0) {
+	        *matches += len;
+		len = text_len+strlen(*matches);
+		found = new char[len+2];
+		if (S_ISDIR(st.st_mode) && !matches[1]) {
+		    sprintf(found,"%s%s/",wtilde,*matches);
+		} else {
+		    sprintf(found,"%s%s",wtilde,*matches);
+		}
+	    } else {
+		if (S_ISDIR(st.st_mode) && !matches[1]) {
+		    found = new char[strlen(*matches)+2];
+		    sprintf(found,"%s/",*matches);
+		} else {
+		    found = strdup(*matches);
+		}
+	    }
+	    if (matches[1])
+		*state = 3;
+	    else
+		*state = 1;
+	}
+    }
+    return found;
+}
+#endif /* HAVE_READLINE */
 
 AddressBar::AddressBar(YWindow *parent): YInputLine(parent) {
+#ifdef HAVE_READLINE
+    using_history();
+#endif
 }
 
 AddressBar::~AddressBar() {
@@ -27,7 +163,41 @@ bool AddressBar::handleKey(const XKeyEvent &key) {
         KeySym k = XKeycodeToKeysym(xapp->display(), (KeyCode)key.keycode, 0);
         int m = KEY_MODMASK(key.state);
 
+#ifdef HAVE_READLINE
+	if (k == XK_Tab) {
+	    int state=0, p;
+	    char *f;
+	    char *text = strdup(getText());
+	    p = prevWord(strlen(text), false);
+	    text += p;
+	    f = find_completion(text,&state);
+	    if (state & 1) {
+		char *t = f;
+		if (p != 0) {
+		    t = new char[strlen(f)+p+2];
+		    *text = '\0';
+		    text -= p;
+		    sprintf(t,"%s%s",text,f);
+		    free(text);
+		    free(f);
+		}
+		setText(t);
+		free(t);
+	    }
+	    if (!state || state & 2)
+		; // printf("\a\n");
+    	    return true; // for future compatibility
+	} else if (k == XK_Up || k == XK_Down) {
+	    HIST_ENTRY *hist;
+	    hist = k == XK_Down ? next_history() : previous_history();
+	    if (hist == NULL)
+		return true;
+	    setText(hist->line);
+	    return true;
+        } else if (k == XK_KP_Enter || k == XK_Return) {
+#else
         if (k == XK_KP_Enter || k == XK_Return) {
+#endif
             const char *t = getText();
             const char *args[7];
             int i = 0;
@@ -50,6 +220,9 @@ bool AddressBar::handleKey(const XKeyEvent &key) {
             if (m & ControlMask)
                 if (t == 0 || t[0] == 0)
                     args[1] = 0;
+#ifdef HAVE_READLINE
+	    add_history((char *)t);
+#endif
             app->runProgram(args[0], args);
             selectAll();
             return true;
diff --git a/icewm/src/config.h.in b/icewm/src/config.h.in
index ce58d3a..5c1f553 100644
--- a/icewm/src/config.h.in
+++ b/icewm/src/config.h.in
@@ -351,5 +351,8 @@
 /* Define to 1 if the X Window System is missing or not being used. */
 #undef X_DISPLAY_MISSING
 
+/* Define to 1 if the readline (address bar history) support used. */
+#undef HAVE_READLINE
+
 /* Define to `unsigned int' if <sys/types.h> does not define. */
 #undef size_t
diff --git a/icewm/src/yinput.cc b/icewm/src/yinput.cc
index 3647241..6e81368 100644
--- a/icewm/src/yinput.cc
+++ b/icewm/src/yinput.cc
@@ -84,7 +84,7 @@ void YInputLine::setText(const char *text) {
     fText = newstr(text);
     markPos = curPos = leftOfs = 0;
     if (fText)
-        curPos = strlen(fText);
+        markPos = curPos = strlen(fText);
     limit();
     repaint();
 }
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin