summaryrefslogtreecommitdiff
path: root/src/actions.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/actions.c')
-rw-r--r--src/actions.c6005
1 files changed, 0 insertions, 6005 deletions
diff --git a/src/actions.c b/src/actions.c
deleted file mode 100644
index d847fa7..0000000
--- a/src/actions.c
+++ /dev/null
@@ -1,6005 +0,0 @@
-/* Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts <sabetts@vcn.bc.ca>
- *
- * This file is part of ratpoison.
- *
- * ratpoison is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * ratpoison is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307 USA
- */
-
-#include <unistd.h>
-#include <ctype.h> /* for isspace */
-#include <sys/wait.h>
-#include <X11/keysym.h>
-#include <string.h>
-#include <strings.h>
-#include <time.h>
-#include <errno.h>
-#include <signal.h>
-#include <X11/Xproto.h>
-
-#include "ratpoison.h"
-
-#ifdef HAVE_LIBXTST
-# include <X11/extensions/XTest.h>
-#endif
-
-
-#define ARG_STRING(elt) args[elt]->string
-#define ARG(elt, type) args[elt]->arg.type
-
-struct set_var
-{
- char *var;
- cmdret *(*set_fn)(struct cmdarg **);
- int nargs;
- struct argspec *args;
- struct list_head node;
-};
-
-static cmdret * set_resizeunit (struct cmdarg **args);
-static cmdret * set_wingravity (struct cmdarg **args);
-static cmdret * set_transgravity (struct cmdarg **args);
-static cmdret * set_maxsizegravity (struct cmdarg **args);
-static cmdret * set_bargravity (struct cmdarg **args);
-static cmdret * set_font (struct cmdarg **args);
-static cmdret * set_padding (struct cmdarg **args);
-static cmdret * set_border (struct cmdarg **args);
-static cmdret * set_barborder (struct cmdarg **args);
-static cmdret * set_barinpadding (struct cmdarg **args);
-static cmdret * set_inputwidth (struct cmdarg **args);
-static cmdret * set_waitcursor (struct cmdarg **args);
-static cmdret * set_winfmt (struct cmdarg **args);
-static cmdret * set_winname (struct cmdarg **args);
-static cmdret * set_framefmt (struct cmdarg **args);
-static cmdret * set_fgcolor (struct cmdarg **args);
-static cmdret * set_bgcolor (struct cmdarg **args);
-static cmdret * set_fwcolor (struct cmdarg **args);
-static cmdret * set_bwcolor (struct cmdarg **args);
-static cmdret * set_barpadding (struct cmdarg **args);
-static cmdret * set_winliststyle (struct cmdarg **args);
-static cmdret * set_framesels (struct cmdarg **args);
-static cmdret * set_maxundos (struct cmdarg **args);
-static cmdret * set_infofmt (struct cmdarg **args);
-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);
-
-LIST_HEAD(set_vars);
-
-/* FIXME This variable should really be kept static for group.c */
-extern struct numset *group_numset;
-
-static void
-add_set_var (char *name, cmdret * (*fn)(struct cmdarg **), int nargs, ...)
-{
- int i = 0;
- struct set_var *var;
- va_list va;
-
- var = xmalloc (sizeof (struct set_var));
- var->var = name;
- var->set_fn = fn;
- var->nargs = nargs;
- var->args = xmalloc(sizeof(struct argspec) * nargs);
-
- /* Fill var->args */
- va_start(va, nargs);
- for (i=0; i<nargs; i++)
- {
- var->args[i].prompt = va_arg(va, char*);
- var->args[i].type = va_arg(va, int);
- }
- va_end(va);
-
- list_add (&var->node, &set_vars);
-}
-
-static void
-set_var_free (struct set_var *var)
-{
- if (var == NULL)
- return;
- free(var->args);
- free(var);
-}
-
-static void
-init_set_vars(void)
-{
- add_set_var ("resizeunit", set_resizeunit, 1, "", arg_NUMBER);
- add_set_var ("maxundos", set_maxundos, 1, "", arg_NUMBER);
- add_set_var ("wingravity", set_wingravity, 1, "", arg_GRAVITY);
- add_set_var ("transgravity", set_transgravity, 1, "", arg_GRAVITY);
- add_set_var ("maxsizegravity", set_maxsizegravity, 1, "", arg_GRAVITY);
- add_set_var ("bargravity", set_bargravity, 1, "", arg_GRAVITY);
- add_set_var ("font", set_font, 1, "", arg_STRING);
- add_set_var ("padding", set_padding, 4,
- "", arg_NUMBER, "", arg_NUMBER, "", arg_NUMBER, "", arg_NUMBER);
- add_set_var ("border", set_border, 1, "", arg_NUMBER);
- add_set_var ("barborder", set_barborder, 1, "", arg_NUMBER);
- add_set_var ("barinpadding", set_barinpadding, 1, "", arg_NUMBER);
- add_set_var ("inputwidth", set_inputwidth, 1, "", arg_NUMBER);
- add_set_var ("waitcursor", set_waitcursor, 1, "", arg_NUMBER);
- add_set_var ("winfmt", set_winfmt, 1, "", arg_REST);
- add_set_var ("winname", set_winname, 1, "", arg_STRING);
- add_set_var ("framefmt", set_framefmt, 1, "", arg_REST);
- add_set_var ("fgcolor", set_fgcolor, 1, "", arg_STRING);
- add_set_var ("bgcolor", set_bgcolor, 1, "", arg_STRING);
- add_set_var ("fwcolor", set_fwcolor, 1, "", arg_STRING);
- add_set_var ("bwcolor", set_bwcolor, 1, "", arg_STRING);
- add_set_var ("barpadding", set_barpadding, 2, "", arg_NUMBER, "", arg_NUMBER);
- add_set_var ("winliststyle", set_winliststyle, 1, "", arg_STRING);
- add_set_var ("framesels", set_framesels, 1, "", arg_STRING);
- add_set_var ("infofmt", set_infofmt, 1, "", arg_REST);
- add_set_var ("topkmap", set_topkmap, 1, "", arg_STRING);
- 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);
-}
-
-/* rp_keymaps is ratpoison's list of keymaps. */
-LIST_HEAD(rp_keymaps);
-LIST_HEAD(user_commands);
-
-/* i_nrequired is the number required when called
- interactively. ni_nrequired is when called non-interactively. */
-static void
-add_command (char *name, cmdret * (*fn)(int, struct cmdarg **), int nargs, int i_nrequired, int ni_nrequired, ...)
-{
- int i = 0;
- struct user_command *cmd;
- va_list va;
-
- cmd = xmalloc (sizeof (struct user_command));
- cmd->name = name;
- cmd->func = fn;
- cmd->num_args = nargs;
- cmd->ni_required_args = ni_nrequired;
- cmd->i_required_args = i_nrequired;
- cmd->args = xmalloc(sizeof(struct argspec) * nargs);
-
- /* Fill cmd->args */
- va_start(va, ni_nrequired);
- for (i=0; i<nargs; i++)
- {
- cmd->args[i].prompt = va_arg(va, char*);
- cmd->args[i].type = va_arg(va, int);
- }
- va_end(va);
-
- list_add (&cmd->node, &user_commands);
-}
-
-static void
-user_command_free(struct user_command *cmd)
-{
- if (cmd == NULL )
- return;
-
- free(cmd->args);
- free(cmd);
-}
-
-void
-init_user_commands(void)
-{
- /*@begin (tag required for genrpbindings) */
- add_command ("abort", cmd_abort, 0, 0, 0);
- add_command ("addhook", cmd_addhook, 2, 2, 2,
- "Hook: ", arg_HOOK,
- "Command: ", arg_COMMAND);
- add_command ("alias", cmd_alias, 2, 2, 2,
- "Alias: ", arg_STRING,
- "Command: ", arg_COMMAND);
- add_command ("banish", cmd_banish, 0, 0, 0);
- add_command ("chdir", cmd_chdir, 1, 0, 0,
- "Dir: ", arg_REST);
- add_command ("clrunmanaged", cmd_clrunmanaged, 0, 0, 0);
- add_command ("colon", cmd_colon, 1, 0, 0,
- "", arg_REST);
- add_command ("curframe", cmd_curframe, 0, 0, 0);
- add_command ("definekey", cmd_definekey, 3, 3, 3,
- "Keymap: ", arg_KEYMAP,
- "Key: ", arg_KEY,
- "Command: ", arg_COMMAND);
- add_command ("undefinekey", cmd_undefinekey, 2, 2, 2,
- "Keymap: ", arg_KEYMAP,
- "Key: ", arg_KEY);
- add_command ("delete", cmd_delete, 0, 0, 0);
- add_command ("delkmap", cmd_delkmap, 1, 1, 1,
- "Keymap: ", arg_KEYMAP);
- add_command ("echo", cmd_echo, 1, 1, 1,
- "Echo: ", arg_RAW);
- add_command ("escape", cmd_escape, 1, 1, 1,
- "Key: ", arg_KEY);
- add_command ("exec", cmd_exec, 1, 1, 1,
- "/bin/sh -c ", arg_SHELLCMD);
- add_command ("execa", cmd_execa, 1, 1, 1,
- "/bin/sh -c ", arg_SHELLCMD);
- add_command ("execf", cmd_execf, 2, 2, 2,
- "frame to execute in:", arg_FRAME,
- "/bin/sh -c ", arg_SHELLCMD);
- add_command ("fdump", cmd_fdump, 1, 0, 0,
- "", arg_NUMBER);
- add_command ("focus", cmd_next_frame, 0, 0, 0);
- add_command ("focusprev", cmd_prev_frame, 0, 0, 0);
- add_command ("focusdown", cmd_focusdown, 0, 0, 0);
- add_command ("exchangeup", cmd_exchangeup, 0, 0, 0);
- add_command ("exchangedown", cmd_exchangedown, 0, 0, 0);
- add_command ("exchangeleft", cmd_exchangeleft, 0, 0, 0);
- add_command ("exchangeright", cmd_exchangeright, 0, 0, 0);
- add_command ("swap", cmd_swap, 2, 1, 1,
- "destination frame: ", arg_FRAME,
- "source frame: ", arg_FRAME);
- add_command ("focuslast", cmd_focuslast, 0, 0, 0);
- add_command ("focusleft", cmd_focusleft, 0, 0, 0);
- add_command ("focusright", cmd_focusright, 0, 0, 0);
- add_command ("focusup", cmd_focusup, 0, 0, 0);
- add_command ("frestore", cmd_frestore, 1, 1, 1,
- "Frames: ", arg_REST);
- add_command ("fselect", cmd_fselect, 1, 1, 1,
- "", arg_FRAME);
- add_command ("gdelete", cmd_gdelete, 1, 0, 0,
- "Group:", arg_GROUP);
- add_command ("getenv", cmd_getenv, 1, 1, 1,
- "Variable: ", arg_STRING);
- add_command ("gmerge", cmd_gmerge, 1, 1, 1,
- "Group: ", arg_GROUP);
- add_command ("gmove", cmd_gmove, 1, 1, 1,
- "Group: ", arg_GROUP);
- add_command ("gnew", cmd_gnew, 1, 1, 1,
- "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);
- add_command ("gprev", cmd_gprev, 0, 0, 0);
- add_command ("gother", cmd_gother, 0, 0, 0);
- add_command ("gravity", cmd_gravity, 1, 0, 0,
- "Gravity: ", arg_GRAVITY);
- add_command ("groups", cmd_groups, 0, 0, 0);
- add_command ("gselect", cmd_gselect, 1, 1, 1,
- "Group: ", arg_GROUP);
- add_command ("help", cmd_help, 1, 0, 0,
- "Keymap: ", arg_KEYMAP);
- add_command ("hsplit", cmd_h_split, 1, 0, 0,
- "Split: ", arg_STRING);
- add_command ("info", cmd_info, 1, 0, 0,
- "Format: ", arg_REST);
- add_command ("kill", cmd_kill, 0, 0, 0);
- add_command ("lastmsg", cmd_lastmsg, 0, 0, 0);
- add_command ("license", cmd_license, 0, 0, 0);
- add_command ("link", cmd_link, 2, 1, 1,
- "Key: ", arg_STRING,
- "Keymap: ", arg_KEYMAP);
- add_command ("listhook", cmd_listhook, 1, 1, 1,
- "Hook: ", arg_HOOK);
- add_command ("meta", cmd_meta, 1, 0, 0,
- "key: ", arg_KEY);
- add_command ("msgwait", cmd_msgwait, 1, 0, 0,
- "", arg_NUMBER);
- add_command ("newkmap", cmd_newkmap, 1, 1, 1,
- "Keymap: ", arg_STRING);
- add_command ("newwm", cmd_newwm, 1, 1, 1,
- "Switch to wm: ", arg_REST);
- add_command ("next", cmd_next, 0, 0, 0);
- add_command ("nextscreen", cmd_nextscreen, 0, 0, 0);
- add_command ("number", cmd_number, 2, 1, 1,
- "Number: ", arg_NUMBER,
- "Number: ", arg_NUMBER);
- add_command ("only", cmd_only, 0, 0, 0);
- add_command ("other", cmd_other, 0, 0, 0);
- add_command ("prev", cmd_prev, 0, 0, 0);
- add_command ("prevscreen", cmd_prevscreen, 0, 0, 0);
- add_command ("quit", cmd_quit, 0, 0, 0);
- add_command ("ratinfo", cmd_ratinfo, 0, 0, 0);
- add_command ("ratrelinfo", cmd_ratrelinfo, 0, 0, 0);
- add_command ("banishrel", cmd_banishrel, 0, 0, 0);
- add_command ("ratwarp", cmd_ratwarp, 2, 2, 2,
- "X: ", arg_NUMBER,
- "Y: ", arg_NUMBER);
- add_command ("ratrelwarp", cmd_ratrelwarp, 2, 2, 2,
- "X: ", arg_NUMBER,
- "Y: ", arg_NUMBER);
- add_command ("ratclick", cmd_ratclick, 1, 0, 0,
- "Button: ", arg_NUMBER);
- add_command ("rathold", cmd_rathold, 2, 1, 1,
- "State: ", arg_STRING,
- "Button: ", arg_NUMBER);
- add_command ("readkey", cmd_readkey, 1, 1, 1,
- "Keymap: ", arg_KEYMAP);
- add_command ("redisplay", cmd_redisplay, 0, 0, 0);
- add_command ("remhook", cmd_remhook, 2, 2, 2,
- "Hook: ", arg_HOOK,
- "Command: ", arg_COMMAND);
- add_command ("remove", cmd_remove, 0, 0, 0);
- add_command ("resize", cmd_resize, 2, 0, 2,
- "", arg_NUMBER,
- "", arg_NUMBER);
- add_command ("restart", cmd_restart, 0, 0, 0);
- add_command ("rudeness", cmd_rudeness, 1, 0, 0,
- "Rudeness: ", arg_NUMBER);
- add_command ("select", cmd_select, 1, 0, 1,
- "Select window: ", arg_REST);
- add_command ("set", cmd_set, 2, 0, 0,
- "", arg_VARIABLE,
- "", arg_REST);
- add_command ("setenv", cmd_setenv, 2, 2, 2,
- "Variable: ", arg_STRING,
- "Value: ", arg_REST);
- add_command ("shrink", cmd_shrink, 0, 0, 0);
- add_command ("sfrestore", cmd_sfrestore, 1, 1, 1,
- "Frames: ", arg_REST);
- add_command ("source", cmd_source, 1, 1, 1,
- "File: ", arg_REST);
- add_command ("sselect", cmd_sselect, 1, 1, 1,
- "Screen: ", arg_NUMBER);
- add_command ("startup_message", cmd_startup_message, 1, 1, 1,
- "Startup message: ", arg_STRING);
- add_command ("time", cmd_time, 0, 0, 0);
- add_command ("title", cmd_rename, 1, 1, 1,
- "Set window's title to: ", arg_REST);
- add_command ("tmpwm", cmd_tmpwm, 1, 1, 1,
- "Tmp wm: ", arg_REST);
- add_command ("unalias", cmd_unalias, 1, 1, 1,
- "Alias: ", arg_STRING);
- add_command ("unmanage", cmd_unmanage, 1, 1, 0,
- "Unmanage: ", arg_REST);
- add_command ("unsetenv", cmd_unsetenv, 1, 1, 1,
- "Variable: ", arg_STRING);
- add_command ("verbexec", cmd_verbexec, 1, 1, 1,
- "/bin/sh -c ", arg_SHELLCMD);
- add_command ("version", cmd_version, 0, 0, 0);
- add_command ("vsplit", cmd_v_split, 1, 0, 0,
- "Split: ", arg_STRING);
- add_command ("warp", cmd_warp, 1, 1, 1,
- "Warp State: ", arg_STRING);
- add_command ("windows", cmd_windows, 1, 0, 0,
- "", arg_REST);
- add_command ("cnext", cmd_cnext, 0, 0, 0);
- add_command ("cother", cmd_cother, 0, 0, 0);
- add_command ("cprev", cmd_cprev, 0, 0, 0);
- add_command ("dedicate", cmd_dedicate, 1, 0, 0,
- "", arg_NUMBER);
- add_command ("describekey", cmd_describekey, 1, 1, 1,
- "Keymap: ", arg_KEYMAP);
- add_command ("inext", cmd_inext, 0, 0, 0);
- add_command ("iother", cmd_iother, 0, 0, 0);
- add_command ("iprev", cmd_iprev, 0, 0, 0);
- add_command ("prompt", cmd_prompt, 1, 0, 0,
- "", arg_REST);
- add_command ("sdump", cmd_sdump, 0, 0, 0);
- add_command ("sfdump", cmd_sfdump, 0, 0, 0);
- add_command ("undo", cmd_undo, 0, 0, 0);
- add_command ("redo", cmd_redo, 0, 0, 0);
- add_command ("putsel", cmd_putsel, 1, 1, 1,
- "Text: ", arg_RAW);
- add_command ("getsel", cmd_getsel, 0, 0, 0);
- add_command ("compat", cmd_compat, 0, 0, 0);
- /*@end (tag required for genrpbindings) */
-
- /* Commands to help debug ratpoison. */
-#ifdef DEBUG
-#endif
-
- /* the following screen commands may or may not be able to be
- implemented. See the screen documentation for what should be
- emulated with these commands */
-#if 0
- add_command ("msgminwait", cmd_unimplemented, 0);
- add_command ("nethack", cmd_unimplemented, 0);
- add_command ("sleep", cmd_unimplemented, 0);
- add_command ("stuff", cmd_unimplemented, 0);
-#endif
-
- init_set_vars();
-}
-
-typedef struct
-{
- char *name;
- char *alias;
-} alias_t;
-
-static alias_t *alias_list;
-static int alias_list_size;
-static int alias_list_last;
-
-static cmdret* frestore (char *data, rp_screen *s);
-static char* fdump (rp_screen *screen);
-
-/* Delete all entries in the redo list. */
-static void
-clear_frame_redos (void)
-{
- rp_frame_undo *cur;
- struct list_head *tmp, *iter;
-
- list_for_each_safe_entry (cur, iter, tmp, &rp_frame_redos, node)
- {
- if (cur->frames) free (cur->frames);
- list_del (&(cur->node));
- }
-}
-
-void
-del_frame_undo (rp_frame_undo *u)
-{
- if (!u) return;
- if (u->frames) free (u->frames);
- list_del (&(u->node));
- free (u);
-}
-
-static void
-push_frame_undo(rp_screen *screen)
-{
- rp_frame_undo *cur;
- if (list_size (&rp_frame_undos) > defaults.maxundos)
- {
- /* Delete the oldest node */
- list_last (cur, &rp_frame_undos, node);
- del_frame_undo (cur);
- }
- cur = xmalloc (sizeof(rp_frame_undo));
- cur->frames = fdump (screen);
- cur->screen = screen;
- list_add (&cur->node, &rp_frame_undos);
- /* Since we're creating new frames the redo list is now invalid, so
- clear it. */
- clear_frame_redos();
-}
-
-static rp_frame_undo *
-pop_frame_list (struct list_head *undo_list, struct list_head *redo_list)
-{
- rp_screen *screen = current_screen();
- rp_frame_undo *first, *new;
-
- /* Is there something to restore? */
- list_first (first, undo_list, node);
- if (!first)
- return NULL;
-
- /* First save the current layout into undo */
- new = xmalloc (sizeof(rp_frame_undo));
- new->frames = fdump (screen);
- new->screen = screen;
- list_add (&new->node, redo_list);
-
- list_del (&(first->node));
- return first;
-}
-
-/* Pop the head of the frame undo list off and put it in the redo list. */
-static rp_frame_undo *
-pop_frame_undo (void)
-{
- return pop_frame_list (&rp_frame_undos, &rp_frame_redos);
-}
-
-/* Pop the head of the frame redo list off and put it in the undo list. */
-static rp_frame_undo *
-pop_frame_redo (void)
-{
- return pop_frame_list (&rp_frame_redos, &rp_frame_undos);
-}
-
-rp_action*
-find_keybinding_by_action (char *action, rp_keymap *map)
-{
- int i;
-
- for (i=0; i<map->actions_last; i++)
- {
- if (!strcmp (map->actions[i].data, action))
- {
- return &map->actions[i];
- }
- }
-
- return NULL;
-}
-
-rp_action*
-find_keybinding (KeySym keysym, unsigned int state, rp_keymap *map)
-{
- int i;
- for (i = 0; i < map->actions_last; i++)
- {
- if (map->actions[i].key == keysym
- && map->actions[i].state == state)
- return &map->actions[i];
- }
- return NULL;
-}
-
-static char *
-find_command_by_keydesc (char *desc, rp_keymap *map)
-{
- int i = 0;
- char *keysym_name;
-
- while (i < map->actions_last)
- {
- keysym_name = keysym_to_string (map->actions[i].key, map->actions[i].state);
- if (!strcmp (keysym_name, desc))
- {
- free (keysym_name);
- return map->actions[i].data;
- }
- free (keysym_name);
- i++;
- }
-
- return NULL;
-}
-
-static char *
-resolve_command_from_keydesc (char *desc, int depth, rp_keymap *map)
-{
- char *cmd, *c;
-
- c = find_command_by_keydesc (desc, map);
- if (!c)
- return NULL;
-
- /* is it a link? */
- if (strncmp (c, "link", 4) || depth > MAX_LINK_DEPTH)
- /* it is not */
- return c;
-
- cmd = resolve_command_from_keydesc (&c[5], depth + 1, map);
- return (cmd != NULL) ? cmd : c;
-}
-
-
-static void
-add_keybinding (KeySym keysym, int state, char *cmd, rp_keymap *map)
-{
- if (map->actions_last >= map->actions_size)
- {
- /* double the key table size */
- map->actions_size *= 2;
- map->actions = (rp_action*) xrealloc (map->actions, sizeof (rp_action) * map->actions_size);
- PRINT_DEBUG (("realloc()ed key_table %d\n", map->actions_size));
- }
-
- map->actions[map->actions_last].key = keysym;
- map->actions[map->actions_last].state = state;
- /* free this on shutdown, or re/unbinding */
- map->actions[map->actions_last].data = xstrdup (cmd);
-
- map->actions_last++;
-}
-
-static void
-replace_keybinding (rp_action *key_action, char *newcmd)
-{
- if (strlen (key_action->data) < strlen (newcmd))
- key_action->data = (char*) realloc (key_action->data, strlen (newcmd) + 1);
-
- strcpy (key_action->data, newcmd);
-}
-
-static int
-remove_keybinding (KeySym keysym, unsigned int state, rp_keymap *map)
-{
- int i;
- int found = -1;
-
- for (i=0; i<map->actions_last; i++)
- {
- if (map->actions[i].key == keysym && map->actions[i].state == state)
- {
- found = i;
- break;
- }
- }
-
- if (found >= 0)
- {
- free (map->actions[found].data);
-
- memmove (&map->actions[found], &map->actions[found+1],
- sizeof (rp_action) * (map->actions_last - found - 1));
- map->actions_last--;
-
- return 1;
- }
-
- return 0;
-}
-
-static rp_keymap *
-keymap_new (char *name)
-{
- rp_keymap *map;
-
- /* All keymaps must have a name. */
- if (name == NULL)
- return NULL;
-
- map = xmalloc (sizeof (rp_keymap));
- map->name = xstrdup (name);
- map->actions_size = 1;
- map->actions = (rp_action*) xmalloc (sizeof (rp_action) * map->actions_size);
- map->actions_last = 0;
-
- return map;
-}
-
-rp_keymap *
-find_keymap (char *name)
-{
- rp_keymap *cur;
-
- list_for_each_entry (cur, &rp_keymaps, node)
- {
- if (!strcmp (name, cur->name))
- {
- return cur;
- }
- }
-
- return NULL;
-}
-
-/* Search the alias table for a match. If a match is found, return its
- index into the table. Otherwise return -1. */
-static int
-find_alias_index (char *name)
-{
- int i;
-
- for (i=0; i<alias_list_last; i++)
- if (!strcmp (name, alias_list[i].name))
- return i;
-
- return -1;
-}
-
-static void
-add_alias (char *name, char *alias)
-{
- int i;
-
- /* Are we updating an existing alias, or creating a new one? */
- i = find_alias_index (name);
- if (i >= 0)
- {
- free (alias_list[i].alias);
- alias_list[i].alias = xstrdup (alias);
- }
- else
- {
- if (alias_list_last >= alias_list_size)
- {
- alias_list_size *= 2;
- alias_list = xrealloc (alias_list, sizeof (alias_t) * alias_list_size);
- }
-
- alias_list[alias_list_last].name = xstrdup (name);
- alias_list[alias_list_last].alias = xstrdup (alias);
- alias_list_last++;
- }
-}
-
-void
-initialize_default_keybindings (void)
-{
- rp_keymap *map, *top;
-
- map = keymap_new (ROOT_KEYMAP);
- list_add (&map->node, &rp_keymaps);
-
- top = keymap_new (defaults.top_kmap);
- list_add (&top->node, &rp_keymaps);
-
- /* Initialive the alias list. */
- alias_list_size = 5;
- alias_list_last = 0;
- alias_list = xmalloc (sizeof (alias_t) * alias_list_size);
-
- prefix_key.sym = KEY_PREFIX;
- prefix_key.state = MODIFIER_PREFIX;
-
- /* Add the prefix key to the top-level map. */
- add_keybinding (prefix_key.sym, prefix_key.state, "readkey " ROOT_KEYMAP, top);
-
- add_keybinding (prefix_key.sym, prefix_key.state, "other", map);
- add_keybinding (prefix_key.sym, 0, "meta", map);
- add_keybinding (XK_g, RP_CONTROL_MASK, "abort", map);
- add_keybinding (XK_0, 0, "select 0", map);
- add_keybinding (XK_1, 0, "select 1", map);
- add_keybinding (XK_2, 0, "select 2", map);
- add_keybinding (XK_3, 0, "select 3", map);
- add_keybinding (XK_4, 0, "select 4", map);
- add_keybinding (XK_5, 0, "select 5", map);
- add_keybinding (XK_6, 0, "select 6", map);
- add_keybinding (XK_7, 0, "select 7", map);
- add_keybinding (XK_8, 0, "select 8", map);
- add_keybinding (XK_9, 0, "select 9", map);
- add_keybinding (XK_minus, 0, "select -", map);
- add_keybinding (XK_A, 0, "title", map);
- add_keybinding (XK_A, RP_CONTROL_MASK, "title", map);
- add_keybinding (XK_K, 0, "kill", map);
- add_keybinding (XK_K, RP_CONTROL_MASK, "kill", map);
- add_keybinding (XK_Return, 0, "next", map);
- add_keybinding (XK_Return, RP_CONTROL_MASK, "next", map);
- add_keybinding (XK_a, 0, "time", map);
- add_keybinding (XK_a, RP_CONTROL_MASK, "time", map);
- add_keybinding (XK_b, 0, "banish", map);
- add_keybinding (XK_b, RP_CONTROL_MASK, "banish", map);
- add_keybinding (XK_c, 0, "exec " TERM_PROG, map);
- add_keybinding (XK_c, RP_CONTROL_MASK, "exec " TERM_PROG, map);
- add_keybinding (XK_colon, 0, "colon", map);
- add_keybinding (XK_exclam, 0, "exec", map);
- add_keybinding (XK_exclam, RP_CONTROL_MASK, "colon exec " TERM_PROG " -e ", map);
- add_keybinding (XK_i, 0, "info", map);
- add_keybinding (XK_i, RP_CONTROL_MASK, "info", map);
- add_keybinding (XK_k, 0, "delete", map);
- add_keybinding (XK_k, RP_CONTROL_MASK, "delete", map);
- add_keybinding (XK_l, 0, "redisplay", map);
- add_keybinding (XK_l, RP_CONTROL_MASK, "redisplay", map);
- add_keybinding (XK_m, 0, "lastmsg", map);
- add_keybinding (XK_m, RP_CONTROL_MASK, "lastmsg", map);
- add_keybinding (XK_n, 0, "next", map);
- add_keybinding (XK_n, RP_CONTROL_MASK, "next", map);
- add_keybinding (XK_p, 0, "prev", map);
- add_keybinding (XK_p, RP_CONTROL_MASK, "prev", map);
- add_keybinding (XK_quoteright, 0, "select", map);
- add_keybinding (XK_quoteright, RP_CONTROL_MASK, "select", map);
- add_keybinding (XK_space, 0, "next", map);
- add_keybinding (XK_space, RP_CONTROL_MASK, "next", map);
- add_keybinding (XK_v, 0, "version", map);
- add_keybinding (XK_v, RP_CONTROL_MASK, "version", map);
- add_keybinding (XK_V, 0, "license", map);
- add_keybinding (XK_V, RP_CONTROL_MASK, "license", map);
- add_keybinding (XK_w, 0, "windows", map);
- add_keybinding (XK_w, RP_CONTROL_MASK, "windows", map);
- add_keybinding (XK_s, 0, "split", map);
- add_keybinding (XK_s, RP_CONTROL_MASK, "split", map);
- add_keybinding (XK_S, 0, "hsplit", map);
- add_keybinding (XK_S, RP_CONTROL_MASK, "hsplit", map);
- add_keybinding (XK_Tab, 0, "focus", map);
- add_keybinding (XK_Tab, RP_META_MASK, "focuslast", map);
- add_keybinding (XK_Left, RP_CONTROL_MASK, "exchangeleft", map);
- add_keybinding (XK_Right, RP_CONTROL_MASK, "exchangeright", map);
- add_keybinding (XK_Up, RP_CONTROL_MASK, "exchangeup", map);
- add_keybinding (XK_Down, RP_CONTROL_MASK, "exchangedown", map);
- add_keybinding (XK_Left, 0, "focusleft", map);
- add_keybinding (XK_Right, 0, "focusright", map);
- add_keybinding (XK_Up, 0, "focusup", map);
- add_keybinding (XK_Down, 0, "focusdown", map);
- add_keybinding (XK_Q, 0, "only", map);
- add_keybinding (XK_R, 0, "remove", map);
- add_keybinding (XK_f, 0, "fselect", map);
- add_keybinding (XK_f, RP_CONTROL_MASK, "fselect", map);
- add_keybinding (XK_F, 0, "curframe", map);
- add_keybinding (XK_r, 0, "resize", map);
- add_keybinding (XK_r, RP_CONTROL_MASK, "resize", map);
- add_keybinding (XK_question, 0, "help " ROOT_KEYMAP, map);
- add_keybinding (XK_underscore, RP_CONTROL_MASK, "undo", map);
- add_keybinding (XK_u, 0, "undo", map);
- add_keybinding (XK_u, RP_CONTROL_MASK, "undo", map);
- add_keybinding (XK_U, 0, "redo", map);
- add_keybinding (XK_x, 0, "swap", map);
- add_keybinding (XK_x, RP_CONTROL_MASK, "swap", map);
- add_keybinding (XK_N, 0, "nextscreen", map);
- add_keybinding (XK_P, 0, "prevscreen", map);
-
- add_alias ("unbind", "undefinekey " ROOT_KEYMAP);
- add_alias ("bind", "definekey " ROOT_KEYMAP);
- add_alias ("split", "vsplit");
-}
-
-cmdret *
-cmdret_new (int success, char *fmt, ...)
-{
- cmdret *ret = xmalloc (sizeof (cmdret));
- va_list ap;
-
- ret->success = success;
-
- if (fmt)
- {
- va_start (ap, fmt);
- ret->output = xvsprintf (fmt, ap);
- va_end (ap);
- }
- else
- ret->output = NULL;
-
- return ret;
-}
-
-void
-cmdret_free (cmdret *ret)
-{
- if (ret->output)
- free (ret->output);
- free (ret);
-}
-
-void
-keymap_free (rp_keymap *map)
-{
- int i;
-
- /* Free the data in the actions. */
- for (i=0; i<map->actions_last; i++)
- {
- free (map->actions[i].data);
- }
-
- /* Free the map data. */
- free (map->actions);
- free (map->name);
-
- /* ...and the map itself. */
- free (map);
-}
-
-void
-free_keymaps (void)
-{
- rp_keymap *cur;
- struct list_head *tmp, *iter;
-
- list_for_each_safe_entry (cur, iter, tmp, &rp_keymaps, node)
- {
- list_del (&cur->node);
- keymap_free (cur);
- }
-}
-
-void
-free_aliases (void)
-{
- int i;
-
- /* Free the alias data. */
- for (i=0; i<alias_list_last; i++)
- {
- free (alias_list[i].name);
- free (alias_list[i].alias);
- }
-
- /* Free the alias list. */
- free (alias_list);
-}
-
-void
-free_user_commands (void)
-{
- struct user_command *cur;
- struct set_var *var;
- struct list_head *tmp, *iter;
-
- list_for_each_safe_entry (cur, iter, tmp, &user_commands, node)
- {
- list_del (&cur->node);
- user_command_free (cur);
- }
- list_for_each_safe_entry (var, iter, tmp, &set_vars, node)
- {
- list_del (&var->node);
- set_var_free (var);
- }
-}
-
-/* return a KeySym from a string that contains either a hex value or
- an X keysym description */
-static int string_to_keysym (char *str)
-{
- int retval;
- int keysym;
-
- retval = sscanf (str, "0x%x", &keysym);
-
- if (!retval || retval == EOF)
- keysym = XStringToKeysym (str);
-
- return keysym;
-}
-
-/* Parse a key description. 's' is, naturally, the key description. */
-static cmdret *
-parse_keydesc (char *s, struct rp_key *key)
-{
- char *token, *next_token, *keydesc;
-
- if (s == NULL)
- return NULL;
-
- /* Avoid mangling s. */
- keydesc = xstrdup (s);
-
- key->state = 0;
- key->sym = 0;
-
- if (!strchr (keydesc, '-'))
- {
- /* Its got no hyphens in it, so just grab the keysym */
- key->sym = string_to_keysym (keydesc);
-
- if (key->sym == NoSymbol)
- {
- cmdret *ret = cmdret_new (RET_FAILURE, "parse_keydesc: Unknown key '%s'", keydesc);
- free (keydesc);
- return ret;
- }
- }
- else if (keydesc[strlen (keydesc) - 1] == '-')
- {
- /* A key description can't end in a -. */
- free (keydesc);
- return cmdret_new (RET_FAILURE, "parse_keydesc: Can't parse key '%s'", s);
- }
- else
- {
- /* Its got hyphens, so parse out the modifiers and keysym */
- token = strtok (keydesc, "-");
-
- if (token == NULL)
- {
- /* It was nothing but hyphens */
- free (keydesc);
- return cmdret_new (RET_FAILURE, "parse_keydesc: Can't parse key '%s'", s);
- }
-
- do
- {
- next_token = strtok (NULL, "-");
-
- if (next_token == NULL)
- {
- /* There is nothing more to parse and token contains the
- keysym name. */
- key->sym = string_to_keysym (token);
-
- if (key->sym == NoSymbol)
- {
- cmdret *ret = cmdret_new (RET_FAILURE, "parse_keydesc: Unknown key '%s'", token);
- free (keydesc);
- return ret;
- }
- }
- else
- {
- /* Which modifier is it? Only accept modifiers that are
- present. ie don't accept a hyper modifier if the keymap
- has no hyper key. */
- if (!strcmp (token, "C"))
- {
- key->state |= RP_CONTROL_MASK;
- }
- else if (!strcmp (token, "M"))
- {
- key->state |= RP_META_MASK;
- }
- else if (!strcmp (token, "A"))
- {
- key->state |= RP_ALT_MASK;
- }
- else if (!strcmp (token, "S"))
- {
- key->state |= RP_SHIFT_MASK;
- }
- else if (!strcmp (token, "s"))
- {
- key->state |= RP_SUPER_MASK;
- }
- else if (!strcmp (token, "H"))
- {
- key->state |= RP_HYPER_MASK;
- }
- else
- {
- free (keydesc);
- return cmdret_new (RET_FAILURE, "parse_keydesc: Unknown modifier '%s'", token);
- }
- }
-
- token = next_token;
- } while (next_token != NULL);
- }
-
- /* Successfully parsed the key. */
- free (keydesc);
- return NULL;
-}
-
-static void
-grab_rat (void)
-{
- XGrabPointer (dpy, current_screen()->root, True, 0,
- GrabModeAsync, GrabModeAsync,
- None, current_screen()->rat, CurrentTime);
-}
-
-static void
-ungrab_rat (void)
-{
- XUngrabPointer (dpy, CurrentTime);
-}
-
-/* Unmanage window */
-cmdret *
-cmd_unmanage (int interactive, struct cmdarg **args)
-{
- if (args[0] == NULL && !interactive)
- {
- cmdret *ret;
- char *s = list_unmanaged_windows();
-
- if (s)
- ret = cmdret_new (RET_SUCCESS, "%s", s);
- else
- ret = cmdret_new (RET_SUCCESS, NULL);
-
- free (s);
- return ret;
- }
-
- if (args[0])
- add_unmanaged_window(ARG_STRING(0));
- else
- return cmdret_new (RET_FAILURE, "unmanage: at least one argument required");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Clear the unmanaged window list */
-cmdret *
-cmd_clrunmanaged (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- clear_unmanaged_list();
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_undefinekey (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *ret = NULL;
- rp_keymap *map;
- struct rp_key *key;
-
- map = ARG (0, keymap);
- key = ARG (1, key);
-
- /* If we're updating the top level map, we'll need to update the
- keys grabbed. */
- if (map == find_keymap (defaults.top_kmap))
- ungrab_keys_all_wins ();
-
- /* If no comand is specified, then unbind the key. */
- if (!remove_keybinding (key->sym, key->state, map))
- ret = cmdret_new (RET_FAILURE, "undefinekey: key '%s' is not bound", ARG_STRING(1));
-
- /* Update the grabbed keys. */
- if (map == find_keymap (defaults.top_kmap))
- grab_keys_all_wins ();
- XSync (dpy, False);
-
- if (ret)
- return ret;
- else
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_definekey (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *ret = NULL;
- rp_keymap *map;
- struct rp_key *key;
- char *cmd;
- rp_action *key_action;
-
- map = ARG(0,keymap);
- key = ARG(1,key);
- cmd = ARG_STRING(2);
-
- /* If we're updating the top level map, we'll need to update the
- keys grabbed. */
- if (map == find_keymap (defaults.top_kmap))
- ungrab_keys_all_wins ();
-
- if ((key_action = find_keybinding (key->sym, key->state, map)))
- replace_keybinding (key_action, cmd);
- else
- add_keybinding (key->sym, key->state, cmd, map);
-
- /* Update the grabbed keys. */
- if (map == find_keymap (defaults.top_kmap))
- grab_keys_all_wins ();
- XSync (dpy, False);
-
- if (ret)
- return ret;
- else
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_unimplemented (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- return cmdret_new (RET_FAILURE, "FIXME: unimplemented command");
-}
-
-cmdret *
-cmd_source (int interactive UNUSED, struct cmdarg **args)
-{
- FILE *fileptr;
-
- if ((fileptr = fopen (ARG_STRING(0), "r")) == NULL)
- return cmdret_new (RET_FAILURE, "source: %s : %s", ARG_STRING(0), strerror(errno));
- else
- {
- set_close_on_exec (fileptr);
- read_rc_file (fileptr);
- fclose (fileptr);
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_meta (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *ret = NULL;
- struct rp_key key;
- XEvent ev;
-
- if (current_window() == NULL)
- return cmdret_new (RET_FAILURE, NULL);
-
- ev.xkey.type = KeyPress;
- ev.xkey.display = dpy;
- ev.xkey.window = current_window()->w;
-
- if (args[0])
- {
- if((ret = parse_keydesc (ARG_STRING(0), &key)))
- return ret;
-
- ev.xkey.state = rp_mask_to_x11_mask (key.state);
- if(!(ev.xkey.keycode = XKeysymToKeycode (dpy, key.sym)))
- return cmdret_new (RET_FAILURE, "meta: Couldn't convert keysym to keycode");
- }
- else
- {
- ev.xkey.state = rp_mask_to_x11_mask (prefix_key.state);
- ev.xkey.keycode = XKeysymToKeycode (dpy, prefix_key.sym);
- }
- XSendEvent (dpy, current_window()->w, False, KeyPressMask, &ev);
-
- /* XTestFakeKeyEvent (dpy, XKeysymToKeycode (dpy, 't'), True, 0); */
-
- XSync (dpy, False);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_prev (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_window *cur, *win;
- cur = current_window();
- win = group_prev_window (rp_current_group, cur);
-
- if (win)
- set_active_window (win);
- else if (cur)
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
- else
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_MANAGED_WINDOWS);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_prev_frame (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- frame = find_frame_prev (current_frame());
- if (!frame)
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_FRAME);
- else
- set_active_frame (frame, 0);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_next (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_window *cur, *win;
- cur = current_window();
- win = group_next_window (rp_current_group, cur);
-
- if (win)
- set_active_window (win);
- else if (cur)
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
- else
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_MANAGED_WINDOWS);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_next_frame (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- frame = find_frame_next (current_frame());
- if (!frame)
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_FRAME);
- else
- set_active_frame (frame, 0);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_other (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_window *w;
-
-/* w = find_window_other (); */
- w = group_last_window (rp_current_group, current_screen());
-
- if (!w)
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
- else
- set_active_window_force (w);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static int
-string_to_window_number (char *str)
-{
- int i;
- char *s;
-
- for (i = 0, s = str; *s; s++)
- {
- if (*s < '0' || *s > '9')
- break;
- i = i * 10 + (*s - '0');
- }
-
- return *s ? -1 : i;
-}
-
-static struct list_head *
-trivial_completions (char* str UNUSED)
-{
- struct list_head *list;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- return list;
-}
-
-static struct list_head *
-keymap_completions (char* str UNUSED)
-{
- rp_keymap *cur;
- struct list_head *list;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- list_for_each_entry (cur, &rp_keymaps, node)
- {
- struct sbuf *name;
-
- name = sbuf_new (0);
- sbuf_copy (name, cur->name);
- list_add_tail (&name->node, list);
- }
-
- return list;
-}
-
-static struct list_head *
-window_completions (char* str UNUSED)
-{
- rp_window_elem *cur;
- struct list_head *list;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- /* Gather the names of all the windows. */
- list_for_each_entry (cur, &rp_current_group->mapped_windows, node)
- {
- struct sbuf *name;
-
- name = sbuf_new (0);
- sbuf_copy (name, window_name (cur->win));
- list_add_tail (&name->node, list);
- }
-
- return list;
-}
-
-/* switch to window number or name */
-cmdret *
-cmd_select (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *ret = NULL;
- char *str;
- int n;
-
- /* FIXME: This is manually done because of the kinds of things
- select accepts. */
- if (args[0] == NULL)
- str = get_input (MESSAGE_PROMPT_SWITCH_TO_WINDOW, hist_SELECT,
- window_completions);
- else
- str = xstrdup (ARG_STRING(0));
-
- /* User aborted. */
- if (str == NULL)
- return cmdret_new (RET_FAILURE, NULL);
-
- /* Only search if the string contains something to search for. */
- if (strlen (str) > 0)
- {
- if (strlen (str) == 1 && str[0] == '-')
- {
- blank_frame (current_frame());
- ret = cmdret_new (RET_SUCCESS, NULL);
- }
- /* try by number */
- else if ((n = string_to_window_number (str)) >= 0)
- {
- rp_window_elem *elem = group_find_window_by_number (rp_current_group, n);
-
- if (elem)
- {
- goto_window (elem->win);
- ret = cmdret_new (RET_SUCCESS, NULL);
- }
- else
- {
- /* show the window list as feedback */
- show_bar (current_screen (), defaults.window_fmt);
- ret = cmdret_new (RET_FAILURE,
- "select: unknown window number '%d'", n);
- }
- }
- else
- /* try by name */
- {
- rp_window *win = find_window_name (str);
-
- if (win)
- {
- goto_window (win);
- ret = cmdret_new (RET_SUCCESS, NULL);
- }
- else
- ret = cmdret_new (RET_FAILURE, "select: unknown window '%s'", str);
- }
- }
- else
- /* Silently fail, since the user didn't provide a window spec */
- ret = cmdret_new (RET_SUCCESS, NULL);
-
- free (str);
-
- return ret;
-}
-
-cmdret *
-cmd_rename (int interactive UNUSED, struct cmdarg **args)
-{
- if (current_window() == NULL)
- return cmdret_new (RET_FAILURE, NULL);
-
- free (current_window()->user_name);
- current_window()->user_name = xstrdup (ARG_STRING(0));
- current_window()->named = 1;
- hook_run (&rp_title_changed_hook);
-
- /* Update the program bar. */
- update_window_names (current_screen(), defaults.window_fmt);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_delete (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- XEvent ev;
- int status;
-
- if (current_window() == NULL)
- return cmdret_new (RET_FAILURE, NULL);
-
- ev.xclient.type = ClientMessage;
- ev.xclient.window = current_window()->w;
- ev.xclient.message_type = wm_protocols;
- ev.xclient.format = 32;
- ev.xclient.data.l[0] = wm_delete;
- ev.xclient.data.l[1] = CurrentTime;
-
- status = XSendEvent(dpy, current_window()->w, False, 0, &ev);
- if (status == 0)
- PRINT_DEBUG (("Delete window failed\n"));
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_kill (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- if (current_window() == NULL)
- return cmdret_new (RET_FAILURE, NULL);
-
- if (XKillClient(dpy, current_window()->w) == BadValue)
- {
- return cmdret_new (RET_FAILURE,
- "kill failed (got BadValue, this may be a bug)");
- }
- else
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_version (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- return cmdret_new (RET_SUCCESS, "%s", PACKAGE " " VERSION " (built " __DATE__ " " __TIME__ ")");
-}
-
-static char *
-frame_selector (unsigned int n)
-{
- if (n < strlen (defaults.frame_selectors))
- {
- return xsprintf (" %c ", defaults.frame_selectors[n]);
- }
- else
- {
- return xsprintf (" %d ", n);
- }
-}
-
-/* Return true if ch is nth frame selector. */
-static int
-frame_selector_match (char ch)
-{
- size_t i;
-
- /* Is it in the frame selector string? */
- for (i=0; i<strlen (defaults.frame_selectors); i++)
- {
- if (ch == defaults.frame_selectors[i])
- return i;
- }
-
- /* Maybe it's a number less than 9 and the frame selector doesn't
- define that many selectors. */
- if (ch >= '0' && ch <= '9'
- && (size_t)(ch - '0') >= strlen (defaults.frame_selectors))
- {
- return ch - '0';
- }
-
- return -1;
-}
-
-static cmdret *
-read_string (struct argspec *spec, struct sbuf *s, int history_id, completion_fn fn, struct cmdarg **arg)
-{
- char *input;
-
- if (s)
- input = xstrdup (sbuf_get(s));
- else
- input = get_input (spec->prompt, history_id, fn);
-
- if (input)
- {
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = spec->type;
- (*arg)->string = input;
- return NULL;
- }
-
- *arg = NULL;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-read_keymap (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
- char *input;
- if (s)
- input = xstrdup (sbuf_get (s));
- else
- input = get_input (spec->prompt, hist_KEYMAP, keymap_completions);
-
- if (input)
- {
- rp_keymap *map;
- map = find_keymap (input);
- if (map == NULL)
- {
- cmdret *ret = cmdret_new (RET_FAILURE, "unknown keymap '%s'", input);
- free (input);
- return ret;
- }
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = spec->type;
- (*arg)->arg.keymap = map;
- (*arg)->string = input;
- return NULL;
- }
-
- *arg = NULL;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-read_keydesc (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
- char *input;
- if (s)
- input = xstrdup (sbuf_get (s));
- else
- input = get_input (spec->prompt, hist_KEY, trivial_completions);
-
- if (input)
- {
- cmdret *ret;
- struct rp_key *key = xmalloc (sizeof(struct rp_key));
- ret = parse_keydesc (input, key);
- if (ret) {
- free (key);
- return ret;
- }
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = spec->type;
- (*arg)->arg.key = key;
- (*arg)->string = input;
- return NULL;
- }
-
- *arg = NULL;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static struct list_head *
-group_completions (char *str UNUSED)
-{
- struct list_head *list;
- rp_group *cur;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- /* Grab all the group names. */
- list_for_each_entry (cur, &rp_groups, node)
- {
- struct sbuf *s;
-
- s = sbuf_new (0);
- /* A group may not have a name, so if it doesn't, use it's
- number. */
- if (cur->name)
- {
- sbuf_copy (s, cur->name);
- }
- else
- {
- sbuf_printf (s, "%d", cur->number);
- }
-
- list_add_tail (&s->node, list);
- }
-
- return list;
-}
-
-static struct list_head *
-colon_completions (char* str UNUSED)
-{
- int i;
- struct user_command *uc;
- struct sbuf *s;
- struct list_head *list;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- /* Put all the aliases in our list. */
- for(i=0; i<alias_list_last; ++i)
- {
- s = sbuf_new (0);
- sbuf_copy (s, alias_list[i].name);
- /* The space is so when the user completes a space is
- conveniently inserted after the command. */
- sbuf_concat (s, " ");
- list_add_tail (&s->node, list);
- }
-
- /* Put all the commands in our list. */
- list_for_each_entry (uc, &user_commands, node)
- {
- s = sbuf_new (0);
- sbuf_copy (s, uc->name);
- /* The space is so when the user completes a space is
- conveniently inserted after the command. */
- sbuf_concat (s, " ");
- list_add_tail (&s->node, list);
- }
-
- return list;
-}
-
-static cmdret *
-read_command (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
- return read_string (spec, s, hist_COMMAND, colon_completions, arg);
-}
-
-static struct list_head *
-exec_completions (char *str)
-{
- size_t n = 256;
- char *partial;
- struct sbuf *line;
- FILE *file;
- struct list_head *head;
- char *completion_string;
-
- /* Initialize our list. */
- head = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (head);
-
- /* FIXME: A Bash dependancy?? */
- completion_string = xsprintf("bash -c \"compgen -ac %s|sort\"", str);
- file = popen (completion_string, "r");
- free (completion_string);
- if (!file)
- {
- PRINT_ERROR (("popen failed\n"));
- return head;
- }
-
- partial = (char*)xmalloc (n);
-
- /* Read data from the file, split it into lines and store it in a
- list. */
- line = sbuf_new (0);
- while (fgets (partial, n, file) != NULL)
- {
- /* Read a chunk from the file into our line accumulator. */
- sbuf_concat (line, partial);
-
- if (feof(file) || (*(sbuf_get (line) + strlen(sbuf_get (line)) - 1) == '\n'))
- {
- char *s;
- struct sbuf *elem;
-
- s = sbuf_get (line);
-
- /* Frob the newline into */
- if (*(s + strlen(s) - 1) == '\n')
- *(s + strlen(s) - 1) = '\0';
-
- /* Add our line to the list. */
- elem = sbuf_new (0);
- sbuf_copy (elem, s);
- list_add_tail (&elem->node, head);
-
- sbuf_clear (line);
- }
- }
-
- sbuf_free (line);
-
- free (partial);
- pclose (file);
-
- return head;
-}
-
-static cmdret *
-read_shellcmd (struct argspec *spec, struct sbuf *s, struct cmdarg **arg, const char *command_name)
-{
- cmdret *ret;
-
- ret = read_string (spec, s, hist_SHELLCMD, exec_completions, arg);
- if (command_name && !s && !ret) {
- /* store for command history */
- char *str = xmalloc (strlen(command_name) + strlen((*arg)->string) + 2);
- sprintf (str, "%s %s", command_name, (*arg)->string);
- history_add (hist_COMMAND, str);
- free(str);
- }
- return ret;
-}
-
-/* Return NULL on abort/failure. */
-static cmdret *
-read_frame (struct sbuf *s, struct cmdarg **arg)
-{
- rp_frame *frame;
- int fnum = -1;
- KeySym c;
- char keysym_buf[513];
- int keysym_bufsize = sizeof (keysym_buf);
- unsigned int mod;
- Window *wins;
- int i, j;
- rp_frame *cur;
- int frames;
-
- if (s == NULL)
- {
- frames = 0;
- for (j=0; j<num_screens; j++)
- frames += num_frames(&screens[j]);
-
- wins = xmalloc (sizeof (Window) * frames);
-
- /* Loop through each frame and display its number in it's top
- left corner. */
- i = 0;
- for (j=0; j<num_screens; j++)
- {
- XSetWindowAttributes attr;
- rp_screen *screen = &screens[j];
-
- /* Set up the window attributes to be used in the loop. */
- attr.border_pixel = screen->fg_color;
- attr.background_pixel = screen->bg_color;
- attr.override_redirect = True;
-
- list_for_each_entry (cur, &screen->frames, node)
- {
- int width, height;
- char *num;
-
- /* Create the string to be displayed in the window and
- determine the height and width of the window. */
- /* num = xsprintf (" %d ", cur->number); */
- num = frame_selector (cur->number);
- width = defaults.bar_x_padding * 2 + rp_text_width (screen, num, -1);
- height = (FONT_HEIGHT (screen) + defaults.bar_y_padding * 2);
-
- /* Create and map the window. */
- wins[i] = XCreateWindow (dpy, screen->root, screen->left + cur->x, screen->top + cur->y, width, height, 1,
- CopyFromParent, CopyFromParent, CopyFromParent,
- CWOverrideRedirect | CWBorderPixel | CWBackPixel,
- &attr);
- XMapWindow (dpy, wins[i]);
- XClearWindow (dpy, wins[i]);
-
- /* Display the frame's number inside the window. */
- rp_draw_string (screen, wins[i], STYLE_NORMAL,
- defaults.bar_x_padding,
- defaults.bar_y_padding + FONT_ASCENT(screen),
- num, -1);
-
- free (num);
- i++;
- }
- }
- XSync (dpy, False);
-
- /* Read a key. */
- read_single_key (&c, &mod, keysym_buf, keysym_bufsize);
-
- /* Destroy our number windows and free the array. */
- for (i=0; i<frames; i++)
- XDestroyWindow (dpy, wins[i]);
-
- free (wins);
-
- /* FIXME: We only handle one character long keysym names. */
- if (strlen (keysym_buf) == 1)
- {
- fnum = frame_selector_match (keysym_buf[0]);
- if (fnum == -1)
- goto frame_fail;
- }
- else
- {
- goto frame_fail;
- }
- }
- else
- {
- fnum = strtol (sbuf_get (s), NULL, 10);
- }
- /* Now that we have a frame number to go to, let's try to jump to
- it. */
- frame = find_frame_number (fnum);
- if (frame)
- {
- /* We have to return a string, because commands get lists of
- strings. Sucky, yes. The command is simply going to parse it
- back into an rp_frame. */
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = arg_FRAME;
- (*arg)->string = NULL;
- (*arg)->arg.frame = frame;
- return NULL;
- }
-
-
- frame_fail:
- *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_window_number (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);
- }
-
- 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)
-{
- int ret = -1;
-
- if (!strcasecmp (data, "northwest") || !strcasecmp (data, "nw") || !strcmp (data, "7"))
- ret = NorthWestGravity;
- if (!strcasecmp (data, "north") || !strcasecmp (data, "n") || !strcmp (data, "8"))
- ret = NorthGravity;
- if (!strcasecmp (data, "northeast") || !strcasecmp (data, "ne") || !strcmp (data, "9"))
- ret = NorthEastGravity;
- if (!strcasecmp (data, "west") || !strcasecmp (data, "w") || !strcmp (data, "4"))
- ret = WestGravity;
- if (!strcasecmp (data, "center") || !strcasecmp (data, "c") || !strcmp (data, "5"))
- ret = CenterGravity;
- if (!strcasecmp (data, "east") || !strcasecmp (data, "e") || !strcmp (data, "6"))
- ret = EastGravity;
- if (!strcasecmp (data, "southwest") || !strcasecmp (data, "sw") || !strcmp (data, "1"))
- ret = SouthWestGravity;
- if (!strcasecmp (data, "south") || !strcasecmp (data, "s") || !strcmp (data, "2"))
- ret = SouthGravity;
- if (!strcasecmp (data, "southeast") || !strcasecmp (data, "se") || !strcmp (data, "3"))
- ret = SouthEastGravity;
-
- return ret;
-}
-
-static cmdret *
-read_gravity (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
- char *input;
-
- if (s)
- input = xstrdup (sbuf_get(s));
- else
- input = get_input (spec->prompt, hist_GRAVITY, trivial_completions);
-
- if (input)
- {
- int g = parse_wingravity (input);
- if (g == -1)
- {
- cmdret *ret = cmdret_new (RET_FAILURE, "bad gravity '%s'", input);
- free (input);
- return ret;
- }
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = arg_GRAVITY;
- (*arg)->arg.gravity = g;
- (*arg)->string = input;
- return NULL;
- }
-
- *arg = NULL;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Given a string, find a matching group. First check if the string is
- a number, then check if it's the name of a group. */
-static rp_group *
-find_group (char *str)
-{
- rp_group *group;
- int n;
-
- /* Check if the user typed a group number. */
- n = string_to_window_number (str);
- if (n >= 0)
- {
- group = groups_find_group_by_number (n);
- if (group)
- return group;
- }
-
- group = groups_find_group_by_name (str, 0);
- return group;
-}
-
-static cmdret *
-read_group (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
- char *input;
-
- if (s)
- input = xstrdup (sbuf_get(s));
- else
- input = get_input (spec->prompt, hist_GROUP, group_completions);
-
- if (input)
- {
- rp_group *g = find_group (input);
-
- if (g)
- {
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = arg_GROUP;
- (*arg)->arg.group = g;
- (*arg)->string = input;
- return NULL;
- }
- else
- {
- cmdret *ret = cmdret_new (RET_FAILURE, "unknown group '%s'", input);
- free (input);
- return ret;
- }
- }
-
- *arg = NULL;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static struct list_head *
-hook_completions (char* str UNUSED)
-{
- struct list_head *list;
- struct rp_hook_db_entry *entry;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- for (entry = rp_hook_db; entry->name; entry++)
- {
- struct sbuf *hookname;
-
- hookname = sbuf_new(0);
- sbuf_copy (hookname, entry->name);
- list_add_tail (&hookname->node, list);
- }
-
- return list;
-}
-
-static cmdret *
-read_hook (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
- char *input;
-
- if (s)
- input = xstrdup (sbuf_get(s));
- else
- input = get_input (spec->prompt, hist_HOOK, hook_completions);
-
- if (input)
- {
- struct list_head *hook = hook_lookup (input);
-
- if (hook)
- {
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = arg_HOOK;
- (*arg)->arg.hook = hook;
- (*arg)->string = input;
- return NULL;
- }
- else
- {
- cmdret *ret = cmdret_new (RET_FAILURE, "unknown hook '%s'", input);
- free (input);
- return ret;
- }
- }
-
- *arg = NULL;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static struct set_var *
-find_variable (char *str)
-{
- struct set_var *cur;
- list_for_each_entry (cur, &set_vars, node)
- {
- if (!strcmp (str, cur->var))
- return cur;
- }
- return NULL;
-}
-
-static struct list_head *
-var_completions (char *str UNUSED)
-{
- struct list_head *list;
- struct set_var *cur;
-
- /* Initialize our list. */
- list = xmalloc (sizeof (struct list_head));
- INIT_LIST_HEAD (list);
-
- /* Grab all the group names. */
- list_for_each_entry (cur, &set_vars, node)
- {
- struct sbuf *s;
- s = sbuf_new (0);
- sbuf_copy (s, cur->var);
- list_add_tail (&s->node, list);
- }
-
- return list;
-}
-
-static cmdret *
-read_variable (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
- char *input;
-
- if (s)
- input = xstrdup (sbuf_get(s));
- else
- input = get_input (spec->prompt, hist_VARIABLE, var_completions);
-
- if (input)
- {
- struct set_var *var = find_variable (input);
- if (var == NULL)
- {
- cmdret *ret = cmdret_new (RET_FAILURE, "unknown variable '%s'", input);
- free (input);
- return ret;
- }
-
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = arg_VARIABLE;
- (*arg)->arg.variable = var;
- (*arg)->string = input;
- return NULL;
- }
-
- *arg = NULL;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-read_number (struct argspec *spec, struct sbuf *s, struct cmdarg **arg)
-{
- char *input;
-
- if (s)
- input = xstrdup (sbuf_get(s));
- else
- /* numbers should perhaps be more fine grained, or hist_NONE */
- input = get_input (spec->prompt, hist_OTHER, trivial_completions);
-
- if (input)
- {
- *arg = xmalloc (sizeof(struct cmdarg));
- (*arg)->type = arg_NUMBER;
- (*arg)->arg.number = strtol (input, NULL, 10);
- (*arg)->string = input;
- return NULL;
- }
-
- *arg = NULL;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-read_arg (struct argspec *spec, struct sbuf *s, struct cmdarg **arg, const char *command_name)
-{
- cmdret *ret = NULL;
-
- switch (spec->type)
- {
- case arg_STRING:
- case arg_REST:
- case arg_RAW:
- ret = read_string (spec, s, hist_OTHER, trivial_completions, arg);
- break;
- case arg_KEYMAP:
- ret = read_keymap (spec, s, arg);
- break;
- case arg_KEY:
- ret = read_keydesc (spec, s, arg);
- break;
- case arg_NUMBER:
- ret = read_number (spec, s, arg);
- break;
- case arg_GRAVITY:
- ret = read_gravity (spec, s, arg);
- break;
- case arg_COMMAND:
- ret = read_command (spec, s, arg);
- break;
- case arg_SHELLCMD:
- ret = read_shellcmd (spec, s, arg, command_name);
- break;
- case arg_WINDOW:
- ret = read_window (spec, s, arg);
- break;
- case arg_FRAME:
- ret = read_frame (s, arg);
- break;
- case arg_GROUP:
- ret = read_group (spec, s, arg);
- break;
- case arg_HOOK:
- ret = read_hook (spec, s, arg);
- break;
- case arg_VARIABLE:
- ret = read_variable (spec, s, arg);
- break;
- }
-
- return ret;
-}
-
-/* Return -1 on failure. Return the number of args on success. */
-static cmdret *
-parsed_input_to_args (int num_args, struct argspec *argspec, struct list_head *list,
- struct list_head *args, int *parsed_args, const char *command_name)
-{
- struct sbuf *s;
- struct cmdarg *arg;
- cmdret *ret;
-
- PRINT_DEBUG (("list len: %d\n", list_size (list)));
-
- *parsed_args = 0;
-
- /* Convert the existing entries to cmdarg's. */
- list_for_each_entry (s, list, node)
- {
- if (*parsed_args >= num_args) break;
- ret = read_arg (&argspec[*parsed_args], s, &arg, command_name);
- /* If there was an error, then abort. */
- if (ret)
- return ret;
-
- list_add_tail (&arg->node, args);
- (*parsed_args)++;
- }
-
- return NULL;
-}
-
-/* Prompt the user for missing arguments. Returns non-zero on
- failure. 0 on success. */
-static cmdret *
-fill_in_missing_args (struct user_command *cmd, struct list_head *list, struct list_head *args, const char *command_name)
-{
- cmdret *ret;
- struct cmdarg *arg;
- int i = 0;
-
- ret = parsed_input_to_args (cmd->num_args, cmd->args, list, args, &i, command_name);
- if (ret)
- return ret;
-
- /* Fill in the rest of the required arguments. */
- for(; i < cmd->i_required_args; i++)
- {
- ret = read_arg (&cmd->args[i], NULL, &arg, command_name);
- if (ret)
- return ret;
- list_add_tail (&arg->node, args);
- }
-
- return NULL;
-}
-
-/* Stick a list of sbuf's in list. if nargs >= 0 then only parse nargs
- arguments and and the rest of the string to the list. Return 0 on
- success. non-zero on failure. When raw is true, then when we hit
- nargs, we should keep any whitespace at the beginning. When false,
- gobble the whitespace. */
-static cmdret *
-parse_args (char *str, struct list_head *list, int nargs, int raw)
-{
- cmdret *ret = NULL;
- char *i;
- char *tmp;
- int len = 0;
- int str_escape = 0;
- int in_str = 0;
- int gobble = 1;
- int parsed_args = 0;
-
- if (str == NULL)
- return NULL;
-
- tmp = malloc (strlen(str) + 1);
-
- for (i=str; *i; i++)
- {
- /* Have we hit the arg limit? */
- if (raw && parsed_args >= nargs)
- {
- struct sbuf *s = sbuf_new(0);
- if (!raw)
- while (*i && isspace (*i)) i++;
- if (*i)
- {
- sbuf_concat(s, i);
- list_add_tail (&s->node, list);
- }
- len = 0;
- break;
- }
-
- /* Should we eat the whitespace? */
- if (gobble)
- {
- while (*i && isspace (*i)) i++;
- gobble = 0;
- }
-
- /* Escaped characters always get added. */
- if (str_escape)
- {
- tmp[len] = *i;
- len++;
- str_escape = 0;
- }
- else if (*i == '\\')
- {
- str_escape = 1;
- }
- else if (*i == '"')
- {
- if (in_str)
- {
- /* End the arg. */
- struct sbuf *s = sbuf_new(0);
- sbuf_nconcat(s, tmp, len);
- list_add_tail (&s->node, list);
- len = 0;
- gobble = 1;
- in_str = 0;
- parsed_args++;
- }
- else if (len == 0)
- {
- /* A string open can only start at the beginning of an
- argument. */
- in_str = 1;
- }
- else
- {
- ret = cmdret_new (RET_FAILURE, "parse error in '%s'", str);
- break;
- }
- }
- else if (isspace (*i) && !in_str)
- {
- /* End the current arg, and start a new one. */
- struct sbuf *s = sbuf_new(0);
- sbuf_nconcat(s, tmp, len);
- list_add_tail (&s->node, list);
- len = 0;
- gobble = 1;
- parsed_args++;
- }
- else
- {
- /* Add the character to the argument. */
- tmp[len] = *i;
- len++;
- }
- }
- /* Add the remaining text in tmp. */
- if (ret == NULL && len)
- {
- struct sbuf *s = sbuf_new(0);
- sbuf_nconcat(s, tmp, len);
- list_add_tail (&s->node, list);
- }
-
- /* Free our memory and return. */
- free (tmp);
- return ret;
-}
-
-/* Convert the list to an array, for easier access in commands. */
-static struct cmdarg **
-arg_array (struct list_head *head)
-{
- int i = 0;
- struct cmdarg **args, *cur;
-
- args = (struct cmdarg **)xmalloc (sizeof (struct cmdarg *) * (list_size (head) + 1));
- list_for_each_entry (cur, head, node)
- {
- args[i] = cur;
- i++;
- }
-
- /* NULL terminate the array. */
- args[list_size (head)] = NULL;
- return args;
-}
-
-static void
-arg_free (struct cmdarg *arg)
-{
- if (arg)
- {
- /* read_frame doesn't fill in string. */
- if (arg->string)
- free (arg->string);
- switch (arg->type)
- {
- case arg_KEY:
- free (arg->arg.key);
- break;
- case arg_REST:
- case arg_STRING:
- case arg_NUMBER:
- case arg_WINDOW:
- case arg_FRAME:
- case arg_COMMAND:
- case arg_SHELLCMD:
- case arg_KEYMAP:
- case arg_GRAVITY:
- case arg_GROUP:
- case arg_HOOK:
- case arg_VARIABLE:
- case arg_RAW:
- /* Do nothing */
- break;
- default:
- PRINT_ERROR (("Missed an arg type.\n"));
- break;
- }
- free (arg);
- }
-}
-
-cmdret *
-command (int interactive, char *data)
-{
- /* This static counter is used to exit from recursive alias calls. */
- static int alias_recursive_depth = 0;
- cmdret *result = NULL;
- char *cmd, *rest;
- char *input;
- user_command *uc;
- int i;
-
- if (data == NULL)
- return cmdret_new (RET_FAILURE, NULL);
-
- /* get a writable copy for strtok() */
- input = xstrdup (data);
-
- cmd = input;
- /* skip beginning whitespace. */
- while (*cmd && isspace (*cmd)) cmd++;
- rest = cmd;
- /* skip til we get to whitespace */
- while (*rest && !isspace (*rest)) rest++;
- /* mark that spot as the end of the command and make rest point to
- the rest of the string. */
- if (*rest)
- {
- *rest = 0;
- rest++;
- }
-
- PRINT_DEBUG (("cmd==%s rest==%s\n", cmd, rest?rest:"NULL"));
-
- /* Look for it in the aliases, first. */
- for (i=0; i<alias_list_last; i++)
- {
- if (!strcmp (cmd, alias_list[i].name))
- {
- struct sbuf *s;
-
- /* Append any arguments onto the end of the alias' command. */
- s = sbuf_new (0);
- sbuf_concat (s, alias_list[i].alias);
- if (rest != NULL && *rest)
- sbuf_printf_concat (s, " %s", rest);
-
- alias_recursive_depth++;
- if (alias_recursive_depth >= MAX_ALIAS_RECURSIVE_DEPTH)
- result = cmdret_new (RET_FAILURE, "command: alias recursion has exceeded maximum depth");
- else
- result = command (interactive, sbuf_get (s));
- alias_recursive_depth--;
-
- sbuf_free (s);
- goto done;
- }
- }
-
- /* If it wasn't an alias, maybe its a command. */
- list_for_each_entry (uc, &user_commands, node)
- {
- if (!strcmp (cmd, uc->name))
- {
- struct sbuf *scur;
- struct cmdarg *acur;
- struct list_head *iter, *tmp;
- struct list_head head, args;
- int nargs = 0, raw = 0;
-
- INIT_LIST_HEAD (&args);
- INIT_LIST_HEAD (&head);
-
- /* We need to tell parse_args about arg_REST and arg_SHELLCMD. */
- for (i=0; i<uc->num_args; i++)
- if (uc->args[i].type == arg_REST
- || uc->args[i].type == arg_COMMAND
- || uc->args[i].type == arg_SHELLCMD
- || uc->args[i].type == arg_RAW)
- {
- raw = 1;
- nargs = i;
- break;
- }
-
- /* Parse the arguments and call the function. */
- result = parse_args (rest, &head, nargs, raw);
- if (result)
- goto free_lists;
-
- /* Interactive commands prompt the user for missing args. */
- if (interactive)
- result = fill_in_missing_args (uc, &head, &args, uc->name);
- else
- {
- int parsed_args;
- result = parsed_input_to_args (uc->num_args, uc->args, &head, &args, &parsed_args, uc->name);
- }
-
- if (result == NULL)
- {
- if ((interactive && list_size (&args) < uc->i_required_args)
- || (!interactive && list_size (&args) < uc->ni_required_args))
- {
- result = cmdret_new (RET_FAILURE, "not enough arguments.");
- goto free_lists;
- }
- else if (list_size (&head) > uc->num_args)
- {
- result = cmdret_new (RET_FAILURE, "too many arguments.");
- goto free_lists;
- }
- else
- {
- struct cmdarg **cmdargs = arg_array (&args);
- result = uc->func (interactive, cmdargs);
- free (cmdargs);
- }
- }
-
- free_lists:
- /* Free the parsed strings */
- list_for_each_safe_entry (scur, iter, tmp, &head, node)
- sbuf_free(scur);
- /* Free the args */
- list_for_each_safe_entry (acur, iter, tmp, &args, node)
- arg_free (acur);
-
- goto done;
- }
- }
-
- result = cmdret_new (RET_FAILURE, MESSAGE_UNKNOWN_COMMAND, cmd);
-
- done:
- free (input);
- return result;
-}
-
-cmdret *
-cmd_colon (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *result;
- char *input;
-
- if (args[0] == NULL)
- input = get_input (MESSAGE_PROMPT_COMMAND, hist_COMMAND, colon_completions);
- else
- input = get_more_input (MESSAGE_PROMPT_COMMAND, ARG_STRING(0), hist_COMMAND,
- colon_completions);
-
- /* User aborted. */
- if (input == NULL)
- return cmdret_new (RET_FAILURE, NULL);
-
- result = command (1, input);
- free (input);
- return result;
-}
-
-cmdret *
-cmd_exec (int interactive UNUSED, struct cmdarg **args)
-{
- spawn (ARG_STRING(0), 0, current_frame());
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_execa (int interactive UNUSED, struct cmdarg **args)
-{
- spawn (ARG_STRING(0), 0, NULL);
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_execf (int interactive UNUSED, struct cmdarg **args)
-{
- spawn (ARG_STRING(1), 0, ARG(0,frame));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-int
-spawn(char *cmd, int raw, rp_frame *frame)
-{
- rp_child_info *child;
- int pid;
-
- pid = fork();
- if (pid == 0)
- {
- /* Some process setup to make sure the spawned process runs
- in its own session. */
- putenv(current_screen()->display_string);
-#ifdef HAVE_SETSID
- setsid();
-#endif
-#if defined (HAVE_SETPGID)
- setpgid (0, 0);
-#elif defined (HAVE_SETPGRP)
- setpgrp (0, 0);
-#endif
- /* raw means don't run it through sh. */
- if (raw)
- execl (cmd, cmd, NULL);
- execl("/bin/sh", "sh", "-c", cmd, NULL);
- _exit(EXIT_FAILURE);
- }
-
-/* wait((int *) 0); */
- PRINT_DEBUG (("spawned %s\n", cmd));
-
- /* Add this child process to our list. */
- child = malloc (sizeof (rp_child_info));
- child->cmd = strdup (cmd);
- child->pid = pid;
- child->terminated = 0;
- child->frame = frame;
- child->group = rp_current_group;
- child->screen = current_screen();
- child->window_mapped = 0;
-
- list_add (&child->node, &rp_children);
-
- return pid;
-}
-
-/* Switch to a different Window Manager. Thanks to
-"Chr. v. Stuckrad" <stucki@math.fu-berlin.de> for the patch. */
-cmdret *
-cmd_newwm(int interactive UNUSED, struct cmdarg **args)
-{
- /* in the event loop, this will switch WMs. */
- rp_exec_newwm = xstrdup (ARG_STRING(0));
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_quit(int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- kill_signalled = 1;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Show the current time on the bar. Thanks to Martin Samuelsson
- <cosis@lysator.liu.se> for the patch. Thanks to Jonathan Walther
- <krooger@debian.org> for making it pretty. */
-cmdret *
-cmd_time (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- char *msg, *tmp;
- time_t timep;
- cmdret *ret;
-
- timep = time (NULL);
- tmp = ctime (&timep);
- msg = xstrdup (tmp);
- msg[strcspn (msg, "\n")] = '\0' ; /* Remove the newline */
-
- ret = cmdret_new (RET_SUCCESS, "%s", msg);
- free (msg);
-
- return ret;
-}
-
-/* Assign a new number to a window ala screen's number command. */
-cmdret *
-cmd_number (int interactive UNUSED, struct cmdarg **args)
-{
- int old_number, new_number;
- rp_window_elem *other_win, *win;
-
- if (args[0] == NULL)
- {
- /* XXX: Fix this. */
- print_window_information (rp_current_group, current_window());
- return cmdret_new (RET_SUCCESS, NULL);
- }
-
- /* Gather the args. */
- new_number = ARG(0,number);
- if (args[1])
- win = group_find_window_by_number (rp_current_group, ARG(1,number));
- else
- win = group_find_window (&rp_current_group->mapped_windows, current_window());
-
- /* Make the switch. */
- if ( new_number >= 0 && win)
- {
- /* Find other window with same number and give it old number. */
- other_win = group_find_window_by_number (rp_current_group, new_number);
- if (other_win != NULL)
- {
- old_number = win->number;
- other_win->number = old_number;
-
- /* Resort the window in the list */
- group_resort_window (rp_current_group, other_win);
- }
- else
- {
- numset_release (rp_current_group->numset, win->number);
- }
-
- win->number = new_number;
- numset_add_num (rp_current_group->numset, new_number);
-
- /* resort the the window in the list */
- group_resort_window (rp_current_group, win);
-
- /* Update the window list. */
- update_window_names (win->win->scr, defaults.window_fmt);
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Toggle the display of the program bar */
-cmdret *
-cmd_windows (int interactive, struct cmdarg **args)
-{
- struct sbuf *window_list = NULL;
- int dummy;
- rp_screen *s;
- char *fmt;
-
- if (args[0] == NULL)
- fmt = defaults.window_fmt;
- else
- fmt = ARG_STRING(0);
-
- if (interactive)
- {
- 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_bar (s, fmt);
-
- return cmdret_new (RET_SUCCESS, NULL);
- }
- else
- {
- cmdret *ret;
-
- window_list = sbuf_new (0);
- get_window_list (fmt, "\n", window_list, &dummy, &dummy);
- ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (window_list));
- sbuf_free (window_list);
- return ret;
- }
-}
-
-cmdret *
-cmd_abort (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Redisplay the current window by sending 2 resize events. */
-cmdret *
-cmd_redisplay (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- force_maximize (current_window());
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Reassign the prefix key. */
-cmdret *
-cmd_escape (int interactive UNUSED, struct cmdarg **args)
-{
- struct rp_key *key;
- rp_action *action;
- rp_keymap *map, *top;
-
- top = find_keymap (defaults.top_kmap);
- map = find_keymap (ROOT_KEYMAP);
- key = ARG(0,key);
-
- /* Update the "other" keybinding */
- action = find_keybinding(prefix_key.sym, prefix_key.state, map);
- if (action != NULL && !strcmp (action->data, "other"))
- {
- action->key = key->sym;
- action->state = key->state;
- }
-
- /* Update the "meta" keybinding */
- action = find_keybinding(prefix_key.sym, 0, map);
- if (action != NULL && !strcmp (action->data, "meta"))
- {
- action->key = key->sym;
- if (key->state != 0)
- action->state = 0;
- else
- action->state = RP_CONTROL_MASK;
- }
-
- /* Remove the grab on the current prefix key */
- ungrab_keys_all_wins();
-
- action = find_keybinding(prefix_key.sym, prefix_key.state, top);
- if (action != NULL && !strcmp (action->data, "readkey " ROOT_KEYMAP))
- {
- action->key = key->sym;
- action->state = key->state;
- }
-
- /* Add the grab for the new prefix key */
- grab_keys_all_wins();
-
- /* Finally, keep track of the current prefix. */
- prefix_key.sym = key->sym;
- prefix_key.state = key->state;
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* User accessible call to display the passed in string. */
-cmdret *
-cmd_echo (int interactive UNUSED, struct cmdarg **args)
-{
- marked_message_printf (0, 0, "%s", ARG_STRING(0));
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-
-static cmdret *
-read_split (char *str, int max, int *p)
-{
- int a, b;
-
- if (sscanf(str, "%d/%d", &a, &b) == 2)
- {
- *p = (int)(max * (float)(a) / (float)(b));
- }
- else if (sscanf(str, "%d", p) == 1)
- {
- if (*p < 0)
- *p = max + *p;
- }
- else
- {
- /* Failed to read input. */
- return cmdret_new (RET_FAILURE, "bad split '%s'", str);
- }
-
- return NULL;
-}
-
-cmdret *
-cmd_v_split (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *ret;
- rp_frame *frame;
- int pixels;
-
- push_frame_undo (current_screen()); /* fdump to stack */
- frame = current_frame();
-
- /* Default to dividing the frame in half. */
- if (args[0] == NULL)
- pixels = frame->height / 2;
- else
- {
- ret = read_split (ARG_STRING(0), frame->height, &pixels);
- if (ret)
- return ret;
- }
-
- if (pixels > 0)
- h_split_frame (frame, pixels);
- else
- return cmdret_new (RET_FAILURE, "vsplit: invalid argument");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_h_split (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *ret;
- rp_frame *frame;
- int pixels;
-
- push_frame_undo (current_screen()); /* fdump to stack */
- frame = current_frame();
-
- /* Default to dividing the frame in half. */
- if (args[0] == NULL)
- pixels = frame->width / 2;
- else
- {
- ret = read_split (ARG_STRING(0), frame->width, &pixels);
- if (ret)
- return ret;
- }
-
- if (pixels > 0)
- v_split_frame (frame, pixels);
- else
- return cmdret_new (RET_FAILURE, "hsplit: invalid argument");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_only (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- push_frame_undo (current_screen()); /* fdump to stack */
- remove_all_splits();
- maximize (current_window());
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_remove (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_screen *s = current_screen();
- rp_frame *frame;
-
- push_frame_undo (current_screen()); /* fdump to stack */
-
- if (num_frames(s) <= 1)
- {
- return cmdret_new (RET_FAILURE, "remove: cannot remove only frame");
- }
-
- frame = find_frame_next (current_frame());
-
- if (frame)
- {
- remove_frame (current_frame());
- set_active_frame (frame, 0);
- show_frame_indicator(0);
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_shrink (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- push_frame_undo (current_screen()); /* fdump to stack */
- resize_shrink_to_window (current_frame());
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-typedef struct resize_binding resize_binding;
-
-struct resize_binding
-{
- struct rp_key key;
- enum resize_action {RESIZE_UNKNOWN=0, RESIZE_VGROW, RESIZE_VSHRINK,
- RESIZE_HGROW, RESIZE_HSHRINK, RESIZE_TO_WINDOW,
- RESIZE_ABORT, RESIZE_END } action;
-};
-
-static resize_binding resize_bindings[] =
- { {{INPUT_ABORT_KEY, INPUT_ABORT_MODIFIER}, RESIZE_ABORT},
- {{RESIZE_VGROW_KEY, RESIZE_VGROW_MODIFIER}, RESIZE_VGROW},
- {{RESIZE_VSHRINK_KEY, RESIZE_VSHRINK_MODIFIER}, RESIZE_VSHRINK},
- {{RESIZE_HGROW_KEY, RESIZE_HGROW_MODIFIER}, RESIZE_HGROW},
- {{RESIZE_HSHRINK_KEY, RESIZE_HSHRINK_MODIFIER}, RESIZE_HSHRINK},
- {{RESIZE_SHRINK_TO_WINDOW_KEY,RESIZE_SHRINK_TO_WINDOW_MODIFIER},RESIZE_TO_WINDOW},
- {{RESIZE_END_KEY, RESIZE_END_MODIFIER}, RESIZE_END},
-/* Some more default keys
- * (after the values from conf.h, so that they have lower priority):
- * first the arrow keys: */
- {{XK_Escape, 0}, RESIZE_ABORT},
- {{XK_Down, 0}, RESIZE_VGROW},
- {{XK_Up, 0}, RESIZE_VSHRINK},
- {{XK_Right, 0}, RESIZE_HGROW},
- {{XK_Left, 0}, RESIZE_HSHRINK},
-/* some vi-like bindings: */
- {{XK_j, 0}, RESIZE_VGROW},
- {{XK_k, 0}, RESIZE_VSHRINK},
- {{XK_l, 0}, RESIZE_HGROW},
- {{XK_h, 0}, RESIZE_HSHRINK},
- {{0, 0}, RESIZE_UNKNOWN} };
-
-
-cmdret *
-cmd_resize (int interactive, struct cmdarg **args)
-{
- rp_screen *s = current_screen ();
-
- /* If the user calls resize with arguments, treat it like the
- non-interactive version. */
- if (interactive && args[0] == NULL)
- {
- char buffer[513];
- unsigned int mod;
- KeySym c;
- struct list_head *bk;
-
- /* If we haven't got at least 2 frames, there isn't anything to
- scale. */
- if (num_frames (s) < 2)
- return cmdret_new (RET_FAILURE, NULL);
-
- /* Save the frameset in case the user aborts. */
- bk = screen_copy_frameset (s);
-
- /* Get ready to read keys. */
- grab_rat();
- XGrabKeyboard (dpy, s->key_window, False, GrabModeAsync, GrabModeAsync, CurrentTime);
-
- while (1)
- {
- struct resize_binding *binding;
-
- show_frame_message ("Resize frame");
- read_key (&c, &mod, buffer, sizeof (buffer));
-
- /* Convert the mask to be compatible with ratpoison. */
- mod = x11_mask_to_rp_mask (mod);
-
- for (binding = resize_bindings; binding->action; binding++)
- {
- if (c == binding->key.sym && mod == binding->key.state)
- break;
- }
-
- if (binding->action == RESIZE_VGROW)
- resize_frame_vertically (current_frame(), defaults.frame_resize_unit);
- else if (binding->action == RESIZE_VSHRINK)
- resize_frame_vertically (current_frame(), -defaults.frame_resize_unit);
- else if (binding->action == RESIZE_HGROW)
- resize_frame_horizontally (current_frame(), defaults.frame_resize_unit);
- else if (binding->action == RESIZE_HSHRINK)
- resize_frame_horizontally (current_frame(), -defaults.frame_resize_unit);
- else if (binding->action == RESIZE_TO_WINDOW)
- resize_shrink_to_window (current_frame());
- else if (binding->action == RESIZE_ABORT)
- {
- rp_frame *cur;
-
- screen_restore_frameset (s, bk);
- list_for_each_entry (cur, &s->frames, node)
- {
- maximize_all_windows_in_frame (cur);
- }
- break;
- }
- else if (binding->action == RESIZE_END)
- {
- frameset_free (bk);
- break;
- }
- }
-
- /* It is our responsibility to free this. */
- free (bk);
-
- hide_frame_indicator ();
- ungrab_rat();
- XUngrabKeyboard (dpy, CurrentTime);
- }
- else
- {
- if (args[0] && args[1])
- {
- resize_frame_horizontally (current_frame(), ARG(0,number));
- resize_frame_vertically (current_frame(), ARG(1,number));
- }
- else
- return cmdret_new (RET_FAILURE, "resize: two numeric arguments required");
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_resizeunit (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.frame_resize_unit);
-
- if (ARG(0,number) >= 0)
- defaults.frame_resize_unit = ARG(0,number);
- else
- return cmdret_new (RET_FAILURE, "defresizeunit: invalid argument");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* banish the rat pointer */
-cmdret *
-cmd_banish (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_screen *s;
-
- s = current_screen ();
-
- XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->left + s->width - 2, s->top + s->height - 2);
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_banishrel (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_screen *s = current_screen();
- rp_window *w = current_window();
- rp_frame *f = current_frame();
-
- if (w)
- XWarpPointer (dpy, None, w->w, 0, 0, 0, 0, w->x + w->width - 2, w->y + w->height - 2);
- else
- XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, f->x + f->width, f->y + f->height);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_ratinfo (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_screen *s;
- Window root_win, child_win;
- int mouse_x, mouse_y, root_x, root_y;
- unsigned int mask;
-
- s = current_screen();
- XQueryPointer (dpy, s->root, &root_win, &child_win, &mouse_x, &mouse_y, &root_x, &root_y, &mask);
-
- return cmdret_new (RET_SUCCESS, "%d %d", mouse_x, mouse_y);
-}
-
-cmdret *
-cmd_ratrelinfo (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_screen *s;
- rp_window *rpw;
- rp_frame *f;
- Window root_win, child_win;
- int mouse_x, mouse_y, root_x, root_y;
- unsigned int mask;
-
- s = current_screen();
- rpw = current_window();
- f = current_frame();
-
- if (rpw)
- XQueryPointer (dpy, rpw->w, &root_win, &child_win, &mouse_x, &mouse_y, &root_x, &root_y, &mask);
- else
- {
- XQueryPointer (dpy, s->root, &root_win, &child_win, &mouse_x, &mouse_y, &root_x, &root_y, &mask);
- root_x -= f->x;
- root_y -= f->y;
- }
-
- return cmdret_new (RET_SUCCESS, "%d %d", root_x, root_y);
-}
-
-cmdret *
-cmd_ratwarp (int interactive UNUSED, struct cmdarg **args)
-{
- rp_screen *s;
-
- s = current_screen ();
- XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, ARG(0,number), ARG(1,number));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_ratrelwarp (int interactive UNUSED, struct cmdarg **args)
-{
- XWarpPointer (dpy, None, None, 0, 0, 0, 0, ARG(0,number), ARG(1,number));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_ratclick (int interactive UNUSED, struct cmdarg **args)
-{
- int button = 1;
-
- if (args[0])
- {
- button = ARG(0,number);
- if (button < 1 || button > 3)
- return cmdret_new (RET_SUCCESS, "ratclick: invalid argument");
- }
-
-#ifdef HAVE_LIBXTST
- XTestFakeButtonEvent(dpy, button, True, CurrentTime);
- XTestFakeButtonEvent(dpy, button, False, CurrentTime);
- return cmdret_new (RET_SUCCESS, NULL);
-#else
- return cmdret_new (RET_FAILURE, "ratclick: Please compile with the Xtst extension");
-#endif
-}
-
-cmdret *
-cmd_rathold (int interactive UNUSED, struct cmdarg **args)
-{
- int button = 1;
-
- if (args[1])
- {
- button = ARG(1,number);
- if (button < 1 || button > 3)
- return cmdret_new (RET_SUCCESS, "ratclick: invalid argument");
- }
-
-#ifdef HAVE_LIBXTST
- if (!strcmp(ARG_STRING(0), "down"))
- XTestFakeButtonEvent(dpy, button, True, CurrentTime);
- else if(!strcmp(ARG_STRING(0),"up"))
- XTestFakeButtonEvent(dpy, button, False, CurrentTime);
- else
- return cmdret_new (RET_FAILURE, "rathold: '%s' invalid argument", ARG_STRING(0));
-
- return cmdret_new (RET_SUCCESS, NULL);
-#else
- return cmdret_new (RET_FAILURE, "rathold: Please compile with the Xtst extension");
-#endif
-}
-
-cmdret *
-cmd_curframe (int interactive, struct cmdarg **args UNUSED)
-{
- if (interactive)
- {
- show_frame_indicator(1);
- return cmdret_new (RET_SUCCESS, NULL);
- }
- else
- return cmdret_new(RET_SUCCESS, "%d", current_frame()->number);
-}
-
-/* Thanks to Martin Samuelsson <cosis@lysator.liu.se> for the
- original patch. */
-cmdret *
-cmd_license (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_screen *s = current_screen();
- int x = 10;
- int y = 10;
- int i;
- int max_width = 0;
- char *license_text[] = { PACKAGE " " VERSION, "(built " __DATE__ " " __TIME__ ")",
- "",
- "Copyright (C) 2000, 2001, 2002, 2003, 2004 Shawn Betts",
- "",
- "ratpoison is free software; you can redistribute it and/or modify ",
- "it under the terms of the GNU General Public License as published by ",
- "the Free Software Foundation; either version 2, or (at your option) ",
- "any later version.",
- "",
- "ratpoison is distributed in the hope that it will be useful, ",
- "but WITHOUT ANY WARRANTY; without even the implied warranty of ",
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ",
- "GNU General Public License for more details.",
- "",
- "You should have received a copy of the GNU General Public License ",
- "along with this software; see the file COPYING. If not, write to ",
- "the Free Software Foundation, Inc., 59 Temple Place, Suite 330, ",
- "Boston, MA 02111-1307 USA",
- "",
- "Send bugreports, fixes, enhancements, t-shirts, money, beer & pizza ",
- "to ratpoison-devel@nongnu.org or visit ",
- "http://www.nongnu.org/ratpoison/",
- "",
- "[Press any key to end.] ",
- NULL};
-
- /* Switch to the default colormap. */
- if (current_window())
- XUninstallColormap (dpy, current_window()->colormap);
- XInstallColormap (dpy, s->def_cmap);
-
- XMapRaised (dpy, s->help_window);
-
- /* Find the longest line. */
- for(i=0; license_text[i]; i++)
- {
- int tmp;
-
- tmp = rp_text_width (s, license_text[i], -1);
- if (tmp > max_width)
- max_width = tmp;
- }
-
- /* Offset the text so its in the center. */
- x = s->left + (s->width - max_width) / 2;
- y = s->top + (s->height - i * FONT_HEIGHT (s)) / 2;
- if (x < 0) x = 0;
- if (y < 0) y = 0;
-
- /* Print the text. */
- for(i=0; license_text[i]; i++)
- {
- rp_draw_string (s, s->help_window, STYLE_NORMAL,
- x, y + FONT_ASCENT(s),
- license_text[i], -1);
-
- y += FONT_HEIGHT (s);
- }
-
- /* Wait for a key press. */
- read_any_key ();
- XUnmapWindow (dpy, s->help_window);
-
- /* Possibly restore colormap. */
- if (current_window())
- {
- XUninstallColormap (dpy, s->def_cmap);
- XInstallColormap (dpy, current_window()->colormap);
- }
-
- /* The help window overlaps the bar, so redraw it. */
- if (current_screen()->bar_is_raised)
- redraw_last_message();
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_help (int interactive, struct cmdarg **args)
-{
- rp_keymap *map;
-
- if (args[0])
- map = ARG(0,keymap);
- else
- map = find_keymap (ROOT_KEYMAP);
-
- if (interactive)
- {
- rp_screen *s = current_screen();
- int i, old_i;
- int x = 10;
- int y = 0;
- int header_offset;
- int width, max_width = 0;
- /* 1 if we are drawing keys, 0 if we are drawing commands */
- int drawing_keys = 1;
- char *keysym_name;
-
- /* Switch to the default colormap. */
- if (current_window())
- XUninstallColormap (dpy, current_window()->colormap);
- XInstallColormap (dpy, s->def_cmap);
-
- XMapRaised (dpy, s->help_window);
-
- rp_draw_string (s, s->help_window, STYLE_NORMAL,
- 10, y + FONT_ASCENT(s),
- "ratpoison key bindings", -1);
-
- y += FONT_HEIGHT (s) * 2;
-
- /* Only print the "Command key" for the root keymap */
- if (map == find_keymap (ROOT_KEYMAP))
- {
- rp_draw_string (s, s->help_window, STYLE_NORMAL,
- 10, y + FONT_ASCENT(s),
- "Command key: ", -1);
-
- keysym_name = keysym_to_string (prefix_key.sym, prefix_key.state);
- rp_draw_string (s, s->help_window, STYLE_NORMAL,
- 10 + rp_text_width (s, "Command key: ", -1),
- y + FONT_ASCENT(s),
- keysym_name, -1);
- free (keysym_name);
-
- y += FONT_HEIGHT (s) * 2;
- }
-
- header_offset = y;
-
- i = old_i = 0;
- while (i < map->actions_last && old_i < map->actions_last)
- {
- if (drawing_keys)
- {
- keysym_name =
- keysym_to_string (map->actions[i].key, map->actions[i].state);
-
- rp_draw_string (s, s->help_window, STYLE_NORMAL,
- x, y + FONT_ASCENT(s),
- keysym_name, -1);
-
- width = rp_text_width (s, keysym_name, -1);
- if (width > max_width)
- max_width = width;
-
- free (keysym_name);
- }
- else
- {
- rp_draw_string (s, s->help_window, STYLE_NORMAL,
- x, y + FONT_ASCENT(s),
- map->actions[i].data, -1);
-
- width = rp_text_width (s, map->actions[i].data, -1);
- if (width > max_width)
- max_width = width;
- }
-
- y += FONT_HEIGHT (s);
- /* Make sure the next line fits entirely within the window. */
- if (y + FONT_HEIGHT (s) >= (s->top + s->height))
- {
- if (drawing_keys)
- {
- x += max_width + 10;
- drawing_keys = 0;
- i = old_i;
- }
- else
- {
- x += max_width + 20;
- drawing_keys = 1;
- i++;
- old_i = i;
- }
-
- max_width = 0;
- y = header_offset;
- }
- else
- {
- i++;
- if (i == map->actions_last && drawing_keys)
- {
- x += max_width + 10;
- drawing_keys = 0;
- y = header_offset;
- i = old_i;
- max_width = 0;
- }
- }
- }
-
- read_any_key();
- XUnmapWindow (dpy, s->help_window);
-
- /* Possibly restore colormap. */
- if (current_window())
- {
- XUninstallColormap (dpy, s->def_cmap);
- XInstallColormap (dpy, current_window()->colormap);
- }
-
- /* The help window overlaps the bar, so redraw it. */
- if (current_screen()->bar_is_raised)
- redraw_last_message();
-
- return cmdret_new (RET_SUCCESS, NULL);
- }
- else
- {
- struct sbuf *help_list;
- char *keysym_name;
- int i;
- cmdret *ret;
-
- help_list = sbuf_new (0);
-
- for (i = 0; i < map->actions_last; i++)
- {
- keysym_name = keysym_to_string (map->actions[i].key, map->actions[i].state);
- sbuf_concat (help_list, keysym_name);
- free (keysym_name);
- sbuf_concat (help_list, " ");
- sbuf_concat (help_list, map->actions[i].data);
- if (i < map->actions_last - 1)
- sbuf_concat (help_list, "\n");
- }
-
- ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (help_list));
- sbuf_free (help_list);
- return ret;
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_rudeness (int interactive UNUSED, struct cmdarg **args)
-{
- int num;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d",
- rp_honour_transient_raise
- | (rp_honour_normal_raise << 1)
- | (rp_honour_transient_map << 2)
- | (rp_honour_normal_map << 3));
-
- num = ARG(0,number);
- if (num < 0 || num > 15)
- return cmdret_new (RET_FAILURE, "rudeness: invalid level '%s'", ARG_STRING(0));
-
- rp_honour_transient_raise = num & 1 ? 1 : 0;
- rp_honour_normal_raise = num & 2 ? 1 : 0;
- rp_honour_transient_map = num & 4 ? 1 : 0;
- rp_honour_normal_map = num & 8 ? 1 : 0;
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-char *
-wingravity_to_string (int g)
-{
- switch (g)
- {
- case NorthWestGravity:
- return "nw";
- case WestGravity:
- return "w";
- case SouthWestGravity:
- return "sw";
- case NorthGravity:
- return "n";
- case CenterGravity:
- return "c";
- case SouthGravity:
- return "s";
- case NorthEastGravity:
- return "ne";
- case EastGravity:
- return "e";
- case SouthEastGravity:
- return "se";
- }
-
- PRINT_DEBUG (("Unknown gravity!\n"));
- return "Unknown";
-}
-
-cmdret *
-cmd_gravity (int interactive UNUSED, struct cmdarg **args)
-{
- int gravity;
- rp_window *win;
-
- win = current_window();
- if (!win)
- return cmdret_new (RET_FAILURE, NULL);
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", wingravity_to_string (win->gravity));
-
- if ((gravity = parse_wingravity (ARG_STRING(0))) < 0)
- return cmdret_new (RET_FAILURE, "gravity: unknown gravity");
- else
- {
- win->gravity = gravity;
- maximize (win);
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_wingravity (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", wingravity_to_string (defaults.win_gravity));
-
- defaults.win_gravity = ARG(0,gravity);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_transgravity (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", wingravity_to_string (defaults.trans_gravity));
-
- defaults.trans_gravity = ARG(0,gravity);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_maxsizegravity (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", wingravity_to_string (defaults.maxsize_gravity));
-
- defaults.maxsize_gravity = ARG(0,gravity);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_msgwait (int interactive UNUSED, struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.bar_timeout);
-
- if (ARG(0,number) < 0)
- return cmdret_new (RET_FAILURE, "msgwait: invalid argument");
- else
- defaults.bar_timeout = ARG(0,number);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_bargravity (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", wingravity_to_string (defaults.bar_location));
-
- defaults.bar_location = ARG(0,gravity);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static void
-update_gc (rp_screen *s)
-{
- XGCValues gcv;
-
- gcv.foreground = s->fg_color;
- gcv.background = s->bg_color;
- gcv.function = GXcopy;
- gcv.line_width = 1;
- gcv.subwindow_mode = IncludeInferiors;
- XFreeGC (dpy, s->normal_gc);
- s->normal_gc = XCreateGC(dpy, s->root,
- GCForeground | GCBackground
- | GCFunction | GCLineWidth
- | GCSubwindowMode, &gcv);
- gcv.foreground = s->bg_color;
- gcv.background = s->fg_color;
- XFreeGC (dpy, s->inverse_gc);
- s->inverse_gc = XCreateGC(dpy, s->root,
- GCForeground | GCBackground
- | GCFunction | GCLineWidth
- | GCSubwindowMode, &gcv);
-}
-
-#ifndef USE_XFT_FONT
-static void
-update_all_gcs (void)
-{
- int i;
-
- for (i=0; i<num_screens; i++)
- {
- update_gc (&screens[i]);
- }
-}
-#endif
-
-static cmdret *
-set_historysize (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.history_size);
-
- defaults.history_size = ARG(0, number);
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_historycompaction (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.history_compaction);
-
- defaults.history_compaction = ARG(0, number);
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_historyexpansion (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.history_expansion);
-#ifndef HAVE_HISTORY
- if (ARG(0, number)) {
- return cmdret_new (RET_FAILURE, "Not compiled with libhistory");
- }
-#endif
- defaults.history_expansion = ARG(0, number);
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_font (struct cmdarg **args)
-{
-#ifdef USE_XFT_FONT
- XftFont *font;
- rp_screen *s = current_screen ();
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.font_string);
-
- font = XftFontOpenName (dpy, s->screen_num, ARG_STRING (0));
-
- if (font == NULL)
- return cmdret_new (RET_FAILURE, "deffont: unknown font");
-
- XftFontClose (dpy, s->xft_font);
- s->xft_font = font;
-#else
- XFontSet font;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.font_string);
-
- font = load_query_font_set (dpy, ARG_STRING(0));
- if (font == NULL)
- return cmdret_new (RET_FAILURE, "deffont: unknown font");
-
- /* Save the font as the default. */
- XFreeFontSet (dpy, defaults.font);
- defaults.font = font;
- set_extents_of_fontset(font);
- update_all_gcs();
-#endif
-
- free (defaults.font_string);
- defaults.font_string = xstrdup (ARG_STRING(0));
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_padding (struct cmdarg **args)
-{
- rp_frame *frame;
- int l, t, r, b;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d %d %d %d",
- defaults.padding_left,
- defaults.padding_top,
- defaults.padding_right,
- defaults.padding_bottom);
-
- l = ARG(0,number);
- t = ARG(1,number);
- r = ARG(2,number);
- b = ARG(3,number);
-
- /* Resize the frames to make sure they are not too big and not too
- small. */
- list_for_each_entry (frame,&(current_screen()->frames),node)
- {
- int bk_pos, bk_len;
-
- /* Resize horizontally. */
- bk_pos = frame->x;
- bk_len = frame->width;
-
- if (frame->x == defaults.padding_left)
- {
- frame->x = l;
- frame->width += bk_pos - l;
- }
-
- if ((bk_pos + bk_len) == (current_screen()->left + current_screen()->width - defaults.padding_right))
- frame->width = current_screen()->left + current_screen()->width - r - frame->x;
-
- /* Resize vertically. */
- bk_pos = frame->y;
- bk_len = frame->height;
-
- if (frame->y == defaults.padding_top)
- {
- frame->y = t;
- frame->height += bk_pos - t;
- }
-
- if ((bk_pos + bk_len) == (current_screen()->top + current_screen()->height - defaults.padding_bottom))
- frame->height = current_screen()->top + current_screen()->height - b - frame->y;
-
- maximize_all_windows_in_frame (frame);
- }
-
- defaults.padding_left = l;
- defaults.padding_right = r;
- defaults.padding_top = t;
- defaults.padding_bottom = b;
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_border (struct cmdarg **args)
-{
- rp_window *win;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.window_border_width);
-
- if (ARG(0,number) < 0)
- return cmdret_new (RET_FAILURE, "defborder: invalid argument");
-
- defaults.window_border_width = ARG(0,number);
-
- /* Update all the visible windows. */
- list_for_each_entry (win,&rp_mapped_window,node)
- {
- if (win_get_frame (win))
- maximize (win);
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_barborder (struct cmdarg **args)
-{
- int i;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.bar_border_width);
-
- if (ARG(0,number) < 0)
- return cmdret_new (RET_FAILURE, "defbarborder: invalid argument");
-
- defaults.bar_border_width = ARG(0,number);
-
- /* Update the frame and bar windows. */
- for (i=0; i<num_screens; i++)
- {
- XSetWindowBorderWidth (dpy, screens[i].bar_window, defaults.bar_border_width);
- XSetWindowBorderWidth (dpy, screens[i].frame_window, defaults.bar_border_width);
- XSetWindowBorderWidth (dpy, screens[i].input_window, defaults.bar_border_width);
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_barinpadding (struct cmdarg **args)
-{
- int new_value;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.bar_in_padding);
-
- new_value = ARG(0,number);
- if (new_value < 0)
- return cmdret_new (RET_FAILURE, "defbarborder: invalid argument");
-
- defaults.bar_in_padding = new_value;
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_inputwidth (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.input_window_size);
-
- if (ARG(0,number) < 0)
- return cmdret_new (RET_FAILURE, "definputwidth: invalid argument");
- else
- defaults.input_window_size = ARG(0,number);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_waitcursor (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.wait_for_key_cursor);
-
- defaults.wait_for_key_cursor = ARG(0,number);
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_infofmt (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.info_fmt);
-
- free (defaults.info_fmt);
- defaults.info_fmt = xstrdup (ARG_STRING(0));
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_topkmap (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.top_kmap);
-
- if (!find_keymap (ARG_STRING(0)))
- return cmdret_new(RET_FAILURE, "Unknown keymap %s", ARG_STRING(0));
-
- ungrab_keys_all_wins();
-
- free (defaults.top_kmap);
- defaults.top_kmap = xstrdup (ARG_STRING(0));
-
- grab_keys_all_wins();
- XSync(dpy, False);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_winfmt (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.window_fmt);
-
- free (defaults.window_fmt);
- defaults.window_fmt = xstrdup (ARG_STRING(0));
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_winname (struct cmdarg **args)
-{
- char *name;
-
- if (args[0] == NULL)
- switch (defaults.win_name)
- {
- case WIN_NAME_TITLE:
- return cmdret_new (RET_SUCCESS, "title");
- case WIN_NAME_RES_NAME:
- return cmdret_new (RET_SUCCESS, "name");
- case WIN_NAME_RES_CLASS:
- return cmdret_new (RET_SUCCESS, "class");
- default:
- PRINT_DEBUG (("Unknown win_name\n"));
- return cmdret_new (RET_FAILURE, "unknown");
- }
-
- name = ARG_STRING(0);
-
- /* FIXME: Using strncmp is sorta dirty since `title' and
- `titlefoobar' would both match. But its quick and dirty. */
- if (!strncmp (name, "title", 5))
- defaults.win_name = WIN_NAME_TITLE;
- else if (!strncmp (name, "name", 4))
- defaults.win_name = WIN_NAME_RES_NAME;
- else if (!strncmp (name, "class", 5))
- defaults.win_name = WIN_NAME_RES_CLASS;
- else
- return cmdret_new (RET_FAILURE, "defwinname: invalid argument");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_framefmt (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.frame_fmt);
-
- free (defaults.frame_fmt);
- defaults.frame_fmt = xstrdup (ARG_STRING(0));
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_fgcolor (struct cmdarg **args)
-{
- int i;
- XColor color, junk;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.fgcolor_string);
-
- for (i=0; i<num_screens; i++)
- {
- if (!XAllocNamedColor (dpy, screens[i].def_cmap, ARG_STRING(0), &color, &junk))
- return cmdret_new (RET_FAILURE, "deffgcolor: unknown color");
-
- screens[i].fg_color = color.pixel;
- update_gc (&screens[i]);
- XSetWindowBorder (dpy, screens[i].bar_window, color.pixel);
- XSetWindowBorder (dpy, screens[i].input_window, color.pixel);
- XSetWindowBorder (dpy, screens[i].frame_window, color.pixel);
- XSetWindowBorder (dpy, screens[i].help_window, color.pixel);
-
-#ifdef USE_XFT_FONT
- if (!XftColorAllocName (dpy, DefaultVisual (dpy, screens[i].screen_num),
- DefaultColormap (dpy, screens[i].screen_num),
- ARG_STRING(0), &screens[i].xft_fg_color))
- return cmdret_new (RET_FAILURE, "deffgcolor: unknown color");
-#endif
-
- free (defaults.fgcolor_string);
- defaults.fgcolor_string = xstrdup (ARG_STRING(0));
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_bgcolor (struct cmdarg **args)
-{
- int i;
- XColor color, junk;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.bgcolor_string);
-
- for (i=0; i<num_screens; i++)
- {
- if (!XAllocNamedColor (dpy, screens[i].def_cmap, ARG_STRING(0), &color, &junk))
- return cmdret_new (RET_FAILURE, "defbgcolor: unknown color");
-
- screens[i].bg_color = color.pixel;
- update_gc (&screens[i]);
- XSetWindowBackground (dpy, screens[i].bar_window, color.pixel);
- XSetWindowBackground (dpy, screens[i].input_window, color.pixel);
- XSetWindowBackground (dpy, screens[i].frame_window, color.pixel);
- XSetWindowBackground (dpy, screens[i].help_window, color.pixel);
-
-#ifdef USE_XFT_FONT
- if (!XftColorAllocName (dpy, DefaultVisual (dpy, screens[i].screen_num),
- DefaultColormap (dpy, screens[i].screen_num),
- ARG_STRING(0), &screens[i].xft_bg_color))
- return cmdret_new (RET_FAILURE, "deffgcolor: unknown color");
-#endif
-
- free (defaults.bgcolor_string);
- defaults.bgcolor_string = xstrdup (ARG_STRING(0));
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_fwcolor (struct cmdarg **args)
-{
- int i;
- XColor color, junk;
- rp_window *win = current_window();
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.fwcolor_string);
-
- for (i=0; i<num_screens; i++)
- {
- if (!XAllocNamedColor (dpy, screens[i].def_cmap, ARG_STRING(0), &color, &junk))
- return cmdret_new (RET_FAILURE, "deffwcolor: unknown color");
-
- screens[i].fw_color = color.pixel;
- update_gc (&screens[i]);
-
- free (defaults.fwcolor_string);
- defaults.fwcolor_string = xstrdup (ARG_STRING(0));
- }
-
- /* Update current window. */
- if (win != NULL)
- XSetWindowBorder (dpy, win->w, win->scr->fw_color);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_bwcolor (struct cmdarg **args)
-{
- int i;
- XColor color, junk;
- rp_window *win, *cur = current_window();
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.bwcolor_string);
-
- for (i=0; i<num_screens; i++)
- {
- if (!XAllocNamedColor (dpy, screens[i].def_cmap, ARG_STRING(0), &color, &junk))
- return cmdret_new (RET_FAILURE, "defbwcolor: unknown color");
-
- screens[i].bw_color = color.pixel;
- update_gc (&screens[i]);
-
- free (defaults.bwcolor_string);
- defaults.bwcolor_string = xstrdup (ARG_STRING(0));
- }
-
- /* Update all the visible windows. */
- list_for_each_entry (win,&rp_mapped_window,node)
- {
- if (win != cur)
- XSetWindowBorder (dpy, win->w, win->scr->bw_color);
- }
-
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_setenv (int interactive UNUSED, struct cmdarg **args)
-{
-
- const char *var = ARG_STRING(0), *val = ARG_STRING(1);
- int ret;
-
-#ifdef HAVE_SETENV
-
- PRINT_DEBUG(("setenv (\"%s\", \"%s\", 1)\n", var, val));
- ret = setenv (var, val, 1);
-
-#else /* not HAVE_SETENV */
-
- struct sbuf *env;
-
- /* Setup the environment string. */
- env = sbuf_new (strlen (var) + 1 + strlen (val) + 1);
-
- sbuf_copy (env, var);
- sbuf_concat (env, "=");
- sbuf_concat (env, val);
-
- /* Stick it in the environment. We must *not* free it. */
- PRINT_DEBUG(("putenv(\"%s\")\n", sbuf_get(env)));
- ret = putenv (sbuf_free_struct (env));
-
-#endif /* not HAVE_SETENV */
-
- if (ret == -1)
- return cmdret_new (RET_FAILURE, "cmd_setenv failed: %s", strerror(errno));
- else
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_getenv (int interactive UNUSED, struct cmdarg **args)
-{
- char *value;
-
- value = getenv (ARG_STRING(0));
- if (value)
- return cmdret_new (RET_SUCCESS, "%s", value);
- else
- return cmdret_new (RET_FAILURE, NULL);
-}
-
-/* Thanks to Gergely Nagy <algernon@debian.org> for the original
- patch. */
-cmdret *
-cmd_chdir (int interactive UNUSED, struct cmdarg **args)
-{
- char *dir;
-
- if (args[0] == NULL)
- {
- dir = getenv ("HOME");
- if (dir == NULL || *dir == '\0')
- {
- return cmdret_new (RET_FAILURE, "chdir: HOME not set");
- }
- }
- else
- dir = ARG_STRING(0);
-
- if (chdir (dir) == -1)
- return cmdret_new (RET_FAILURE, "chdir: %s: %s", dir, strerror(errno));
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Thanks to Gergely Nagy <algernon@debian.org> for the original
- patch. */
-cmdret *
-cmd_unsetenv (int interactive UNUSED, struct cmdarg **args)
-{
- const char *var = ARG_STRING(0);
- int ret;
-
- /* Use unsetenv() where possible since putenv("FOO") is not legit everywhere */
-#ifdef HAVE_UNSETENV
- ret = unsetenv(var);
-#else
- /* MinGW doesn't have unsetenv() and uses putenv("FOO=") */
- struct sbuf *s = sbuf_new (strlen (var) + 1 + 1);
- sbuf_copy (s, var);
- sbuf_concat (s, "=");
- /* let putenv() decide whether to call free() */
- ret = putenv (sbuf_free_struct (s));
-#endif
-
- if (ret == -1)
- return cmdret_new (RET_FAILURE, "cmd_unsetenv failed: %s", strerror (errno));
- else
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Thanks to Gergely Nagy <algernon@debian.org> for the original
- patch. */
-cmdret *
-cmd_info (int interactive UNUSED, struct cmdarg **args)
-{
- struct sbuf *buf;
- if (current_window() != NULL)
- {
- rp_window *win = current_window();
- rp_window_elem *win_elem;
- win_elem = group_find_window (&rp_current_group->mapped_windows, win);
- if (!win_elem)
- win_elem = group_find_window (&rp_current_group->unmapped_windows, win);
- if (!win_elem)
- {
- rp_group *g = groups_find_group_by_window(win);
- if (g != NULL)
- win_elem = group_find_window (&g->mapped_windows, win);
- if (!win_elem && g != NULL)
- win_elem = group_find_window (&g->unmapped_windows, win);
- }
- if (win_elem)
- {
- char *s;
- cmdret *ret;
-
- if (args[0] == NULL)
- s = defaults.info_fmt;
- else
- s = ARG_STRING(0);
- buf = sbuf_new (0);
- format_string (s, win_elem, buf);
- ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (buf));
- sbuf_free (buf);
- return ret;
- }
- }
-
- return cmdret_new (RET_SUCCESS, "No window.");
-}
-
-/* Thanks to Gergely Nagy <algernon@debian.org> for the original
- patch. */
-cmdret *
-cmd_lastmsg (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- show_last_message();
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_focusup (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- if ((frame = find_frame_up (current_frame())))
- set_active_frame (frame, 0);
- else
- show_frame_indicator(0);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_focusdown (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- if ((frame = find_frame_down (current_frame())))
- set_active_frame (frame, 0);
- else
- show_frame_indicator(0);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_focusleft (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- if ((frame = find_frame_left (current_frame())))
- set_active_frame (frame, 0);
- else
- show_frame_indicator(0);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_focusright (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- if ((frame = find_frame_right (current_frame())))
- set_active_frame (frame, 0);
- else
- show_frame_indicator(0);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_exchangeup (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- if ((frame = find_frame_up (current_frame())))
- exchange_with_frame (current_frame(), frame);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_exchangedown (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- if ((frame = find_frame_down (current_frame())))
- exchange_with_frame (current_frame(), frame);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_exchangeleft (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- if ((frame = find_frame_left (current_frame())))
- exchange_with_frame (current_frame(), frame);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_exchangeright (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame;
-
- if ((frame = find_frame_right (current_frame())))
- exchange_with_frame (current_frame(), frame);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_swap (int interactive UNUSED, struct cmdarg **args)
-{
- rp_screen *s;
- rp_frame *dest_frame;
- rp_frame *src_frame;
-
- dest_frame = ARG(0, frame);
- src_frame = args[1] ? ARG (1, frame) : current_frame();
-
- if (!rp_have_xinerama)
- {
- s = frames_screen(src_frame);
- if (screen_find_frame_by_frame(s, dest_frame) == NULL)
- return cmdret_new (RET_FAILURE, "swap: frames on different screens");
- }
-
- exchange_with_frame (src_frame, dest_frame);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_restart (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- hup_signalled = 1;
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_startup_message (int interactive, struct cmdarg **args)
-{
- if (args[0] == NULL && !interactive)
- return cmdret_new (RET_SUCCESS, "%s", defaults.startup_message ? "on":"off");
-
- if (!strcasecmp (ARG_STRING(0), "on"))
- defaults.startup_message = 1;
- else if (!strcasecmp (ARG_STRING(0), "off"))
- defaults.startup_message = 0;
- else
- return cmdret_new (RET_FAILURE, "startup_message: invalid argument");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_focuslast (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame *frame = find_last_frame();
-
- if (frame)
- set_active_frame (frame, 0);
- else
- return cmdret_new (RET_FAILURE, "focuslast: no other frame");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_link (int interactive, struct cmdarg **args)
-{
- char *cmd = NULL;
- rp_keymap *map;
-
- if (args[1])
- map = ARG(1,keymap);
- else
- map = find_keymap (ROOT_KEYMAP);
-
- cmd = resolve_command_from_keydesc (args[0]->string, 0, map);
- if (cmd)
- return command (interactive, cmd);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Thanks to Doug Kearns <djkea2@mugc.its.monash.edu.au> for the
- original patch. */
-static cmdret *
-set_barpadding (struct cmdarg **args)
-{
- int x, y;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d %d", defaults.bar_x_padding, defaults.bar_y_padding);
-
- x = ARG(0,number);
- y = ARG(1,number);
-
- if (x >= 0 && y >= 0)
- {
- defaults.bar_x_padding = x;
- defaults.bar_y_padding = y;
- }
- else
- return cmdret_new (RET_FAILURE, "defbarpadding: invalid arguments");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_alias (int interactive UNUSED, struct cmdarg **args)
-{
- /* Add or update the alias. */
- add_alias (ARG_STRING(0), ARG_STRING(1));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_unalias (int interactive UNUSED, struct cmdarg **args)
-{
- int i;
-
- /* Are we updating an existing alias, or creating a new one? */
- i = find_alias_index (ARG_STRING(0));
- if (i >= 0)
- {
- char *tmp;
-
- alias_list_last--;
-
- /* Free the alias and put the last alias in the the space to
- keep alias_list from becoming sparse. This code must jump
- through some hoops to correctly handle the case when
- alias_list_last == i. */
- tmp = alias_list[i].alias;
- alias_list[i].alias = xstrdup (alias_list[alias_list_last].alias);
- free (tmp);
- free (alias_list[alias_list_last].alias);
-
- /* Do the same for the name element. */
- tmp = alias_list[i].name;
- alias_list[i].name = xstrdup (alias_list[alias_list_last].name);
- free (tmp);
- free (alias_list[alias_list_last].name);
- }
- else
- return cmdret_new (RET_SUCCESS, "unalias: alias not found");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_nextscreen (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- int new_screen;
-
- /* No need to go through the motions when we don't have to. */
- if (num_screens <= 1)
- return cmdret_new (RET_FAILURE, "nextscreen: no other screen");
-
- new_screen = rp_current_screen + 1;
- if (new_screen >= num_screens)
- new_screen = 0;
-
- set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame), 1);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_prevscreen (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- int new_screen;
-
- /* No need to go through the motions when we don't have to. */
- if (num_screens <= 1)
- return cmdret_new (RET_SUCCESS, "prevscreen: no other screen");
-
- new_screen = rp_current_screen - 1;
- if (new_screen < 0)
- new_screen = num_screens - 1;
-
- set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame), 1);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_sselect(int interactive UNUSED, struct cmdarg **args)
-{
- int new_screen;
-
- new_screen = ARG(0,number);
- if (new_screen < 0)
- return cmdret_new (RET_FAILURE, "sselect: out of range");
-
- if (new_screen < num_screens)
- set_active_frame (screen_get_frame (&screens[new_screen], screens[new_screen].current_frame), 1);
- else
- return cmdret_new (RET_FAILURE, "sselect: out of range");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_warp (int interactive, struct cmdarg **args)
-{
- if (args[0] == NULL && !interactive)
- return cmdret_new (RET_SUCCESS, "%s", defaults.warp ? "on":"off");
-
- if (!strcasecmp (ARG_STRING(0), "on"))
- defaults.warp = 1;
- else if (!strcasecmp (ARG_STRING(0), "off"))
- defaults.warp = 0;
- else
- return cmdret_new (RET_FAILURE, "warp: invalid argument");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static void
-sync_wins (rp_screen *s)
-{
- rp_window *win, *wintmp;
- XWindowAttributes attr;
- unsigned int i, nwins;
- Window dw1, dw2, *wins;
- XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins);
-
- /* Remove any windows in our cached lists that aren't in the query
- tree. These windows have been destroyed. */
- list_for_each_entry_safe (win, wintmp, &rp_mapped_window, node)
- {
- int found;
-
- found = 0;
- for (i=0; i<nwins; i++)
- {
- if (win->w == wins[i])
- {
- found = 1;
- break;
- }
- }
- if (!found)
- {
- ignore_badwindow++;
-
- /* If, somehow, the window is not withdrawn before it is destroyed,
- perform the necessary steps to withdraw the window before it is
- unmanaged. */
- if (win->state == IconicState)
- {
- PRINT_DEBUG (("Destroying Iconic Window (%s)\n", window_name (win)));
- withdraw_window (win);
- }
- else if (win->state == NormalState)
- {
- rp_frame *frame;
-
- PRINT_DEBUG (("Destroying Normal Window (%s)\n", window_name (win)));
- frame = find_windows_frame (win);
- if (frame)
- {
- cleanup_frame (frame);
- if (frame->number == win->scr->current_frame)
- set_active_frame (frame, 0);
- }
- withdraw_window (win);
- }
-
- /* Now that the window is guaranteed to be in the unmapped window
- list, we can safely stop managing it. */
- unmanage (win);
- ignore_badwindow--;
- }
- }
-
- for (i=0; i<nwins; i++)
- {
- XGetWindowAttributes(dpy, wins[i], &attr);
- if (wins[i] == s->bar_window
- || wins[i] == s->key_window
- || wins[i] == s->input_window
- || wins[i] == s->frame_window
- || wins[i] == s->help_window
- || attr.override_redirect == True) continue;
-
- /* Find the window in our mapped window list. */
- win = find_window_in_list (wins[i], &rp_mapped_window);
- if (win)
- {
- rp_frame *frame;
- /* If the window is viewable and it is in a frame, then
- maximize it and go to the next window. */
- if (attr.map_state == IsViewable)
- {
- frame = find_windows_frame (win);
- if (frame)
- {
- maximize (win);
- }
- else
- {
- hide_window (win);
- }
- }
- else if (attr.map_state == IsUnmapped
- && get_state (win) == IconicState)
- {
- frame = find_windows_frame (win);
- if (frame)
- {
- unhide_window (win);
- maximize (win);
- }
- }
- else
- {
- PRINT_DEBUG (("I don't know what to do...\n"));
- }
-
- /* We've handled the window. */
- continue;
- }
-
- /* Try the unmapped window list. */
- win = find_window_in_list (wins[i], &rp_unmapped_window);
- if (win)
- {
- /* If the window is viewable and it is in a frame, then
- maximize it and go to the next window. */
- if (attr.map_state == IsViewable)
- {
- /* We need to map it since it's visible now. */
- map_window (win);
- }
- else if (attr.map_state == IsUnmapped
- && get_state (win) == IconicState)
- {
- /* We need to map the window and then hide it. */
- map_window (win);
- hide_window (win);
- }
- else
- {
- PRINT_DEBUG (("I think it's all sync'd up...\n"));
- }
-
- /* We've handled the window. */
- continue;
- }
-
- /* The window isn't in the mapped or unmapped window list so add
- it. */
- win = add_to_window_list (s, wins[i]);
-
- /* If it's visible or iconized. "Map" it. */
- if (attr.map_state == IsViewable
- || (attr.map_state == IsUnmapped
- && get_state (win) == IconicState))
- map_window (win);
- }
-
-}
-
-static int tmpwm_error_raised = 0;
-
-static int
-tmpwm_error_handler (Display *d UNUSED, XErrorEvent *e)
-{
- if (e->request_code == X_ChangeWindowAttributes && e->error_code == BadAccess)
- {
- PRINT_DEBUG (("failed to grab root properties\n"));
- tmpwm_error_raised++;
- }
- return 0;
-}
-
-/* Temporarily give control over to another window manager, reclaiming */
-/* control when that WM terminates. */
-cmdret *
-cmd_tmpwm (int interactive UNUSED, struct cmdarg **args)
-{
- struct list_head *tmp, *iter;
- rp_window *win = NULL;
- int child;
- int status;
- int pid;
- int i;
- int (*old_handler)(Display *, XErrorEvent *);
-
- push_frame_undo (current_screen()); /* fdump to stack */
-
- /* Release event selection on the root windows, so the new WM can
- have it. */
- for (i=0; i<num_screens; i++)
- {
- XSelectInput(dpy, RootWindow (dpy, screens[i].screen_num), 0);
- deactivate_screen(&screens[i]);
- }
-
- /* Ungrab all our keys. */
- ungrab_keys_all_wins();
-
- /* Don't listen for any events from any window. */
- list_for_each_safe_entry (win, iter, tmp, &rp_mapped_window, node)
- {
- unhide_window (win);
- maximize (win);
- XSelectInput (dpy, win->w, 0);
- }
-
- list_for_each_safe_entry (win, iter, tmp, &rp_unmapped_window, node)
- XSelectInput (dpy, win->w, 0);
-
- XSync (dpy, False);
-
- /* Disable our SIGCHLD handler */
- set_sig_handler (SIGCHLD, SIG_DFL);
- /* Launch the new WM and wait for it to terminate. */
- pid = spawn (ARG_STRING(0), 0, NULL);
- PRINT_DEBUG (("spawn pid: %d\n", pid));
- do
- {
- child = waitpid (pid, &status, 0);
- } while (child != -1 && child != pid);
- /* Enable our SIGCHLD handler */
- set_sig_handler (SIGCHLD, chld_handler);
- /* Some processes may have quit while our sigchld handler was
- disabled, so check for them. */
- check_child_procs();
-
- /* Enable the event selection on the root window. We need to loop
- until we don't get an X error. This is due to a race between the
- X server cleaning up after the temporary wm and ratpoison
- grabbing events. */
- old_handler = XSetErrorHandler (tmpwm_error_handler);
- do {
- tmpwm_error_raised = 0;
- for (i=0; i<num_screens; i++)
- {
- XSelectInput(dpy, RootWindow (dpy, screens[i].screen_num),
- PropertyChangeMask | ColormapChangeMask
- | SubstructureRedirectMask | SubstructureNotifyMask
- | StructureNotifyMask);
- XSync (dpy, False);
- }
- if (tmpwm_error_raised)
- sleep(1);
- } while (tmpwm_error_raised);
- XSetErrorHandler (old_handler);
-
- for (i=0; i<num_screens; i++)
- activate_screen (&screens[i]);
-
- /* Sort through all the windows in each group and pick out the ones
- that are unmapped or destroyed. */
- for (i=0; i<num_screens; i++)
- sync_wins (&screens[i]);
-
- /* At this point, new windows have the top level keys grabbed but
- existing windows don't. So grab them on all windows just to be
- sure. */
- grab_keys_all_wins();
-
- /* If no window has focus, give the key_window focus. */
- if (current_window())
- set_active_window (current_window());
- else
- set_window_focus (current_screen()->key_window);
-
- /* And we're back in ratpoison. */
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Return a new string with the frame selector or it as a string if no
- selector exists for the number. */
-
-/* Select a frame by number. */
-cmdret *
-cmd_fselect (int interactive, struct cmdarg **args)
-{
- set_active_frame (ARG(0,frame), 1);
- if (interactive)
- return cmdret_new (RET_SUCCESS, NULL);
- else
- return cmdret_new (RET_SUCCESS, "%d", ARG(0,frame)->number);
-}
-
-static char *
-fdump (rp_screen *screen)
-{
- struct sbuf *s;
- char *tmp;
- rp_frame *cur;
-
- s = sbuf_new (0);
-
- /* FIXME: Oooh, gross! there's a trailing comma, yuk! */
- list_for_each_entry (cur, &(screen->frames), node)
- {
- char *t;
-
- t = frame_dump (cur, screen);
- sbuf_concat (s, t);
- sbuf_concat (s, ",");
- free (t);
- }
-
- tmp = sbuf_free_struct (s);
- return tmp;
-}
-
-cmdret *
-cmd_fdump (int interactively UNUSED, struct cmdarg **args)
-{
- if (args[0] == NULL)
- {
- char *s = fdump (current_screen());
- cmdret *ret = cmdret_new (RET_SUCCESS, "%s", s);
- free (s);
- return ret;
- }
- else
- {
- int snum;
- snum = ARG(0,number);
-
- if (snum < 0 || num_screens <= snum)
- return cmdret_new (RET_FAILURE, "fdump: invalid argument");
- else
- {
- char *s = fdump (&screens[snum]);
- cmdret *ret = cmdret_new (RET_SUCCESS, "%s", s);
- free (s);
- return ret;
- }
- }
-}
-
-static cmdret *
-frestore (char *data, rp_screen *s)
-{
- char *token;
- char *d;
- rp_frame *new, *cur;
- rp_window *win;
- struct list_head fset;
- int max = -1;
- char *nexttok = NULL;
-
- INIT_LIST_HEAD (&fset);
-
- d = xstrdup (data);
- token = strtok_r (d, ",", &nexttok);
- if (token == NULL)
- {
- free (d);
- return cmdret_new (RET_FAILURE, "frestore: invalid frame format");
- }
-
- /* Build the new frame set. */
- while (token != NULL)
- {
- new = frame_read (token, s);
- if (new == NULL)
- {
- free (d);
- return cmdret_new (RET_SUCCESS, "frestore: invalid frame format");;
- }
- list_add_tail (&new->node, &fset);
- token = strtok_r (NULL, ",", &nexttok);
- }
-
- free (d);
-
- /* Clear all the frames. */
- list_for_each_entry (cur, &s->frames, node)
- {
- PRINT_DEBUG (("blank %d\n", cur->number));
- blank_frame (cur);
- }
-
- /* Get rid of the frames' numbers */
- screen_free_nums (s);
-
- /* Splice in our new frameset. */
- screen_restore_frameset (s, &fset);
-/* numset_clear (s->frames_numset); */
-
- /* Process the frames a bit to make sure everything lines up. */
- list_for_each_entry (cur, &s->frames, node)
- {
- PRINT_DEBUG (("restore %d %d\n", cur->number, cur->win_number));
-
- /* Grab the frame's number, but if it already exists request a
- new one. */
- if (!numset_add_num (s->frames_numset, cur->number)) {
- cur->number = numset_request (s->frames_numset);
- }
-
- /* Find the current frame based on last_access. */
- if (cur->last_access > max)
- {
- s->current_frame = cur->number;
- max = cur->last_access;
- }
-
- /* Update the window the frame points to. */
- if (cur->win_number != EMPTY)
- {
- set_frames_window (cur, find_window_number (cur->win_number));
- }
- }
-
- /* Show the windows in the frames. */
- list_for_each_entry (win, &rp_mapped_window, node)
- {
- if (win->frame_number != EMPTY)
- {
- maximize (win);
- unhide_window (win);
- }
- }
-
- set_active_frame (current_frame(), 0);
- update_bar (s);
- show_frame_indicator(0);
-
- PRINT_DEBUG (("Done.\n"));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_frestore (int interactively UNUSED, struct cmdarg **args)
-{
- push_frame_undo (current_screen()); /* fdump to stack */
- return frestore (ARG_STRING(0), current_screen());
-}
-
-cmdret *
-cmd_verbexec (int interactive UNUSED, struct cmdarg **args)
-{
- marked_message_printf(0, 0, "Running %s", ARG_STRING(0));
- spawn (ARG_STRING(0), 0, current_frame());
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_winliststyle (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.window_list_style ? "column":"row");
-
- if (!strcmp ("column", ARG_STRING(0)))
- defaults.window_list_style = STYLE_COLUMN;
- else if (!strcmp ("row", ARG_STRING(0)))
- defaults.window_list_style = STYLE_ROW;
- else
- return cmdret_new (RET_FAILURE, "defwinliststyle: invalid argument");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_gnext (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- set_current_group (group_next_group ());
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_gprev (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- set_current_group (group_prev_group ());
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_gother (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- set_current_group (group_last_group ());
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_gnew (int interactive UNUSED, struct cmdarg **args)
-{
- if (groups_find_group_by_name (ARG_STRING (0), 1))
- return cmdret_new (RET_FAILURE, "gnew: group already exists");
- set_current_group (group_add_new_group (ARG_STRING(0)));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_gnewbg (int interactive UNUSED, struct cmdarg **args)
-{
- if (groups_find_group_by_name (ARG_STRING (0), 1))
- return cmdret_new (RET_FAILURE, "gnewbg: group already exists");
- group_add_new_group (ARG_STRING(0));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_gnumber (int interactive UNUSED, struct cmdarg **args)
-{
- int old_number, new_number;
- rp_group *other_g, *g;
-
-/* FIXME Implement this. */
-// if (args[0] == NULL)
-// {
-// /* XXX: Fix this. */
-// print_window_information (rp_current_group, current_window());
-// return cmdret_new (RET_SUCCESS, NULL);
-// }
-
- /* 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 (group_numset, g->number);
- }
-
- g->number = new_number;
- numset_add_num (group_numset, new_number);
-
- /* resort the the window in the list */
- group_resort_group (g);
-
-/* FIXME Implement updating of groups bar. */
-// /* Update the window list. */
-// update_window_names (win->win->scr, defaults.window_fmt);
- }
-
- 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));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_gselect (int interactive, struct cmdarg **args)
-{
- rp_group *g;
-
- g = find_group (ARG_STRING(0));
-
- if (g)
- set_current_group (g);
- else
- return cmd_groups (interactive, NULL);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-/* Show all the groups, with the current one highlighted. */
-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));
- }
-
- /* Display it or return it. */
- if (interactive)
- {
- marked_message (sbuf_get (buffer), mark_start, mark_end);
- sbuf_free (buffer);
- return cmdret_new (RET_SUCCESS, NULL);
- }
- else
- {
- cmdret *ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get(buffer));
- sbuf_free(buffer);
- return ret;
- }
-}
-
-/* Move a window to a different group. */
-cmdret *
-cmd_gmove (int interactive UNUSED, struct cmdarg **args)
-{
- if (current_window() == NULL)
- return cmdret_new (RET_FAILURE, "gmove: no focused window");
-
- group_move_window (ARG(0,group), current_window());
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_gmerge (int interactive UNUSED, struct cmdarg **args)
-{
- groups_merge (ARG(0,group), rp_current_group);
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_addhook (int interactive UNUSED, struct cmdarg **args)
-{
- struct list_head *hook;
- struct sbuf *cmd;
-
- hook = hook_lookup (ARG_STRING(0));
- if (hook == NULL)
- return cmdret_new (RET_FAILURE, "addhook: unknown hook '%s'", ARG_STRING(0));
-
- /* Add the command to the hook */
- cmd = sbuf_new (0);
- sbuf_copy (cmd, ARG_STRING(1));
- hook_add (hook, cmd);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_remhook (int interactive UNUSED, struct cmdarg **args)
-{
- struct sbuf *cmd;
-
- /* Remove the command from the hook */
- cmd = sbuf_new (0);
- sbuf_copy (cmd, ARG_STRING(1));
- hook_remove (ARG(0,hook), cmd);
- sbuf_free (cmd);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_listhook (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *ret;
- struct sbuf *buffer;
- struct list_head *hook;
- struct sbuf *cur;
-
- hook = hook_lookup (ARG_STRING(0));
- if (hook == NULL)
- return cmdret_new (RET_FAILURE, "listhook: unknown hook '%s'", ARG_STRING(0));
-
- if (list_empty(hook))
- return cmdret_new (RET_FAILURE, " Nothing defined for %s ", ARG_STRING(0));
-
- buffer = sbuf_new(0);
-
- list_for_each_entry (cur, hook, node)
- {
- sbuf_printf_concat(buffer, "%s", sbuf_get (cur));
- if (cur->node.next != hook)
- sbuf_printf_concat(buffer, "\n");
- }
-
- ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (buffer));
- sbuf_free (buffer);
- return ret;
-}
-
-cmdret *
-cmd_gdelete (int interactive UNUSED, struct cmdarg **args)
-{
- rp_group *g;
-
- if (args[0] == NULL)
- g = rp_current_group;
- else
- g = ARG(0,group);
-
- switch (group_delete_group (g))
- {
- case GROUP_DELETE_GROUP_OK:
- break;
- case GROUP_DELETE_GROUP_NONEMPTY:
- return cmdret_new (RET_FAILURE, "gdelete: non-empty group");
- break;
- case GROUP_DELETE_LAST_GROUP:
- return cmdret_new (RET_FAILURE, "gdelete: cannot delete the sole group");
- break;
- default:
- return cmdret_new (RET_FAILURE, "gdelete: unknown return code (this shouldn't happen)");
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_readkey (int interactive UNUSED, struct cmdarg **args)
-{
- char *keysym_name;
- rp_action *key_action;
- KeySym keysym; /* Key pressed */
- unsigned int mod; /* Modifiers */
- int rat_grabbed = 0;
- rp_keymap *map;
-
- map = ARG(0,keymap);
-
- /* Change the mouse icon to indicate to the user we are waiting for
- more keystrokes */
- if (defaults.wait_for_key_cursor)
- {
- grab_rat();
- rat_grabbed = 1;
- }
-
- read_single_key (&keysym, &mod, NULL, 0);
-
- if (rat_grabbed)
- ungrab_rat();
-
- if ((key_action = find_keybinding (keysym, x11_mask_to_rp_mask (mod), map)))
- {
- return command (1, key_action->data);
- }
- else
- {
- cmdret *ret;
- /* No key match, notify user. */
- keysym_name = keysym_to_string (keysym, x11_mask_to_rp_mask (mod));
- ret = cmdret_new (RET_FAILURE, "readkey: unbound key '%s'", keysym_name);
- free (keysym_name);
- return ret;
- }
-}
-
-cmdret *
-cmd_newkmap (int interactive UNUSED, struct cmdarg **args)
-{
- rp_keymap *map;
-
- map = find_keymap (ARG_STRING(0));
- if (map)
- return cmdret_new (RET_FAILURE, "newkmap: keymap '%s' already exists", ARG_STRING(0));
-
- map = keymap_new (ARG_STRING(0));
- list_add_tail (&map->node, &rp_keymaps);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_delkmap (int interactive UNUSED, struct cmdarg **args)
-{
- rp_keymap *map, *top, *root;
-
- top = find_keymap (defaults.top_kmap);
- root = find_keymap (ROOT_KEYMAP);
-
- map = ARG(0,keymap);
- if (map == root || map == top)
- return cmdret_new (RET_FAILURE, "delkmap: cannot delete keymap '%s'", ARG_STRING(0));
-
- list_del (&map->node);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-static cmdret *
-set_framesels (struct cmdarg **args)
-{
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%s", defaults.frame_selectors);
-
- free (defaults.frame_selectors);
- defaults.frame_selectors = xstrdup (ARG_STRING(0));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_set (int interactive UNUSED, struct cmdarg **args)
-{
- if (args[0] == NULL)
- {
- /* List all the settings. */
- cmdret *ret;
- struct sbuf *s = sbuf_new(0);
- struct set_var *cur, *last;
-
- list_last (last, &set_vars, node);
- list_for_each_entry (cur, &set_vars, node)
- {
- cmdret *r;
- r = cur->set_fn (args);
- sbuf_printf_concat (s, "%s: %s", cur->var, r->output);
- /* Skip a newline on the last line. */
- if (cur != last)
- sbuf_concat (s, "\n");
- cmdret_free (r);
- }
-
- /* Return the accumulated string. */
- ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (s));
- sbuf_free (s);
- return ret;
- }
- else
- {
- struct sbuf *scur;
- struct cmdarg *acur;
- struct list_head *iter, *tmp;
- struct list_head head, arglist;
- int i, nargs = 0, raw = 0;
- int parsed_args;
- cmdret *result = NULL;
- struct cmdarg **cmdargs;
- char *input;
-
- INIT_LIST_HEAD (&arglist);
- INIT_LIST_HEAD (&head);
-
- /* We need to tell parse_args about arg_REST and arg_SHELLCMD. */
- for (i=0; i<ARG(0,variable)->nargs; i++)
- if (ARG(0,variable)->args[i].type == arg_REST
- || ARG(0,variable)->args[i].type == arg_COMMAND
- || ARG(0,variable)->args[i].type == arg_SHELLCMD
- || ARG(0,variable)->args[i].type == arg_RAW)
- {
- raw = 1;
- nargs = i;
- break;
- }
-
- /* Parse the arguments and call the function. */
- if (args[1])
- input = xstrdup (args[1]->string);
- else
- input = xstrdup ("");
- result = parse_args (input, &head, nargs, raw);
- free (input);
-
- if (result)
- goto failed;
- result = parsed_input_to_args (ARG(0,variable)->nargs, ARG(0,variable)->args,
- &head, &arglist, &parsed_args, NULL);
- if (result)
- goto failed;
- /* 0 or nargs is acceptable */
- if (list_size (&arglist) > 0 && list_size (&arglist) < ARG(0,variable)->nargs)
- {
- result = cmdret_new (RET_FAILURE, "not enough arguments.");
- goto failed;
- }
- else if (list_size (&head) > ARG(0,variable)->nargs)
- {
- result = cmdret_new (RET_FAILURE, "too many arguments.");
- goto failed;
- }
-
- cmdargs = arg_array (&arglist);
- result = ARG(0,variable)->set_fn (cmdargs);
- free (cmdargs);
-
- /* Free the lists. */
- failed:
- /* Free the parsed strings */
- list_for_each_safe_entry (scur, iter, tmp, &head, node)
- sbuf_free(scur);
- /* Free the args */
- list_for_each_safe_entry (acur, iter, tmp, &arglist, node)
- arg_free (acur);
-
- return result;
- }
-}
-
-cmdret *
-cmd_sfdump (int interactively UNUSED, struct cmdarg **args UNUSED)
-{
- cmdret *ret;
- struct sbuf *s;
- char *tmp2;
- rp_frame *cur;
- int i;
-
- s = sbuf_new (0);
-
- for (i=0; i<num_screens; i++)
- {
- tmp2 = xsprintf (" %d,", (rp_have_xinerama)?(screens[i].xine_screen_num):(screens[i].screen_num));
-
- /* FIXME: Oooh, gross! there's a trailing comma, yuk! */
- list_for_each_entry (cur, &(screens[i].frames), node)
- {
- char *tmp;
-
- tmp = frame_dump (cur, &screens[i]);
- sbuf_concat (s, tmp);
- sbuf_concat (s, tmp2);
- free (tmp);
- }
-
- free (tmp2);
- }
- ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (s));
- sbuf_free (s);
- return ret;
-}
-
-cmdret *
-cmd_sfrestore (int interactively UNUSED, struct cmdarg **args)
-{
- int out_of_screen = 0;
- int number_of_frames = 0;
- int j;
- long x;
- char *d;
- char *token;
- char *ptr;
- struct sbuf *buffer[num_screens];
-
- /* initialize frameset-buffer for each screen */
- for (j=0; j<num_screens; j++) {
- buffer[j] = sbuf_new(0);
- }
-
- /* now split the whole input to the corresponding screens */
- d = xstrdup (ARG_STRING(0));
-
- token = strtok (d, ",");
- if (token == NULL) {
- free (d);
- return cmdret_new (RET_FAILURE, "sfrestore: invalid frame format");
- }
-
- while (token != NULL) {
- /* search for end of frameset */
- ptr = token;
- while (*ptr != ')') {
- ptr++;
- }
- /* skip space */
- ptr++;
-
- /* convert to integer */
- x = strtol (ptr, NULL, 10);
-
- /* check that specified screen number is not bigger than current number of connected screens */
- if (x < num_screens) {
- /* append frameset to buffer[x] */
- sbuf_concat(buffer[x], token);
- sbuf_concat(buffer[x], ",");
- number_of_frames++;
- }
- else {
- out_of_screen++;
- }
-
- /* continue with next frameset */
- token = strtok (NULL, ",");
- }
-
- free (d);
-
- /* now restore the frames for each screen */
- for (j=0; j<num_screens; j++) {
- push_frame_undo (&screens[j]); /* fdump to stack */
- /* FIXME: store RET_SUCCESS || RET_FAILURE for each screen and output it later */
- frestore (sbuf_get(buffer[j]), &screens[j]);
- /* clear buffer */
- sbuf_free(buffer[j]);
- }
-
- if (!out_of_screen) {
- return cmdret_new (RET_SUCCESS, "Restored %i Frame(s)", number_of_frames);
- }
- else {
- return cmdret_new (RET_SUCCESS, "Restored %i Frame(s), %i Frame(s) out of Screen(s)", number_of_frames, out_of_screen);
- }
-}
-
-cmdret *
-cmd_sdump (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- cmdret *ret;
- struct sbuf *s;
- char *tmp;
- int i;
-
- s = sbuf_new (0);
- for (i=0; i<num_screens; ++i)
- {
- tmp = screen_dump (&screens[i]);
- sbuf_concat (s, tmp);
- if (i + 1 != num_screens) /* No trailing comma. */
- sbuf_concat (s, ",");
- free (tmp);
- }
-
- ret = cmdret_new (RET_SUCCESS, "%s", sbuf_get (s));
- sbuf_free (s);
- return ret;
-}
-
-static cmdret *
-set_maxundos (struct cmdarg **args)
-{
- rp_frame_undo *cur;
-
- if (args[0] == NULL)
- return cmdret_new (RET_SUCCESS, "%d", defaults.maxundos);
-
- if (ARG(0,number) < 0)
- return cmdret_new (RET_FAILURE, "defmaxundos: invalid argument");
-
- defaults.maxundos = ARG(0,number);
-
- /* Delete any superfluous undos */
- while (list_size (&rp_frame_undos) > defaults.maxundos)
- {
- /* Delete the oldest node */
- list_last (cur, &rp_frame_undos, node);
- del_frame_undo (cur);
- }
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_cnext (int interactive, struct cmdarg **args)
-{
- rp_window *cur, *last, *win;
-
- cur = current_window();
- if (!cur || !cur->res_class) /* Can't be done. */
- return cmd_next (interactive, args);
-
- /* CUR !in cycle list, so LAST marks last node. */
- last = group_prev_window (rp_current_group, cur);
-
- if (last)
- for (win = group_next_window (rp_current_group, cur);
- win;
- win = group_next_window (rp_current_group, win))
- {
- if (win->res_class
- && strcmp (cur->res_class, win->res_class))
- {
- set_active_window_force (win);
- return cmdret_new (RET_SUCCESS, NULL);
- }
-
- if (win == last) break;
- }
-
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
-}
-
-cmdret *
-cmd_cprev (int interactive, struct cmdarg **args)
-{
- rp_window *cur, *last, *win;
-
- cur = current_window();
- if (!cur || !cur->res_class) /* Can't be done. */
- return cmd_next (interactive, args);
-
- /* CUR !in cycle list, so LAST marks last node. */
- last = group_next_window (rp_current_group, cur);
-
- if (last)
- for (win = group_prev_window (rp_current_group, cur);
- win;
- win = group_prev_window (rp_current_group, win))
- {
- if (win->res_class
- && strcmp (cur->res_class, win->res_class))
- {
- set_active_window_force (win);
- return cmdret_new (RET_SUCCESS, NULL);
- }
-
- if (win == last) break;
- }
-
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
-}
-
-cmdret *
-cmd_inext (int interactive, struct cmdarg **args)
-{
- rp_window *cur, *last, *win;
-
- cur = current_window();
- if (!cur || !cur->res_class) /* Can't be done. */
- return cmd_next (interactive, args);
-
- /* CUR !in cycle list, so LAST marks last node. */
- last = group_prev_window (rp_current_group, cur);
-
- if (last)
- for (win = group_next_window (rp_current_group, cur);
- win;
- win = group_next_window (rp_current_group, win))
- {
- if (win->res_class
- && !strcmp (cur->res_class, win->res_class))
- {
- set_active_window_force (win);
- return cmdret_new (RET_SUCCESS, NULL);
- }
-
- if (win == last) break;
- }
-
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
-}
-
-cmdret *
-cmd_iprev (int interactive, struct cmdarg **args)
-{
- rp_window *cur, *last, *win;
-
- cur = current_window();
- if (!cur || !cur->res_class) /* Can't be done. */
- return cmd_next (interactive, args);
-
- /* CUR !in cycle list, so LAST marks last node. */
- last = group_next_window (rp_current_group, cur);
-
- if (last)
- for (win = group_prev_window (rp_current_group, cur);
- win;
- win = group_prev_window (rp_current_group, win))
- {
- if (win->res_class
- && !strcmp (cur->res_class, win->res_class))
- {
- set_active_window_force (win);
- return cmdret_new (RET_SUCCESS, NULL);
- }
-
- if (win == last) break;
- }
-
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
-}
-
-cmdret *
-cmd_cother (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_window *cur, *w = NULL;
-
- cur = current_window();
- if (cur)
- w = group_last_window_by_class (rp_current_group, cur->res_class);
-
- if (!w)
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
- else
- set_active_window_force (w);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_iother (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_window *cur, *w = NULL;
-
- cur = current_window();
- if (cur)
- w = group_last_window_by_class_complement (rp_current_group, cur->res_class);
-
- if (!w)
- return cmdret_new (RET_FAILURE, "%s", MESSAGE_NO_OTHER_WINDOW);
- else
- set_active_window_force (w);
-
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_undo (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame_undo *cur;
-
- cur = pop_frame_undo ();
- if (!cur)
- return cmdret_new (RET_FAILURE, "No more undo information available");
- else
- {
- cmdret *ret;
-
- ret = frestore (cur->frames, cur->screen);
- return ret;
- }
-}
-
-cmdret *
-cmd_redo (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- rp_frame_undo *cur;
-
- /* The current layout goes on the undo. */
-
- cur = pop_frame_redo ();
- if (!cur)
- return cmdret_new (RET_FAILURE, "No more redo information available");
- else
- {
- cmdret *ret;
-
- ret = frestore (cur->frames, cur->screen);
- return ret;
- }
-}
-
-cmdret *
-cmd_prompt (int interactive UNUSED, struct cmdarg **args)
-{
- cmdret *ret;
- char *output;
-
- if (args[0] == NULL)
- output = get_input (MESSAGE_PROMPT_COMMAND, hist_PROMPT,
- trivial_completions);
- else
- {
- char *arg_str, *prefix;
-
- arg_str = ARG_STRING(0);
- prefix = strchr (arg_str, ':');
-
- if (prefix)
- {
- struct sbuf *query;
-
- prefix++; /* Don't return the colon. */
- query = sbuf_new (prefix - arg_str);
- sbuf_nconcat (query, arg_str, prefix - arg_str);
- output = get_more_input (sbuf_get (query), prefix, hist_PROMPT,
- trivial_completions);
- sbuf_free (query);
- }
- else
- {
- output = get_input (arg_str, hist_PROMPT, trivial_completions);
- }
- }
-
- if (output == NULL)
- return cmdret_new (RET_FAILURE, NULL); /* User aborted */
-
- ret = cmdret_new (RET_SUCCESS, "%s", output);
- free (output);
-
- return ret;
-}
-
-cmdret *
-cmd_describekey (int interactive UNUSED, struct cmdarg **args)
-{
- char *keysym_name;
- rp_action *key_action;
- KeySym keysym; /* Key pressed */
- unsigned int mod; /* Modifiers */
- int rat_grabbed = 0;
- rp_keymap *map;
-
- map = ARG(0,keymap);
-
- /* Change the mouse icon to indicate to the user we are waiting for
- more keystrokes */
- if (defaults.wait_for_key_cursor)
- {
- grab_rat();
- rat_grabbed = 1;
- }
-
- read_single_key (&keysym, &mod, NULL, 0);
-
- if (rat_grabbed)
- ungrab_rat();
-
- if ((key_action = find_keybinding (keysym, x11_mask_to_rp_mask (mod), map)))
- {
- cmdret *ret;
- keysym_name = keysym_to_string (keysym, x11_mask_to_rp_mask (mod));
- ret = cmdret_new (RET_SUCCESS, "%s bound to '%s'", keysym_name, key_action->data);
- free (keysym_name);
- return ret;
- }
- else
- {
- cmdret *ret;
- /* No key match, notify user. */
- keysym_name = keysym_to_string (keysym, x11_mask_to_rp_mask (mod));
- ret = cmdret_new (RET_SUCCESS, "describekey: unbound key '%s'", keysym_name);
- free (keysym_name);
- return ret;
- }
-}
-
-cmdret *
-cmd_dedicate (int interactive UNUSED, struct cmdarg **args)
-{
- rp_frame *f;
-
- f = current_frame();
- if (!f) return cmdret_new (RET_SUCCESS, NULL);
-
- if (args[0])
- /* Whatever you set it to. */
- f->dedicated = ARG(0,number);
- else
- /* Just toggle it, rather than on or off. */
- f->dedicated = !(f->dedicated);
-
- return cmdret_new (RET_SUCCESS, "Consider this frame %s.",
- f->dedicated ? "chaste":"promiscuous");
-}
-
-cmdret *
-cmd_putsel (int interactive UNUSED, struct cmdarg **args)
-{
- set_selection(ARG_STRING(0));
- return cmdret_new (RET_SUCCESS, NULL);
-}
-
-cmdret *
-cmd_getsel (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- char *sel = get_selection();
- cmdret *ret;
- ret = cmdret_new (RET_SUCCESS, "%s", sel);
- free (sel);
- return ret;
-}
-
-/* This is a command that restores old commands that have been
- recently depricated. */
-cmdret *
-cmd_compat (int interactive UNUSED, struct cmdarg **args UNUSED)
-{
- add_alias ("defresizeunit", "set resizeunit");
- add_alias ("defwingravity", "set wingravity");
- add_alias ("deftransgravity", "set transgravity");
- add_alias ("defmaxsizegravity", "set maxsizegravity");
- add_alias ("defbargravity", "set bargravity");
- add_alias ("deffont", "set font");
- add_alias ("defpadding", "set padding");
- add_alias ("defborder", "set border");
- add_alias ("defbarborder", "set barborder");
- add_alias ("definputwidth", "set inputwidth");
- add_alias ("defwaitcursor", "set waitcursor");
- add_alias ("defwinfmt", "set winfmt");
- add_alias ("defwinname", "set winname");
- add_alias ("deffgcolor", "set fgcolor");
- add_alias ("defbgcolor", "set bgcolor");
- add_alias ("defbarpadding", "set barpadding");
- add_alias ("defwinliststyle", "set winliststyle");
- add_alias ("defframesels", "set framesels");
- add_alias ("defmaxundos", "set maxundos");
-
- return cmdret_new (RET_SUCCESS, NULL);
-}