Re: select patch

Johannes Altmanninger <[email protected]> Fri, 20 Jun 2014 15:52:12 +0200
Newsgroups gmane.comp.window-managers.ratpoison.devel
Message-ID <[email protected]>
Thanks! Now everything works just fine.
The only thing that is missing now is the documentation :)

On 06/20/2014 03:14 PM, Peter Pentchev wrote:
> On Fri, Jun 20, 2014 at 02:43:48PM +0200, Johannes Altmanninger wrote:
>> Now I have rewritten find_window_name() again, it is much cleaner this way,
>> no need for unnecessary temporary variables anymore :)
>> It works the same as before but I still get the "assignment from
>> incompatible pointer type" warning...
> Take a look at how strncmp() is declared on your system; it is most
> probably something like
>
>    int strncmp(const char *s1, const char *s2, size_t len);
>
> Your typedef should be the same.
>
> G'luck,
> Peter
>

_______________________________________________
Ratpoison-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/ratpoison-devel
select.patch (text/x-patch, 9.7 KB)
diff --git a/src/actions.c b/src/actions.c
index 7579101..6b35f37 100644
--- a/src/actions.c
+++ b/src/actions.c
@@ -81,6 +81,7 @@ static cmdret * set_topkmap (struct cmdarg **args);
 static cmdret * set_historysize (struct cmdarg **args);
 static cmdret * set_historycompaction (struct cmdarg **args);
 static cmdret * set_historyexpansion (struct cmdarg **args);
+static cmdret * set_selectstyle (struct cmdarg **args);
 
 LIST_HEAD(set_vars);
 
@@ -150,6 +151,7 @@ init_set_vars(void)
   add_set_var ("historysize", set_historysize, 1, "", arg_NUMBER);
   add_set_var ("historycompaction", set_historycompaction, 1, "", arg_NUMBER);
   add_set_var ("historyexpansion", set_historyexpansion, 1, "", arg_NUMBER);
+  add_set_var ("selectstyle", set_selectstyle, 1, "", arg_STRING);
 }
 
 /* rp_keymaps is ratpoison's list of keymaps. */
