diff options
author | Jérémie Courrèges-Anglas <jca@wxcvbn.org> | 2013-05-27 16:27:35 +0200 |
---|---|---|
committer | Jérémie Courrèges-Anglas <jca@wxcvbn.org> | 2013-05-27 16:27:35 +0200 |
commit | 7f384e37279dcab8dcad0149293483a23aa7aec4 (patch) | |
tree | 96d1093fa617ff3a924e3af07d2d3f374b8bfa41 | |
parent | 164d3dc35fc82200086c5cecd6b3d2fab236f999 (diff) | |
parent | d3793dba2a57d2512ca0a7987b3385986ec2c9ea (diff) | |
download | ratpoison-7f384e37279dcab8dcad0149293483a23aa7aec4.zip |
Merge "gnumber" feature from |cos|'s repo
-rw-r--r-- | doc/ratpoison.1 | 3 | ||||
-rw-r--r-- | doc/ratpoison.texi | 9 | ||||
-rw-r--r-- | src/actions.c | 123 | ||||
-rw-r--r-- | src/actions.h | 1 | ||||
-rw-r--r-- | src/bar.c | 60 | ||||
-rw-r--r-- | src/bar.h | 2 | ||||
-rw-r--r-- | src/group.c | 91 | ||||
-rw-r--r-- | src/group.h | 6 |
8 files changed, 242 insertions, 53 deletions
diff --git a/doc/ratpoison.1 b/doc/ratpoison.1 index 8b53288..3ab0a92 100644 --- a/doc/ratpoison.1 +++ b/doc/ratpoison.1 @@ -373,6 +373,9 @@ Create a new group named \fIgroupf\fP, but do not select it. .cmd gnext Select the next group. Most window commands only see windows in the effective group. +.cmd gnumber +Give the number \fInew\fP to the group with the number \fIold\fP or +the current group. .cmd gother Select the last accessed group. Most window commands only see windows in the effective group. diff --git a/doc/ratpoison.texi b/doc/ratpoison.texi index d6552d5..7b9ce78 100644 --- a/doc/ratpoison.texi +++ b/doc/ratpoison.texi @@ -600,6 +600,15 @@ Go to the previous group in the list. Rename current group. @end deffn +@deffn Command gnumber @var{GROUP} @var{target} +Set a group's number to @var{GROUP}. If another group occupies the +requested number already, then the groups' numbers are swapped. + +The second argument, @var{target}, is optional. It should be the +number of the group whose number will be changed. If @var{target} is +omitted ratpoison defaults to the current group. +@end deffn + @deffn Command gselect @var{group} Select a particular group by name or number. If @var{group} is not provided, ratpoison will interactively prompt for the group. diff --git a/src/actions.c b/src/actions.c index e31df72..3f9691e 100644 --- a/src/actions.c +++ b/src/actions.c @@ -261,6 +261,9 @@ init_user_commands(void) "Name: ", arg_STRING); add_command ("gnewbg", cmd_gnewbg, 1, 1, 1, "Name: ", arg_STRING); + add_command ("gnumber", cmd_gnumber, 2, 1, 1, + "Number: ", arg_NUMBER, + "Number: ", arg_NUMBER); add_command ("grename", cmd_grename, 1, 1, 1, "Change group name to: ", arg_REST); add_command ("gnext", cmd_gnext, 0, 0, 0); @@ -5077,11 +5080,61 @@ cmd_gnewbg (int interactive UNUSED, struct cmdarg **args) } cmdret * +cmd_gnumber (int interactive UNUSED, struct cmdarg **args) +{ + int old_number, new_number; + rp_group *other_g, *g; + + struct numset *g_numset = group_get_numset(); + + /* Gather the args. */ + new_number = ARG(0,number); + if (args[1]) + g = groups_find_group_by_number (ARG(1,number)); + else + g = rp_current_group; + + /* Make the switch. */ + if (new_number >= 0 && g) + { + /* Find other window with same number and give it old number. */ + other_g = groups_find_group_by_number (new_number); + if (other_g != NULL) + { + old_number = g->number; + other_g->number = old_number; + + /* Resort the window in the list */ + group_resort_group (other_g); + } + else + { + numset_release (g_numset, g->number); + } + + g->number = new_number; + numset_add_num (g_numset, new_number); + + /* resort the the window in the list */ + group_resort_group (g); + + /* Update the group list. */ + update_group_names (current_screen()); + } + + return cmdret_new (RET_SUCCESS, NULL); +} + +cmdret * cmd_grename (int interactive UNUSED, struct cmdarg **args) { if (groups_find_group_by_name (ARG_STRING (0), 1)) return cmdret_new (RET_FAILURE, "grename: duplicate group name"); group_rename (rp_current_group, ARG_STRING(0)); + + /* Update the group list. */ + update_group_names (current_screen()); + return cmdret_new (RET_SUCCESS, NULL); } @@ -5104,65 +5157,31 @@ cmd_gselect (int interactive, struct cmdarg **args) cmdret * cmd_groups (int interactive, struct cmdarg **args UNUSED) { - rp_group *cur; - int mark_start = 0, mark_end = 0; - struct sbuf *buffer; - rp_group *last; - - last = group_last_group (); - buffer = sbuf_new (0); - - /* Generate the string. */ - list_for_each_entry (cur, &rp_groups, node) - { - char *fmt; - char separator; - - if (cur == rp_current_group) - mark_start = strlen (sbuf_get (buffer)); - - /* Pad start of group name with a space for row - style. non-Interactive always gets a column.*/ - if (defaults.window_list_style == STYLE_ROW && interactive) - sbuf_concat (buffer, " "); - - if(cur == rp_current_group) - separator = '*'; - else if(cur == last) - separator = '+'; - else - separator = '-'; - - fmt = xsprintf ("%d%c%s", cur->number, separator, cur->name); - sbuf_concat (buffer, fmt); - free (fmt); - - /* Pad end of group name with a space for row style. */ - if (defaults.window_list_style == STYLE_ROW && interactive) - { - sbuf_concat (buffer, " "); - } - else - { - if (cur->node.next != &rp_groups) - sbuf_concat (buffer, "\n"); - } - - if (cur == rp_current_group) - mark_end = strlen (sbuf_get (buffer)); - } + struct sbuf *group_list = NULL; + int dummy; + rp_screen *s; - /* Display it or return it. */ if (interactive) { - marked_message (sbuf_get (buffer), mark_start, mark_end); - sbuf_free (buffer); + s = current_screen (); + /* This is a yukky hack. If the bar already hidden then show the + bar. This handles the case when msgwait is 0 (the bar sticks) + and the user uses this command to toggle the bar on and + off. OR the timeout is >0 then show the bar. Which means, + always show the bar if msgwait is >0 which fixes the case + when a command in the prefix hook displays the bar. */ + if (!hide_bar (s) || defaults.bar_timeout > 0) show_group_bar (s); + return cmdret_new (RET_SUCCESS, NULL); } else { - cmdret *ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get(buffer)); - sbuf_free(buffer); + cmdret *ret; + + group_list = sbuf_new (0); + get_group_list ("\n", group_list, &dummy, &dummy); + ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (group_list)); + sbuf_free (group_list); return ret; } } diff --git a/src/actions.h b/src/actions.h index 5db4a56..519c1a7 100644 --- a/src/actions.h +++ b/src/actions.h @@ -138,6 +138,7 @@ RP_CMD (gmove); RP_CMD (gnew); RP_CMD (gnewbg); RP_CMD (gnext); +RP_CMD (gnumber); RP_CMD (gprev); RP_CMD (gother); RP_CMD (gravity); @@ -40,7 +40,8 @@ /* Possible values for bar_is_raised status. */ #define BAR_IS_HIDDEN 0 #define BAR_IS_WINDOW_LIST 1 -#define BAR_IS_MESSAGE 2 +#define BAR_IS_GROUP_LIST 2 +#define BAR_IS_MESSAGE 3 /* A copy of the last message displayed in the message bar. */ static char *last_msg = NULL; @@ -104,6 +105,31 @@ show_bar (rp_screen *s, char *fmt) return 0; } +/* Show group listing in bar. */ +int +show_group_bar (rp_screen *s) +{ + if (!s->bar_is_raised) + { + s->bar_is_raised = BAR_IS_GROUP_LIST; + XMapRaised (dpy, s->bar_window); + update_group_names (s); + + /* Switch to the default colormap */ + if (current_window()) + XUninstallColormap (dpy, current_window()->colormap); + XInstallColormap (dpy, s->def_cmap); + + reset_alarm(); + return 1; + } + + /* If the bar is raised we still need to display the window + names. */ + update_group_names (s); + return 0; +} + int bar_x (rp_screen *s, int width) { @@ -172,6 +198,11 @@ update_bar (rp_screen *s) return; } + if (s->bar_is_raised == BAR_IS_GROUP_LIST) { + update_group_names (s); + return; + } + if (s->bar_is_raised == BAR_IS_HIDDEN) return; @@ -207,6 +238,33 @@ update_window_names (rp_screen *s, char *fmt) sbuf_free (bar_buffer); } +/* Note that we use marked_message_internal to avoid resetting the + alarm. */ +void +update_group_names (rp_screen *s) +{ + struct sbuf *bar_buffer; + int mark_start = 0; + int mark_end = 0; + + if (s->bar_is_raised != BAR_IS_GROUP_LIST) return; + + bar_buffer = sbuf_new (0); + + if (defaults.window_list_style == STYLE_ROW) + { + get_group_list (NULL, bar_buffer, &mark_start, &mark_end); + marked_message_internal (sbuf_get (bar_buffer), mark_start, mark_end); + } + else + { + get_group_list ("\n", bar_buffer, &mark_start, &mark_end); + marked_message_internal (sbuf_get (bar_buffer), mark_start, mark_end); + } + + sbuf_free (bar_buffer); +} + void message (char *s) { @@ -23,8 +23,10 @@ #define _RATPOISON_BAR_H 1 void update_window_names (rp_screen *s, char *fmt); +void update_group_names (rp_screen *s); void update_bar (rp_screen *s); int show_bar (rp_screen *s, char *fmt); +int show_group_bar (rp_screen *s); int hide_bar (rp_screen *s); int bar_y (rp_screen *s, int height); int bar_x (rp_screen *s, int width); diff --git a/src/group.c b/src/group.c index 5246b33..2bbfead 100644 --- a/src/group.c +++ b/src/group.c @@ -60,6 +60,67 @@ free_groups(void) } } +struct numset * +group_get_numset(void) +{ + return group_numset; +} + +/* get the group list and store it in buffer delimiting each window + with delim. mark_start and mark_end will be filled with the text + positions for the start and end of the current window. */ +void +get_group_list (char *delim, struct sbuf *buffer, + int *mark_start, int *mark_end) +{ + rp_group *cur; + + if (buffer == NULL) return; + + sbuf_clear (buffer); + rp_group *last; + last = group_last_group (); + + /* Generate the string. */ + list_for_each_entry (cur, &rp_groups, node) + { + char *fmt; + char separator; + + if (cur == rp_current_group) + *mark_start = strlen (sbuf_get (buffer)); + + if(cur == rp_current_group) + separator = '*'; + else if(cur == last) + separator = '+'; + else + separator = '-'; + + /* A hack, pad the group with a space at the beginning and end + if there is no delimiter. */ + if (!delim) + sbuf_concat (buffer, " "); + + fmt = xsprintf ("%d%c%s", cur->number, separator, cur->name); + sbuf_concat (buffer, fmt); + free (fmt); + + /* A hack, pad the group with a space at the beginning and end + if there is no delimiter. */ + if (!delim) + sbuf_concat (buffer, " "); + + /* Only put the delimiter between the group, and not after the the last + group. */ + if (delim && cur->node.next != &rp_groups) + sbuf_concat (buffer, delim); + + if (cur == rp_current_group) + *mark_end = strlen (sbuf_get (buffer)); + } +} + rp_group * group_new (int number, char *name) { @@ -94,14 +155,44 @@ rp_group * group_add_new_group (char *name) { rp_group *g; + rp_group *cur; g = group_new (numset_request (group_numset), name); + + list_for_each_entry (cur, &rp_groups, node) + { + if (cur->number > g->number) + { + list_add_tail (&g->node, &cur->node); + return g; + } + } + list_add_tail (&g->node, &rp_groups); return g; } void +group_resort_group (rp_group *g) +{ + rp_group *cur; + struct list_head *last = &rp_groups; + + list_del (&g->node); + list_for_each_entry (cur, &rp_groups, node) + { + if (cur->number > g->number) + { + list_add (&g->node, last); + return; + } + last = &cur->node; + } + list_add (&g->node, last); +} + +void group_rename (rp_group *g, char *name) { if (g->name) diff --git a/src/group.h b/src/group.h index 364100f..1081043 100644 --- a/src/group.h +++ b/src/group.h @@ -39,6 +39,10 @@ void groups_map_window (rp_window *win); void group_unmap_window (rp_group *g, rp_window *win); void groups_unmap_window (rp_window *win); +struct numset *group_get_numset (void); +void get_group_list (char *delim, struct sbuf *buffer, int *mark_start, + int *mark_end); + rp_window *group_prev_window (rp_group *g, rp_window *win); rp_window *group_next_window (rp_group *g, rp_window *win); rp_group *groups_find_group_by_name (char *s, int exact_match); @@ -52,6 +56,8 @@ rp_group *group_prev_group (void); rp_group *group_next_group (void); rp_group *group_last_group (void); +void group_resort_group (rp_group *g); + rp_group *group_add_new_group (char *name); void group_rename (rp_group *g, char *name); |