summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJérémie Courrèges-Anglas <jca@wxcvbn.org>2013-05-27 16:27:35 +0200
committerJérémie Courrèges-Anglas <jca@wxcvbn.org>2013-05-27 16:27:35 +0200
commit7f384e37279dcab8dcad0149293483a23aa7aec4 (patch)
tree96d1093fa617ff3a924e3af07d2d3f374b8bfa41
parent164d3dc35fc82200086c5cecd6b3d2fab236f999 (diff)
parentd3793dba2a57d2512ca0a7987b3385986ec2c9ea (diff)
downloadratpoison-7f384e37279dcab8dcad0149293483a23aa7aec4.zip
Merge "gnumber" feature from |cos|'s repo
-rw-r--r--doc/ratpoison.13
-rw-r--r--doc/ratpoison.texi9
-rw-r--r--src/actions.c123
-rw-r--r--src/actions.h1
-rw-r--r--src/bar.c60
-rw-r--r--src/bar.h2
-rw-r--r--src/group.c91
-rw-r--r--src/group.h6
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);
diff --git a/src/bar.c b/src/bar.c
index 25d9a46..d9982c2 100644
--- a/src/bar.c
+++ b/src/bar.c
@@ -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)
{
diff --git a/src/bar.h b/src/bar.h
index 2156802..0d70644 100644
--- a/src/bar.h
+++ b/src/bar.h
@@ -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);