@@ -1412,10 +1414,13 @@ cmd_select (int interactive UNUSED, struct cmdarg **args)
       else
         /* try by name */
         {
-          rp_window *win = find_window_name (str, 1);
-
+          rp_window *win = find_window_name (str, MATCH_EXACT);
+          if (!win)
+            win = find_window_name (str, MATCH_IGNORECASE);
+          if (!win)
+            win = find_window_name (str, MATCH_PREFIX);
           if (!win)
-            win = find_window_name (str, 0);
+            win = find_window_name (str, MATCH_IGNORECASE | MATCH_PREFIX);
 
           if (win)
             {
@@ -1885,55 +1890,55 @@ read_frame (struct sbuf *s,  struct cmdarg **arg)
     return cmdret_new (RET_FAILURE, "frame not found");
 }
 
-static cmdret *
-read_window (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
-  rp_window *win = NULL;
-  char *name;
-  int n;
-
-  if (s)
-    name = xstrdup (sbuf_get (s));
-  else
-    name = get_input (spec->prompt, hist_WINDOW, window_completions);
-
-  if (name)
-    {
-      /* try by number */
-      if ((n = string_to_positive_int (name)) >= 0)
-        {
-          rp_window_elem *elem = group_find_window_by_number (rp_current_group, n);
-          if (elem)
-            win = elem->win;
-        }
-      else
-        /* try by name */
-        {
-          win = find_window_name (name, 1);
-          if (win == NULL)
-            win = find_window_name (name, 0);
-        }
-
-      if (win)
-        {
-          *arg = xmalloc (sizeof(struct cmdarg));
-          (*arg)->type = arg_WINDOW;
-          (*arg)->arg.win = win;
-          (*arg)->string = name;
-          return NULL;
-        }
-      else
-        {
-          free (name);
-          *arg = NULL;
-          return cmdret_new (RET_SUCCESS, NULL);
-        }
-    }
-
-  /* user abort. */
-  *arg = NULL;
-  return cmdret_new (RET_SUCCESS, NULL);
-}
+//static cmdret *
+//read_window (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
+//{
+//  rp_window *win = NULL;
+//  char *name;
+//  int n;
+//
+//  if (s)
+//    name = xstrdup (sbuf_get (s));
+//  else
+//    name = get_input (spec->prompt, hist_WINDOW, window_completions);
+//
+//  if (name)
+//    {
+//      /* try by number */
+//      if ((n = string_to_positive_int (name)) >= 0)
+//        {
+//          rp_window_elem *elem = group_find_window_by_number (rp_current_group, n);
+//          if (elem)
+//            win = elem->win;
+//        }
+//      else
+//        /* try by name */
+//        {
+//          win = find_window_name (name, 1);
+//          if (win == NULL)
+//            win = find_window_name (name, 0);
+//        }
+//
+//      if (win)
+//        {
+//          *arg = xmalloc (sizeof(struct cmdarg));
+//          (*arg)->type = arg_WINDOW;
+//          (*arg)->arg.win = win;
+//          (*arg)->string = name;
+//          return NULL;
+//        }
+//      else
+//        {
+//          free (name);
+//          *arg = NULL;
+//          return cmdret_new (RET_SUCCESS, NULL);
+//        }
+//    }
+//
+//  /* user abort. */
+//  *arg = NULL;
+//  return cmdret_new (RET_SUCCESS, NULL);
+//}
 
 static int
 parse_wingravity (char *data)
@@ -2237,9 +2242,9 @@ read_arg (struct argspec *spec, struct sbuf *s, struct cmdarg **arg, const char
     case arg_SHELLCMD:
       ret = read_shellcmd (spec, s, arg, command_name);
       break;
-    case arg_WINDOW:
-      ret = read_window (spec, s, arg);
-      break;
+    //case arg_WINDOW:
+    //  ret = read_window (spec, s, arg);
+    //  break;
     case arg_FRAME:
       ret = read_frame (s, arg);
       break;
@@ -2460,7 +2465,7 @@ arg_free (struct cmdarg *arg)
         case arg_REST:
         case arg_STRING:
         case arg_NUMBER:
-        case arg_WINDOW:
+        //case arg_WINDOW:
         case arg_FRAME:
         case arg_COMMAND:
         case arg_SHELLCMD:
@@ -5684,6 +5689,25 @@ set_maxundos (struct cmdarg **args)
   return cmdret_new (RET_SUCCESS, NULL);
 }
 
+static cmdret *
+set_selectstyle (struct cmdarg **args)
+{
+  if (args[0] == NULL)
+    return cmdret_new (RET_SUCCESS, "%s",
+            defaults.select_style == SELECT_SIMPLE
+                ? "simple"
+                : "cycle"
+            );
+
+  if (!strncmp ("simple", ARG_STRING(0), 6))
+      defaults.select_style = SELECT_SIMPLE;
+  else if (!strncmp ("cycle", ARG_STRING(0), 5))
+      defaults.select_style = SELECT_PREFER_NOTSELECTED;
+  else
+      return cmdret_new (RET_FAILURE, "set selectstyle: invalid argument");
+  return cmdret_new (RET_SUCCESS, NULL);
+}
+
 cmdret *
 cmd_cnext (int interactive, struct cmdarg **args)
 {
diff --git a/src/actions.h b/src/actions.h
index 519c1a7..2c15826 100644
--- a/src/actions.h
+++ b/src/actions.h
@@ -34,7 +34,7 @@ enum argtype { arg_REST,
                arg_NUMBER,
                arg_STRING,
                arg_FRAME,
-               arg_WINDOW,
+               //arg_WINDOW,
                arg_COMMAND,
                arg_SHELLCMD,
                arg_KEYMAP,
diff --git a/src/data.h b/src/data.h
index f4bd185..01a8f1a 100644
--- a/src/data.h
+++ b/src/data.h
@@ -275,6 +275,9 @@ struct rp_defaults
 
   /* Frame indicator format */
   char *frame_fmt;
+
+  /* How the select command behaves */
+  int select_style;
 };
 
 /* Information about a child process. */
diff --git a/src/globals.h b/src/globals.h
index 1fb7e0f..db864fc 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -76,6 +76,11 @@
 #define UNUSED
 #endif
 
+#define MAX_WINDOW_NAME_LENGTH   0x04ff
+
+#define SELECT_SIMPLE                0
+#define SELECT_PREFER_NOTSELECTED    1
+
 /* The list of groups. */
 extern struct list_head rp_groups;
 
diff --git a/src/main.c b/src/main.c
index 52dbcce..7d3e191 100644
--- a/src/main.c
+++ b/src/main.c
@@ -599,6 +599,7 @@ init_defaults (void)
   defaults.history_expansion = False;
   defaults.frame_selectors = xstrdup ("");
   defaults.maxundos = 20;
+  defaults.select_style = SELECT_SIMPLE ;
 }
 
 int
diff --git a/src/window.c b/src/window.c
index de9032a..e38ab42 100644
--- a/src/window.c
+++ b/src/window.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "ratpoison.h"
 
@@ -283,31 +284,62 @@ find_window_number (int n)
 }
 
 rp_window *
-find_window_name (char *name, int exact_match)
+find_window_name (char *name, int match_type)
 {
-  rp_window_elem *cur;
-
-  if (!exact_match)
+  typedef int (*compare_window_name_function)
+                (const char *name1, const char *name2, size_t length);
+  compare_window_name_function my_compare;
+  size_t compare_length = MAX_WINDOW_NAME_LENGTH;
+  switch(match_type)
     {
-      list_for_each_entry (cur, &rp_current_group->mapped_windows, node)
-        {
-          if (str_comp (name, window_name (cur->win), strlen (name)))
-            return cur->win;
-        }
+    case MATCH_EXACT:
+      my_compare = strncmp;
+      break;
+    case MATCH_IGNORECASE:
+      my_compare = strncasecmp;
+      break;
+    case MATCH_PREFIX:
+      my_compare = strncmp;
+      compare_length = strlen(name);
+      break;
+    case MATCH_IGNORECASE | MATCH_PREFIX:
+      my_compare = strncasecmp;
+      compare_length = strlen(name);
+      break;
+    default:
+      my_compare = strncmp;
     }
-  else
+  // number of the currently selected window
+  int current_win_number = current_window() ? current_window()->number : 0;
+  rp_window_elem *cur;
+
+  int may_return = 1;
+  if (defaults.select_style == SELECT_PREFER_NOTSELECTED)
+      may_return = 0;
+
+  rp_window *first_match = NULL;
+
+  list_for_each_entry (cur, &rp_current_group->mapped_windows, node)
     {
-      list_for_each_entry (cur, &rp_current_group->mapped_windows, node)
+      if (!my_compare (name, window_name(cur->win), compare_length))
         {
-          if (!strcmp (name, window_name (cur->win)))
-            return cur->win;
+          if (may_return)
+            {
+              return cur->win;
+            }
+          else
+            {
+              if(cur->win->number == current_win_number)
+                may_return = 1;
+              if(!first_match)
+                first_match = cur->win;
+            }
         }
     }
-
-  /* didn't find it */
-  return NULL;
+  return first_match;
 }
 
+
 /* Return the previous window in the list. Assumes window is in the
    mapped window list. */
 rp_window*
diff --git a/src/window.h b/src/window.h
index fdd246c..aff1bc9 100644
--- a/src/window.h
+++ b/src/window.h
@@ -40,7 +40,10 @@ char *window_name (rp_window *win);
 /* int goto_window_name (char *name); */
 rp_window *find_window_other (rp_screen *screen);
 rp_window *find_window_by_number (int n);
-rp_window *find_window_name (char *name, int exact_match);
+rp_window *find_window_name (char *name, int match_type);
+#define MATCH_EXACT              0x0000
+#define MATCH_PREFIX             0x0001
+#define MATCH_IGNORECASE         0x0002
 rp_window *find_window_prev (rp_window *w);
 rp_window *find_window_prev_with_frame (rp_window *w);
 rp_window *find_window_next (rp_window *w);