diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/.gitignore | 6 | ||||
-rw-r--r-- | src/Makefile.am | 78 | ||||
-rw-r--r-- | src/actions.c | 6005 | ||||
-rw-r--r-- | src/actions.h | 239 | ||||
-rw-r--r-- | src/bar.c | 607 | ||||
-rw-r--r-- | src/bar.h | 39 | ||||
-rw-r--r-- | src/communications.c | 155 | ||||
-rw-r--r-- | src/communications.h | 27 | ||||
-rw-r--r-- | src/completions.c | 181 | ||||
-rw-r--r-- | src/completions.h | 28 | ||||
-rw-r--r-- | src/conf.h | 134 | ||||
-rw-r--r-- | src/data.h | 392 | ||||
-rw-r--r-- | src/editor.c | 580 | ||||
-rw-r--r-- | src/editor.h | 49 | ||||
-rw-r--r-- | src/events.c | 1012 | ||||
-rw-r--r-- | src/events.h | 28 | ||||
-rw-r--r-- | src/format.c | 314 | ||||
-rw-r--r-- | src/format.h | 27 | ||||
-rw-r--r-- | src/frame.c | 302 | ||||
-rw-r--r-- | src/frame.h | 47 | ||||
-rw-r--r-- | src/getopt.c | 1052 | ||||
-rw-r--r-- | src/getopt.h | 133 | ||||
-rw-r--r-- | src/getopt1.c | 194 | ||||
-rw-r--r-- | src/globals.c | 346 | ||||
-rw-r--r-- | src/globals.h | 217 | ||||
-rw-r--r-- | src/group.c | 661 | ||||
-rw-r--r-- | src/group.h | 68 | ||||
-rw-r--r-- | src/history.c | 320 | ||||
-rw-r--r-- | src/history.h | 45 | ||||
-rw-r--r-- | src/hook.c | 93 | ||||
-rw-r--r-- | src/hook.h | 29 | ||||
-rw-r--r-- | src/input.c | 622 | ||||
-rw-r--r-- | src/input.h | 39 | ||||
-rw-r--r-- | src/linkedlist.c | 204 | ||||
-rw-r--r-- | src/linkedlist.h | 215 | ||||
-rw-r--r-- | src/main.c | 863 | ||||
-rw-r--r-- | src/manage.c | 1001 | ||||
-rw-r--r-- | src/manage.h | 60 | ||||
-rw-r--r-- | src/messages.h | 56 | ||||
-rw-r--r-- | src/number.c | 149 | ||||
-rw-r--r-- | src/number.h | 46 | ||||
-rw-r--r-- | src/ratpoison.h | 113 | ||||
-rw-r--r-- | src/sbuf.c | 145 | ||||
-rw-r--r-- | src/sbuf.h | 49 | ||||
-rw-r--r-- | src/screen.c | 497 | ||||
-rw-r--r-- | src/screen.h | 48 | ||||
-rw-r--r-- | src/split.c | 1090 | ||||
-rw-r--r-- | src/split.h | 60 | ||||
-rw-r--r-- | src/window.c | 820 | ||||
-rw-r--r-- | src/window.h | 73 | ||||
-rw-r--r-- | src/xinerama.c | 99 | ||||
-rw-r--r-- | src/xinerama.h | 28 |
52 files changed, 0 insertions, 19685 deletions
diff --git a/src/.gitignore b/src/.gitignore deleted file mode 100644 index 77cfffb..0000000 --- a/src/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.deps -config.h -config.h.in -stamp-h1 -*.o -ratpoison diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index b4ce142..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,78 +0,0 @@ -## Process this file with automake to produce Makefile.in -## 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 of the License, 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 program; if not, write to the Free Software -## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -## -## $Id: Makefile.am,v 1.24 2006/11/21 17:03:31 brl Exp $ - -bin_PROGRAMS = ratpoison -MAINTAINERCLEANFILES = Makefile.in config.h.in - -AM_LDFLAGS=${X_LDFLAGS} -ratpoison_LDADD=${XFT_LIBS} ${X_LIBS} ${X_EXTRA_LIBS} ${HISTORY_LIBS} -AM_CPPFLAGS=${X_CFLAGS} ${XFT_CFLAGS} - -ratpoison_SOURCES = actions.c \ - actions.h \ - bar.c \ - bar.h \ - completions.c \ - completions.h \ - communications.c \ - communications.h \ - conf.h \ - data.h \ - editor.c \ - editor.h \ - events.c \ - events.h \ - format.c \ - format.h \ - frame.c \ - frame.h \ - getopt.c \ - getopt.h \ - getopt1.c \ - globals.h \ - globals.c \ - group.h \ - group.c \ - history.h \ - history.c \ - hook.c \ - hook.h \ - input.c \ - input.h \ - linkedlist.h \ - linkedlist.c \ - main.c \ - manage.c \ - manage.h \ - messages.h \ - number.c \ - number.h \ - ratpoison.h \ - sbuf.c \ - sbuf.h \ - screen.h \ - screen.c \ - split.c \ - split.h \ - window.c \ - window.h \ - xinerama.c \ - xinerama.h 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); -} diff --git a/src/actions.h b/src/actions.h deleted file mode 100644 index 519c1a7..0000000 --- a/src/actions.h +++ /dev/null @@ -1,239 +0,0 @@ -/* Prototypes of all actions that can be performed with keystrokes. - * 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 - */ - -#ifndef _RATPOISON_ACTIONS_H -#define _RATPOISON_ACTIONS_H 1 - -#define MAX_COMMAND_LENGTH 100 -#define MAX_ARGS_LENGTH 100 - -#include <ratpoison.h> - -typedef struct user_command user_command; - -/* arg_REST and arg_SHELLCMD eat the rest of the input. */ -enum argtype { arg_REST, - arg_NUMBER, - arg_STRING, - arg_FRAME, - arg_WINDOW, - arg_COMMAND, - arg_SHELLCMD, - arg_KEYMAP, - arg_KEY, - arg_GRAVITY, - arg_GROUP, - arg_HOOK, - arg_VARIABLE, - arg_RAW}; - -union arg_union { - rp_frame *frame; - int number; - float fnumber; - rp_window *win; - rp_keymap *keymap; - rp_group *group; - struct list_head *hook; - struct set_var *variable; - struct rp_key *key; - int gravity; - }; - -struct cmdarg -{ - int type; - char *string; - union arg_union arg; - struct list_head node; -}; - -struct argspec -{ - int type; - char *prompt; -}; - -/* The structure returned by a command. */ -typedef struct cmdret cmdret; -struct cmdret -{ - char *output; - int success; -}; - -struct -user_command -{ - char *name; - cmdret * (*func)(int, struct cmdarg **); - struct argspec *args; - int num_args; - /* The number of required arguments. Any arguments after that are - optional and won't be filled in when called - interactively. ni_required_args is used when called non-interactively, - i_required_args when called interactively. */ - int ni_required_args, i_required_args; - - struct list_head node; -}; - -int spawn(char *data, int raw, rp_frame *frame); -cmdret *command (int interactive, char *data); - -/* command function prototypes. */ -#define RP_CMD(cmd) cmdret *cmd_ ## cmd (int interactive, struct cmdarg **args) -RP_CMD (abort); -RP_CMD (addhook); -RP_CMD (alias); -RP_CMD (banish); -RP_CMD (banishrel); -RP_CMD (bind); -RP_CMD (compat); -RP_CMD (chdir); -RP_CMD (clrunmanaged); -RP_CMD (colon); -RP_CMD (curframe); -RP_CMD (delete); -RP_CMD (echo); -RP_CMD (escape); -RP_CMD (exec); -RP_CMD (execa); -RP_CMD (execf); -RP_CMD (fdump); -RP_CMD (focusdown); -RP_CMD (focuslast); -RP_CMD (focusleft); -RP_CMD (focusright); -RP_CMD (focusup); -RP_CMD (exchangeup); -RP_CMD (exchangedown); -RP_CMD (exchangeleft); -RP_CMD (exchangeright); -RP_CMD (swap); -RP_CMD (frestore); -RP_CMD (fselect); -RP_CMD (gdelete); -RP_CMD (getenv); -RP_CMD (gmerge); -RP_CMD (gmove); -RP_CMD (gnew); -RP_CMD (gnewbg); -RP_CMD (gnext); -RP_CMD (gnumber); -RP_CMD (gprev); -RP_CMD (gother); -RP_CMD (gravity); -RP_CMD (grename); -RP_CMD (groups); -RP_CMD (gselect); -RP_CMD (h_split); -RP_CMD (help); -RP_CMD (info); -RP_CMD (kill); -RP_CMD (lastmsg); -RP_CMD (license); -RP_CMD (link); -RP_CMD (listhook); -RP_CMD (meta); -RP_CMD (msgwait); -RP_CMD (newwm); -RP_CMD (next); -RP_CMD (next_frame); -RP_CMD (nextscreen); -RP_CMD (number); -RP_CMD (only); -RP_CMD (other); -RP_CMD (prev); -RP_CMD (prev_frame); -RP_CMD (prevscreen); -RP_CMD (quit); -RP_CMD (redisplay); -RP_CMD (remhook); -RP_CMD (remove); -RP_CMD (rename); -RP_CMD (resize); -RP_CMD (restart); -RP_CMD (rudeness); -RP_CMD (select); -RP_CMD (setenv); -RP_CMD (shrink); -RP_CMD (source); -RP_CMD (startup_message); -RP_CMD (time); -RP_CMD (tmpwm); -RP_CMD (unalias); -RP_CMD (unbind); -RP_CMD (unimplemented); -RP_CMD (unmanage); -RP_CMD (unsetenv); -RP_CMD (v_split); -RP_CMD (verbexec); -RP_CMD (version); -RP_CMD (warp); -RP_CMD (windows); -RP_CMD (readkey); -RP_CMD (newkmap); -RP_CMD (delkmap); -RP_CMD (definekey); -RP_CMD (undefinekey); -RP_CMD (set); -RP_CMD (sselect); -RP_CMD (ratwarp); -RP_CMD (ratinfo); -RP_CMD (ratrelinfo); -RP_CMD (ratclick); -RP_CMD (ratrelwarp); -RP_CMD (rathold); -RP_CMD (cnext); -RP_CMD (cother); -RP_CMD (cprev); -RP_CMD (dedicate); -RP_CMD (describekey); -RP_CMD (inext); -RP_CMD (iother); -RP_CMD (iprev); -RP_CMD (prompt); -RP_CMD (sdump); -RP_CMD (sfdump); -RP_CMD (sfrestore); -RP_CMD (undo); -RP_CMD (redo); -RP_CMD (putsel); -RP_CMD (getsel); - -void del_frame_undo (rp_frame_undo *u); - -rp_keymap *find_keymap (char *name); -void init_user_commands(void); -void initialize_default_keybindings (void); -cmdret *cmdret_new (int success, char *fmt, ...); -void cmdret_free (cmdret *ret); -void keymap_free (rp_keymap *map); -void free_user_commands (void); -void free_aliases (void); -void free_keymaps (void); -char *wingravity_to_string (int g); -rp_action* find_keybinding (KeySym keysym, unsigned int state, rp_keymap *map); -rp_action* find_keybinding_by_action (char *action, rp_keymap *map); - - -#endif /* ! _RATPOISON_ACTIONS_H */ diff --git a/src/bar.c b/src/bar.c deleted file mode 100644 index 8af3308..0000000 --- a/src/bar.c +++ /dev/null @@ -1,607 +0,0 @@ -/* Functionality for a bar across the bottom of the screen listing the - * windows currently managed. - * - * 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 <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -#ifdef USE_XFT_FONT -#include <X11/Xft/Xft.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "ratpoison.h" - -#include "assert.h" - -/* Possible values for bar_is_raised status. */ -#define BAR_IS_HIDDEN 0 -#define BAR_IS_WINDOW_LIST 1 -#define BAR_IS_MESSAGE 2 - -/* A copy of the last message displayed in the message bar. */ -static char *last_msg = NULL; -static int last_mark_start = 0; -static int last_mark_end = 0; - -static void marked_message_internal (char *msg, int mark_start, int mark_end); - -/* Reset the alarm to auto-hide the bar in BAR_TIMEOUT seconds. */ -static void -reset_alarm (void) -{ - alarm (defaults.bar_timeout); - alarm_signalled = 0; -} - -/* Hide the bar from sight. */ -int -hide_bar (rp_screen *s) -{ - if (s->bar_is_raised) - { - s->bar_is_raised = 0; - XUnmapWindow (dpy, s->bar_window); - - /* Possibly restore colormap. */ - if (current_window()) - { - XUninstallColormap (dpy, s->def_cmap); - XInstallColormap (dpy, current_window()->colormap); - } - - return 1; - } - - return 0; -} - -/* Show window listing in bar. */ -int -show_bar (rp_screen *s, char *fmt) -{ - if (!s->bar_is_raised) - { - s->bar_is_raised = BAR_IS_WINDOW_LIST; - XMapRaised (dpy, s->bar_window); - update_window_names (s, fmt); - - /* Switch to the default colormap */ - if (current_window()) - XUninstallColormap (dpy, current_window()->colormap); - XInstallColormap (dpy, s->def_cmap); - - reset_alarm(); - return 1; - } - - /* If the bar is raised we still need to display the window - names. */ - update_window_names (s, fmt); - return 0; -} - -int -bar_x (rp_screen *s, int width) -{ - int x = 0; - - switch (defaults.bar_location) - { - case NorthWestGravity: - case WestGravity: - case SouthWestGravity: - x = s->left + (defaults.bar_in_padding ? 0 : defaults.padding_left); - break; - case NorthGravity: - case CenterGravity: - case SouthGravity: - x = s->left + (s->width - width - defaults.bar_border_width * 2) / 2 - - (defaults.bar_in_padding ? 0 : defaults.padding_left); - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - x = s->left + s->width - width - defaults.bar_border_width * 2 - - (defaults.bar_in_padding ? 0 : defaults.padding_right); - break; - } - - return x; -} - -int -bar_y (rp_screen *s, int height) -{ - int y = 0; - - switch (defaults.bar_location) - { - case NorthEastGravity: - case NorthGravity: - case NorthWestGravity: - y = s->top + (defaults.bar_in_padding ? 0 : defaults.padding_top); - break; - case EastGravity: - case CenterGravity: - case WestGravity: - y = s->top + (s->height - height - - defaults.bar_border_width * 2) / 2 - - (defaults.bar_in_padding ? 0 : defaults.padding_top); - break; - case SouthEastGravity: - case SouthGravity: - case SouthWestGravity: - y = s->top + (s->height - height - - defaults.bar_border_width * 2) - - (defaults.bar_in_padding ? 0 : defaults.padding_top); - break; - } - - return y; -} - -void -update_bar (rp_screen *s) -{ - if (s->bar_is_raised == BAR_IS_WINDOW_LIST) { - update_window_names (s, defaults.window_fmt); - return; - } - - if (s->bar_is_raised == BAR_IS_HIDDEN) - return; - - redraw_last_message(); -} - -/* Note that we use marked_message_internal to avoid resetting the - alarm. */ -void -update_window_names (rp_screen *s, char *fmt) -{ - struct sbuf *bar_buffer; - int mark_start = 0; - int mark_end = 0; - - if (s->bar_is_raised != BAR_IS_WINDOW_LIST) return; - - bar_buffer = sbuf_new (0); - - if(defaults.window_list_style == STYLE_ROW) - { - get_window_list (fmt, NULL, bar_buffer, &mark_start, &mark_end); - marked_message_internal (sbuf_get (bar_buffer), mark_start, mark_end); - } - else - { - get_window_list (fmt, "\n", bar_buffer, &mark_start, &mark_end); - marked_message_internal (sbuf_get (bar_buffer), mark_start, mark_end); - } - - -/* marked_message (sbuf_get (bar_buffer), mark_start, mark_end); */ - sbuf_free (bar_buffer); -} - -void -message (char *s) -{ - marked_message (s, 0, 0); -} - -void -marked_message_printf (int mark_start, int mark_end, char *fmt, ...) -{ - char *buffer; - va_list ap; - - va_start (ap, fmt); - buffer = xvsprintf (fmt, ap); - va_end (ap); - - marked_message (buffer, mark_start, mark_end); - free (buffer); -} - -static int -count_lines (char* msg, int len) -{ - int ret = 1; - int i; - - if (len < 1) - return 1; - - for(i=0; i<len; i++) - { - if (msg[i] == '\n') ret++; - } - - return ret; -} - - -static int -max_line_length (char* msg) -{ - rp_screen *s = current_screen (); - size_t i; - size_t start; - int ret = 0; - - /* Count each line and keep the length of the longest one. */ - for(start=0, i=0; i <= strlen(msg); i++) - { - if(msg[i] == '\n' || msg[i] == '\0') - { - int current_width; - - /* Check if this line is the longest so far. */ - current_width = rp_text_width (s, msg + start, i - start); - if(current_width > ret) - { - ret = current_width; - } - - /* Update the start of the new line. */ - start = i + 1; - } - } - - return ret; -} - -static int -pos_in_line (char* msg, int pos) -{ - int ret; - int i; - - if(pos <= 0) - return 0; - - /* Go backwards until we hit the beginning of the string or a new - line. */ - ret = 0; - for(i=pos-1; i>=0; ret++, i--) - { - if(msg[i]=='\n') - break; - } - - return ret; -} - -static int -line_beginning (char* msg, int pos) -{ - int ret = 0; - int i; - - if(pos <= 0) - return 0; - - /* Go backwards until we hit a new line or the beginning of the - string. */ - for(i=pos-1; i>=0; --i) - { - if (msg[i]=='\n') - { - ret = i + 1; - break; - } - } - - return ret; -} - -static void -draw_partial_string (rp_screen *s, char *msg, int line_no, int start, int end, int style) -{ - int line_height = FONT_HEIGHT (s); - - rp_draw_string (s, s->bar_window, style, - defaults.bar_x_padding, - defaults.bar_y_padding + FONT_ASCENT(s) - + line_no * line_height, - msg + start, end - start + 1); -} - -static void -draw_string (rp_screen *s, char *msg, int mark_start, int mark_end) -{ - size_t i; - int line_no; - int start; - int style = STYLE_NORMAL, update = 0; - - /* Walk through the string, print each line. */ - start = 0; - line_no = 0; -/* if (mark_start == 0 && mark_end == 0) */ -/* mark_start = mark_end = -1; */ - - for(i=0; i < strlen(msg); ++i) - { - if (i == (size_t)mark_start) - { - style = STYLE_INVERSE; - update = 1; - } - if (i == (size_t)mark_end) - { - style = STYLE_NORMAL; - update = 1; - } - if (msg[i] == '\n') - update = 2; - - if (update) - { - draw_partial_string (s, msg, line_no, start, update == 2 ? i-1:i, style); - start = i; - if (update == 2) - { - line_no++; - start++; - } - update = 0; - } - } - - /* Print the last line. */ - draw_partial_string (s, msg, line_no, start, strlen (msg)-1, style); - XSync (dpy, False); -} - -/* Move the marks if they are outside the string or if the start is - after the end. */ -static void -correct_mark (int msg_len, int *mark_start, int *mark_end) -{ - /* Make sure the marks are inside the string. */ - if (*mark_start < 0) - *mark_start = 0; - - if (*mark_end < 0) - *mark_end = 0; - - if (*mark_start > msg_len) - *mark_start = msg_len; - - if (*mark_end > msg_len) - *mark_end = msg_len; - - /* Make sure the marks aren't reversed. */ - if (*mark_start > *mark_end) - { - int tmp; - tmp = *mark_start; - *mark_start = *mark_end; - *mark_end = tmp; - } - -} - -/* Raise the bar and put it in the right spot */ -static void -prepare_bar (rp_screen *s, int width, int height) -{ - width = width < s->width ? width : s->width; - height = height < s->height ? height : s->height; - XMoveResizeWindow (dpy, s->bar_window, - bar_x (s, width), bar_y (s, height), - width, height); - - /* Map the bar if needed */ - if (!s->bar_is_raised) - { - s->bar_is_raised = BAR_IS_MESSAGE; - XMapRaised (dpy, s->bar_window); - - /* Switch to the default colormap */ - if (current_window()) - XUninstallColormap (dpy, current_window()->colormap); - XInstallColormap (dpy, s->def_cmap); - } - - XRaiseWindow (dpy, s->bar_window); - XClearWindow (dpy, s->bar_window); - XSync (dpy, False); -} - -static void -get_mark_box (char *msg, size_t mark_start, size_t mark_end, - int *x, int *y, int *width, int *height) -{ - rp_screen *s = current_screen (); - int start, end; - int mark_end_is_new_line = 0; - int start_line; - int end_line; - int start_pos_in_line; - int end_pos_in_line; - int start_line_beginning; - int end_line_beginning; - - /* If the mark_end is on a new line or the end of the string, then - back it up one character. */ - if (msg[mark_end-1] == '\n' || mark_end == strlen (msg)) - { - mark_end--; - mark_end_is_new_line = 1; - } - - start_line = count_lines(msg, mark_start); - end_line = count_lines(msg, mark_end); - - start_pos_in_line = pos_in_line(msg, mark_start); - end_pos_in_line = pos_in_line(msg, mark_end); - - start_line_beginning = line_beginning(msg, mark_start); - end_line_beginning = line_beginning(msg, mark_end); - - PRINT_DEBUG (("start_line = %d, end_line = %d\n", start_line, end_line)); - PRINT_DEBUG (("start_line_beginning = %d, end_line_beginning = %d\n", - start_line_beginning, end_line_beginning)); - - if (mark_start == 0 || start_pos_in_line == 0) - start = 0; - else - start = rp_text_width (s, &msg[start_line_beginning], - start_pos_in_line) + defaults.bar_x_padding; - - end = rp_text_width (s, &msg[end_line_beginning], - end_pos_in_line) + defaults.bar_x_padding * 2; - - if (mark_end != strlen (msg)) - end -= defaults.bar_x_padding; - - /* A little hack to highlight to the end of the line, if the - mark_end is at the end of a line. */ - if (mark_end_is_new_line) - { - *width = max_line_length(msg) + defaults.bar_x_padding * 2; - } - else - { - *width = end - start; - } - - *x = start; - *y = (start_line - 1) * FONT_HEIGHT (s) + defaults.bar_y_padding; - *height = (end_line - start_line + 1) * FONT_HEIGHT (s); -} - -static void -draw_box (rp_screen *s, int x, int y, int width, int height) -{ - XGCValues lgv; - GC lgc; - unsigned long mask; - - lgv.foreground = s->fg_color; - mask = GCForeground; - lgc = XCreateGC(dpy, s->root, mask, &lgv); - - XFillRectangle (dpy, s->bar_window, lgc, - x, y, width, height); - XFreeGC (dpy, lgc); -} - -static void -draw_mark (rp_screen *s, char *msg, int mark_start, int mark_end) -{ - int x, y, width, height; - - /* when this happens, there is no mark. */ - if (mark_end == 0 || mark_start == mark_end) - return; - - get_mark_box (msg, mark_start, mark_end, - &x, &y, &width, &height); - draw_box (s, x, y, width, height); -} - -static void -update_last_message (char *msg, int mark_start, int mark_end) -{ - free (last_msg); - last_msg = xstrdup (msg); - last_mark_start = mark_start; - last_mark_end = mark_end; -} - -void -marked_message (char *msg, int mark_start, int mark_end) -{ - /* Schedule the bar to be hidden after some amount of time. */ - reset_alarm (); - marked_message_internal (msg, mark_start, mark_end); -} - -static void -marked_message_internal (char *msg, int mark_start, int mark_end) -{ - rp_screen *s = current_screen (); - int num_lines; - int width; - int height; - - PRINT_DEBUG (("msg = %s\n", msg?msg:"NULL")); - PRINT_DEBUG (("mark_start = %d, mark_end = %d\n", mark_start, mark_end)); - - /* Calculate the width and height of the window. */ - num_lines = count_lines (msg, strlen(msg)); - width = defaults.bar_x_padding * 2 + max_line_length(msg); - height = FONT_HEIGHT (s) * num_lines + defaults.bar_y_padding * 2; - - prepare_bar (s, width, height); - - /* Draw the mark over the designated part of the string. */ - correct_mark (strlen (msg), &mark_start, &mark_end); - draw_mark (s, msg, mark_start, mark_end); - - draw_string (s, msg, mark_start, mark_end); - - /* Keep a record of the message. */ - update_last_message (msg, mark_start, mark_end); -} - -/* Use this just to update the bar. show_last_message will draw it and - leave it up for a period of time. */ -void -redraw_last_message (void) -{ - char *msg; - - if (last_msg == NULL) return; - - /* A little kludge to avoid last_msg in marked_message from being - strdup'd right after freeing the pointer. Note: in this case - marked_message's msg arg would have been the same as - last_msg. */ - msg = xstrdup (last_msg); - marked_message_internal (msg, last_mark_start, last_mark_end); - free (msg); -} - -void -show_last_message (void) -{ - redraw_last_message(); - reset_alarm(); -} - -/* Free any memory associated with the bar. */ -void -free_bar (void) -{ - free (last_msg); - last_msg = NULL; -} diff --git a/src/bar.h b/src/bar.h deleted file mode 100644 index 2156802..0000000 --- a/src/bar.h +++ /dev/null @@ -1,39 +0,0 @@ -/* functions for managing the program bar - * 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 - */ - -#ifndef _RATPOISON_BAR_H -#define _RATPOISON_BAR_H 1 - -void update_window_names (rp_screen *s, char *fmt); -void update_bar (rp_screen *s); -int show_bar (rp_screen *s, char *fmt); -int hide_bar (rp_screen *s); -int bar_y (rp_screen *s, int height); -int bar_x (rp_screen *s, int width); - -void message (char *s); -void marked_message (char *s, int mark_start, int mark_end); -void marked_message_printf (int mark_start, int mark_end, char *fmt, ...); -void redraw_last_message (void); -void show_last_message (void); -void free_bar (void); - -#endif /* ! _RATPOISON_BAR_H */ diff --git a/src/communications.c b/src/communications.c deleted file mode 100644 index 76f3b98..0000000 --- a/src/communications.c +++ /dev/null @@ -1,155 +0,0 @@ -/* communications.c -- Send commands to a running copy of ratpoison. - * 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 <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/Xproto.h> - -#include <string.h> - -#include "ratpoison.h" - - -/* Sending commands to ratpoison */ -static int -receive_command_result (Window w) -{ - int query; - int return_status = RET_FAILURE; - Atom type_ret; - int format_ret; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *result = NULL; - - /* First, find out how big the property is. */ - query = XGetWindowProperty (dpy, w, rp_command_result, - 0, 0, False, xa_string, - &type_ret, &format_ret, &nitems, &bytes_after, - &result); - - /* Failed to retrieve property. */ - if (query != Success || result == NULL) - { - PRINT_DEBUG (("failed to get command result length\n")); - return return_status; - } - - /* XGetWindowProperty always allocates one extra byte even if - the property is zero length. */ - XFree (result); - - /* Now that we have the length of the message, we can get the - whole message. */ - query = XGetWindowProperty (dpy, w, rp_command_result, - 0, (bytes_after / 4) + (bytes_after % 4 ? 1 : 0), - True, xa_string, &type_ret, &format_ret, &nitems, - &bytes_after, &result); - - /* Failed to retrieve property. */ - if (query != Success || result == NULL) - { - PRINT_DEBUG (("failed to get command result\n")); - return return_status; - } - - /* - * We can receive: - * - an empty string, indicating a success but no output - * - a string starting with '1', indicating a success and an output - * - a string starting with '0', indicating a failure and an optional output - */ - switch (result[0]) - { - case '\0': /* Command succeeded but no string to print */ - return_status = RET_SUCCESS; - break; - case '0': /* Command failed, don't print an empty line if no explanation - was given */ - if (result[1] != '\0') - fprintf (stderr, "%s\n", &result[1]); - return_status = RET_FAILURE; - break; - case '1': /* Command succeeded, print the output */ - printf ("%s\n", &result[1]); - return_status = RET_SUCCESS; - break; - default: /* We probably got junk, so ignore it */ - return_status = RET_FAILURE; - } - - /* Free the result. */ - XFree (result); - - return return_status; -} - -int -send_command (unsigned char interactive, unsigned char *cmd, int screen_num) -{ - Window w, root; - int done = 0, return_status = RET_FAILURE; - struct sbuf *s; - - s = sbuf_new(0); - sbuf_printf(s, "%c%s", interactive, cmd); - - - /* If the user specified a specific screen, then send the event to - that screen. */ - if (screen_num >= 0) - root = RootWindow (dpy, screen_num); - else - root = DefaultRootWindow (dpy); - - w = XCreateSimpleWindow (dpy, root, 0, 0, 1, 1, 0, 0, 0); - - /* Select first to avoid race condition */ - XSelectInput (dpy, w, PropertyChangeMask); - - XChangeProperty (dpy, w, rp_command, xa_string, - 8, PropModeReplace, (unsigned char*)sbuf_get(s), strlen ((char *)cmd) + 2); - - XChangeProperty (dpy, root, - rp_command_request, XA_WINDOW, - 8, PropModeAppend, (unsigned char *)&w, sizeof (Window)); - - sbuf_free (s); - - while (!done) - { - XEvent ev; - - XMaskEvent (dpy, PropertyChangeMask, &ev); - if (ev.xproperty.atom == rp_command_result - && ev.xproperty.state == PropertyNewValue) - { - return_status = receive_command_result(ev.xproperty.window); - done = 1; - } - } - - XDestroyWindow (dpy, w); - - return return_status; -} diff --git a/src/communications.h b/src/communications.h deleted file mode 100644 index 6cdd33c..0000000 --- a/src/communications.h +++ /dev/null @@ -1,27 +0,0 @@ -/* communications.h -- Send commands to a running copy of ratpoison. - * 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 - */ - -#ifndef _RATPOISON_COMMUNICATIONS_H -#define _RATPOISON_COMMUNICATIONS_H 1 - -int send_command (unsigned char interactive, unsigned char *cmd, int screen_num); - -#endif /* ! _RATPOISON_COMMUNICATIONS_H */ diff --git a/src/completions.c b/src/completions.c deleted file mode 100644 index fc32c38..0000000 --- a/src/completions.c +++ /dev/null @@ -1,181 +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 <string.h> - -#include "ratpoison.h" -#include "completions.h" - -rp_completions * -completions_new (completion_fn list_fn) -{ - rp_completions *c; - - c = (rp_completions *) xmalloc (sizeof(rp_completions)); - - INIT_LIST_HEAD (&c->completion_list); - c->complete_fn = list_fn; - c->last_match = NULL; - c->partial = NULL; - c->virgin = 1; - - return c; -} - -void -completions_free (rp_completions *c) -{ - struct sbuf *cur; - struct list_head *tmp, *iter; - - /* Clear our list */ - list_for_each_safe_entry (cur, iter, tmp, &c->completion_list, node) - { - list_del (&cur->node); - sbuf_free (cur); - } - - /* Free the partial string. */ - if (c->partial) - free (c->partial); - - free (c); -} - -static void -completions_assign (rp_completions *c, struct list_head *new_list) -{ - struct sbuf *cur; - struct list_head *tmp, *iter; - - /* Clear our list */ - list_for_each_safe_entry (cur, iter, tmp, &c->completion_list, node) - { - list_del (&cur->node); - sbuf_free (cur); - } - - /* splice the list into completion_list. Note that we SHOULDN'T free - new_list, because they share the same memory. */ - INIT_LIST_HEAD (&c->completion_list); - list_splice (new_list, &c->completion_list); - - list_first (c->last_match, &c->completion_list, node); -} - -static void -completions_update (rp_completions *c, char *partial) -{ - struct list_head *new_list; - - new_list = c->complete_fn (partial); - - c->virgin = 0; - if (c->partial) - free (c->partial); - c->partial = xstrdup (partial); - - completions_assign (c, new_list); - - /* Free the head structure for our list. */ - free (new_list); -} - -static char * -completions_prev_match (rp_completions *c) -{ - struct sbuf *cur; - - /* search forward from our last match through the list looking for - another match. */ - for (cur = list_prev_entry (c->last_match, &c->completion_list, node); - cur != c->last_match; - cur = list_prev_entry (cur, &c->completion_list, node)) - { - if (str_comp (sbuf_get (cur), c->partial, strlen (c->partial))) - { - /* We found a match so update our last_match pointer and - return the string. */ - c->last_match = cur; - return sbuf_get (cur); - } - } - - return NULL; -} - -static char * -completions_next_match (rp_completions *c) -{ - struct sbuf *cur; - - /* search forward from our last match through the list looking for - another match. */ - for (cur = list_next_entry (c->last_match, &c->completion_list, node); - cur != c->last_match; - cur = list_next_entry (cur, &c->completion_list, node)) - { - if (str_comp (sbuf_get (cur), c->partial, strlen (c->partial))) - { - /* We found a match so update our last_match pointer and - return the string. */ - c->last_match = cur; - return sbuf_get (cur); - } - } - - return NULL; -} - -/* Return a completed string that starts with partial. */ -char * -completions_complete (rp_completions *c, char *partial, int direction) -{ - if (c->virgin) - { - completions_update (c, partial); - - /* Since it's never been completed on and c->last_match points - to the first element of the list which may be a match. So - check it. FIXME: This is a bit of a hack. */ - if (c->last_match == NULL) - return NULL; - - /* c->last_match contains the first match in the forward - direction. So if we're looking for the previous match, then - check the previous element from last_match. */ - if (direction == COMPLETION_PREVIOUS) - c->last_match = list_prev_entry (c->last_match, &c->completion_list, node); - - /* Now check if last_match is a match for partial. */ - if (str_comp (sbuf_get (c->last_match), c->partial, strlen (c->partial))) - return sbuf_get (c->last_match); - } - - if (c->last_match == NULL) - return NULL; - - /* Depending on the direction, find our "next" match. */ - if (direction == COMPLETION_NEXT) - return completions_next_match (c); - - /* Otherwise get the previous match */ - return completions_prev_match (c); -} diff --git a/src/completions.h b/src/completions.h deleted file mode 100644 index d3c44af..0000000 --- a/src/completions.h +++ /dev/null @@ -1,28 +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 - */ - -#ifndef _RATPOISON_COMPLETIONS_H -#define _RATPOISON_COMPLETIONS_H 1 - -char *completions_complete (rp_completions *c, char *partial, int direction); -rp_completions *completions_new (completion_fn list_fn); -void completions_free (rp_completions *c); - -#endif /* ! _RATPOISON_COMPLETIONS_H */ diff --git a/src/conf.h b/src/conf.h deleted file mode 100644 index 708b688..0000000 --- a/src/conf.h +++ /dev/null @@ -1,134 +0,0 @@ -/* Config file for ratpoison. Edit these values and recompile. - * 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 - */ - -#ifndef _RATPOISON_CONF_H -#define _RATPOISON_CONF_H 1 - -#include "data.h" -#include "actions.h" - -#define KEY_PREFIX XK_t -#define MODIFIER_PREFIX RP_CONTROL_MASK - -/* This is the abort key when typing input. */ -#define INPUT_ABORT_KEY XK_g -#define INPUT_ABORT_MODIFIER RP_CONTROL_MASK - -/* This is the previous history entry key when typing input. */ -#define INPUT_PREV_HISTORY_KEY XK_p -#define INPUT_PREV_HISTORY_MODIFIER RP_CONTROL_MASK - -/* This is the next history entry key when typing input. */ -#define INPUT_NEXT_HISTORY_KEY XK_n -#define INPUT_NEXT_HISTORY_MODIFIER RP_CONTROL_MASK - -/* Key used to enlarge frame vertically when in resize mode. */ -#define RESIZE_VGROW_KEY XK_n -#define RESIZE_VGROW_MODIFIER RP_CONTROL_MASK - -/* Key used to shrink frame vertically when in resize mode. */ -#define RESIZE_VSHRINK_KEY XK_p -#define RESIZE_VSHRINK_MODIFIER RP_CONTROL_MASK - -/* Key used to enlarge frame horizontally when in resize mode. */ -#define RESIZE_HGROW_KEY XK_f -#define RESIZE_HGROW_MODIFIER RP_CONTROL_MASK - -/* Key used to shrink frame horizontally when in resize mode. */ -#define RESIZE_HSHRINK_KEY XK_b -#define RESIZE_HSHRINK_MODIFIER RP_CONTROL_MASK - -/* Key used to shrink frame to fit it's current window. */ -#define RESIZE_SHRINK_TO_WINDOW_KEY XK_s -#define RESIZE_SHRINK_TO_WINDOW_MODIFIER 0 - -/* Key used to exit resize mode. */ -#define RESIZE_END_KEY XK_Return -#define RESIZE_END_MODIFIER 0 - -/* Number of history items to store. */ -#define INPUT_MAX_HISTORY 50 - -/* Treat windows with maxsize hints as if they were a transient window - (don't hide the windows underneath, and center them) */ -#define MAXSIZE_WINDOWS_ARE_TRANSIENTS - -/* Treat windows with aspect hints as if they were a transient window - (don't hide the windows underneath, and center them) */ -#define ASPECT_WINDOWS_ARE_TRANSIENTS - -/* An alias command could recursively call inself infinitely. This - stops that behavior. */ -#define MAX_ALIAS_RECURSIVE_DEPTH 16 - -/* Pressing a key sends the mouse to the bottom right corner. This - doesn't work very well yet. */ -/* #define HIDE_MOUSE */ - -/* When the last window closes, quit ratpoison. */ -/* #define AUTO_CLOSE */ - -/* If for some sick reason you don't want ratpoison to manage a - window, put its name in this list. These windows get drawn but - ratpoison won't have any knowledge of them and you won't be able to - jump to them or give them keyboard focus. This has been added - mostly for use with hand-helds. */ -#define UNMANAGED_WINDOW_LIST "xapm","xclock","xscribble" - -/* Maximum depth of a link. Used in the 'link' command. */ -#define MAX_LINK_DEPTH 16 - -/* Bad window messages can be safely ignored now that ratpoison has - become stable enough. Comment this line if you wish to be notified - about bad window messages. */ -#define IGNORE_BADWINDOW 1 - -/* This is the name of the first group that is created. */ -#define DEFAULT_GROUP_NAME "default" - -/* Maximum allowed history size */ -#define MAX_HISTORY_SIZE 100 - -/* The default filename in which to store the history */ -#define HISTORY_FILE ".ratpoison_history" - -/* Use a visual bell in the input window */ -#define VISUAL_BELL 1 - -/* The name of the root keymap */ -#define ROOT_KEYMAP "root" - -/* The name of the top level keymap */ -#define TOP_KEYMAP "top" - -/* The default font */ -#define DEFAULT_FONT "-*-fixed-bold-r-normal-*-15-*-*-*-c-*-*-*" -#define BACKUP_FONT "*" - -#define DEFAULT_XFT_FONT "Mono-11" - -/* maximum xvsprintf result string length for systems with pre-C99 snprintf: - * on errors that are either permanent or cannot be distinguished from those - * as libc's snprintf might by returning -1 for too small buffers, at most - * the double of this value is tried before giving up */ -#define MAX_LEGACY_SNPRINTF_SIZE 102400 - -#endif /* !_ _RATPOISON_CONF_H */ diff --git a/src/data.h b/src/data.h deleted file mode 100644 index 2be9a98..0000000 --- a/src/data.h +++ /dev/null @@ -1,392 +0,0 @@ -/* our datatypes and global variables - * 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 - */ - -#ifndef _RATPOISON_DATA_H -#define _RATPOISON_DATA_H - -#include "linkedlist.h" -#include "number.h" - -#include <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -#ifdef USE_XFT_FONT -#include <X11/Xft/Xft.h> -#endif - -typedef struct rp_window rp_window; -typedef struct rp_screen rp_screen; -typedef struct rp_action rp_action; -typedef struct rp_keymap rp_keymap; -typedef struct rp_frame rp_frame; -typedef struct rp_child_info rp_child_info; -typedef struct rp_group rp_group; -typedef struct rp_window_elem rp_window_elem; -typedef struct rp_completions rp_completions; -typedef struct rp_input_line rp_input_line; - -struct rp_frame -{ - int number; - int x, y, width, height; - - /* The number of the window that is focused in this frame. */ - int win_number; - - /* For determining the last frame. */ - int last_access; - - /* Boolean that is set when a frame is - `dedicated' (a.k.a. glued) to one window. */ - unsigned int dedicated; - - struct list_head node; -}; - -struct rp_window -{ - rp_screen *scr; - Window w; - int state; - int last_access; - int named; - - /* A number uniquely identifying this window. This is a different - number than the one given to it by the group it is in. This - number is used for internal purposes, whereas the group number is - what the user sees. */ - int number; - - /* Window name hints. */ - char *user_name; - char *wm_name; - char *res_name; - char *res_class; - - /* Dimensions */ - int x, y, width, height, border; - - /* WM Hints */ - XSizeHints *hints; - - /* Colormap */ - Colormap colormap; - - /* Is this a transient window? */ - int transient; - Window transient_for; - - /* Saved mouse position */ - int mouse_x, mouse_y; - - /* The alignment of the window. Decides to what side or corner the - window sticks to. */ - int gravity; - - /* A window can be visible inside a frame but not the frame's - current window. This keeps track of what frame the window was - mapped into. */ - int frame_number; - - /* Sometimes a window is intended for a certain frame. When a window - is mapped and this is >0 then use the frame (if it exists). */ - int intended_frame_number; - - struct list_head node; -}; - -struct rp_window_elem -{ - rp_window *win; - int number; - struct list_head node; -}; - -/* An rp_group is a group of windows. By default all windows are added - to the same group. But a new group can be created. All new windows - will be part of this new current group. The windows of any other - group may be visible in another frame, but will not show up in the - window list and will not be accessible with select, next, or - prev. These window navigation commands only navigate the current - group. */ -struct rp_group -{ - /* The name and number of this group. This is to allow the user to - quickly jump to the desired group. */ - char *name; - int number; - - /* For determining the last group. */ - int last_access; - - /* The list of windows participating in this group. */ - struct list_head mapped_windows, unmapped_windows; - - /* This numset is responsible for giving out numbers for each window - in the group. */ - struct numset *numset; - - /* This structure can exist in a list. */ - struct list_head node; -}; - -struct rp_screen -{ - GC normal_gc, inverse_gc; - Window root, bar_window, key_window, input_window, frame_window, help_window; - int bar_is_raised; - int screen_num; /* Our screen number as dictated my X */ - int xine_screen_num; /* Our screen number for the Xinerama extension */ - Colormap def_cmap; - Cursor rat; - unsigned long fg_color, bg_color, fw_color, bw_color; /* The pixel color. */ - - /* Here to abstract over the Xinerama vs X screens difference */ - int left, top, width, height; - - char *display_string; - - /* A list of frames that may or may not contain windows. There should - always be one in the list. */ - struct list_head frames; - - /* Keep track of which numbers have been given to frames. */ - struct numset *frames_numset; - - /* The number of the currently focused frame. One for each screen so - when you switch screens the focus doesn't get frobbed. */ - int current_frame; - -#ifdef USE_XFT_FONT - XftFont *xft_font; - XftColor xft_fg_color, xft_bg_color; -#endif -}; - -struct rp_action -{ - KeySym key; - unsigned int state; - char *data; /* misc data to be passed to the function */ -/* void (*func)(void *); */ -}; - -struct rp_keymap -{ - char *name; - rp_action *actions; - int actions_last; - int actions_size; - - /* This structure can be part of a list. */ - struct list_head node; -}; - -struct rp_key -{ - KeySym sym; - unsigned int state; -}; - -struct rp_defaults -{ - /* Default positions for new normal windows, transient windows, and - normal windows with maxsize hints. */ - int win_gravity; - int trans_gravity; - int maxsize_gravity; - - int input_window_size; - int window_border_width; - - int bar_x_padding; - int bar_y_padding; - int bar_location; - int bar_timeout; - int bar_border_width; - int bar_in_padding; - - int frame_indicator_timeout; - int frame_resize_unit; - - int padding_left; - int padding_right; - int padding_top; - int padding_bottom; - - XFontSet font; - char *font_string; - int utf8_locale; - - char *fgcolor_string; - char *bgcolor_string; - char *fwcolor_string; - char *bwcolor_string; - - int wait_for_key_cursor; - - char *window_fmt; - char *info_fmt; - - /* Which name to use: wm_name, res_name, res_class. */ - int win_name; - - int startup_message; - - /* Decides whether the window list is displayed in a row or a - column. */ - int window_list_style; - - /* Pointer warping toggle. */ - int warp; - - int history_size; - /* remove older history when adding the same again */ - int history_compaction; - /* expand ! when compiled with libhistory */ - int history_expansion; - - char *frame_selectors; - - /* How many frame sets to remember when undoing. */ - int maxundos; - - /* The name of the top level keymap */ - char *top_kmap; - - /* Frame indicator format */ - char *frame_fmt; -}; - -/* Information about a child process. */ -struct rp_child_info -{ - /* The command that was executed. */ - char *cmd; - - /* PID of the process. */ - int pid; - - /* Return status when the child process finished. */ - int status; - - /* When this is != 0 then the process finished. */ - int terminated; - - /* what was current when it was launched? */ - rp_group *group; - rp_frame *frame; - rp_screen *screen; - - /* Non-zero when the pid has mapped a window. This is to prevent - every window the program opens from getting mapped in the frame - it was launched from. Only the first window should do this. */ - int window_mapped; - - /* This structure can exist in a list. */ - struct list_head node; -}; - -/* These defines should be used to specify the modifier mask for keys - and they are translated into the X11 modifier mask when the time - comes to compare modifier masks. */ -#define RP_SHIFT_MASK 1 -#define RP_CONTROL_MASK 2 -#define RP_META_MASK 4 -#define RP_ALT_MASK 8 -#define RP_SUPER_MASK 16 -#define RP_HYPER_MASK 32 - -struct modifier_info -{ -/* unsigned int mode_switch_mask; */ - unsigned int meta_mod_mask; - unsigned int alt_mod_mask; - unsigned int super_mod_mask; - unsigned int hyper_mod_mask; - - /* Keep track of these because they mess up the grab and should be - ignored. */ - unsigned int num_lock_mask; - unsigned int scroll_lock_mask; -}; - -typedef struct list_head *(*completion_fn)(char *string); - -struct rp_completions -{ - /* A pointer to the partial string that is being completed. We need - to store this so that the user can cycle through all possible - completions. */ - char *partial; - - /* A pointer to the string that was last matched string. Used to - keep track of where we are in the completion list. */ - struct sbuf *last_match; - - /* A list of sbuf's which are possible completions. */ - struct list_head completion_list; - - /* The function that generates the completions. */ - completion_fn complete_fn; - - /* virgin = 1 means no completions have been attempted on the input - string. */ - unsigned short int virgin; -}; - -struct rp_input_line -{ - char *buffer; - char *prompt; - char *saved; - int position; - int length; - int size; - rp_completions *compl; - Atom selection; - int history_id; -}; - -/* The hook dictionary. */ -struct rp_hook_db_entry -{ - char *name; - struct list_head *hook; -}; - -typedef struct rp_frame_undo rp_frame_undo; -struct rp_frame_undo -{ - char *frames; - rp_screen *screen; - struct list_head node; -}; - -typedef struct rp_xselection rp_xselection; -struct rp_xselection -{ - char *text; - int len; -}; - -#endif /* _RATPOISON_DATA_H */ diff --git a/src/editor.c b/src/editor.c deleted file mode 100644 index 6c17754..0000000 --- a/src/editor.c +++ /dev/null @@ -1,580 +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 <ctype.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <X11/Xlib.h> -#include <X11/keysym.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> - -#include "ratpoison.h" - -/* bind functions */ -static edit_status editor_forward_char (rp_input_line *line); -static edit_status editor_backward_char (rp_input_line *line); -static edit_status editor_forward_word (rp_input_line *line); -static edit_status editor_backward_word (rp_input_line *line); -static edit_status editor_beginning_of_line (rp_input_line *line); -static edit_status editor_end_of_line (rp_input_line *line); -static edit_status editor_delete_char (rp_input_line *line); -static edit_status editor_backward_delete_char (rp_input_line *line); -static edit_status editor_kill_word (rp_input_line *line); -static edit_status editor_backward_kill_word (rp_input_line *line); -static edit_status editor_kill_line (rp_input_line *line); -static edit_status editor_paste_selection (rp_input_line *line); -static edit_status editor_abort (rp_input_line *line); -static edit_status editor_no_action (rp_input_line *line); -static edit_status editor_enter (rp_input_line *line); -static edit_status editor_history_previous (rp_input_line *line); -static edit_status editor_history_next (rp_input_line *line); -static edit_status editor_backward_kill_line (rp_input_line *line); -static edit_status editor_complete_prev (rp_input_line *line); -static edit_status editor_complete_next (rp_input_line *line); - -/* default edit action */ -static edit_status editor_insert (rp_input_line *line, char *keysym_buf); - - -static char *saved_command = NULL; - -typedef struct edit_binding edit_binding; - -struct edit_binding -{ - struct rp_key key; - edit_status (*func)(rp_input_line *); -}; - -static edit_binding edit_bindings[] = - { {{XK_g, RP_CONTROL_MASK}, editor_abort}, - {{XK_Escape, 0}, editor_abort}, - {{XK_f, RP_CONTROL_MASK}, editor_forward_char}, - {{XK_Right, 0}, editor_forward_char}, - {{XK_b, RP_CONTROL_MASK}, editor_backward_char}, - {{XK_Left, 0}, editor_backward_char}, - {{XK_f, RP_META_MASK}, editor_forward_word}, - {{XK_b, RP_META_MASK}, editor_backward_word}, - {{XK_a, RP_CONTROL_MASK}, editor_beginning_of_line}, - {{XK_Home, 0}, editor_beginning_of_line}, - {{XK_e, RP_CONTROL_MASK}, editor_end_of_line}, - {{XK_End, 0}, editor_end_of_line}, - {{XK_d, RP_CONTROL_MASK}, editor_delete_char}, - {{XK_Delete, 0}, editor_delete_char}, - {{XK_BackSpace, 0}, editor_backward_delete_char}, - {{XK_h, RP_CONTROL_MASK}, editor_backward_delete_char}, - {{XK_BackSpace, RP_META_MASK}, editor_backward_kill_word}, - {{XK_d, RP_META_MASK}, editor_kill_word}, - {{XK_k, RP_CONTROL_MASK}, editor_kill_line}, - {{XK_u, RP_CONTROL_MASK}, editor_backward_kill_line}, - {{XK_y, RP_CONTROL_MASK}, editor_paste_selection}, - {{XK_p, RP_CONTROL_MASK}, editor_history_previous}, - {{XK_Up, 0}, editor_history_previous}, - {{XK_n, RP_CONTROL_MASK}, editor_history_next}, - {{XK_Down, 0}, editor_history_next}, - {{XK_Return, 0}, editor_enter}, - {{XK_m, RP_CONTROL_MASK}, editor_enter}, - {{XK_KP_Enter, 0}, editor_enter}, - {{XK_Tab, 0}, editor_complete_next}, - {{XK_ISO_Left_Tab, 0}, editor_complete_prev}, - { {0, 0}, 0} }; - -rp_input_line * -input_line_new (char *prompt, char *preinput, int history_id, completion_fn fn) -{ - rp_input_line *line; - - line = xmalloc (sizeof (rp_input_line)); - line->prompt = prompt; - line->compl = completions_new (fn); - line->history_id = history_id; - - /* Allocate some memory to start with */ - line->size = strlen (preinput) + 100; - line->buffer = (char *) xmalloc (line->size); - - /* load in the preinput */ - strcpy (line->buffer, preinput); - line->position = line->length = strlen (preinput); - - return line; -} - -void -input_line_free (rp_input_line *line) -{ - completions_free (line->compl); - free (line->buffer); - free (line); -} - -edit_status -execute_edit_action (rp_input_line *line, KeySym ch, unsigned int modifier, char *keysym_buf) -{ - struct edit_binding *binding = NULL; - int found_binding = 0; - edit_status status; - - for (binding = edit_bindings; binding->func; binding++) - { - if (ch == binding->key.sym && modifier == binding->key.state) - { - found_binding = 1; - break; - } - } - - if (found_binding) - status = binding->func (line); - else if (modifier) - status = editor_no_action (line); - else - status = editor_insert (line, keysym_buf); - - return status; -} - -static edit_status -editor_forward_char (rp_input_line *line) -{ - if (line->position == line->length) - return EDIT_NO_OP; - - if (RP_IS_UTF8_START (line->buffer[line->position])) - { - do - line->position++; - while (RP_IS_UTF8_CONT (line->buffer[line->position])); - } - else - line->position++; - - return EDIT_MOVE; -} - -static edit_status -editor_backward_char (rp_input_line *line) -{ - if (line->position == 0) - return EDIT_NO_OP; - - do - line->position--; - while (line->position > 0 && RP_IS_UTF8_CONT (line->buffer[line->position])); - - return EDIT_MOVE; -} - -static edit_status -editor_forward_word (rp_input_line *line) -{ - if (line->position == line->length) - return EDIT_NO_OP; - - while (line->position < line->length - && !isalnum (line->buffer[line->position])) - line->position++; - - while (line->position < line->length - && (isalnum (line->buffer[line->position]) - || RP_IS_UTF8_CHAR (line->buffer[line->position]))) - line->position++; - - return EDIT_MOVE; -} - -static edit_status -editor_backward_word (rp_input_line *line) -{ - if (line->position == 0) - return EDIT_NO_OP; - - while (line->position > 0 && !isalnum (line->buffer[line->position])) - line->position--; - - while (line->position > 0 - && (isalnum (line->buffer[line->position]) - || RP_IS_UTF8_CHAR (line->buffer[line->position]))) - line->position--; - - return EDIT_MOVE; -} - -static edit_status -editor_beginning_of_line (rp_input_line *line) -{ - if (line->position == 0) - return EDIT_NO_OP; - else - { - line->position = 0; - return EDIT_MOVE; - } -} - -static edit_status -editor_end_of_line (rp_input_line *line) -{ - if (line->position == line->length) - return EDIT_NO_OP; - else - { - line->position = line->length; - return EDIT_MOVE; - } -} - -static edit_status -editor_delete_char (rp_input_line *line) -{ - size_t diff = 0; - - if (line->position == line->length) - return EDIT_NO_OP; - - if (RP_IS_UTF8_START (line->buffer[line->position])) - { - do - diff++; - while (RP_IS_UTF8_CONT (line->buffer[line->position + diff])); - } - else - diff++; - - memmove (&line->buffer[line->position], - &line->buffer[line->position + diff], - line->length - line->position + diff + 1); - - line->length -= diff; - - return EDIT_DELETE; -} - -static edit_status -editor_backward_delete_char (rp_input_line *line) -{ - size_t diff = 1; - - if (line->position == 0) - return EDIT_NO_OP; - - while (line->position - diff > 0 - && RP_IS_UTF8_CONT (line->buffer[line->position - diff])) - diff++; - - memmove (&line->buffer[line->position - diff], - &line->buffer[line->position], - line->length - line->position + 1); - - line->position -= diff; - line->length -= diff; - - return EDIT_DELETE; -} - -static edit_status -editor_kill_word (rp_input_line *line) -{ - size_t diff = 0; - - if (line->position == line->length) - return EDIT_NO_OP; - - while (line->position + diff < line->length && - !isalnum (line->buffer[line->position + diff])) - diff++; - - while (line->position + diff < line->length - && (isalnum (line->buffer[line->position + diff]) - || RP_IS_UTF8_CHAR (line->buffer[line->position + diff]))) - diff++; - - /* Add the word to the X11 selection. */ - set_nselection (&line->buffer[line->position], diff); - - memmove (&line->buffer[line->position], - &line->buffer[line->position + diff], - line->length - line->position + diff + 1); - - line->length -= diff; - - return EDIT_DELETE; -} - -static edit_status -editor_backward_kill_word (rp_input_line *line) -{ - size_t diff = 1; - - if (line->position == 0) - return EDIT_NO_OP; - - while (line->position - diff > 0 && - !isalnum (line->buffer[line->position - diff])) - diff++; - - while (line->position - diff > 0 - && (isalnum (line->buffer[line->position - diff]) - || RP_IS_UTF8_CHAR (line->buffer[line->position - diff]))) - diff++; - - /* Add the word to the X11 selection. */ - set_nselection (&line->buffer[line->position - diff], diff); - - memmove (&line->buffer[line->position - diff], - &line->buffer[line->position], - line->length - line->position + 1); - - line->position -= diff; - line->length -= diff; - - return EDIT_DELETE; -} - -static edit_status -editor_kill_line (rp_input_line *line) -{ - if (line->position == line->length) - return EDIT_NO_OP; - - /* Add the line to the X11 selection. */ - set_selection (&line->buffer[line->position]); - - line->length = line->position; - line->buffer[line->length] = '\0'; - - return EDIT_DELETE; -} - -/* Do the dirty work of killing a line backwards. */ -static void -backward_kill_line (rp_input_line *line) -{ - memmove (&line->buffer[0], - &line->buffer[line->position], - line->length - line->position + 1); - - line->length -= line->position; - line->position = 0; -} - -static edit_status -editor_backward_kill_line (rp_input_line *line) -{ - if (line->position == 0) - return EDIT_NO_OP; - - /* Add the line to the X11 selection. */ - set_nselection (line->buffer, line->position); - - backward_kill_line (line); - - return EDIT_DELETE; -} - -static edit_status -editor_history_previous (rp_input_line *line) -{ - const char *entry = history_previous (line->history_id); - - if (entry) - { - if (!saved_command) - { - line->buffer[line->length] = '\0'; - saved_command = xstrdup (line->buffer); - PRINT_DEBUG (("saved current command line: \'%s\'\n", saved_command)); - } - - free (line->buffer); - line->buffer = xstrdup (entry); - line->length = strlen (line->buffer); - line->size = line->length + 1; - line->position = line->length; - PRINT_DEBUG (("entry: \'%s\'\n", line->buffer)); - } - else - { - PRINT_DEBUG (("- do nothing -\n")); - return EDIT_NO_OP; - } - - return EDIT_INSERT; -} - -static edit_status -editor_history_next (rp_input_line *line) -{ - const char *entry = history_next (line->history_id); - - if (entry) - { - free (line->buffer); - line->buffer = xstrdup (entry); - PRINT_DEBUG (("entry: \'%s\'\n", line->buffer)); - } - else if (saved_command) - { - free (line->buffer); - line->buffer = saved_command; - saved_command = NULL; - PRINT_DEBUG (("restored command line: \'%s\'\n", line->buffer)); - } - else - { - PRINT_DEBUG (("- do nothing -\n")); - return EDIT_NO_OP; - } - - line->length = strlen (line->buffer); - line->size = line->length + 1; - line->position = line->length; - - return EDIT_INSERT; -} - -static edit_status -editor_abort (rp_input_line *line UNUSED) -{ - return EDIT_ABORT; -} - -static edit_status -editor_no_action (rp_input_line *line UNUSED) -{ - return EDIT_NO_OP; -} - -static edit_status -editor_insert (rp_input_line *line, char *keysym_buf) -{ - size_t nbytes; - - PRINT_DEBUG (("keysym_buf: '%s'\n", keysym_buf)); - - nbytes = strlen (keysym_buf); - if (line->length + nbytes > line->size - 1) - { - /* FIXME: This seems like a very bad idea. */ - line->size += nbytes + 100; - line->buffer = xrealloc (line->buffer, line->size); - } - - memmove (&line->buffer[line->position + nbytes], - &line->buffer[line->position], - line->length - line->position + 1); - memcpy (&line->buffer[line->position], keysym_buf, nbytes); - - line->length += nbytes; - line->position += nbytes; - - return EDIT_INSERT; -} - -static edit_status -editor_enter (rp_input_line *line) -{ - int result; - char *expansion; - - line->buffer[line->length] = '\0'; - - if (!defaults.history_expansion) { - history_add (line->history_id, line->buffer); - return EDIT_DONE; - } - - result = history_expand_line (line->history_id, line->buffer, &expansion); - - PRINT_DEBUG (("History Expansion - result: %d\n", result)); - PRINT_DEBUG (("History Expansion - expansion: \'%s\'\n", expansion)); - - if (result == -1 || result == 2) - { - marked_message_printf (0, 0, "%s", expansion); - free (expansion); - return EDIT_ABORT; - } - else /* result == 0 || result == 1 */ - { - history_add (line->history_id, expansion); - free (line->buffer); - line->buffer = expansion; - } - - return EDIT_DONE; -} - -static edit_status -editor_paste_selection (rp_input_line *line) -{ - char *text; - text = get_selection(); - if (text) - { - editor_insert(line, text); - free (text); - return EDIT_INSERT; - } - else - return EDIT_NO_OP; -} - -static edit_status -editor_complete (rp_input_line *line, int direction) -{ - char *tmp; - char *s; - - /* Create our partial string that will be used for completion. It is - the characters up to the position of the cursor. */ - tmp = xmalloc ((line->position + 1) * sizeof (char)); - strncpy (tmp, line->buffer, line->position); - tmp[line->position] = '\0'; - - /* We don't need to free s because it's a string from the completion - list. */ - s = completions_complete (line->compl, tmp, direction); - free (tmp); - - if (s == NULL) - return EDIT_NO_OP; - - /* Insert the completion. */ - backward_kill_line (line); - editor_insert (line, s); - - return EDIT_COMPLETE; -} - -static edit_status -editor_complete_next (rp_input_line *line) -{ - return editor_complete (line, COMPLETION_NEXT); -} - -static edit_status -editor_complete_prev (rp_input_line *line) -{ - return editor_complete (line, COMPLETION_PREVIOUS); -} diff --git a/src/editor.h b/src/editor.h deleted file mode 100644 index b6e4b76..0000000 --- a/src/editor.h +++ /dev/null @@ -1,49 +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 - */ - -#ifndef _RATPOISON_EDITOR_H -#define _RATPOISON_EDITOR_H 1 - -typedef enum edit_status edit_status; - -enum -edit_status -{ - EDIT_INSERT, - EDIT_DELETE, - EDIT_MOVE, - EDIT_COMPLETE, - EDIT_ABORT, - EDIT_DONE, - EDIT_NO_OP -}; - -/* UTF-8 handling macros */ -#define RP_IS_UTF8_CHAR(c) (defaults.utf8_locale && (c) & 0xC0) -#define RP_IS_UTF8_START(c) (defaults.utf8_locale && ((c) & 0xC0) == 0xC0) -#define RP_IS_UTF8_CONT(c) (defaults.utf8_locale && ((c) & 0xC0) == 0x80) - -/* Input line functions */ -rp_input_line *input_line_new (char *prompt, char *preinput, int history_id, completion_fn fn); -void input_line_free (rp_input_line *line); - -edit_status execute_edit_action (rp_input_line *line, KeySym ch, unsigned int modifier, char *keysym_buf); - -#endif /* ! _RATPOISON_EDITOR_H */ diff --git a/src/events.c b/src/events.c deleted file mode 100644 index 37bfc01..0000000 --- a/src/events.c +++ /dev/null @@ -1,1012 +0,0 @@ -/* Ratpoison X events - * 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 <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/keysym.h> -#include <X11/Xmd.h> /* for CARD32. */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <signal.h> -#include <errno.h> -#include <unistd.h> -#include <sys/time.h> -#include <sys/wait.h> - -#include "ratpoison.h" - -/* The event currently being processed. Mostly used in functions from - action.c which need to forward events to other windows. */ -XEvent rp_current_event; - -/* RAISED is non zero if a raised message should be used 0 for a map message. */ -void -show_rudeness_msg (rp_window *win, int raised) -{ - rp_group *g = groups_find_group_by_window (win); - rp_window_elem *elem = group_find_window (&g->mapped_windows, win); - if (g == rp_current_group) - { - if (win->transient) - marked_message_printf (0, 0, raised ? MESSAGE_RAISE_TRANSIENT:MESSAGE_MAP_TRANSIENT, - elem->number, window_name (win)); - else - marked_message_printf (0, 0, raised ? MESSAGE_RAISE_WINDOW:MESSAGE_MAP_WINDOW, - elem->number, window_name (win)); - } - else - { - if (win->transient) - marked_message_printf (0, 0, raised ? MESSAGE_RAISE_TRANSIENT_GROUP:MESSAGE_MAP_TRANSIENT_GROUP, - elem->number, window_name (win), g->name); - else - marked_message_printf (0, 0, raised ? MESSAGE_RAISE_WINDOW_GROUP:MESSAGE_MAP_WINDOW_GROUP, - elem->number, window_name (win), g->name); - } -} - -static void -new_window (XCreateWindowEvent *e) -{ - rp_window *win; - rp_screen *s; - - if (e->override_redirect) - return; - - win = find_window (e->window); - - /* In Xinerama mode, all windows have the same root, so check - * all Xinerama screens - */ - if (rp_have_xinerama) - { - /* New windows belong to the current screen */ - s = &screens[rp_current_screen]; - } - else - { - s = find_screen (e->parent); - } - if (is_rp_window_for_screen(e->window, s)) return; - - if (s && win == NULL - && e->window != s->key_window - && e->window != s->bar_window - && e->window != s->input_window - && e->window != s->frame_window - && e->window != s->help_window) - { - win = add_to_window_list (s, e->window); - update_window_information (win); - } -} - -static void -unmap_notify (XEvent *ev) -{ - rp_frame *frame; - rp_window *win; - - /* ignore SubstructureNotify unmaps. */ - if(ev->xunmap.event != ev->xunmap.window - && ev->xunmap.send_event != True) - return; - - /* FIXME: Should we only look in the mapped window list? */ - win = find_window_in_list (ev->xunmap.window, &rp_mapped_window); - - if (win == NULL) - return; - - switch (win->state) - { - case IconicState: - PRINT_DEBUG (("Withdrawing iconized window '%s'\n", window_name (win))); - if (ev->xunmap.send_event) withdraw_window (win); - break; - case NormalState: - PRINT_DEBUG (("Withdrawing normal window '%s'\n", window_name (win))); - /* If the window was inside a frame, fill the frame with another - window. */ - frame = find_windows_frame (win); - if (frame) - { - cleanup_frame (frame); - if (frame->number == win->scr->current_frame - && current_screen() == win->scr) - set_active_frame (frame, 0); - /* Since we may have switched windows, call the hook. */ - if (frame->win_number != EMPTY) - hook_run (&rp_switch_win_hook); - } - - withdraw_window (win); - break; - } - - update_window_names (win->scr, defaults.window_fmt); -} - -static void -map_request (XEvent *ev) -{ - rp_window *win; - - win = find_window (ev->xmap.window); - if (win == NULL) - { - PRINT_DEBUG (("Map request from an unknown window.\n")); - XMapWindow (dpy, ev->xmap.window); - return; - } - - PRINT_DEBUG (("Map request from a managed window\n")); - - switch (win->state) - { - case WithdrawnState: - if (unmanaged_window (win->w)) - { - PRINT_DEBUG (("Mapping Unmanaged Window\n")); - XMapWindow (dpy, win->w); - break; - } - else - { - PRINT_DEBUG (("Mapping Withdrawn Window\n")); - map_window (win); - break; - } - break; - case IconicState: - PRINT_DEBUG (("Mapping Iconic window\n")); - if (win->last_access == 0) - { - /* Depending on the rudeness level, actually map the - window. */ - if ((rp_honour_transient_map && win->transient) - || (rp_honour_normal_map && !win->transient)) - set_active_window (win); - } - else - { - /* Depending on the rudeness level, actually map the - window. */ - if ((rp_honour_transient_raise && win->transient) - || (rp_honour_normal_raise && !win->transient)) - set_active_window (win); - else - show_rudeness_msg (win, 1); - } - break; - } -} - -static void -destroy_window (XDestroyWindowEvent *ev) -{ - rp_window *win; - - win = find_window (ev->window); - if (win == NULL) return; - - 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 - && current_screen() == win->scr) - set_active_frame (frame, 0); - /* Since we may have switched windows, call the hook. */ - if (frame->win_number != EMPTY) - hook_run (&rp_switch_win_hook); - } - 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--; -} - -static void -configure_request (XConfigureRequestEvent *e) -{ - XWindowChanges changes; - rp_window *win; - - win = find_window (e->window); - - if (win) - { - if (e->value_mask & CWStackMode) - { - if (e->detail == Above && win->state != WithdrawnState) - { - /* Depending on the rudeness level, actually map the - window. */ - if ((rp_honour_transient_raise && win->transient) - || (rp_honour_normal_raise && !win->transient)) - { - if (win->state == IconicState) - set_active_window (win); - else if (find_windows_frame (win)) - goto_window (win); - } - else if (current_window() != win) - { - show_rudeness_msg (win, 1); - } - - } - - PRINT_DEBUG(("request CWStackMode %d\n", e->detail)); - } - - PRINT_DEBUG (("'%s' window size: %d %d %d %d %d\n", window_name (win), - win->x, win->y, win->width, win->height, win->border)); - - /* Collect the changes to be granted. */ - if (e->value_mask & CWBorderWidth) - { - changes.border_width = e->border_width; - win->border = e->border_width; - PRINT_DEBUG(("request CWBorderWidth %d\n", e->border_width)); - } - - if (e->value_mask & CWWidth) - { - changes.width = e->width; - win->width = e->width; - PRINT_DEBUG(("request CWWidth %d\n", e->width)); - } - - if (e->value_mask & CWHeight) - { - changes.height = e->height; - win->height = e->height; - PRINT_DEBUG(("request CWHeight %d\n", e->height)); - } - - if (e->value_mask & CWX) - { - changes.x = e->x; - win->x = e->x; - PRINT_DEBUG(("request CWX %d\n", e->x)); - } - - if (e->value_mask & CWY) - { - changes.y = e->y; - win->y = e->y; - PRINT_DEBUG(("request CWY %d\n", e->y)); - } - - if (e->value_mask & (CWX|CWY|CWBorderWidth|CWWidth|CWHeight)) - { - /* Grant the request, then immediately maximize it. */ - XConfigureWindow (dpy, win->w, - e->value_mask & (CWX|CWY|CWBorderWidth|CWWidth|CWHeight), - &changes); - XSync(dpy, False); - if (win->state == NormalState) - maximize (win); - } - } - else - { - /* Its an unmanaged window, so give it what it wants. But don't - change the stack mode.*/ - if (e->value_mask & CWX) changes.x = e->x; - if (e->value_mask & CWY) changes.x = e->x; - if (e->value_mask & CWWidth) changes.x = e->x; - if (e->value_mask & CWHeight) changes.x = e->x; - if (e->value_mask & CWBorderWidth) changes.x = e->x; - XConfigureWindow (dpy, e->window, - e->value_mask & (CWX|CWY|CWBorderWidth|CWWidth|CWHeight), - &changes); - } -} - -static void -client_msg (XClientMessageEvent *ev) -{ - PRINT_DEBUG (("Received client message.\n")); - - if (ev->message_type == wm_change_state) - { - rp_window *win; - - PRINT_DEBUG (("WM_CHANGE_STATE\n")); - - win = find_window (ev->window); - if (win == NULL) return; - if (ev->format == 32 && ev->data.l[0] == IconicState) - { - /* FIXME: This means clients can hide themselves without the - user's intervention. This is bad, but Emacs is the only - program I know of that iconifies itself and this is - generally from the user pressing C-z. */ - PRINT_DEBUG (("Iconify Request.\n")); - if (win->state == NormalState) - { - rp_window *w = find_window_other(win->scr); - - if (w) - set_active_window (w); - else - blank_frame (screen_get_frame (win->scr, win->scr->current_frame)); - } - } - else - { - PRINT_ERROR (("Non-standard WM_CHANGE_STATE format\n")); - } - } -} - -static void -handle_key (KeySym ks, unsigned int mod, rp_screen *s) -{ - rp_action *key_action; - rp_keymap *map = find_keymap (defaults.top_kmap); - - if (map == NULL) - { - PRINT_ERROR (("Unable to find %s keymap\n", defaults.top_kmap)); - return; - } - - PRINT_DEBUG (("handling key...\n")); - - /* All functions hide the program bar and the frame indicator. */ - if (defaults.bar_timeout > 0) hide_bar (s); - hide_frame_indicator(); - - /* Disable any alarm that was going to go off. */ - alarm (0); - alarm_signalled = 0; - - /* Call the top level key pressed hook. */ - hook_run (&rp_key_hook); - - PRINT_DEBUG (("handle_key\n")); - - /* Read a key and execute the command associated with it on the - default keymap. Ignore the key if it doesn't have a binding. */ - if ((key_action = find_keybinding (ks, x11_mask_to_rp_mask (mod), map))) - { - cmdret *result; - - PRINT_DEBUG(("%s\n", key_action->data)); - - result = command (1, key_action->data); - - if (result) - { - if (result->output) - message (result->output); - cmdret_free (result); - } - } - else - { - PRINT_DEBUG(("Impossible: No matching key")); - } -} - -static void -key_press (XEvent *ev) -{ - rp_screen *s; - unsigned int modifier; - KeySym ks; - - if (rp_have_xinerama) - s = current_screen(); - else - s = find_screen (ev->xkey.root); - - if (!s) return; - -#ifdef HIDE_MOUSE - XWarpPointer (dpy, None, s->root, 0, 0, 0, 0, s->left + s->width - 2, s->top + s->height - 2); -#endif - - modifier = ev->xkey.state; - cook_keycode ( &ev->xkey, &ks, &modifier, NULL, 0, 1); - - handle_key (ks, modifier, s); -} - -/* Read a command off the window and execute it. Some commands return - text. This text is passed back using the RP_COMMAND_RESULT - Atom. The client will wait for this property change so something - must be returned. */ -static cmdret * -execute_remote_command (Window w) -{ - int status; - cmdret *ret; - Atom type_ret; - int format_ret; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *req; - - status = XGetWindowProperty (dpy, w, rp_command, - 0, 0, False, xa_string, - &type_ret, &format_ret, &nitems, &bytes_after, - &req); - - if (status != Success || req == NULL) - { - return cmdret_new (RET_FAILURE, "Couldn't get RP_COMMAND Property"); - } - - /* XGetWindowProperty always allocates one extra byte even if - the property is zero length. */ - XFree (req); - - status = XGetWindowProperty (dpy, w, rp_command, - 0, (bytes_after / 4) + (bytes_after % 4 ? 1 : 0), - True, xa_string, &type_ret, &format_ret, &nitems, - &bytes_after, &req); - - if (status != Success || req == NULL) - { - return cmdret_new (RET_FAILURE, "Couldn't get RP_COMMAND Property"); - } - - PRINT_DEBUG (("command: %s\n", req)); - ret = command (req[0], (char *)&req[1]); - XFree (req); - - return ret; -} - -/* Command requests are posted as a property change using the - RP_COMMAND_REQUEST Atom on the root window. A Command request is a - Window that holds the actual command as a property using the - RP_COMMAND Atom. receive_command reads the list of Windows and - executes their associated command. */ -static void -receive_command (Window root) -{ - cmdret *cmd_ret; - char *result; - Atom type_ret; - int format_ret; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *prop_return; - int offset; - - /* Init offset to 0. In the case where there is more than one window - in the property, a partial read does not delete the property and - we need to grab the next window by incementing offset to the - offset of the next window. */ - offset = 0; - do - { - int ret; - int length; - Window w; - - length = sizeof (Window) / 4 + (sizeof (Window) % 4 ?1:0); - ret = XGetWindowProperty (dpy, root, - rp_command_request, - offset, length, - True, XA_WINDOW, &type_ret, &format_ret, - &nitems, - &bytes_after, &prop_return); - - /* Update the offset to point to the next window (if there is - another one). */ - offset += length; - - if (ret != Success) - { - PRINT_ERROR (("XGetWindowProperty Failed\n")); - if (prop_return) - XFree (prop_return); - break; - } - - /* If there was no window, then we're done. */ - if (prop_return == NULL) - { - PRINT_DEBUG (("No property to read\n")); - break; - } - - /* We grabbed a window, so now read the command stored in - this window and execute it. */ - w = *(Window *)prop_return; - XFree (prop_return); - cmd_ret = execute_remote_command (w); - - /* notify the client of any text that was returned by the - command. see communications.c:receive_command_result() */ - if (cmd_ret->output) - result = xsprintf ("%c%s", cmd_ret->success ? '1':'0', cmd_ret->output); - else if (!cmd_ret->success) - result = xstrdup("0"); - else - result = NULL; - - if (result) - XChangeProperty (dpy, w, rp_command_result, xa_string, - 8, PropModeReplace, (unsigned char *)result, strlen (result)); - else - XChangeProperty (dpy, w, rp_command_result, xa_string, - 8, PropModeReplace, NULL, 0); - free (result); - cmdret_free (cmd_ret); - } while (bytes_after > 0); -} - -static void -property_notify (XEvent *ev) -{ - rp_window *win; - - PRINT_DEBUG (("atom: %ld\n", ev->xproperty.atom)); - - if (ev->xproperty.atom == rp_command_request - && is_a_root_window (ev->xproperty.window) - && ev->xproperty.state == PropertyNewValue) - { - PRINT_DEBUG (("ratpoison command\n")); - receive_command(ev->xproperty.window); - } - - win = find_window (ev->xproperty.window); - - if (win) - { - if (ev->xproperty.atom == _net_wm_pid) - { - struct rp_child_info *child_info; - - PRINT_DEBUG (("updating _NET_WM_PID\n")); - child_info = get_child_info(win->w); - if (child_info && !child_info->window_mapped) - { - if (child_info->frame) - { - PRINT_DEBUG (("frame=%p\n", child_info->frame)); - win->intended_frame_number = child_info->frame->number; - /* Only map the first window in the launch frame. */ - child_info->window_mapped = 1; - } - /* TODO: also adopt group information? */ - } - } else - switch (ev->xproperty.atom) - { - case XA_WM_NAME: - PRINT_DEBUG (("updating window name\n")); - if (update_window_name (win)) { - update_window_names (win->scr, defaults.window_fmt); - hook_run (&rp_title_changed_hook); - } - break; - - case XA_WM_NORMAL_HINTS: - PRINT_DEBUG (("updating window normal hints\n")); - update_normal_hints (win); - if (win->state == NormalState) - maximize (win); - break; - - case XA_WM_TRANSIENT_FOR: - PRINT_DEBUG (("Transient for\n")); - win->transient = XGetTransientForHint (dpy, win->w, &win->transient_for); - break; - - default: - PRINT_DEBUG (("Unhandled property notify event: %ld\n", ev->xproperty.atom)); - break; - } - } -} - -static void -colormap_notify (XEvent *ev) -{ - rp_window *win; - - win = find_window (ev->xcolormap.window); - - if (win != NULL) - { - XWindowAttributes attr; - - /* SDL sets the colormap just before destroying the window, so - ignore BadWindow errors. */ - ignore_badwindow++; - - XGetWindowAttributes (dpy, win->w, &attr); - win->colormap = attr.colormap; - - if (win == current_window() - && !current_screen()->bar_is_raised) - { - XInstallColormap (dpy, win->colormap); - } - - ignore_badwindow--; - } -} - -static void -focus_change (XFocusChangeEvent *ev) -{ - rp_window *win; - - /* We're only interested in the NotifyGrab mode */ - if (ev->mode != NotifyGrab) return; - - win = find_window (ev->window); - - if (win != NULL) - { - PRINT_DEBUG (("Re-grabbing prefix key\n")); - grab_top_level_keys (win->w); - } -} - -static void -mapping_notify (XMappingEvent *ev) -{ - ungrab_keys_all_wins(); - - switch (ev->request) - { - case MappingModifier: - update_modifier_map(); - /* This is meant to fall through. */ - case MappingKeyboard: - XRefreshKeyboardMapping (ev); - break; - } - - grab_keys_all_wins(); -} - -static void -configure_notify (XConfigureEvent *ev) -{ - rp_screen *s; - - s = find_screen(ev->window); - if (s != NULL) - /* This is a root window of a screen, - * look if its width or height changed: */ - screen_update(s,ev->width,ev->height); -} - -/* This is called whan an application has requested the - selection. Copied from rxvt. */ -static void -selection_request (XSelectionRequestEvent *rq) -{ - XEvent ev; - CARD32 target_list[4]; - Atom target; - static Atom xa_targets = None; - static Atom xa_text = None; /* XXX */ - XTextProperty ct; - XICCEncodingStyle style; - char *cl[4]; - - if (xa_text == None) - xa_text = XInternAtom(dpy, "TEXT", False); - if (xa_targets == None) - xa_targets = XInternAtom(dpy, "TARGETS", False); - - ev.xselection.type = SelectionNotify; - ev.xselection.property = None; - ev.xselection.display = rq->display; - ev.xselection.requestor = rq->requestor; - ev.xselection.selection = rq->selection; - ev.xselection.target = rq->target; - ev.xselection.time = rq->time; - - if (rq->target == xa_targets) { - target_list[0] = (CARD32) xa_targets; - target_list[1] = (CARD32) xa_string; - target_list[2] = (CARD32) xa_text; - target_list[3] = (CARD32) xa_compound_text; - XChangeProperty(dpy, rq->requestor, rq->property, rq->target, - (8 * sizeof(target_list[0])), PropModeReplace, - (unsigned char *)target_list, - (sizeof(target_list) / sizeof(target_list[0]))); - ev.xselection.property = rq->property; - } else if (rq->target == xa_string - || rq->target == xa_compound_text - || rq->target == xa_text) { - if (rq->target == xa_string) { - style = XStringStyle; - target = xa_string; - } else { - target = xa_compound_text; - style = (rq->target == xa_compound_text) ? XCompoundTextStyle - : XStdICCTextStyle; - } - cl[0] = selection.text; - XmbTextListToTextProperty(dpy, cl, 1, style, &ct); - XChangeProperty(dpy, rq->requestor, rq->property, - target, 8, PropModeReplace, - ct.value, ct.nitems); - ev.xselection.property = rq->property; - } - XSendEvent(dpy, rq->requestor, False, 0, &ev); -} - -static void -selection_clear (void) -{ - if (selection.text) - free (selection.text); - selection.text = NULL; - selection.len = 0; -} - -/* Given an event, call the correct function to handle it. */ -static void -delegate_event (XEvent *ev) -{ - switch (ev->type) - { - case ConfigureRequest: - PRINT_DEBUG (("--- Handling ConfigureRequest ---\n")); - configure_request (&ev->xconfigurerequest); - break; - - case CreateNotify: - PRINT_DEBUG (("--- Handling CreateNotify ---\n")); - new_window (&ev->xcreatewindow); - break; - - case DestroyNotify: - PRINT_DEBUG (("--- Handling DestroyNotify ---\n")); - destroy_window (&ev->xdestroywindow); - break; - - case ClientMessage: - PRINT_DEBUG (("--- Handling ClientMessage ---\n")); - client_msg (&ev->xclient); - break; - - case ColormapNotify: - PRINT_DEBUG (("--- Handling ColormapNotify ---\n")); - colormap_notify (ev); - break; - - case PropertyNotify: - PRINT_DEBUG (("--- Handling PropertyNotify ---\n")); - property_notify (ev); - break; - - case MapRequest: - PRINT_DEBUG (("--- Handling MapRequest ---\n")); - map_request (ev); - break; - - case KeyPress: - PRINT_DEBUG (("--- Handling KeyPress ---\n")); - key_press (ev); - break; - - case UnmapNotify: - PRINT_DEBUG (("--- Handling UnmapNotify ---\n")); - unmap_notify (ev); - break; - - case FocusOut: - PRINT_DEBUG (("--- Handling FocusOut ---\n")); - focus_change (&ev->xfocus); - break; - - case FocusIn: - PRINT_DEBUG (("--- Handling FocusIn ---\n")); - focus_change (&ev->xfocus); - break; - - case MappingNotify: - PRINT_DEBUG (("--- Handling MappingNotify ---\n")); - mapping_notify( &ev->xmapping ); - break; - - case SelectionRequest: - selection_request(&ev->xselectionrequest); - break; - - case SelectionClear: - selection_clear(); - break; - - case ConfigureNotify: - PRINT_DEBUG (("--- Handling ConfigureNotify ---\n")); - configure_notify( &ev->xconfigure ); - break; - - case MapNotify: - case Expose: - case MotionNotify: - case KeyRelease: - case ReparentNotify: - case EnterNotify: - case SelectionNotify: - case CirculateRequest: - /* Ignore these events. */ - break; - - default: - PRINT_DEBUG (("--- Unknown event %d ---\n",- ev->type)); - } -} - -static void -handle_signals (void) -{ - /* An alarm means we need to hide the popup windows. */ - if (alarm_signalled > 0) - { - int i; - - PRINT_DEBUG (("Alarm received.\n")); - - /* Only hide the bar if it times out. */ - if (defaults.bar_timeout > 0) - for (i=0; i<num_screens; i++) - hide_bar (&screens[i]); - - hide_frame_indicator(); - alarm_signalled = 0; - } - - if (chld_signalled > 0) - { - rp_child_info *cur; - struct list_head *iter, *tmp; - - /* Report and remove terminated processes. */ - list_for_each_safe_entry (cur, iter, tmp, &rp_children, node) - { - if (cur->terminated) - { - /* Report any child that didn't return 0. */ - if (cur->status != 0) - marked_message_printf (0,0, "/bin/sh -c \"%s\" finished (%d)", - cur->cmd, cur->status); - list_del (&cur->node); - free (cur->cmd); - free (cur); - } - } - - chld_signalled = 0; - } - - if (rp_exec_newwm) - { - int i; - - PRINT_DEBUG (("Switching to %s\n", rp_exec_newwm)); - - putenv(current_screen()->display_string); - unhide_all_windows(); - XSync(dpy, False); - for (i=0; i<num_screens; i++) - { - deactivate_screen(&screens[i]); - } - execlp(rp_exec_newwm, rp_exec_newwm, NULL); - - /* Failed. Clean up. */ - PRINT_ERROR (("exec %s ", rp_exec_newwm)); - perror(" failed"); - free (rp_exec_newwm); - rp_exec_newwm = NULL; - for (i=0; i<num_screens; i++) - { - activate_screen(&screens[i]); - } - } - - if (hup_signalled > 0) - { - PRINT_DEBUG (("Restarting\n")); - hook_run (&rp_restart_hook); - clean_up (); - execvp(myargv[0], myargv); - } - - if (kill_signalled > 0) - { - PRINT_DEBUG (("Exiting\n")); - hook_run (&rp_quit_hook); - clean_up (); - exit (EXIT_SUCCESS); - } - - /* Report any X11 errors that have occurred. */ - if (rp_error_msg) - { - marked_message_printf (0, 6, "ERROR: %s", rp_error_msg); - free (rp_error_msg); - rp_error_msg = NULL; - } -} - -/* The main loop. */ -void -listen_for_events (void) -{ - int x_fd; - fd_set fds; - - x_fd = ConnectionNumber (dpy); - FD_ZERO (&fds); - - /* Loop forever. */ - for (;;) - { - handle_signals (); - - /* Handle the next event. */ - FD_SET (x_fd, &fds); - XFlush(dpy); - - if (QLength (dpy) > 0 - || select(x_fd+1, &fds, NULL, NULL, NULL) == 1) - { - XNextEvent (dpy, &rp_current_event); - delegate_event (&rp_current_event); - XSync(dpy, False); - } - } -} diff --git a/src/events.h b/src/events.h deleted file mode 100644 index 69eb27d..0000000 --- a/src/events.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Function prototypes - * 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 - */ - -#ifndef _RATPOISON_EVENTS_H -#define _RATPOISON_EVENTS_H 1 - -void listen_for_events (void); -void show_rudeness_msg (rp_window *win, int raised); - -#endif /* _RATPOISON_EVENTS_H */ diff --git a/src/format.c b/src/format.c deleted file mode 100644 index 0706f21..0000000 --- a/src/format.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2006 Antti Nykänen <aon@iki.fi> - * - * 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 <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "ratpoison.h" - -/* Function prototypes for format char expanders. */ -#define RP_FMT(fn) static void fmt_ ## fn (rp_window_elem *elem, struct sbuf *buf) -RP_FMT(framenum); -RP_FMT(lastaccess); -RP_FMT(name); -RP_FMT(number); -RP_FMT(resname); -RP_FMT(resclass); -RP_FMT(status); -RP_FMT(windowid); -RP_FMT(height); -RP_FMT(width); -RP_FMT(incheight); -RP_FMT(incwidth); -RP_FMT(gravity); -RP_FMT(screen); -RP_FMT(xinescreen); -RP_FMT(transient); -RP_FMT(maxsize); -RP_FMT(pid); - -struct fmt_item { - /* The format character */ - char fmt_char; - - /* Callback to return the expanded string. */ - void (*fmt_fn)(rp_window_elem *, struct sbuf *); -}; - -struct fmt_item fmt_items[] = { - { 'a', fmt_resname }, - { 'g', fmt_gravity }, - { 'h', fmt_height }, - { 'H', fmt_incheight }, - { 'c', fmt_resclass }, - { 'f', fmt_framenum }, - { 'i', fmt_windowid }, - { 'l', fmt_lastaccess }, - { 'n', fmt_number }, - { 'p', fmt_pid }, - { 's', fmt_status }, - { 'S', fmt_screen }, - { 't', fmt_name }, - { 'T', fmt_transient }, - { 'M', fmt_maxsize }, - { 'w', fmt_width }, - { 'W', fmt_incwidth }, - { 'x', fmt_xinescreen }, - { 0, NULL } -}; - -/* if width >= 0 then limit the width of s to width chars. */ -static void -concat_width (struct sbuf *buf, char *s, int width) -{ - if (width >= 0) - { - char *s1 = xsprintf ("%%.%ds", width); - char *s2 = xsprintf (s1, s); - sbuf_concat (buf, s2); - free (s1); - free (s2); - } - else - sbuf_concat (buf, s); -} - -void -format_string (char *fmt, rp_window_elem *win_elem, struct sbuf *buffer) -{ -#define STATE_READ 0 -#define STATE_NUMBER 1 -#define STATE_ESCAPE 2 - int state = STATE_READ; - char dbuf[10]; - int width = -1; - struct sbuf *retbuf; - int fip, found; - - retbuf = sbuf_new (0); - - for(; *fmt; fmt++) - { - if (*fmt == '%' && state == STATE_READ) - { - state = STATE_ESCAPE; - continue; - } - - if ((state == STATE_ESCAPE || state == STATE_NUMBER) && isdigit(*fmt)) - { - /* Accumulate the width one digit at a time. */ - if (state == STATE_ESCAPE) - width = 0; - width *= 10; - width += *fmt - '0'; - state = STATE_NUMBER; - continue; - } - - found = 0; - if (state == STATE_ESCAPE || state == STATE_NUMBER) - { - if (*fmt == '%') - sbuf_concat (buffer, "%"); - else - { - for (fip = 0; fmt_items[fip].fmt_char; fip++) - { - if (fmt_items[fip].fmt_char == *fmt) - { - sbuf_clear (retbuf); - fmt_items[fip].fmt_fn(win_elem, retbuf); - concat_width (buffer, sbuf_get (retbuf), width); - found = 1; - break; - } - } - if (!found) - { - sbuf_printf_concat (buffer, "%%%c", *fmt); - break; - } - } - state = STATE_READ; - width = -1; - } - else - { - /* Insert the character. */ - dbuf[0] = *fmt; - dbuf[1] = 0; - sbuf_concat (buffer, dbuf); - } - } - sbuf_free (retbuf); -#undef STATE_READ -#undef STATE_ESCAPE -#undef STATE_NUMBER -} - -static void -fmt_framenum (rp_window_elem *win_elem, struct sbuf *buf) -{ - if (win_elem->win->frame_number != EMPTY) - { - sbuf_printf_concat (buf, "%d", win_elem->win->frame_number); - } - else - sbuf_copy (buf, " "); -} - -static void -fmt_lastaccess (rp_window_elem *win_elem, struct sbuf *buf) -{ - sbuf_printf_concat (buf, "%d", win_elem->win->last_access); -} - -static void -fmt_name (rp_window_elem *win_elem, struct sbuf *buf) -{ - sbuf_copy(buf, window_name (win_elem->win)); -} - -static void -fmt_number (rp_window_elem *win_elem, struct sbuf *buf) -{ - sbuf_printf_concat (buf, "%d", win_elem->number); -} - -static void -fmt_resname (rp_window_elem *win_elem, struct sbuf *buf) -{ - if (win_elem->win->res_name) - sbuf_copy (buf, win_elem->win->res_name); - else - sbuf_copy (buf, "None"); -} - -static void -fmt_resclass (rp_window_elem *win_elem, struct sbuf *buf) -{ - if (win_elem->win->res_class) - sbuf_copy (buf, win_elem->win->res_class); - else - sbuf_copy (buf, "None"); -} - -static void -fmt_status (rp_window_elem *win_elem, struct sbuf *buf) -{ - rp_window *other_window; - - other_window = find_window_other (current_screen()); - if (win_elem->win == other_window) - sbuf_copy (buf, "+"); - else if (win_elem->win == current_window()) - sbuf_copy (buf, "*"); - else - sbuf_copy (buf, "-"); -} - -static void -fmt_windowid (rp_window_elem *elem, struct sbuf *buf) -{ - sbuf_printf_concat (buf, "%ld", (unsigned long)elem->win->w); -} - -static void -fmt_height (rp_window_elem *elem, struct sbuf *buf) -{ - sbuf_printf_concat (buf, "%d", elem->win->height); -} - -static void -fmt_width (rp_window_elem *elem, struct sbuf *buf) -{ - sbuf_printf_concat (buf, "%d", elem->win->width); -} - -static void -fmt_incheight (rp_window_elem *elem, struct sbuf *buf) -{ - int height; - height = elem->win->height; - - if (elem->win->hints->flags & PResizeInc) - height /= elem->win->hints->height_inc; - - sbuf_printf_concat (buf, "%d", height); -} - -static void -fmt_incwidth (rp_window_elem *elem, struct sbuf *buf) -{ - int width; - width = elem->win->width; - - if (elem->win->hints->flags & PResizeInc) - width /= elem->win->hints->width_inc; - - sbuf_printf_concat (buf, "%d", width); -} - -static void -fmt_gravity (rp_window_elem *elem, struct sbuf *buf) -{ - sbuf_copy (buf, wingravity_to_string (elem->win->gravity)); -} - -static void -fmt_screen (rp_window_elem *elem, struct sbuf *buf) -{ - sbuf_printf_concat (buf, "%d", elem->win->scr->screen_num); -} - -static void -fmt_xinescreen (rp_window_elem *elem, struct sbuf *buf) -{ - sbuf_printf_concat (buf, "%d", elem->win->scr->xine_screen_num); -} - -static void -fmt_transient (rp_window_elem *elem, struct sbuf *buf) -{ - if (elem->win->transient) - sbuf_concat (buf, "Transient"); -} - -static void -fmt_maxsize (rp_window_elem *elem, struct sbuf *buf) -{ - if (elem->win->hints->flags & PMaxSize) - sbuf_concat (buf, "Maxsize"); -} - -static void -fmt_pid (rp_window_elem *elem, struct sbuf *buf) -{ - struct rp_child_info *info; - - info = get_child_info (elem->win->w); - if (info) - sbuf_printf_concat (buf, "%d", info->pid); - else - sbuf_concat (buf, "?"); -} diff --git a/src/format.h b/src/format.h deleted file mode 100644 index 83b6acb..0000000 --- a/src/format.h +++ /dev/null @@ -1,27 +0,0 @@ -/* Prototypes for format functions. - * Copyright (C) 2006 Antti Nykänen <aon@iki.fi> - * - * 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 - */ - -#ifndef _RATPOISON_FORMAT_H -#define _RATPOISON_FORMAT_H 1 - -void format_string(char *fmt, rp_window_elem *win_elem, struct sbuf *buffer); - -#endif /* _RATPOISON_FORMAT_H */ diff --git a/src/frame.c b/src/frame.c deleted file mode 100644 index c42e2ab..0000000 --- a/src/frame.c +++ /dev/null @@ -1,302 +0,0 @@ -/* functions that manipulate the frame structure. - * 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 "ratpoison.h" - -#include <string.h> - -int -frame_left (rp_frame *frame) -{ - return frame->x; -} - -int -frame_top (rp_frame *frame) -{ - return frame->y; -} - -int -frame_right (rp_frame *frame) -{ - return frame->x + frame->width; -} - -int -frame_bottom (rp_frame *frame) -{ - return frame->y + frame->height; -} - -int -frame_width(rp_frame *frame) -{ - return frame->width; -} - -int -frame_height(rp_frame *frame) -{ - return frame->height; -} - -void -frame_resize_left (rp_frame *frame, int amount) -{ - frame->x -= amount; - frame->width += amount; -} - -void -frame_resize_right (rp_frame *frame, int amount) -{ - frame->width += amount; -} - -void -frame_resize_up (rp_frame *frame, int amount) -{ - frame->y -= amount; - frame->height += amount; -} - -void -frame_resize_down (rp_frame *frame, int amount) -{ - frame->height += amount; -} - -void -frame_move_left (rp_frame *frame, int amount) -{ - frame->x -= amount; -} - -void -frame_move_right (rp_frame *frame, int amount) -{ - frame->x += amount; -} - -void -frame_move_up (rp_frame *frame, int amount) -{ - frame->y -= amount; -} - -void -frame_move_down (rp_frame *frame, int amount) -{ - frame->y += amount; -} - -static void -init_frame (rp_frame *f) -{ - f->number = 0; - f->x = 0; - f->y = 0; - f->width = 0; - f->height = 0; - f->win_number = 0; - f->last_access = 0; - f->dedicated = 0; -} - -rp_frame * -frame_new (rp_screen *s) -{ - rp_frame *f; - - f = xmalloc (sizeof (rp_frame)); - init_frame(f); - f->number = numset_request (s->frames_numset); - - return f; -} - -void -frame_free (rp_screen *s, rp_frame *f) -{ - numset_release (s->frames_numset, f->number); - free (f); -} - - -rp_frame * -frame_copy (rp_frame *frame) -{ - rp_frame *copy; - - copy = xmalloc (sizeof (rp_frame)); - - copy->number = frame->number; - copy->x = frame->x; - copy->y = frame->y; - copy->width = frame->width; - copy->height = frame->height; - copy->win_number = frame->win_number; - copy->last_access = frame->last_access; - - return copy; -} - -char * -frame_dump (rp_frame *frame, rp_screen *screen) -{ - rp_window *win; - char *tmp; - struct sbuf *s; - - /* rather than use win_number, use the X11 window ID. */ - win = find_window_number (frame->win_number); - - s = sbuf_new (0); - sbuf_printf (s, "(frame :number %d :x %d :y %d :width %d :height %d :screenw %d :screenh %d :window %ld :last-access %d :dedicated %d)", - frame->number, - frame->x, - frame->y, - frame->width, - frame->height, - screen->width, - screen->height, - win ? win->w:0, - frame->last_access, - frame->dedicated); - - /* Extract the string and return it, and don't forget to free s. */ - tmp = sbuf_get (s); - free (s); - return tmp; -} - -/* Used only by frame_read */ -#define read_slot(x) do { tmp = strtok_ws (NULL); x = strtol(tmp,NULL,10); } while(0) - -rp_frame * -frame_read (char *str, rp_screen *screen) -{ - Window w = 0L; - rp_window *win; - rp_frame *f; - char *tmp, *d; - int s_width = -1; - int s_height = -1; - - /* Create a blank frame. */ - f = xmalloc (sizeof (rp_frame)); - init_frame(f); - - PRINT_DEBUG(("parsing '%s'\n", str)); - - d = xstrdup(str); - tmp = strtok_ws (d); - - /* Verify it starts with '(frame ' */ - if (strcmp(tmp, "(frame")) - { - PRINT_DEBUG(("Doesn't start with '(frame '\n")); - free (d); - free (f); - return NULL; - } - /* NOTE: there is no check to make sure each field was filled in. */ - tmp = strtok_ws(NULL); - while (tmp) - { - if (!strcmp(tmp, ":number")) - read_slot(f->number); - else if (!strcmp(tmp, ":x")) - read_slot(f->x); - else if (!strcmp(tmp, ":y")) - read_slot(f->y); - else if (!strcmp(tmp, ":width")) - read_slot(f->width); - else if (!strcmp(tmp, ":height")) - read_slot(f->height); - else if (!strcmp(tmp, ":screenw")) - read_slot(s_width); - else if (!strcmp(tmp, ":screenh")) - read_slot(s_height); - else if (!strcmp(tmp, ":window")) - read_slot(w); - else if (!strcmp(tmp, ":last-access")) - read_slot(f->last_access); - else if (!strcmp(tmp, ":dedicated")) { - /* f->dedicated is unsigned, so read into local variable. */ - long dedicated; - - read_slot(dedicated); - if (dedicated <= 0) - f->dedicated = 0; - else - f->dedicated = 1; - } - else if (!strcmp(tmp, ")")) - break; - else - PRINT_ERROR(("Unknown slot %s\n", tmp)); - /* Read the next token. */ - tmp = strtok_ws(NULL); - } - if (tmp) - PRINT_ERROR(("Frame has trailing garbage\n")); - free (d); - - /* adjust x, y, width and height to a possible screen size change */ - if (s_width > 0) - { - f->x = (f->x*screen->width)/s_width; - f->width = (f->width*screen->width)/s_width; - } - if (s_height > 0) - { - f->y = (f->y*screen->height)/s_height; - f->height = (f->height*screen->height)/s_height; - } - - /* Perform some integrity checks on what we got and fix any - problems. */ - if (f->number <= 0) - f->number = 0; - if (f->x <= 0) - f->x = 0; - if (f->y <= 0) - f->y = 0; - if (f->width <= defaults.window_border_width*2) - f->width = defaults.window_border_width*2 + 1; - if (f->height <= defaults.window_border_width*2) - f->height = defaults.window_border_width*2 + 1; - if (f->last_access < 0) - f->last_access = 0; - - /* Find the window with the X11 window ID. */ - win = find_window_in_list (w, &rp_mapped_window); - if (win) - f->win_number = win->number; - else - f->win_number = EMPTY; - - return f; -} - -#undef read_slot diff --git a/src/frame.h b/src/frame.h deleted file mode 100644 index 611ecc0..0000000 --- a/src/frame.h +++ /dev/null @@ -1,47 +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 - */ - -#ifndef FRAME_H -#define FRAME_H - -void frame_move_down (rp_frame *frame, int amount); -void frame_move_up (rp_frame *frame, int amount); -void frame_move_right (rp_frame *frame, int amount); -void frame_move_left (rp_frame *frame, int amount); -void frame_resize_down (rp_frame *frame, int amount); -void frame_resize_up (rp_frame *frame, int amount); -void frame_resize_right (rp_frame *frame, int amount); -void frame_resize_left (rp_frame *frame, int amount); -int frame_height(rp_frame *frame); -int frame_width(rp_frame *frame); -int frame_bottom (rp_frame *frame); -int frame_right (rp_frame *frame); -int frame_top (rp_frame *frame); -int frame_left (rp_frame *frame); - -rp_frame *frame_new (rp_screen *s); -void frame_free (rp_screen *s, rp_frame *f); -rp_frame *frame_copy (rp_frame *frame); -char *frame_dump (rp_frame *frame, rp_screen *screen); -rp_frame *frame_read (char *str, rp_screen *screen); - -rp_screen *frames_screen (rp_frame *); - -#endif diff --git a/src/getopt.c b/src/getopt.c deleted file mode 100644 index d5c40f1..0000000 --- a/src/getopt.c +++ /dev/null @@ -1,1052 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu - before changing it! - - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97 - Free Software Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - This program 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. - - This program 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 program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ - -/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. - Ditto for AIX 3.2 and <stdlib.h>. */ - -#ifndef _NO_PROTO -#define _NO_PROTO -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <strings.h> - -#ifndef HAVE_GETOPT_LONG - -#if !defined (__STDC__) || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include <stdio.h> - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 -#include <gnu-versions.h> -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -/* Don't include stdlib.h for non-GNU C libraries because some of them - contain conflicting prototypes for getopt. */ -#include <stdlib.h> -#include <unistd.h> -#endif /* GNU C library. */ - -#ifdef VMS -#include <unixlib.h> -#if HAVE_STRING_H - 0 -#include <string.h> -#endif -#endif - -#ifndef _ -/* This is for other GNU distributions with internationalized messages. - When compiling libc, the _ macro is predefined. */ -#ifdef HAVE_LIBINTL_H -# include <libintl.h> -# define _(msgid) gettext (msgid) -#else -# define _(msgid) (msgid) -#endif -#endif - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg = NULL; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Formerly, initialization of getopt depended on optind==0, which - causes problems with re-calling getopt as programs generally don't - know that. */ - -int __getopt_initialized = 0; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; - -#ifdef __GNU_LIBRARY__ -/* We want to avoid inclusion of string.h with non-GNU libraries - because there are many ways it can cause trouble. - On some systems, it contains special magic macros that don't work - in GCC. */ -#include <string.h> -#define my_index strchr -#else - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -char *getenv (); - -static char * -my_index (str, chr) - const char *str; - int chr; -{ - while (*str) - { - if (*str == chr) - return (char *) str; - str++; - } - return 0; -} - -/* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ -#ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -#if !defined (__STDC__) || !__STDC__ -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -#endif /* not __STDC__ */ -#endif /* __GNUC__ */ - -#endif /* not __GNU_LIBRARY__ */ - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -#ifdef _LIBC -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; - -static int nonoption_flags_max_len; -static int nonoption_flags_len; - -static int original_argc; -static char *const *original_argv; - -/* Make sure the environment variable bash 2.0 puts in the environment - is valid for the getopt call we must make sure that the ARGV passed - to getopt is that one passed to the process. */ -static void -__attribute__ ((unused)) -store_args_and_env (int argc, char *const *argv) -{ - /* XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ - original_argc = argc; - original_argv = argv; -} -# ifdef text_set_element -text_set_element (__libc_subinit, store_args_and_env); -# endif /* text_set_element */ - -# define SWAP_FLAGS(ch1, ch2) \ - if (nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -#if defined (__STDC__) && __STDC__ -static void exchange (char **); -#endif - -static void -exchange (argv) - char **argv; -{ - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#ifdef _LIBC - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - nonoption_flags_max_len), - '\0', top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Initialize the internal data when the first call is made. */ - -#if defined (__STDC__) && __STDC__ -static const char *_getopt_initialize (int, char *const *, const char *); -#endif -static const char * -_getopt_initialize (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - -#ifdef _LIBC - if (posixly_correct == NULL - && argc == original_argc && argv == original_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', nonoption_flags_max_len - len); - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - optarg = NULL; - - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#ifdef _LIBC -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ - || (optind < nonoption_flags_len \ - && __getopt_nonoption_flags[optind] == '1')) -#else -#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') -#endif - - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf (stderr, - _("%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); - else - /* +option or -option */ - fprintf (stderr, - _("%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); - } - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || my_index (optstring, *nextchar) == NULL) - { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); - else - /* +option or -option */ - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *nextchar++; - char *temp = my_index (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: illegal option -- %c\n"), - argv[0], c); - else - fprintf (stderr, _("%s: invalid option -- %c\n"), - argv[0], c); - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (opterr) - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (opterr) - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - { - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); -} - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ - -#endif /* HAVE_GETOPT_LONG */ diff --git a/src/getopt.h b/src/getopt.h deleted file mode 100644 index d0ae1c6..0000000 --- a/src/getopt.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - This program 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. - - This program 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 program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ - -#ifndef _GETOPT_H -#define _GETOPT_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ -#if defined (__STDC__) && __STDC__ - const char *name; -#else - char *name; -#endif - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -#if defined (__STDC__) && __STDC__ -#ifdef __GNU_LIBRARY__ -/* Many other libraries have conflicting prototypes for getopt, with - differences in the consts, in stdlib.h. To avoid compilation - errors, only prototype getopt for the GNU C library. */ -extern int getopt (int argc, char *const *argv, const char *shortopts); -#else /* not __GNU_LIBRARY__ */ -extern int getopt (); -#endif /* __GNU_LIBRARY__ */ -extern int getopt_long (int argc, char *const *argv, const char *shortopts, - const struct option *longopts, int *longind); -extern int getopt_long_only (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind); - -/* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int argc, char *const *argv, - const char *shortopts, - const struct option *longopts, int *longind, - int long_only); -#else /* not __STDC__ */ -extern int getopt (); -extern int getopt_long (); -extern int getopt_long_only (); - -extern int _getopt_internal (); -#endif /* __STDC__ */ - -#ifdef __cplusplus -} -#endif - -#endif /* getopt.h */ diff --git a/src/getopt1.c b/src/getopt1.c deleted file mode 100644 index 5c1fd42..0000000 --- a/src/getopt1.c +++ /dev/null @@ -1,194 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - This program 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. - - This program 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 program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - USA. */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifndef HAVE_GETOPT_LONG - -#include "getopt.h" - -#if !defined (__STDC__) || !__STDC__ -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include <stdio.h> - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#define GETOPT_INTERFACE_VERSION 2 -#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2 -#include <gnu-versions.h> -#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -#define ELIDE_CODE -#endif -#endif - -#ifndef ELIDE_CODE - - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include <stdlib.h> -#endif - -#ifndef NULL -#define NULL 0 -#endif - -int -getopt_long (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int -getopt_long_only (argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); -} - - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - -#include <stdio.h> - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ - -#endif /* HAVE_GETOPT_LONG */ diff --git a/src/globals.c b/src/globals.c deleted file mode 100644 index 05ebe28..0000000 --- a/src/globals.c +++ /dev/null @@ -1,346 +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 "ratpoison.h" - -#include <unistd.h> /* for usleep(). */ - -int alarm_signalled = 0; -int kill_signalled = 0; -int hup_signalled = 0; -int chld_signalled = 0; -int rat_x; -int rat_y; -int rat_visible = 1; /* rat is visible by default */ - -char *rp_exec_newwm = NULL; - -int rp_font_ascent, rp_font_descent, rp_font_width; - -Atom wm_name; -Atom wm_state; -Atom wm_change_state; -Atom wm_protocols; -Atom wm_delete; -Atom wm_take_focus; -Atom wm_colormaps; - -Atom rp_command; -Atom rp_command_request; -Atom rp_command_result; -Atom rp_selection; - -/* TEXT atoms */ -Atom xa_string; -Atom xa_compound_text; -Atom xa_utf8_string; - -/* netwm atoms */ -Atom _net_wm_pid; -Atom _net_supported; -Atom _net_wm_window_type; -Atom _net_wm_window_type_dialog; -Atom _net_wm_name; - -int rp_current_screen; -rp_screen *screens; -int num_screens; -Display *dpy; - -rp_group *rp_current_group; -LIST_HEAD (rp_groups); -LIST_HEAD (rp_children); -struct rp_defaults defaults; - -int ignore_badwindow = 0; - -char **myargv; - -struct rp_key prefix_key; - -struct modifier_info rp_modifier_info; - -/* rudeness levels */ -int rp_honour_transient_raise = 1; -int rp_honour_normal_raise = 1; -int rp_honour_transient_map = 1; -int rp_honour_normal_map = 1; - -char *rp_error_msg = NULL; - -/* Global frame numset */ -struct numset *rp_frame_numset; - -/* The X11 selection globals */ -rp_xselection selection; - -static void -x_export_selection (void) -{ - /* Hang the selections off screen 0's key window. */ - XSetSelectionOwner(dpy, XA_PRIMARY, screens[0].key_window, CurrentTime); - if (XGetSelectionOwner(dpy, XA_PRIMARY) != screens[0].key_window) - PRINT_ERROR(("can't get primary selection")); - XChangeProperty(dpy, screens[0].root, XA_CUT_BUFFER0, xa_string, 8, - PropModeReplace, (unsigned char*)selection.text, selection.len); -} - -void -set_nselection (char *txt, int len) -{ - int i; - - /* Update the selection structure */ - if (selection.text != NULL) - free(selection.text); - - /* Copy the string by hand. */ - selection.text = malloc(len+1); - selection.len = len + 1; - for (i=0; i<len; i++) - selection.text[i] = txt[i]; - selection.text[len] = 0; - - x_export_selection(); -} - -void -set_selection (char *txt) -{ - /* Update the selection structure */ - if (selection.text != NULL) - free(selection.text); - selection.text = xstrdup (txt); - selection.len = strlen (txt); - - x_export_selection(); -} - -static char * -get_cut_buffer (void) -{ - int nbytes; - char *data; - - PRINT_DEBUG (("trying the cut buffer\n")); - - data = XFetchBytes (dpy, &nbytes); - - if (data) - { - struct sbuf *s = sbuf_new (0); - sbuf_nconcat (s, data, nbytes); - XFree (data); - return sbuf_free_struct (s); - } - else - return NULL; -} - -/* Lifted the code from rxvt. */ -static char * -get_primary_selection(void) -{ - long nread; - unsigned long bytes_after; - XTextProperty ct; - struct sbuf *s = sbuf_new(0); - - for (nread = 0, bytes_after = 1; bytes_after > 0; nread += ct.nitems) { - if ((XGetWindowProperty(dpy, current_screen()->input_window, rp_selection, (nread / 4), 4096, - True, AnyPropertyType, &ct.encoding, - &ct.format, &ct.nitems, &bytes_after, - &ct.value) != Success)) { - XFree(ct.value); - sbuf_free(s); - return NULL; - } - if (ct.value == NULL) - continue; - /* Accumulate the data. FIXME: ct.value may not be NULL - terminated. */ - sbuf_nconcat (s, (const char*)ct.value, ct.nitems); - XFree(ct.value); - } - return sbuf_free_struct (s); -} - -char * -get_selection (void) -{ - Atom property; - XEvent ev; - rp_screen *s = current_screen (); - int loops = 1000; - - /* Just insert our text, if we own the selection. */ - if (selection.text) - { - return xstrdup (selection.text); - } - else - { - /* be a good icccm citizen */ - XDeleteProperty (dpy, s->input_window, rp_selection); - /* TODO: we shouldn't use CurrentTime here, use the time of the XKeyEvent, should we fake it? */ - XConvertSelection (dpy, XA_PRIMARY, xa_string, rp_selection, s->input_window, CurrentTime); - - /* This seems like a hack. */ - while (!XCheckTypedWindowEvent (dpy, s->input_window, SelectionNotify, &ev)) - { - if (loops == 0) - { - PRINT_ERROR (("selection request timed out\n")); - return NULL; - } - usleep (10000); - loops--; - } - - PRINT_DEBUG (("SelectionNotify event\n")); - - property = ev.xselection.property; - - if (property != None) - return get_primary_selection (); - else - return get_cut_buffer (); - } -} - -/* The hook dictionary globals. */ - -LIST_HEAD (rp_key_hook); -LIST_HEAD (rp_switch_win_hook); -LIST_HEAD (rp_switch_frame_hook); -LIST_HEAD (rp_switch_group_hook); -LIST_HEAD (rp_switch_screen_hook); -LIST_HEAD (rp_quit_hook); -LIST_HEAD (rp_restart_hook); -LIST_HEAD (rp_delete_window_hook); -LIST_HEAD (rp_new_window_hook); -LIST_HEAD (rp_title_changed_hook); - -struct rp_hook_db_entry rp_hook_db[]= - {{"key", &rp_key_hook}, - {"switchwin", &rp_switch_win_hook}, - {"switchframe", &rp_switch_frame_hook}, - {"switchgroup", &rp_switch_group_hook}, - {"switchscreen", &rp_switch_screen_hook}, - {"deletewindow", &rp_delete_window_hook}, - {"quit", &rp_quit_hook}, - {"restart", &rp_restart_hook}, - {"newwindow", &rp_new_window_hook}, - {"titlechanged", &rp_title_changed_hook}, - {NULL, NULL}}; - -void -set_rp_window_focus (rp_window *win) -{ - PRINT_DEBUG (("Giving focus to '%s'\n", window_name (win))); - XSetInputFocus (dpy, win->w, - RevertToPointerRoot, CurrentTime); -} - -void -set_window_focus (Window window) -{ - PRINT_DEBUG (("Giving focus to %ld\n", window)); - XSetInputFocus (dpy, window, - RevertToPointerRoot, CurrentTime); -} - -LIST_HEAD (rp_frame_undos); -LIST_HEAD (rp_frame_redos); - -void -init_globals (void) -{ - selection.text = NULL; - selection.len = 0; -} - -/* Wrapper font functions to support Xft */ - -void -rp_draw_string (rp_screen *s, Drawable d, int style, int x, int y, - char *string, int length) -{ - if (length < 0) - length = strlen (string); - -#ifdef USE_XFT_FONT - if (s->xft_font) - { - XftDraw *draw; - draw = XftDrawCreate (dpy, d, DefaultVisual (dpy, s->screen_num), - DefaultColormap (dpy, s->screen_num)); - if (!draw) - { - PRINT_ERROR (("Failed to allocate XftDraw object\n")); - return; - } - - if (defaults.utf8_locale) - { - XftDrawStringUtf8 (draw, style == STYLE_NORMAL ? &s->xft_fg_color : - &s->xft_bg_color, s->xft_font, x, y, - (FcChar8*) string, length); - } - else - { - XftDrawString8 (draw, style == STYLE_NORMAL ? &s->xft_fg_color : - &s->xft_bg_color, s->xft_font, x, y, - (FcChar8*) string, length); - } - XftDrawDestroy (draw); - } - else - PRINT_ERROR (("No Xft font available.\n")); -#else - XmbDrawString (dpy, d, defaults.font, style == STYLE_NORMAL ? s->normal_gc : - s->inverse_gc, x, y, string, length); -#endif -} - -int -rp_text_width (rp_screen *s, char *string, int count) -{ - (void) s; /* avoid "unused" warning */ - if (count < 0) - count = strlen (string); - -#ifdef USE_XFT_FONT - if (s->xft_font) - { - XGlyphInfo extents; - if (defaults.utf8_locale) - XftTextExtentsUtf8 (dpy, s->xft_font, (FcChar8*) string, count, &extents); - else - XftTextExtents8 (dpy, s->xft_font, (FcChar8*) string, count, &extents); - return extents.xOff; - } - PRINT_ERROR (("No Xft font available.\n")); - return 0; -#else - return XmbTextEscapement (defaults.font, string, count); -#endif -} - diff --git a/src/globals.h b/src/globals.h deleted file mode 100644 index 12ccffd..0000000 --- a/src/globals.h +++ /dev/null @@ -1,217 +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 - */ - -#ifndef GLOBALS_H -#define GLOBALS_H - -#include "data.h" - -/* codes used in the cmdret code in actions.c */ -#define RET_SUCCESS 1 -#define RET_FAILURE 0 - -#ifdef USE_XFT_FONT -#include <X11/Xft/Xft.h> - -#define FONT_HEIGHT(s) ((s)->xft_font->ascent + (s)->xft_font->descent) -#define FONT_ASCENT(s) ((s)->xft_font->ascent) - -#else - -#define FONT_HEIGHT(f) (rp_font_ascent + rp_font_descent) -#define FONT_ASCENT(f) (rp_font_ascent) - -#endif - -#define MAX_FONT_WIDTH(f) (rp_font_width) - -#define WIN_EVENTS (StructureNotifyMask | PropertyChangeMask | ColormapChangeMask | FocusChangeMask) -/* EMPTY is used when a frame doesn't contain a window, or a window - doesn't have a frame. Any time a field refers to the number of a - window/frame/screen/etc, Use EMPTY to denote a lack there of. */ -#define EMPTY -1 - -/* Possible values for defaults.window_list_style */ -#define STYLE_ROW 0 -#define STYLE_COLUMN 1 - -/* Possible values for defaults.win_name */ -#define WIN_NAME_TITLE 0 -#define WIN_NAME_RES_CLASS 1 -#define WIN_NAME_RES_NAME 2 - -/* Possible directions to traverse the completions list. */ -#define COMPLETION_NEXT 0 -#define COMPLETION_PREVIOUS 1 - -/* Error codes for group_delete_group() */ -#define GROUP_DELETE_GROUP_OK 0 -#define GROUP_DELETE_GROUP_NONEMPTY 1 -#define GROUP_DELETE_LAST_GROUP 2 - -/* Font styles */ -#define STYLE_NORMAL 0 -#define STYLE_INVERSE 1 - -#ifdef __GNUC__ -#define UNUSED __attribute__ ((unused)) -#else -#define UNUSED -#endif - -/* The list of groups. */ -extern struct list_head rp_groups; - -extern rp_group *rp_current_group; - -/* Each child process is stored in this list. spawn, creates a new - entry in this list, the SIGCHLD handler sets child.terminated to be - true and handle_signals in events.c processes each terminated - process by printing a message saying the process ended and - displaying it's exit code. */ -extern struct list_head rp_children; - -extern struct rp_defaults defaults; - -/* Cached font info. */ -extern int rp_font_ascent, rp_font_descent, rp_font_width; - -/* The prefix key also known as the command character under screen. */ -extern struct rp_key prefix_key; - -/* A list of mapped windows. These windows show up in the window - list and have a number assigned to them. */ -extern struct list_head rp_mapped_window; - -/* A list of unmapped windows. These windows do not have a number - assigned to them and are not visible/active. */ -extern struct list_head rp_unmapped_window; - -extern int rp_current_screen; -extern rp_screen *screens; -extern int num_screens; - -extern XEvent rp_current_event; - -extern Display *dpy; -extern Atom rp_command; -extern Atom rp_command_request; -extern Atom rp_command_result; -extern Atom rp_selection; - -extern Atom wm_name; -extern Atom wm_state; -extern Atom wm_change_state; -extern Atom wm_protocols; -extern Atom wm_delete; -extern Atom wm_take_focus; -extern Atom wm_colormaps; - -/* TEXT atoms */ -extern Atom xa_string; -extern Atom xa_compound_text; -extern Atom xa_utf8_string; - -/* netwm atoms. */ -extern Atom _net_wm_pid; -extern Atom _net_supported; -extern Atom _net_wm_window_type; -extern Atom _net_wm_window_type_dialog; -extern Atom _net_wm_name; - -/* mouse properties */ -extern int rat_x; -extern int rat_y; -extern int rat_visible; - -/* When unmapping or deleting windows, it is sometimes helpful to - ignore a bad window when attempting to clean the window up. This - does just that when set to 1 */ -extern int ignore_badwindow; - -/* Arguments passed to ratpoison. */ -extern char **myargv; - -/* Keeps track of which mod mask each modifier is under. */ -extern struct modifier_info rp_modifier_info; - -/* nonzero if an alarm signal was raised. This means ratpoison should - hide its popup windows. */ -extern int alarm_signalled; -extern int kill_signalled; -extern int hup_signalled; -extern int chld_signalled; - -/* When set to a string, ratpoison should exec the command. The reason - this variable is needed and why it is not exec'd in cmd_newwm is - because if called with ratpoison -c, the rp -c process never - returns. */ -extern char *rp_exec_newwm; - -/* rudeness levels */ -extern int rp_honour_transient_raise; -extern int rp_honour_normal_raise; -extern int rp_honour_transient_map; -extern int rp_honour_normal_map; - -/* Keep track of X11 error messages. */ -extern char *rp_error_msg; - -/* Number sets for windows. */ -extern struct numset *rp_window_numset; - -extern struct list_head rp_key_hook; -extern struct list_head rp_switch_win_hook; -extern struct list_head rp_switch_frame_hook; -extern struct list_head rp_switch_group_hook; -extern struct list_head rp_switch_screen_hook; -extern struct list_head rp_delete_window_hook; -extern struct list_head rp_quit_hook; -extern struct list_head rp_restart_hook; -extern struct list_head rp_new_window_hook; -extern struct list_head rp_title_changed_hook; - -extern struct rp_hook_db_entry rp_hook_db[]; - -void set_rp_window_focus (rp_window *win); -void set_window_focus (Window window); - -extern int rp_have_xinerama; -extern int xine_screen_count; - -extern struct numset *rp_frame_numset; - -extern struct list_head rp_frame_undos; -extern struct list_head rp_frame_redos; - -/* Selection handling globals */ -extern rp_xselection selection; -void set_selection (char *txt); -void set_nselection (char *txt, int len); -char *get_selection (void); - -void init_globals (void); - -/* Wrapper font functions to support Xft */ - -void rp_draw_string (rp_screen *s, Drawable d, int style, int x, int y, char *string, int length); -int rp_text_width (rp_screen *s, char *string, int count); - -#endif diff --git a/src/group.c b/src/group.c deleted file mode 100644 index 5448006..0000000 --- a/src/group.c +++ /dev/null @@ -1,661 +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 "ratpoison.h" - -#include <string.h> - -/* XXX Should be static */ -struct numset *group_numset; - -static void -set_current_group_1 (rp_group *g) -{ - static int counter = 1; - rp_current_group = g; - if (g) - g->last_access = counter++; -} - -void -init_groups(void) -{ - rp_group *g; - - group_numset = numset_new(); - INIT_LIST_HEAD (&rp_groups); - - /* Create the first group in the list (We always need at least - one). */ - g = group_new (numset_request (group_numset), DEFAULT_GROUP_NAME); - set_current_group_1 (g); - list_add_tail (&g->node, &rp_groups); -} - -void -free_groups(void) -{ - rp_group *cur; - struct list_head *iter, *tmp; - - list_for_each_safe_entry (cur, iter, tmp, &rp_groups, node) - { - group_free (cur); - } -} - -rp_group * -group_new (int number, char *name) -{ - rp_group *g; - - g = xmalloc (sizeof (rp_group)); - - if (name) - g->name = xstrdup (name); - else - g->name = NULL; - g->last_access = 0; - g->number = number; - g->numset = numset_new(); - INIT_LIST_HEAD (&g->unmapped_windows); - INIT_LIST_HEAD (&g->mapped_windows); - - return g; -} - -void -group_free (rp_group *g) -{ - if (g->name) - free (g->name); - numset_free (g->numset); - numset_release (group_numset, g->number); - free (g); -} - -rp_group * -group_add_new_group (char *name) -{ - rp_group *g; - rp_group *cur; - - g = group_new (numset_request (group_numset), name); - - list_for_each_entry (cur, &rp_groups, node) - { - if(cur->number > g->number) - { - list_add_tail (&g->node, &cur->node); - return g; - } - } - - list_add_tail (&g->node, &rp_groups); - - return g; -} - -void -group_resort_group (rp_group *g) -{ - rp_group *cur; - struct list_head *last = &rp_groups; - - list_del (&g->node); - list_for_each_entry (cur, &rp_groups, node) - { - if(cur->number > g->number) - { - list_add (&g->node, last); - return; - } - last = &cur->node; - } - list_add (&g->node, last); -} - -void -group_rename (rp_group *g, char *name) -{ - if (g->name) - free (g->name); - g->name = xstrdup (name); -} - -rp_group * -group_next_group (void) -{ - return list_next_entry (rp_current_group, &rp_groups, node); -} - -rp_group * -group_prev_group (void) -{ - return list_prev_entry (rp_current_group, &rp_groups, node); -} - -rp_group * -group_last_group (void) -{ - int last_access = 0; - rp_group *most_recent = NULL; - rp_group *cur; - - list_for_each_entry (cur, &rp_groups, node) - { - if (cur != rp_current_group && cur->last_access > last_access) { - most_recent = cur; - last_access = cur->last_access; - } - } - return most_recent; -} - -rp_group * -groups_find_group_by_name (char *s, int exact_match) -{ - rp_group *cur; - - list_for_each_entry (cur, &rp_groups, node) - { - if (cur->name) - { - if ((!exact_match && str_comp (s, cur->name, strlen (s))) || - (exact_match && !strcmp (cur->name, s))) - return cur; - } - } - - return NULL; -} - -rp_group * -groups_find_group_by_number (int n) -{ - rp_group *cur; - - list_for_each_entry (cur, &rp_groups, node) - { - if (cur->number == n) - return cur; - } - - return NULL; -} - -/* Return the first group that contains the window. */ -rp_group * -groups_find_group_by_window (rp_window *win) -{ - rp_group *cur; - rp_window_elem *elem; - - list_for_each_entry (cur, &rp_groups, node) - { - elem = group_find_window (&cur->mapped_windows, win); - if (elem) - return cur; - } - - return NULL; -} - - -/* Return the first group that is g. */ -rp_group * -groups_find_group_by_group (rp_group *g) -{ - rp_group *cur; - - list_for_each_entry (cur, &rp_groups, node) - { - if (cur == g) - return cur; - } - - return NULL; -} - -rp_window_elem * -group_find_window (struct list_head *list, rp_window *win) -{ - rp_window_elem *cur; - - list_for_each_entry (cur, list, node) - { - if (cur->win == win) - return cur; - } - - return NULL; -} - -rp_window_elem * -group_find_window_by_number (rp_group *g, int num) -{ - rp_window_elem *cur; - - list_for_each_entry (cur, &g->mapped_windows, node) - { - if (cur->number == num) - return cur; - } - - return NULL; - -} - - -/* Insert a window_elem into the correct spot in the group's window - list to preserve window number ordering. */ -static void -group_insert_window (struct list_head *h, rp_window_elem *w) -{ - rp_window_elem *cur; - - list_for_each_entry (cur, h, node) - { - if (cur->number > w->number) - { - list_add_tail (&w->node, &cur->node); - return; - } - } - - list_add_tail(&w->node, h); -} - -static int -group_in_list (struct list_head *h, rp_window_elem *w) -{ - rp_window_elem *cur; - - list_for_each_entry (cur, h, node) - { - if (cur == w) - return 1; - } - - return 0; -} - -/* If a window_elem's number has changed then the list has to be - resorted. */ -void -group_resort_window (rp_group *g, rp_window_elem *w) -{ - /* Only a mapped window can be resorted. */ - if (!group_in_list (&g->mapped_windows, w)) - { - PRINT_DEBUG (("Attempting to restort an unmapped window!\n")); - return; - } - - list_del (&w->node); - group_insert_window (&g->mapped_windows, w); -} - -void -group_add_window (rp_group *g, rp_window *w) -{ - rp_window_elem *we; - - /* Create our container structure for the window. */ - we = malloc (sizeof (rp_window_elem)); - we->win = w; - we->number = -1; - - /* Finally, add it to our list. */ - list_add_tail (&we->node, &g->unmapped_windows); -} - -void -group_map_window (rp_group *g, rp_window *win) -{ - rp_window_elem *we; - - we = group_find_window (&g->unmapped_windows, win); - - if (we) - { - we->number = numset_request (g->numset); - list_del (&we->node); - group_insert_window (&g->mapped_windows, we); - } -} - -void -groups_map_window (rp_window *win) -{ - rp_group *cur; - - list_for_each_entry (cur, &rp_groups, node) - { - group_map_window (cur, win); - } -} - -void -group_unmap_window (rp_group *g, rp_window *win) -{ - rp_window_elem *we; - - we = group_find_window (&g->mapped_windows, win); - - if (we) - { - numset_release (g->numset, we->number); - list_move_tail (&we->node, &g->unmapped_windows); - } -} - -void -groups_unmap_window (rp_window *win) -{ - rp_group *cur; - - list_for_each_entry (cur, &rp_groups, node) - { - group_unmap_window (cur, win); - } -} - -void -group_del_window (rp_group *g, rp_window *win) -{ - rp_window_elem *cur; - struct list_head *iter, *tmp; - - /* The assumption is that a window is unmapped before it's deleted. */ - list_for_each_safe_entry (cur, iter, tmp, &g->unmapped_windows, node) - { - if (cur->win == win) - { - list_del (&cur->node); - free (cur); - } - } - - /* Make sure the window isn't in the list of mapped windows. This - would mean there is a bug. */ -#ifdef DEBUG - list_for_each_entry (cur, &g->mapped_windows, node) - { - if (cur->win == win) - PRINT_DEBUG (("This window wasn't removed from the mapped window list.\n")); - } -#endif -} - -/* Remove the window from any groups in resides in. */ -void -groups_del_window (rp_window *win) -{ - rp_group *cur; - - list_for_each_entry (cur, &rp_groups, node) - { - group_del_window (cur, win); - } -} - -rp_window * -group_last_window (rp_group *g, rp_screen *s) -{ - int last_access = 0; - rp_window_elem *most_recent = NULL; - rp_window_elem *cur; - - list_for_each_entry (cur, &g->mapped_windows, node) - { - if (cur->win->last_access >= last_access - && cur->win != current_window() - && !find_windows_frame (cur->win) - && (cur->win->scr == s || rp_have_xinerama)) - { - most_recent = cur; - last_access = cur->win->last_access; - } - } - - if (most_recent) - return most_recent->win; - - return NULL; -} - -rp_window * -group_next_window (rp_group *g, rp_window *win) -{ - rp_window_elem *cur, *we; - - /* If there is no window, then get the last accessed one. */ - if (win == NULL) - return group_last_window (g, current_screen()); - - /* If we can't find the window, then it's in a different group, so - get the last accessed one in this group. */ - we = group_find_window (&g->mapped_windows, win); - if (we == NULL) - return group_last_window (g, win->scr); - - /* The window is in this group, so find the next one in the list - that isn't already displayed. */ - for (cur = list_next_entry (we, &g->mapped_windows, node); - cur != we; - cur = list_next_entry (cur, &g->mapped_windows, node)) - { - if (!find_windows_frame (cur->win) && (cur->win->scr == win->scr || rp_have_xinerama)) - { - return cur->win; - } - } - - return NULL; -} - -rp_window * -group_prev_window (rp_group *g, rp_window *win) -{ - rp_window_elem *cur, *we; - - /* If there is no window, then get the last accessed one. */ - if (win == NULL) - return group_last_window (g, current_screen()); - - /* If we can't find the window, then it's in a different group, so - get the last accessed one in this group. */ - we = group_find_window (&g->mapped_windows, win); - if (we == NULL) - return group_last_window (g, win->scr); - - /* The window is in this group, so find the previous one in the list - that isn't already displayed. */ - for (cur = list_prev_entry (we, &g->mapped_windows, node); - cur != we; - cur = list_prev_entry (cur, &g->mapped_windows, node)) - { - if (!find_windows_frame (cur->win) && (cur->win->scr == win->scr || rp_have_xinerama)) - { - return cur->win; - } - } - - return NULL; - -} - -void -group_move_window (rp_group *to, rp_window *win) -{ - rp_group *cur, *from = NULL; - rp_window_elem *we = NULL; - - /* Find the group that the window belongs to. FIXME: If the window - exists in multiple groups, then we're going to find the first - group with this window in it. */ - list_for_each_entry (cur, &rp_groups, node) - { - we = group_find_window (&cur->mapped_windows, win); - if (we) - { - from = cur; - break; - } - } - - if (we == NULL || from == NULL) - { - PRINT_DEBUG (("Unable to find window in mapped window lists.\n")); - return; - } - - /* Manually remove the window from one group...*/ - numset_release (from->numset, we->number); - list_del (&we->node); - - /* and shove it into the other one. */ - we->number = numset_request (to->numset); - group_insert_window (&to->mapped_windows, we); -} - -void -groups_merge (rp_group *from, rp_group *to) -{ - rp_window_elem *cur; - struct list_head *iter, *tmp; - - /* Merging a group with itself makes no sense. */ - if (from == to) - return; - - /* Move the unmapped windows. */ - list_for_each_safe_entry (cur, iter, tmp, &from->unmapped_windows, node) - { - list_del (&cur->node); - list_add_tail (&cur->node, &to->unmapped_windows); - } - - /* Move the mapped windows. */ - list_for_each_safe_entry (cur, iter, tmp, &from->mapped_windows, node) - { - numset_release (from->numset, cur->number); - list_del (&cur->node); - - cur->number = numset_request (to->numset); - group_insert_window (&to->mapped_windows, cur); - } -} - -void -set_current_group (rp_group *g) -{ - if (rp_current_group == g || g == NULL) - return; - - set_current_group_1 (g); - - /* Call the switch group hook. */ - hook_run (&rp_switch_group_hook); -} - -int -group_delete_group (rp_group *g) -{ - if (list_empty (&(g->mapped_windows)) - && list_empty (&(g->unmapped_windows))) - { - /* don't delete the last group */ - if (list_size (&rp_groups) == 1) - return GROUP_DELETE_LAST_GROUP; - - /* we can safely delete the group */ - if (g == rp_current_group) - { - rp_group *next = group_last_group (); - set_current_group (next ? next : group_next_group ()); - } - - list_del (&(g->node)); - group_free (g); - return GROUP_DELETE_GROUP_OK; - } - else - { - return GROUP_DELETE_GROUP_NONEMPTY; - } -} - -/* Used by :cother / :iother */ -rp_window * -group_last_window_by_class (rp_group *g, char *class) -{ - int last_access = 0; - rp_window_elem *most_recent = NULL; - rp_window_elem *cur; - rp_screen *s = current_screen(); - - list_for_each_entry (cur, &g->mapped_windows, node) - { - if (cur->win->last_access >= last_access - && cur->win != current_window() - && !find_windows_frame (cur->win) - && (cur->win->scr == s || rp_have_xinerama) - && strcmp(class, cur->win->res_class)) - { - most_recent = cur; - last_access = cur->win->last_access; - } - } - - if (most_recent) - return most_recent->win; - - return NULL; -} - -/* Used by :cother / :iother */ -rp_window * -group_last_window_by_class_complement (rp_group *g, char *class) -{ - int last_access = 0; - rp_window_elem *most_recent = NULL; - rp_window_elem *cur; - rp_screen *s = current_screen(); - - list_for_each_entry (cur, &g->mapped_windows, node) - { - if (cur->win->last_access >= last_access - && cur->win != current_window() - && !find_windows_frame (cur->win) - && (cur->win->scr == s || rp_have_xinerama) - && !strcmp(class, cur->win->res_class)) - { - most_recent = cur; - last_access = cur->win->last_access; - } - } - - if (most_recent) - return most_recent->win; - - return NULL; -} diff --git a/src/group.h b/src/group.h deleted file mode 100644 index 364100f..0000000 --- a/src/group.h +++ /dev/null @@ -1,68 +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 - */ - -#ifndef GROUP_H -#define GROUP_H - -void init_groups (void); -void free_groups (void); - -void group_add_window (rp_group *g, rp_window *w); -void group_resort_window (rp_group *g, rp_window_elem *w); -void group_free (rp_group *g); -rp_group *group_new (int number, char *name); -int group_delete_group (rp_group *g); - -void group_del_window (rp_group *g, rp_window *win); -void groups_del_window (rp_window *win); - -void group_map_window (rp_group *g, rp_window *win); -void groups_map_window (rp_window *win); - -void group_unmap_window (rp_group *g, rp_window *win); -void groups_unmap_window (rp_window *win); - -rp_window *group_prev_window (rp_group *g, rp_window *win); -rp_window *group_next_window (rp_group *g, rp_window *win); -rp_group *groups_find_group_by_name (char *s, int exact_match); -rp_group *groups_find_group_by_number (int n); -rp_group *groups_find_group_by_window (rp_window *win); -rp_group *groups_find_group_by_group (rp_group *g); - -rp_window *group_last_window (rp_group *g, rp_screen *screen); - -rp_group *group_prev_group (void); -rp_group *group_next_group (void); -rp_group *group_last_group (void); - -rp_group *group_add_new_group (char *name); -void group_rename (rp_group *g, char *name); - -rp_window_elem *group_find_window (struct list_head *list, rp_window *win); -rp_window_elem *group_find_window_by_number (rp_group *g, int num); - -void group_move_window (rp_group *to, rp_window *win); -void groups_merge (rp_group *from, rp_group *to); - -void set_current_group (rp_group *g); - -rp_window *group_last_window_by_class (rp_group *g, char *class); -rp_window *group_last_window_by_class_complement (rp_group *g, char *class); -#endif diff --git a/src/history.c b/src/history.c deleted file mode 100644 index a63658c..0000000 --- a/src/history.c +++ /dev/null @@ -1,320 +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 <ctype.h> -#include <errno.h> -#include <string.h> -#include <limits.h> - -#include "ratpoison.h" - -#ifdef HAVE_HISTORY -#include "readline/history.h" -#endif - -static char * -get_history_filename (void) -{ - char *homedir = getenv ("HOME"); - char *filename; - - if (homedir) - { - filename = xmalloc (strlen (homedir) + strlen ("/" HISTORY_FILE) + 1); - sprintf (filename, "%s/" HISTORY_FILE, homedir); - } - else - { - filename = xstrdup (HISTORY_FILE); - } - - return filename; -} - -static const char * -extract_shell_part (const char *p) -{ - if (strncmp(p, "exec", 4) && - strncmp(p, "verbexec", 8)) - return NULL; - while( *p && !isspace(*p) ) - p++; - while( *p && isspace(*p) ) - p++; - if (*p) - return p; - return NULL; -} - -struct history_item { - struct list_head node; - char *line; -}; - -static struct history { - struct list_head head, *current; - size_t count; -} histories[hist_COUNT]; - -#ifndef HAVE_GETLINE -ssize_t -getline(char **lineptr, size_t *n, FILE *f) -{ - size_t ofs; - - if (!*lineptr) { - *lineptr = xmalloc (4096); - *n = 4096; - } - ofs = 0; - do { - (*lineptr)[ofs] = '\0'; - if (!fgets (*lineptr, (*n) - ofs, f)) { - /* do not tread unterminated last lines as errors, - * (it's still a malformed text file and noone should - * have created it) */ - return ofs?(ssize_t)ofs:-1; - } - ofs += strlen ((*lineptr) + ofs); - if (ofs >= *n) - /* should never happen... */ - return -1; - if (ofs > 0 && (*lineptr)[ofs-1] == '\n') - return ofs; - if (ofs + 1 == *n) { - if (*n >= INT_MAX - 4096) - return -1; - *n += 4096; - *lineptr = xrealloc(*lineptr, *n); - } - } while(1); -} -#endif - -static void -history_add_upto (int history_id, const char *item, size_t max) -{ - struct history *h = histories + history_id; - struct history_item *i; - - if (item == NULL || *item == '\0' || isspace(*item)) - return; - - list_last (i, &histories[history_id].head, node); - if (i && !strcmp (i->line, item)) - return; - - if (history_id == hist_COMMAND) { - const char *p = extract_shell_part (item); - if (p) - history_add_upto (hist_SHELLCMD, p, max); - } - - if (defaults.history_compaction && max != INT_MAX) { - struct list_head *l; - - for (l = h->head.prev ; l != &h->head ; l = l->prev) { - if (!strcmp (list_entry(l, struct history_item, node)->line, item)) { - list_del (l); - list_add_tail (l, &h->head); - return; - } - } - } - - while (h->count >= max) { - list_first (i, &h->head, node); - if (!i) { - h->count = 0; - break; - } - list_del (&i->node); - free (i->line); - free (i); - h->count--; - } - - if( max == 0 ) - return; - - i = xmalloc (sizeof (*i)); - i->line = xstrdup (item); - - list_add_tail (&i->node, &h->head); - h->count++; -} - -void -history_add (int history_id, const char *item) -{ - history_add_upto (history_id, item, defaults.history_size); -} - -void -history_load (void) -{ - char *filename = get_history_filename (); - FILE *f; - char *line = NULL; - size_t s = 0; - ssize_t linelen; - int id; - - for (id = hist_NONE ; id < hist_COUNT ; id++ ) { - INIT_LIST_HEAD (&histories[id].head); - histories[id].current = &histories[id].head; - histories[id].count = 0; - } - - if (!filename) - return; - f = fopen (filename, "r"); - if (!f) { - PRINT_DEBUG (("ratpoison: could not read %s - %s\n", filename, strerror (errno))); - free (filename); - return; - } - - while ((linelen = getline (&line, &s, f)) >= 0) { - while (linelen > 0 && (line[linelen-1] == '\n' || line[linelen-1] == '\r')) { - line[--linelen] = '\0'; - } - if (linelen == 0) - continue; - /* defaults.history_size might be only set later */ - history_add_upto (hist_COMMAND, line, INT_MAX); - } - if (ferror (f)) { - PRINT_DEBUG (("ratpoison: error reading %s - %s\n", filename, strerror (errno))); - fclose(f); - free (filename); - return; - } - if (!fclose(f)) - PRINT_DEBUG (("ratpoison: error reading %s - %s\n", filename, strerror (errno))); - free (filename); -} - -void -history_save (void) -{ - char *filename = get_history_filename (); - FILE *f; - struct history_item *item; - - if (!defaults.history_size) - return; - - if (!filename) - return; - f = fopen (filename, "w"); - if (!f) { - PRINT_DEBUG (("ratpoison: could not write %s - %s\n", filename, strerror (errno))); - free (filename); - return; - } - - list_for_each_entry(item, &histories[hist_COMMAND].head, node) { - fputs(item->line, f); - putc('\n', f); - } - - if (ferror (f)) { - PRINT_DEBUG (("ratpoison: error writing %s - %s\n", filename, strerror (errno))); - fclose(f); - free (filename); - return; - } - if (!fclose(f)) - PRINT_DEBUG (("ratpoison: error writing %s - %s\n", filename, strerror (errno))); - free (filename); -} - -void -history_reset (void) -{ - int id; - - for (id = hist_NONE ; id < hist_COUNT ; id++ ) - histories[id].current = &histories[id].head; -} - -void -history_resize (int size) -{ - struct history_item *i; - struct history *h; - int id; - - for (id = hist_NONE ; id < hist_COUNT ; id++ ) { - h = histories + id; - while (h->count >= (size_t)size) { - list_first (i, &h->head, node); - list_del (&i->node); - free (i->line); - free (i); - h->count--; - } - } -} - -const char * -history_previous (int history_id) -{ - if (history_id == hist_NONE) - return NULL; - /* return NULL, if list empty or already at first */ - if (histories[history_id].current == histories[history_id].head.next) - return NULL; - histories[history_id].current = histories[history_id].current->prev; - return list_entry(histories[history_id].current, struct history_item, node)->line; -} - -const char * -history_next (int history_id) -{ - if (history_id == hist_NONE) - return NULL; - /* return NULL, if list empty or already behind last */ - if (histories[history_id].current == &histories[history_id].head) - return NULL; - histories[history_id].current = histories[history_id].current->next; - if (histories[history_id].current == &histories[history_id].head) - return NULL; - return list_entry(histories[history_id].current, struct history_item, node)->line; -} - -int history_expand_line (int history_id UNUSED, char *string, char **output) -{ -#ifdef HAVE_HISTORY - struct history_item *item; - - if (strchr (string, '!')) { - clear_history (); - using_history (); - list_for_each_entry(item, &histories[history_id].head, node) { - add_history (item->line); - } - return history_expand (string, output); - } -#endif - *output = xstrdup(string); - return 0; -} diff --git a/src/history.h b/src/history.h deleted file mode 100644 index 193874d..0000000 --- a/src/history.h +++ /dev/null @@ -1,45 +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 - */ - -#ifndef _RATPOISON_HISTORY_H -#define _RATPOISON_HISTORY_H 1 - -enum { hist_NONE=0, hist_COMMAND, hist_SHELLCMD, - hist_SELECT, hist_KEYMAP, hist_KEY, - hist_WINDOW, hist_GRAVITY, hist_GROUP, - hist_HOOK, hist_VARIABLE, hist_PROMPT, - hist_OTHER, - /* must be last, do not use, for length only: */ - hist_COUNT}; - -#ifndef HAVE_GETLINE -ssize_t getline (char **lineptr, size_t *n, FILE *f); -#endif - -void history_load (void); -void history_save (void); -void history_resize (int size); -void history_reset (void); -void history_add (int, const char *item); -const char *history_next (int); -const char *history_previous (int); -int history_expand_line (int, char *string, char **output); - -#endif /* ! _RATPOISON_HISTORY_H */ diff --git a/src/hook.c b/src/hook.c deleted file mode 100644 index 3ff4751..0000000 --- a/src/hook.c +++ /dev/null @@ -1,93 +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 - */ - -/* A hook is simply a list of strings that get passed to command() in - sequence. */ - -#include "ratpoison.h" - -#include <string.h> - -void -hook_add (struct list_head *hook, struct sbuf *s) -{ - struct sbuf *cur; - - /* Check if it's in the list already. */ - list_for_each_entry (cur, hook, node) - { - if (!strcmp (sbuf_get (cur), sbuf_get (s))) - return; - } - - /* It's not in the list, so add it. */ - list_add_tail (&s->node, hook); -} - -void -hook_remove (struct list_head *hook, struct sbuf *s) -{ - struct list_head *tmp, *iter; - struct sbuf *cur; - - /* If it's in the list, delete it. */ - list_for_each_safe_entry (cur, iter, tmp, hook, node) - { - if (!strcmp (sbuf_get (cur), sbuf_get (s))) - { - list_del (&cur->node); - sbuf_free (cur); - } - } -} - -void -hook_run (struct list_head *hook) -{ - struct sbuf *cur; - cmdret *result; - - list_for_each_entry (cur, hook, node) - { - result = command (1, sbuf_get (cur)); - if (result) - { - if (result->output) - message (result->output); - cmdret_free (result); - } - } -} - -struct list_head * -hook_lookup (char *s) -{ - struct rp_hook_db_entry *entry; - - for (entry = rp_hook_db; entry->name; entry++) - { - if (!strcmp (s, entry->name)) - { - return entry->hook; - } - } - - return NULL; -} diff --git a/src/hook.h b/src/hook.h deleted file mode 100644 index da53428..0000000 --- a/src/hook.h +++ /dev/null @@ -1,29 +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 - */ - -#ifndef HOOKS_H -#define HOOKS_H - -void hook_run (struct list_head *hook); -void hook_remove (struct list_head *hook, struct sbuf *s); -void hook_add (struct list_head *hook, struct sbuf *s); -struct list_head *hook_lookup (char *s); - -#endif diff --git a/src/input.c b/src/input.c deleted file mode 100644 index 5757bf7..0000000 --- a/src/input.c +++ /dev/null @@ -1,622 +0,0 @@ -/* Read kdb input from the user. - * 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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <X11/Xlib.h> -#include <X11/keysym.h> -#include <X11/Xutil.h> - -#include "ratpoison.h" - -/* Convert an X11 modifier mask to the rp modifier mask equivalent, as - best it can (the X server may not have a hyper key defined, for - instance). */ -unsigned int -x11_mask_to_rp_mask (unsigned int mask) -{ - unsigned int result = 0; - - PRINT_DEBUG (("x11 mask = %x\n", mask)); - - result |= mask & ShiftMask ? RP_SHIFT_MASK:0; - result |= mask & ControlMask ? RP_CONTROL_MASK:0; - result |= mask & rp_modifier_info.meta_mod_mask ? RP_META_MASK:0; - result |= mask & rp_modifier_info.alt_mod_mask ? RP_ALT_MASK:0; - result |= mask & rp_modifier_info.hyper_mod_mask ? RP_HYPER_MASK:0; - result |= mask & rp_modifier_info.super_mod_mask ? RP_SUPER_MASK:0; - - PRINT_DEBUG (("rp mask = %x\n", mask)); - - return result; -} - -/* Convert an rp modifier mask to the x11 modifier mask equivalent, as - best it can (the X server may not have a hyper key defined, for - instance). */ -unsigned int -rp_mask_to_x11_mask (unsigned int mask) -{ - unsigned int result = 0; - - PRINT_DEBUG (("rp mask = %x\n", mask)); - - result |= mask & RP_SHIFT_MASK ? ShiftMask:0; - result |= mask & RP_CONTROL_MASK ? ControlMask:0; - result |= mask & RP_META_MASK ? rp_modifier_info.meta_mod_mask:0; - result |= mask & RP_ALT_MASK ? rp_modifier_info.alt_mod_mask:0; - result |= mask & RP_HYPER_MASK ? rp_modifier_info.hyper_mod_mask:0; - result |= mask & RP_SUPER_MASK ? rp_modifier_info.super_mod_mask:0; - - PRINT_DEBUG (("x11 mask = %x\n", result)); - - return result; -} - - -/* /\* The caller is responsible for freeing the keycodes. *\/ */ -/* KeyCode * */ -/* keysym_to_keycodes (KeySym sym, int *n_returned) */ -/* { */ -/* int min_code, max_code; */ -/* int syms_per_code; */ -/* KeySym *syms; */ -/* KeyCode *codes; */ -/* int code, code_col; */ - -/* XDisplayKeycodes (dpy, &min_code, &max_code); */ -/* syms = XGetKeyboardMapping (dpy, */ -/* min_code, max_code - min_code + 1, */ -/* &syms_per_code); */ - -/* *n_returned = 0; */ -/* codes = (KeyCode *)xmalloc (sizeof(KeyCode) * n_returned); */ -/* for (code = min_code; code < max_code; code++) */ -/* for (code_col = 0; code_col < syms_per_code; code_col++) */ -/* { */ -/* int s = syms[((code - min_code) * syms_per_code) + code_col]; */ - -/* if (sym == s) */ -/* { */ -/* n_returned++; */ -/* codes = (KeyCode *)xrealloc (sizeof(KeyCode) * n_returned); */ -/* codes[n_returned-1] = code; */ -/* } */ -/* } */ - -/* XFree ((char *) syms); */ - -/* if (n_returned > 0) */ -/* return codes; */ -/* else */ -/* { */ -/* xfree (codes) */ -/* return NULL; */ -/* } */ -/* } */ - -/* Figure out what keysyms are attached to what modifiers */ -void -update_modifier_map (void) -{ - unsigned int modmasks[] = - { Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask }; - int row, col; /* The row and column in the modifier table. */ - int found_alt_or_meta; - XModifierKeymap *mods; - int min_code, max_code; - int syms_per_code; - KeySym *syms; - - rp_modifier_info.meta_mod_mask = 0; - rp_modifier_info.alt_mod_mask = 0; - rp_modifier_info.super_mod_mask = 0; - rp_modifier_info.hyper_mod_mask = 0; - rp_modifier_info.num_lock_mask = 0; - rp_modifier_info.scroll_lock_mask = 0; - - XDisplayKeycodes (dpy, &min_code, &max_code); - syms = XGetKeyboardMapping (dpy, - min_code, max_code - min_code + 1, - &syms_per_code); - mods = XGetModifierMapping (dpy); - - for (row=3; row < 8; row++) - { - found_alt_or_meta = 0; - for (col=0; col < mods->max_keypermod; col++) - { - KeyCode code = mods->modifiermap[(row * mods->max_keypermod) + col]; - - PRINT_DEBUG (("row: %d col: %d code: %d\n", row, col, code)); - - if (code == 0) continue; - - /* Are any of this keycode's keysyms a meta key? */ - { - int code_col; - - for (code_col = 0; code_col < syms_per_code; code_col++) - { - int sym = syms[((code - min_code) * syms_per_code) + code_col]; - - switch (sym) - { - case XK_Meta_L: - case XK_Meta_R: - found_alt_or_meta = 1; - rp_modifier_info.meta_mod_mask |= modmasks[row - 3]; - PRINT_DEBUG (("Found Meta on %d\n", - rp_modifier_info.meta_mod_mask)); - break; - - case XK_Alt_L: - case XK_Alt_R: - found_alt_or_meta = 1; - rp_modifier_info.alt_mod_mask |= modmasks[row - 3]; - PRINT_DEBUG (("Found Alt on %d\n", - rp_modifier_info.alt_mod_mask)); - break; - - case XK_Super_L: - case XK_Super_R: - if (!found_alt_or_meta) - { - rp_modifier_info.super_mod_mask |= modmasks[row - 3]; - PRINT_DEBUG (("Found Super on %d\n", - rp_modifier_info.super_mod_mask)); - } - code_col = syms_per_code; - col = mods->max_keypermod; - break; - - case XK_Hyper_L: - case XK_Hyper_R: - if (!found_alt_or_meta) - { - rp_modifier_info.hyper_mod_mask |= modmasks[row - 3]; - PRINT_DEBUG (("Found Hyper on %d\n", - rp_modifier_info.hyper_mod_mask)); - } - code_col = syms_per_code; - col = mods->max_keypermod; - - break; - - case XK_Num_Lock: - rp_modifier_info.num_lock_mask |= modmasks[row - 3]; - PRINT_DEBUG (("Found NumLock on %d\n", - rp_modifier_info.num_lock_mask)); - break; - - case XK_Scroll_Lock: - rp_modifier_info.scroll_lock_mask |= modmasks[row - 3]; - PRINT_DEBUG (("Found ScrollLock on %d\n", - rp_modifier_info.scroll_lock_mask)); - break; - default: - break; - } - } - } - } - } - - /* Stolen from Emacs 21.0.90 - xterm.c */ - /* If we couldn't find any meta keys, accept any alt keys as meta keys. */ - if (! rp_modifier_info.meta_mod_mask) - { - rp_modifier_info.meta_mod_mask = rp_modifier_info.alt_mod_mask; - rp_modifier_info.alt_mod_mask = 0; - } - - /* If some keys are both alt and meta, - make them just meta, not alt. */ - if (rp_modifier_info.alt_mod_mask & rp_modifier_info.meta_mod_mask) - { - rp_modifier_info.alt_mod_mask &= ~rp_modifier_info.meta_mod_mask; - } - - XFree ((char *) syms); - XFreeModifiermap (mods); -} - -/* we need a keycode + modifier to generate the proper keysym (such as - @). Return 1 if successful, 0 otherwise. This function can fail if a - keysym doesn't map to a keycode. */ -static int -keysym_to_keycode_mod (KeySym keysym, KeyCode *code, unsigned int *mod) -{ - KeySym lower, upper; - - *mod = 0; - *code = XKeysymToKeycode (dpy, keysym); - lower = XKeycodeToKeysym (dpy, *code, 0); - upper = XKeycodeToKeysym (dpy, *code, 1); - /* If you need to press shift to get the keysym, add the shift - mask. */ - if (upper == keysym && lower != keysym) - *mod = ShiftMask; - - return *code != 0; -} - -/* Grab the key while ignoring annoying modifier keys including - caps lock, num lock, and scroll lock. */ -void -grab_key (KeySym keysym, unsigned int modifiers, Window grab_window) -{ - unsigned int mod_list[8]; - int i; - KeyCode keycode; - unsigned int mod; - - /* Convert to a modifier mask that X Windows will understand. */ - modifiers = rp_mask_to_x11_mask (modifiers); - if (!keysym_to_keycode_mod (keysym, &keycode, &mod)) - return; - PRINT_DEBUG (("keycode_mod: %ld %d %d\n", keysym, keycode, mod)); - modifiers |= mod; - - /* Create a list of all possible combinations of ignored - modifiers. Assumes there are only 3 ignored modifiers. */ - mod_list[0] = 0; - mod_list[1] = LockMask; - mod_list[2] = rp_modifier_info.num_lock_mask; - mod_list[3] = mod_list[1] | mod_list[2]; - mod_list[4] = rp_modifier_info.scroll_lock_mask; - mod_list[5] = mod_list[1] | mod_list[4]; - mod_list[6] = mod_list[2] | mod_list[4]; - mod_list[7] = mod_list[1] | mod_list[2] | mod_list[4]; - - /* Grab every combination of ignored modifiers. */ - for (i=0; i<8; i++) - { - XGrabKey(dpy, keycode, modifiers | mod_list[i], - grab_window, True, GrabModeAsync, GrabModeAsync); - } -} - - -/* Return the name of the keysym. caller must free returned pointer */ -char * -keysym_to_string (KeySym keysym, unsigned int modifier) -{ - static char *null_string = "NULL"; /* A NULL string. */ - struct sbuf *name; - char *tmp; - - name = sbuf_new (0); - - if (modifier & RP_SHIFT_MASK) sbuf_concat (name, "S-"); - if (modifier & RP_CONTROL_MASK) sbuf_concat (name, "C-"); - if (modifier & RP_META_MASK) sbuf_concat (name, "M-"); - if (modifier & RP_ALT_MASK) sbuf_concat (name, "A-"); - if (modifier & RP_HYPER_MASK) sbuf_concat (name, "H-"); - if (modifier & RP_SUPER_MASK) sbuf_concat (name, "s-"); - - /* On solaris machines (perhaps other machines as well) this call - can return NULL. In this case use the "NULL" string. */ - tmp = XKeysymToString (keysym); - if (tmp == NULL) - tmp = null_string; - - sbuf_concat (name, tmp); - - /* Eat the nut and throw away the shells. */ - tmp = sbuf_get (name); - free (name); - - return tmp; -} - -/* Cooks a keycode + modifier into a keysym + modifier. This should be - used anytime meaningful key information is to be extracted from a - KeyPress or KeyRelease event. - - returns the number of bytes in keysym_name. If you are not - interested in the keysym name pass in NULL for keysym_name and 0 - for len. */ -int -cook_keycode (XKeyEvent *ev, KeySym *keysym, unsigned int *mod, char *keysym_name, int len, int ignore_bad_mods) -{ - int nbytes; - int shift = 0; - KeySym lower, upper; - - if (ignore_bad_mods) - { - ev->state &= ~(LockMask - | rp_modifier_info.num_lock_mask - | rp_modifier_info.scroll_lock_mask); - } - - if (len > 0) len--; - nbytes = XLookupString (ev, keysym_name, len, keysym, NULL); - - /* Null terminate the string (not all X servers do it for us). */ - if (keysym_name) { - keysym_name[nbytes] = '\0'; - } - - /* Find out if XLookupString gobbled the shift modifier */ - if (ev->state & ShiftMask) - { - lower = XKeycodeToKeysym (dpy, ev->keycode, 0); - upper = XKeycodeToKeysym (dpy, ev->keycode, 1); - /* If the keysym isn't affected by the shift key, then keep the - shift modifier. */ - if (lower == upper) - shift = ShiftMask; - } - - *mod = ev->state; - *mod &= (rp_modifier_info.meta_mod_mask - | rp_modifier_info.alt_mod_mask - | rp_modifier_info.hyper_mod_mask - | rp_modifier_info.super_mod_mask - | ControlMask - | shift); - - return nbytes; -} - -/* Wait for a key and discard it. */ -void -read_any_key () -{ - char buffer[513]; - unsigned int mod; - KeySym c; - - read_single_key (&c, &mod, buffer, sizeof (buffer)); -} - -/* The same as read_key, but handle focusing the key_window and reverting focus. */ -int -read_single_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) -{ - Window focus; - int revert; - int nbytes; - - XGetInputFocus (dpy, &focus, &revert); - set_window_focus (current_screen()->key_window); - nbytes = read_key (keysym, modifiers, keysym_name, len); - set_window_focus (focus); - - return nbytes; -} - -int -read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len) -{ - XEvent ev; - int nbytes; - - /* Read a key from the keyboard. */ - do - { - XMaskEvent (dpy, KeyPressMask|KeyRelease, &ev); - *modifiers = ev.xkey.state; - nbytes = cook_keycode (&ev.xkey, keysym, modifiers, keysym_name, len, 0); - } while (IsModifierKey (*keysym) || ev.xkey.type == KeyRelease); - - return nbytes; -} - -static void -update_input_window (rp_screen *s, rp_input_line *line) -{ - int prompt_width, input_width, total_width; - int char_len = 0, height; - GC lgc; - XGCValues gcv; - - prompt_width = rp_text_width (s, line->prompt, -1); - input_width = rp_text_width (s, line->buffer, line->length); - total_width = defaults.bar_x_padding * 2 + prompt_width + input_width + MAX_FONT_WIDTH (defaults.font); - height = (FONT_HEIGHT (s) + defaults.bar_y_padding * 2); - - if (RP_IS_UTF8_START (line->buffer[line->position])) - do - char_len++; - while (RP_IS_UTF8_CONT (line->buffer[line->position + char_len])); - else - char_len = 1; - - if (total_width < defaults.input_window_size + prompt_width) - { - total_width = defaults.input_window_size + prompt_width; - } - - XMoveResizeWindow (dpy, s->input_window, - bar_x (s, total_width), bar_y (s, height), total_width, - (FONT_HEIGHT (s) + defaults.bar_y_padding * 2)); - - XClearWindow (dpy, s->input_window); - XSync (dpy, False); - - rp_draw_string (s, s->input_window, STYLE_NORMAL, - defaults.bar_x_padding, - defaults.bar_y_padding + FONT_ASCENT(s), - line->prompt, - -1); - - rp_draw_string (s, s->input_window, STYLE_NORMAL, - defaults.bar_x_padding + prompt_width, - defaults.bar_y_padding + FONT_ASCENT(s), - line->buffer, - line->length); - - gcv.function = GXxor; - gcv.foreground = s->fg_color ^ s->bg_color; - lgc = XCreateGC (dpy, s->input_window, GCFunction | GCForeground, &gcv); - - /* Draw a cheap-o cursor - MkIII */ - XFillRectangle (dpy, s->input_window, lgc, - defaults.bar_x_padding + prompt_width + - rp_text_width (s, line->buffer, line->position), - defaults.bar_y_padding, - rp_text_width (s, &line->buffer[line->position], char_len), - FONT_HEIGHT (s)); - - XFlush (dpy); - XFreeGC (dpy, lgc); -} - -void -ring_bell (void) -{ -#ifdef VISUAL_BELL - GC lgc; - XGCValues gcv; - XWindowAttributes attr; - rp_screen *s = current_screen (); - - XGetWindowAttributes (dpy, s->input_window, &attr); - - gcv.function = GXxor; - gcv.foreground = s->fg_color ^ s->bg_color; - lgc = XCreateGC (dpy, s->input_window, GCFunction | GCForeground, &gcv); - - XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height); - XFlush (dpy); - -#ifdef HAVE_USLEEP - usleep (15000); -#else - { - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 15000; - select (0, NULL, NULL, NULL, &tv); - } -#endif - XFillRectangle (dpy, s->input_window, lgc, 0, 0, attr.width, attr.height); - XFlush (dpy); - XFreeGC (dpy, lgc); -#else - XBell (dpy, 0); -#endif -} - -char * -get_input (char *prompt, int history_id, completion_fn fn) -{ - return get_more_input (prompt, "", history_id, fn); -} - -char * -get_more_input (char *prompt, char *preinput, int history_id, - completion_fn compl_fn) -{ - /* Emacs 21 uses a 513 byte string to store the keysym name. */ - char keysym_buf[513]; - rp_screen *s = current_screen (); - KeySym ch; - unsigned int modifier; - rp_input_line *line; - char *final_input; - edit_status status; - Window focus; - int revert, done = 0; - - history_reset(); - - /* Create our line structure */ - line = input_line_new (prompt, preinput, history_id, compl_fn); - - /* We don't want to draw overtop of the program bar. */ - hide_bar (s); - - /* Switch to the default colormap. */ - if (current_window()) - XUninstallColormap (dpy, current_window()->colormap); - XInstallColormap (dpy, s->def_cmap); - - XMapWindow (dpy, s->input_window); - XRaiseWindow (dpy, s->input_window); - XClearWindow (dpy, s->input_window); - /* Switch focus to our input window to read the next key events. */ - XGetInputFocus (dpy, &focus, &revert); - set_window_focus (s->input_window); - XSync (dpy, False); - - update_input_window (s, line); - - while (!done) - { - read_key (&ch, &modifier, keysym_buf, sizeof (keysym_buf)); - modifier = x11_mask_to_rp_mask (modifier); - PRINT_DEBUG (("ch = %ld, modifier = %d, keysym_buf = %s", - ch, modifier, keysym_buf)); - status = execute_edit_action (line, ch, modifier, keysym_buf); - - switch (status) - { - case EDIT_COMPLETE: - case EDIT_DELETE: - case EDIT_INSERT: - case EDIT_MOVE: - /* If the text changed (and we didn't just complete - something) then set the virgin bit. */ - if (status != EDIT_COMPLETE) - line->compl->virgin = 1; - /* In all cases, we need to redisplay the input string. */ - update_input_window (s, line); - break; - case EDIT_NO_OP: - ring_bell (); - break; - case EDIT_ABORT: - final_input = NULL; - done = 1; - break; - case EDIT_DONE: - final_input = xstrdup (line->buffer); - done = 1; - break; - default: - PRINT_ERROR (("Unhandled status %d; this is a *BUG*\n", status)); - exit (EXIT_FAILURE); - } - } - - /* Clean up our line structure */ - input_line_free (line); - - /* Revert focus. */ - set_window_focus (focus); - XUnmapWindow (dpy, s->input_window); - - /* Possibly restore colormap. */ - if (current_window()) - { - XUninstallColormap (dpy, s->def_cmap); - XInstallColormap (dpy, current_window()->colormap); - } - - return final_input; -} diff --git a/src/input.h b/src/input.h deleted file mode 100644 index 5beb96e..0000000 --- a/src/input.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Function prototypes. - * 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 - */ - -#ifndef _RATPOISON_INPUT_H -#define _RATPOISON_INPUT_H 1 - -char *keysym_to_string (KeySym keysym, unsigned int modifier); -int cook_keycode (XKeyEvent *ev, KeySym *keysym, unsigned int *mod, char *keysym_name, int len, int ignore_bad_mods); -char *get_input (char *prompt, int history_id, completion_fn fn); -char *get_more_input (char *prompt, char *preinput, int history_id, completion_fn fn); -void read_any_key (void); -int read_single_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len); -int read_key (KeySym *keysym, unsigned int *modifiers, char *keysym_name, int len); -unsigned int x11_mask_to_rp_mask (unsigned int mask); -unsigned int rp_mask_to_x11_mask (unsigned int mask); -void update_modifier_map (void); -void grab_key (KeySym keysym, unsigned int modifiers, Window grab_window); - -void ring_bell (void); - -#endif /* ! _RATPOISON_INPUT_H */ diff --git a/src/linkedlist.c b/src/linkedlist.c deleted file mode 100644 index ae3d143..0000000 --- a/src/linkedlist.c +++ /dev/null @@ -1,204 +0,0 @@ -/* This file was taken from the Linux kernel and is - * Copyright (C) 2003 Linus Torvalds - * - * Modified by Shawn Betts. Portions created by Shawn Betts are - * Copyright (C) 2003, 2004 Shawn Betts - * - * 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 "linkedlist.h" - -#if __GNUC__ <= 3 -void -prefetch(const void *x) -{;} -#endif - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -void -__list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -void -list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -void -list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -void -__list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. - */ -void -list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -void -list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -void -list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -void -list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -int -list_empty(struct list_head *head) -{ - return head->next == head; -} - -void -__list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -void -list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -void -list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -int -list_size (struct list_head *list) -{ - struct list_head *cur; - - int i = 0; - list_for_each (cur, list) - i++; - - return i; -} diff --git a/src/linkedlist.h b/src/linkedlist.h deleted file mode 100644 index 4434766..0000000 --- a/src/linkedlist.h +++ /dev/null @@ -1,215 +0,0 @@ -/* This file was taken from the Linux kernel and is - * Copyright (C) 2003 Linus Torvalds - * - * Modified by Shawn Betts. Portions created by Shawn Betts are - * Copyright (C) 2003, 2004 Shawn Betts - * - * 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 - */ - -#ifndef _RATPOISON_LINKLIST_H -#define _RATPOISON_LINKLIST_H - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* Prototypes of C functions. */ -int list_size (struct list_head *list); -void list_splice_init(struct list_head *list, - struct list_head *head); - -void list_splice_init(struct list_head *list, - struct list_head *head); - -void list_splice(struct list_head *list, struct list_head *head); - -void __list_splice(struct list_head *list, - struct list_head *head); - -int list_empty(struct list_head *head); - -void list_move_tail(struct list_head *list, - struct list_head *head); - -void list_move(struct list_head *list, struct list_head *head); - -void list_del_init(struct list_head *entry); -void list_del(struct list_head *entry); -void __list_del(struct list_head * prev, struct list_head * next); -void list_add_tail(struct list_head *new, struct list_head *head); -void list_add(struct list_head *new, struct list_head *head); -void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next); -#if __GNUC__ > 3 -#define prefetch __builtin_prefetch -#else -void prefetch(const void *x); -#endif - -/* Return the last element in the list. */ -#define list_last(last, head, member) \ -{ \ - last = list_entry((head)->prev, typeof(*last), member); \ - if (&last->member == (head)) \ - last = NULL; \ -} - - -/** - * container_of - cast a member of a structure out to the containing structure - * - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) - - -/** - * __list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - * - * This variant differs from list_for_each() in that it's the - * simplest possible list iteration code, no prefetching is done. - * Use this for code that knows the list to be very short (empty - * or 1 entry) most of the time. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \ - pos = pos->prev, prefetch(pos->prev)) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -#define list_for_each_safe_entry(item, pos, n, head, member) \ - for (pos = (head)->next, \ - item = list_entry(pos, typeof(*item), member), \ - n = pos->next \ - ; \ - pos != (head) \ - ; \ - pos = n, \ - item = list_entry(pos, typeof(*item), member), \ - n = pos->next) \ - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - prefetch(pos->member.next); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member), \ - prefetch(pos->member.next)) - -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, \ - n = list_entry(pos->member.next, typeof(*pos), member)) - -#define list_direction_entry(pos, head, member, direction) \ -({ \ - typeof(pos) ret = NULL; \ - struct list_head *a_head = head; \ - if (pos->member.direction == a_head) { \ - ret = list_entry(a_head->direction, \ - typeof(*pos), member); \ - } else { \ - ret = list_entry(pos->member.direction, \ - typeof(*pos), member); \ - } \ - ret; \ -}) - -#define list_next_entry(pos, head, member) \ - list_direction_entry(pos, head, member, next) - -#define list_prev_entry(pos, head, member) \ - list_direction_entry(pos, head, member, prev) - -#define list_for_each_entry_prev(pos, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - prefetch(pos->member.prev); \ - &pos->member != (head); \ - pos = list_entry(pos->member.prev, typeof(*pos), member), \ - prefetch(pos->member.prev)) - -#endif - - -/* Return the first element in the list. */ -#define list_first(first, head, member) \ -{ \ - first = list_entry((head)->next, typeof(*first), member); \ - if (&first->member == (head)) \ - first = NULL; \ -} diff --git a/src/main.c b/src/main.c deleted file mode 100644 index de2a793..0000000 --- a/src/main.c +++ /dev/null @@ -1,863 +0,0 @@ -/* Ratpoison. - * 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 <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/Xproto.h> -#include <X11/cursorfont.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include <getopt.h> -#include <string.h> -#include <sys/wait.h> -#include <ctype.h> - -#include "ratpoison.h" - -#ifdef HAVE_LANGINFO_CODESET -# include <langinfo.h> -#endif - -/* Several systems seem not to have WAIT_ANY defined, so define it if - it isn't. */ -#ifndef WAIT_ANY -# define WAIT_ANY -1 -#endif - -/* Command line options */ -static struct option ratpoison_longopts[] = - { {"help", no_argument, 0, 'h'}, - {"interactive", no_argument, 0, 'i'}, - {"version", no_argument, 0, 'v'}, - {"command", required_argument, 0, 'c'}, - {"display", required_argument, 0, 'd'}, - {"screen", required_argument, 0, 's'}, - {"file", required_argument, 0, 'f'}, - {0, 0, 0, 0} }; - -static char ratpoison_opts[] = "hvic:d:s:f:"; - -void -fatal (const char *msg) -{ - fprintf (stderr, "ratpoison: %s", msg); - abort (); -} - -void * -xmalloc (size_t size) -{ - register void *value = malloc (size); - if (value == 0) - fatal ("Virtual memory exhausted"); - return value; -} - -void * -xrealloc (void *ptr, size_t size) -{ - register void *value = realloc (ptr, size); - if (value == 0) - fatal ("Virtual memory exhausted"); - return value; -} - -char * -xstrdup (const char *s) -{ - char *value; - value = strdup (s); - if (value == 0) - fatal ("Virtual memory exhausted"); - return value; -} - -/* Return a new string based on fmt. */ -char * -xvsprintf (char *fmt, va_list ap) -{ - int size, nchars; - char *buffer; - va_list ap_copy; - - /* A resonable starting value. */ - size = strlen (fmt) + 1; - buffer = (char *)xmalloc (size); - - while (1) - { -#if defined(va_copy) - va_copy (ap_copy, ap); -#elif defined(__va_copy) - __va_copy (ap_copy, ap); -#else - /* If there is no copy macro then this MAY work. On some systems - this could fail because va_list is a pointer so assigning one - to the other as below wouldn't make a copy of the data, but - just the pointer to the data. */ - ap_copy = ap; -#endif - nchars = vsnprintf (buffer, size, fmt, ap_copy); -#if defined(va_copy) || defined(__va_copy) - va_end (ap_copy); -#endif - - if (nchars > -1 && nchars < size) - return buffer; - else if (nchars > -1) - size = nchars + 1; - /* c99 says -1 is an error other than truncation, - * which thus will not go away with a larger buffer. - * To support older system but not making errors fatal - * (ratpoison will abort when trying to get too much memory otherwise), - * try to increase a bit but not too much: */ - else if (size < MAX_LEGACY_SNPRINTF_SIZE) - size *= 2; - else - { - free(buffer); - break; - } - - /* Resize the buffer and try again. */ - buffer = (char *)xrealloc (buffer, size); - } - - return xstrdup("<FAILURE>"); -} - -/* Return a new string based on fmt. */ -char * -xsprintf (char *fmt, ...) -{ - char *buffer; - va_list ap; - - va_start (ap, fmt); - buffer = xvsprintf (fmt, ap); - va_end (ap); - - return buffer; -} - -/* strtok but do it for whitespace and be locale compliant. */ -char * -strtok_ws (char *s) -{ - char *nonws; - static char *last = NULL; - - if (s == NULL) - last = s; - else if (last == NULL) - { - PRINT_ERROR (("strtok_ws() called but not initalized, this is a *BUG*\n")); - abort(); - } - - /* skip to first non-whitespace char. */ - while (*last && isspace (*last)) last++; - - /* If we reached the end of the string here then there is no more - data. */ - if (*last == '\0') - return NULL; - - /* Now skip to the end of the data. */ - nonws = last; - while (*last && !isspace (*last)) last++; - if (*last) - { - *last = '\0'; - last++; - } - return nonws; -} - -/* A case insensitive strncmp. */ -int -str_comp (char *s1, char *s2, int len) -{ - int i; - - for (i=0; i<len; i++) - if (toupper (s1[i]) != toupper (s2[i])) return 0; - - return 1; -} - -static void -sighandler (int signum UNUSED) -{ - kill_signalled++; -} - -static void -hup_handler (int signum UNUSED) -{ - hup_signalled++; -} - -static void -alrm_handler (int signum UNUSED) -{ - alarm_signalled++; -} - -/* Check for child processes that have quit but haven't been - acknowledged yet. Update their structure. */ -void -check_child_procs (void) -{ - rp_child_info *cur; - int pid, status; - while (1) - { - pid = waitpid (WAIT_ANY, &status, WNOHANG); - if (pid <= 0) - break; - - PRINT_DEBUG(("Child status: %d\n", WEXITSTATUS (status))); - - /* Find the child and update its structure. */ - list_for_each_entry (cur, &rp_children, node) - { - if (cur->pid == pid) - { - cur->terminated = 1; - cur->status = WEXITSTATUS (status); - break; - } - } - - chld_signalled = 1; - } -} - -void -chld_handler (int signum UNUSED) -{ - int serrno; - - serrno = errno; - check_child_procs(); - errno = serrno; -} - -static int -handler (Display *d, XErrorEvent *e) -{ - char error_msg[100]; - - if (e->request_code == X_ChangeWindowAttributes && e->error_code == BadAccess) - { - fprintf(stderr, "ratpoison: There can be only ONE.\n"); - exit(EXIT_FAILURE); - } - -#ifdef IGNORE_BADWINDOW - return 0; -#else - if (ignore_badwindow && e->error_code == BadWindow) return 0; -#endif - - XGetErrorText (d, e->error_code, error_msg, sizeof (error_msg)); - fprintf (stderr, "ratpoison: ERROR: %s!\n", error_msg); - - /* If there is already an error to report, replace it with this new - one. */ - if (rp_error_msg) - free (rp_error_msg); - rp_error_msg = xstrdup (error_msg); - - return 0; -} - -void -set_sig_handler (int sig, void (*action)(int)) -{ - /* use sigaction because SVR4 systems do not replace the signal - handler by default which is a tip of the hat to some god-aweful - ancient code. So use the POSIX sigaction call instead. */ - struct sigaction act; - - /* check setting for sig */ - if (sigaction (sig, NULL, &act)) - { - PRINT_ERROR (("Error %d fetching SIGALRM handler\n", errno )); - } - else - { - /* if the existing action is to ignore then leave it intact - otherwise add our handler */ - if (act.sa_handler != SIG_IGN) - { - act.sa_handler = action; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; - if (sigaction (sig, &act, NULL)) - { - PRINT_ERROR (("Error %d setting SIGALRM handler\n", errno )); - } - } - } -} - -static void -print_version (void) -{ - printf ("%s %s (built %s %s)\n", PACKAGE, VERSION, __DATE__, __TIME__); - printf ("Copyright (C) 2000-2008 Shawn Betts\n\n"); - - exit (EXIT_SUCCESS); -} - -static void -print_help (void) -{ - printf ("Help for %s %s\n\n", PACKAGE, VERSION); - printf ("-h, --help Display this help screen\n"); - printf ("-v, --version Display the version\n"); - printf ("-d, --display <dpy> Set the X display to use\n"); - printf ("-s, --screen <num> Only use the specified screen\n"); - printf ("-c, --command <cmd> Send ratpoison a colon-command\n"); - printf ("-i, --interactive Execute commands in interactive mode\n"); - printf ("-f, --file <file> Specify an alternative configuration file\n\n"); - - printf ("Report bugs to ratpoison-devel@nongnu.org\n\n"); - - exit (EXIT_SUCCESS); -} - -void -set_close_on_exec (FILE *fd) -{ - int fnum = fileno (fd); - int flags = fcntl (fnum, F_GETFD); - if (flags >= 0) - fcntl (fnum, F_SETFD, flags | FD_CLOEXEC); -} - -void -read_rc_file (FILE *file) -{ - char *line; - size_t linesize = 256; - - line = xmalloc (linesize); - - while (getline (&line, &linesize, file) != -1) - { - line[strcspn (line, "\n")] = '\0'; - - PRINT_DEBUG (("rcfile line: %s\n", line)); - - if (*line != '\0' && *line != '#') - { - cmdret *result; - result = command (0, line); - - /* Gobble the result. */ - if (result) - cmdret_free (result); - } - } - - free (line); -} - -static void -read_startup_files (char *alt_rcfile) -{ - char *homedir; - FILE *fileptr = NULL; - - if (alt_rcfile) - { - if ((fileptr = fopen (alt_rcfile, "r")) == NULL) - { - /* we probably don't need to report this, its not an error */ - PRINT_DEBUG (("ratpoison: could not open %s\n", alt_rcfile)); - } - } - else - { - /* first check $HOME/.ratpoisonrc and if that does not exist then try - /etc/ratpoisonrc */ - - homedir = getenv ("HOME"); - if (!homedir) - { - PRINT_ERROR (("ratpoison: $HOME not set!?\n")); - } - else - { - char *filename; - filename = xsprintf ("%s/.ratpoisonrc", homedir); - - if ((fileptr = fopen (filename, "r")) == NULL) - { - /* we probably don't need to report this, its not an error */ - PRINT_DEBUG (("ratpoison: could not open %s\n", filename)); - - if ((fileptr = fopen ("/etc/ratpoisonrc", "r")) == NULL) - { - /* neither is this */ - PRINT_DEBUG (("ratpoison: could not open /etc/ratpoisonrc\n")); - } - } - free (filename); - } - } - - if (fileptr) - { - set_close_on_exec(fileptr); - read_rc_file (fileptr); - fclose (fileptr); - } -} - -/* Odd that we spend so much code on making sure the silly welcome - message is correct. Oh well... */ -static void -show_welcome_message (void) -{ - rp_action *help_action; - char *prefix, *help; - rp_keymap *map; - - prefix = keysym_to_string (prefix_key.sym, prefix_key.state); - - map = find_keymap (ROOT_KEYMAP); - - /* Find the help key binding. */ - help_action = find_keybinding_by_action ("help " ROOT_KEYMAP, map); - if (help_action) - help = keysym_to_string (help_action->key, help_action->state); - else - help = NULL; - - - if (help) - { - /* A little kludge to use ? instead of `question' for the help - key. */ - if (!strcmp (help, "question")) - marked_message_printf (0, 0, MESSAGE_WELCOME, prefix, "?"); - else - marked_message_printf (0, 0, MESSAGE_WELCOME, prefix, help); - - free (help); - } - else - { - marked_message_printf (0, 0, MESSAGE_WELCOME, prefix, ":help"); - } - - free (prefix); -} - -static void -init_defaults (void) -{ - defaults.top_kmap = xstrdup(TOP_KEYMAP); - - defaults.win_gravity = NorthWestGravity; - defaults.trans_gravity = CenterGravity; - defaults.maxsize_gravity = CenterGravity; - - defaults.input_window_size = 200; - defaults.window_border_width = 1; - defaults.bar_x_padding = 4; - defaults.bar_y_padding = 0; - defaults.bar_location = NorthEastGravity; - defaults.bar_timeout = 5; - defaults.bar_border_width = 1; - defaults.bar_in_padding = 0; - - defaults.frame_indicator_timeout = 1; - defaults.frame_resize_unit = 10; - - defaults.padding_left = 0; - defaults.padding_right = 0; - defaults.padding_top = 0; - defaults.padding_bottom = 0; - -#ifdef USE_XFT_FONT - defaults.font_string = xstrdup (DEFAULT_XFT_FONT); -#else - /* Attempt to load a font */ - defaults.font = load_query_font_set (dpy, DEFAULT_FONT); - if (defaults.font == NULL) - { - PRINT_ERROR (("ratpoison: Cannot load font %s.\n", DEFAULT_FONT)); - defaults.font = load_query_font_set (dpy, BACKUP_FONT); - if (defaults.font == NULL) - { - PRINT_ERROR (("ratpoison: Cannot load backup font %s . You lose.\n", BACKUP_FONT)); - exit (EXIT_FAILURE); - } - } - - defaults.font_string = xstrdup (DEFAULT_FONT); - set_extents_of_fontset (defaults.font); -#endif - -#ifdef HAVE_LANGINFO_CODESET - defaults.utf8_locale = !strcmp (nl_langinfo (CODESET), "UTF-8"); -#endif - PRINT_DEBUG (("UTF-8 locale detected: %s\n", - defaults.utf8_locale ? "yes" : "no")); - - defaults.fgcolor_string = xstrdup ("black"); - defaults.bgcolor_string = xstrdup ("white"); - defaults.fwcolor_string = xstrdup ("black"); - defaults.bwcolor_string = xstrdup ("black"); - - defaults.wait_for_key_cursor = 1; - - defaults.window_fmt = xstrdup ("%n%s%t"); - defaults.info_fmt = xstrdup ("(%H, %W) %n(%t)"); - defaults.frame_fmt = xstrdup ("Current Frame"); - - defaults.win_name = WIN_NAME_TITLE; - defaults.startup_message = 1; - defaults.warp = 0; - defaults.window_list_style = STYLE_COLUMN; - - defaults.history_size = 20; - defaults.history_compaction = True; - defaults.history_expansion = False; - defaults.frame_selectors = xstrdup (""); - defaults.maxundos = 20; -} - -int -main (int argc, char *argv[]) -{ - int i; - int c; - char **cmd = NULL; - int cmd_count = 0; - int screen_arg = 0; - int screen_num = 0; - char *display = NULL; - unsigned char interactive = 0; - char *alt_rcfile = NULL; - - setlocale (LC_CTYPE, ""); - if (XSupportsLocale ()) - { - if (!XSetLocaleModifiers ("")) - PRINT_ERROR (("Couldn't set X locale modifiers.\n")); - } - else - PRINT_ERROR (("X doesn't seem to support your locale.\n")); - - /* Parse the arguments */ - myargv = argv; - while (1) - { - int option_index = 0; - - c = getopt_long (argc, argv, ratpoison_opts, ratpoison_longopts, &option_index); - if (c == -1) break; - - switch (c) - { - case 'h': - print_help (); - break; - case 'v': - print_version (); - break; - case 'c': - if (!cmd) - { - cmd = xmalloc (sizeof(char *)); - cmd_count = 0; - } - else - { - cmd = xrealloc (cmd, sizeof (char *) * (cmd_count + 1)); - } - - cmd[cmd_count] = xstrdup (optarg); - cmd_count++; - break; - case 'd': - free (display); - display = xstrdup (optarg); - break; - case 's': - screen_arg = 1; - screen_num = strtol (optarg, NULL, 10); - break; - case 'i': - interactive = 1; - break; - case 'f': - free (alt_rcfile); - alt_rcfile = xstrdup (optarg); - break; - - default: - exit (EXIT_FAILURE); - } - } - - /* Report extra unparsed arguments. */ - if (optind < argc) - { - fprintf (stderr, "Error: junk arguments: "); - while (optind < argc) - fprintf (stderr, "%s ", argv[optind++]); - fputc ('\n', stderr); - exit (EXIT_FAILURE); - } - - if (!(dpy = XOpenDisplay (display))) - { - fprintf (stderr, "Can't open display\n"); - exit (EXIT_FAILURE); - } - - /* Set ratpoison specific Atoms. */ - rp_command = XInternAtom (dpy, "RP_COMMAND", False); - rp_command_request = XInternAtom (dpy, "RP_COMMAND_REQUEST", False); - rp_command_result = XInternAtom (dpy, "RP_COMMAND_RESULT", False); - rp_selection = XInternAtom (dpy, "RP_SELECTION", False); - - /* TEXT atoms */ - xa_string = XA_STRING; - xa_compound_text = XInternAtom(dpy, "COMPOUND_TEXT", False); - xa_utf8_string = XInternAtom(dpy, "UTF8_STRING", False); - - if (cmd_count > 0) - { - int j, screen, exit_status = EXIT_SUCCESS; - - screen = screen_arg ? screen_num : -1; - - for (j = 0; j < cmd_count; j++) - { - if (!send_command (interactive, (unsigned char *)cmd[j], screen)) - exit_status = EXIT_FAILURE; - free (cmd[j]); - } - - free (cmd); - XCloseDisplay (dpy); - return exit_status; - } - - /* Set our Atoms */ - wm_name = XInternAtom(dpy, "WM_NAME", False); - wm_state = XInternAtom(dpy, "WM_STATE", False); - wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False); - wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); - wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False); - wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); - wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); - - /* netwm atoms */ - _net_wm_pid = XInternAtom(dpy, "_NET_WM_PID", False); - PRINT_DEBUG (("_NET_WM_PID = %ld\n", _net_wm_pid)); - _net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False); - PRINT_DEBUG (("_NET_SUPPORTED = %ld\n", _net_supported)); - _net_wm_window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); - _net_wm_window_type_dialog = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - _net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", False); - - /* Setup signal handlers. */ - XSetErrorHandler(handler); - set_sig_handler (SIGALRM, alrm_handler); - set_sig_handler (SIGTERM, sighandler); - set_sig_handler (SIGINT, sighandler); - set_sig_handler (SIGHUP, hup_handler); - set_sig_handler (SIGCHLD, chld_handler); - - /* Add RATPOISON to the environment */ - putenv (xsprintf ("RATPOISON=%s", argv[0])); - - /* Setup ratpoison's internal structures */ - init_globals (); - init_defaults (); - init_groups (); - init_window_stuff (); - init_xinerama (); - init_screens (screen_arg, screen_num); - - init_frame_lists (); - update_modifier_map (); - init_user_commands(); - initialize_default_keybindings (); - history_load (); - - /* Scan for windows */ - if (screen_arg) - { - rp_current_screen = screen_num; - scanwins (&screens[0]); - } - else - { - rp_current_screen = 0; - for (i=0; i<num_screens; i++) - { - scanwins (&screens[i]); - } - } - - read_startup_files (alt_rcfile); - if (alt_rcfile) - free (alt_rcfile); - - /* Indicate to the user that ratpoison has booted. */ - if (defaults.startup_message) - show_welcome_message(); - - /* If no window has focus, give the key_window focus. */ - if (current_window() == NULL) - set_window_focus (current_screen()->key_window); - - listen_for_events (); - - return EXIT_SUCCESS; -} - -static void -free_screen (rp_screen *s) -{ - rp_frame *frame; - struct list_head *iter, *tmp; - - /* Relinquish our hold on the root window. */ - XSelectInput(dpy, RootWindow (dpy, s->screen_num), 0); - - list_for_each_safe_entry (frame, iter, tmp, &s->frames, node) - { - frame_free (s, frame); - } - - deactivate_screen(s); - - XDestroyWindow (dpy, s->bar_window); - XDestroyWindow (dpy, s->key_window); - XDestroyWindow (dpy, s->input_window); - XDestroyWindow (dpy, s->frame_window); - XDestroyWindow (dpy, s->help_window); - -#ifdef USE_XFT_FONT - if (s->xft_font) - { - XftColorFree (dpy, DefaultVisual (dpy, s->screen_num), - DefaultColormap (dpy, s->screen_num), &s->xft_fg_color); - XftColorFree (dpy, DefaultVisual (dpy, s->screen_num), - DefaultColormap (dpy, s->screen_num), &s->xft_bg_color); - XftFontClose (dpy, s->xft_font); - } -#endif - - XFreeCursor (dpy, s->rat); - XFreeColormap (dpy, s->def_cmap); - XFreeGC (dpy, s->normal_gc); - XFreeGC (dpy, s->inverse_gc); - - free (s->display_string); -} - -void -clean_up (void) -{ - int i; - - history_save (); - - free_keymaps (); - free_aliases (); - free_user_commands (); - free_bar (); - free_window_stuff (); - free_groups (); - - for (i=0; i<num_screens; i++) - { - free_screen (&screens[i]); - } - free (screens); - - /* Delete the undo histories */ - while (list_size (&rp_frame_undos) > 0) - { - /* Delete the oldest node */ - rp_frame_undo *cur; - list_last (cur, &rp_frame_undos, node); - del_frame_undo (cur); - } - - /* Free the global frame numset shared by all screens. */ - numset_free (rp_frame_numset); - - free_xinerama(); - -#ifndef USE_XFT_FONT - XFreeFontSet (dpy, defaults.font); -#endif - free (defaults.window_fmt); - - XSetInputFocus (dpy, PointerRoot, RevertToPointerRoot, CurrentTime); - XCloseDisplay (dpy); -} - -void -set_extents_of_fontset (XFontSet font) -{ - XFontSetExtents *extent; - extent = XExtentsOfFontSet(font); - rp_font_ascent = extent->max_logical_extent.height * 9 / 10; - rp_font_descent = extent->max_logical_extent.height / 5; - rp_font_width = extent->max_logical_extent.width; -} - -XFontSet load_query_font_set (Display *disp, const char *fontset_name) -{ - XFontSet fontset; - int missing_charset_count; - char **missing_charset_list; - char *def_string; - - fontset = XCreateFontSet(disp, fontset_name, - &missing_charset_list, &missing_charset_count, - &def_string); - if (missing_charset_count) { - PRINT_DEBUG (("Missing charsets in FontSet(%s) creation.\n", fontset_name)); - XFreeStringList(missing_charset_list); - } - return fontset; -} diff --git a/src/manage.c b/src/manage.c deleted file mode 100644 index f404c13..0000000 --- a/src/manage.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* Manage windows, such as Mapping them and making sure the proper key - * Grabs have been put in place. - * - * 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 <X11/X.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <X11/keysymdef.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "ratpoison.h" - -static char **unmanaged_window_list = NULL; -static int num_unmanaged_windows = 0; - -void -clear_unmanaged_list (void) -{ - if (unmanaged_window_list) - { - int i; - - for (i = 0; i < num_unmanaged_windows; i++) - free(unmanaged_window_list[i]); - - free(unmanaged_window_list); - - unmanaged_window_list = NULL; - } - num_unmanaged_windows = 0; -} - -char * -list_unmanaged_windows (void) -{ - char *tmp = NULL; - if (unmanaged_window_list) - { - char *tpos; - int len = 0; - int i; - - for (i = 0; i < num_unmanaged_windows; i++) - len += (strlen(unmanaged_window_list[i]) + 1); - - tmp = xmalloc(len + 1); - tpos = tmp; - - for (i = 0; i < num_unmanaged_windows; i++) - { - sprintf(tpos, "%s\n", unmanaged_window_list[i]); - tpos += strlen(unmanaged_window_list[i])+1; - } - tpos--; - *tpos = '\0'; - } - return tmp; -} - -void -add_unmanaged_window (char *name) -{ - char **tmp; - - if (!name) return; - - tmp = xmalloc((num_unmanaged_windows + 1) * sizeof(char *)); - - if (unmanaged_window_list) - { - memcpy(tmp, unmanaged_window_list, num_unmanaged_windows * sizeof(char *)); - free(unmanaged_window_list); - } - - tmp[num_unmanaged_windows] = xstrdup(name); - num_unmanaged_windows++; - - unmanaged_window_list = tmp; -} - -extern Atom wm_state; - -void -grab_top_level_keys (Window w) -{ -#ifdef HIDE_MOUSE - XGrabKey(dpy, AnyKey, AnyModifier, w, True, - GrabModeAsync, GrabModeAsync); -#else - rp_keymap *map = find_keymap (defaults.top_kmap); - int i; - - if (map == NULL) - { - PRINT_ERROR (("Unable to find %s level keymap\n", defaults.top_kmap)); - return; - } - - PRINT_DEBUG(("grabbing top level key\n")); - for (i=0; i<map->actions_last; i++) - { - PRINT_DEBUG(("%d\n", i)); - grab_key (map->actions[i].key, map->actions[i].state, w); - } -#endif -} - -void -ungrab_top_level_keys (Window w) -{ - XUngrabKey(dpy, AnyKey, AnyModifier, w); -} - -void -ungrab_keys_all_wins (void) -{ - rp_window *cur; - - /* Remove the grab on the current prefix key */ - list_for_each_entry (cur, &rp_mapped_window, node) - { - ungrab_top_level_keys (cur->w); - } -} - -void -grab_keys_all_wins (void) -{ - rp_window *cur; - - /* Remove the grab on the current prefix key */ - list_for_each_entry (cur, &rp_mapped_window, node) - { - grab_top_level_keys (cur->w); - } -} - -rp_screen* -current_screen (void) -{ - int i; - - for (i=0; i<num_screens; i++) - { - if (screens[i].xine_screen_num == rp_current_screen) - return &screens[i]; - } - - /* This should never happen. */ - return &screens[0]; -} - -void -update_normal_hints (rp_window *win) -{ - long supplied; - - XGetWMNormalHints (dpy, win->w, win->hints, &supplied); - - /* Print debugging output for window hints. */ -#ifdef DEBUG - if (win->hints->flags & PMinSize) - PRINT_DEBUG (("minx: %d miny: %d\n", win->hints->min_width, win->hints->min_height)); - - if (win->hints->flags & PMaxSize) - PRINT_DEBUG (("maxx: %d maxy: %d\n", win->hints->max_width, win->hints->max_height)); - - if (win->hints->flags & PResizeInc) - PRINT_DEBUG (("incx: %d incy: %d\n", win->hints->width_inc, win->hints->height_inc)); - -#endif -} - - -static char * -get_wmname (Window w) -{ - char *name = NULL; - XTextProperty text_prop; - int ret = None, n; - char** cl; - - /* If current encoding is UTF-8, try to use the window's _NET_WM_NAME ewmh - property */ - if (defaults.utf8_locale) - { - Atom type = None; - unsigned long nitems, bytes_after; - int format; - char *val = NULL; - - ret = XGetWindowProperty (dpy, w, _net_wm_name, 0, 40, False, - xa_utf8_string, &type, &format, &nitems, - &bytes_after, (unsigned char **) &val); - /* We have a valid UTF-8 string */ - if (ret == Success && type == xa_utf8_string - && format == 8 && nitems > 0) - { - name = xstrdup (val); - XFree (val); - PRINT_DEBUG (("Fetching window name using _NET_WM_NAME succeeded\n")); - PRINT_DEBUG (("WM_NAME: %s\n", name)); - return name; - } - /* Something went wrong for whatever reason */ - if (ret == Success && val) - XFree (val); - PRINT_DEBUG (("Could not fetch window name using _NET_WM_NAME\n")); - } - - if (XGetWMName (dpy, w, &text_prop) == 0) - { - PRINT_DEBUG (("XGetWMName failed\n")); - return NULL; - } - - PRINT_DEBUG (("WM_NAME encoding: ")); - if (text_prop.encoding == xa_string) - PRINT_DEBUG (("STRING\n")); - else if (text_prop.encoding == xa_compound_text) - PRINT_DEBUG (("COMPOUND_TEXT\n")); - else if (text_prop.encoding == xa_utf8_string) - PRINT_DEBUG (("UTF8_STRING\n")); - else - PRINT_DEBUG (("unknown (%d)\n", (int) text_prop.encoding)); - -#ifdef X_HAVE_UTF8_STRING - /* It seems that most applications supporting UTF8_STRING and - _NET_WM_NAME don't bother making their WM_NAME available as - UTF8_STRING (but only as either STRING or COMPOUND_TEXT). - Let's try anyway. */ - if (defaults.utf8_locale && text_prop.encoding == xa_utf8_string) - { - ret = Xutf8TextPropertyToTextList (dpy, &text_prop, &cl, &n); - PRINT_DEBUG (("Xutf8TextPropertyToTextList: %s\n", - ret == Success ? "success" : "error")); - } - else -#endif - { - /* XmbTextPropertyToTextList should be fine for all cases, - even UTF8_STRING encoded WM_NAME */ - ret = XmbTextPropertyToTextList (dpy, &text_prop, &cl, &n); - PRINT_DEBUG (("XmbTextPropertyToTextList: %s\n", - ret == Success ? "success" : "error")); - } - - if (ret == Success && cl && n > 0) - { - name = xstrdup (cl[0]); - XFreeStringList (cl); - } - else if (text_prop.value) - { - /* Convertion failed, try to get the raw string */ - name = xstrdup ((char *) text_prop.value); - XFree (text_prop.value); - } - - if (name == NULL) { - PRINT_DEBUG (("I can't get the WMName.\n")); - } else { - PRINT_DEBUG (("WM_NAME: '%s'\n", name)); - } - - return name; -} - -static XClassHint * -get_class_hints (Window w) -{ - XClassHint *class; - - class = XAllocClassHint(); - - if (class == NULL) - { - PRINT_ERROR (("Not enough memory for WM_CLASS structure.\n")); - exit (EXIT_FAILURE); - } - - XGetClassHint (dpy, w, class); - - return class; -} - -/* Reget the WM_NAME property for the window and update its - name. Return 1 if the name changed. */ -int -update_window_name (rp_window *win) -{ - char *newstr; - int changed = 0; - XClassHint *class; - - newstr = get_wmname (win->w); - if (newstr != NULL) - { - changed = changed || win->wm_name == NULL || strcmp (newstr, win->wm_name); - free (win->wm_name); - win->wm_name = newstr; - } - - class = get_class_hints (win->w); - - if (class->res_class != NULL - && (win->res_class == NULL || strcmp (class->res_class, win->res_class))) - { - changed = 1; - free (win->res_class); - win->res_class = xstrdup(class->res_class); - } - - if (class->res_name != NULL - && (win->res_name == NULL || strcmp (class->res_name, win->res_name))) - { - changed = 1; - free (win->res_name); - win->res_name = xstrdup(class->res_name); - } - - XFree (class->res_name); - XFree (class->res_class); - XFree (class); - return changed; -} - -/* Send an artificial configure event to the window. */ -void -send_configure (Window w, int x, int y, int width, int height, int border) -{ - XConfigureEvent ce; - - ce.type = ConfigureNotify; - ce.event = w; - ce.window = w; - ce.x = x; - ce.y = y; - ce.width = width; - ce.height = height; - ce.border_width = border; - ce.above = None; - ce.override_redirect = 0; - - XSendEvent (dpy, w, False, StructureNotifyMask, (XEvent*)&ce); -} - -/* This function is used to determine if the window should be treated - as a transient. */ -int -window_is_transient (rp_window *win) -{ - return win->transient -#ifdef ASPECT_WINDOWS_ARE_TRANSIENTS - || win->hints->flags & PAspect -#endif -#ifdef MAXSIZE_WINDOWS_ARE_TRANSIENTS -|| (win->hints->flags & PMaxSize - && (win->hints->max_width < win->scr->width - || win->hints->max_height < win->scr->height)) -#endif - ; -} - -static Atom -get_net_wm_window_type (rp_window *win) -{ - Atom type, window_type = None; - int format; - unsigned long nitems; - unsigned long bytes_left; - unsigned char *data; - - if (win == NULL) - return None; - - if (XGetWindowProperty (dpy, win->w, _net_wm_window_type, 0, 1L, - False, XA_ATOM, &type, &format, - &nitems, &bytes_left, - &data) == Success && nitems > 0) - { - window_type = *(Atom *)data; - XFree (data); - PRINT_DEBUG(("hey ya %ld %ld\n", window_type, _net_wm_window_type_dialog)); - } - - return window_type; -} - - -void -update_window_information (rp_window *win) -{ - XWindowAttributes attr; - - update_window_name (win); - - /* Get the WM Hints */ - update_normal_hints (win); - - /* Get the colormap */ - XGetWindowAttributes (dpy, win->w, &attr); - win->colormap = attr.colormap; - win->x = attr.x; - win->y = attr.y; - win->width = attr.width; - win->height = attr.height; - win->border = attr.border_width; - - /* Transient status */ - win->transient = XGetTransientForHint (dpy, win->w, &win->transient_for); - - if (get_net_wm_window_type(win) == _net_wm_window_type_dialog) - win->transient = 1; - - update_window_gravity (win); -} - -void -unmanage (rp_window *w) -{ - list_del (&w->node); - groups_del_window (w); - - free_window (w); - -#ifdef AUTO_CLOSE - if (rp_mapped_window.next == &rp_mapped_window - && rp_mapped_window.prev == &rp_mapped_window) - { - /* If the mapped window list is empty then we have run out of - managed windows, so kill ratpoison. */ - - /* FIXME: The unmapped window list may also have to be checked - in the case that the only mapped window in unmapped and - shortly after another window is mapped most likely by the - same app. */ - - kill_signalled = 1; - } -#endif -} - -/* When starting up scan existing windows and start managing them. */ -void -scanwins(rp_screen *s) -{ - rp_window *win; - XWindowAttributes attr; - unsigned int i, nwins; - Window dw1, dw2, *wins; - - XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins); - PRINT_DEBUG (("windows: %d\n", nwins)); - - for (i = 0; i < nwins; i++) - { - XGetWindowAttributes(dpy, wins[i], &attr); - if (is_rp_window_for_screen(wins[i], s) - || attr.override_redirect == True - || unmanaged_window (wins[i])) continue; - - /* FIXME - with this code, windows which are entirely off-screen - * when RP starts won't ever be managed when Xinerama is enabled. - */ - { - XWindowAttributes root_attr; - - XGetWindowAttributes (dpy, s->root, &root_attr); - PRINT_DEBUG (("attrs: %d %d %d %d %d %d\n", root_attr.x, root_attr.y, - s->left, s->top, s->left + s->width, s->top + s->height));} - - if (rp_have_xinerama - && ((attr.x > s->left + s->width) - || (attr.x < s->left) - || (attr.y > s->top + s->height) - || (attr.y < s->top))) continue; - - win = add_to_window_list (s, wins[i]); - - PRINT_DEBUG (("map_state: %s\n", - attr.map_state == IsViewable ? "IsViewable": - attr.map_state == IsUnviewable ? "IsUnviewable" : "IsUnmapped")); - PRINT_DEBUG (("state: %s\n", - get_state(win) == IconicState ? "Iconic": - get_state(win) == NormalState ? "Normal" : "Other")); - - /* Collect mapped and iconized windows. */ - if (attr.map_state == IsViewable - || (attr.map_state == IsUnmapped - && get_state (win) == IconicState)) - map_window (win); - } - - XFree(wins); -} - -int -unmanaged_window (Window w) -{ - char *wname; - int i; - - if (!unmanaged_window_list) return 0; - - for (i = 0; i < num_unmanaged_windows; i++) - { - wname = get_wmname(w); - if (!wname) return 0; - if (!strcmp(unmanaged_window_list[i], wname)) - { - free(wname); - return 1; - } - free(wname); - } - return 0; -} - -/* Set the state of the window. */ -void -set_state (rp_window *win, int state) -{ - long data[2]; - - win->state = state; - - data[0] = (long)win->state; - data[1] = (long)None; - - XChangeProperty (dpy, win->w, wm_state, wm_state, 32, - PropModeReplace, (unsigned char *)data, 2); -} - -/* Get the WM state of the window. */ -long -get_state (rp_window *win) -{ - long state = WithdrawnState; - Atom type; - int format; - unsigned long nitems; - unsigned long bytes_left; - unsigned char *data; - - if (win == NULL) - return state; - - if (XGetWindowProperty (dpy, win->w, wm_state, 0L, 2L, - False, wm_state, &type, &format, - &nitems, &bytes_left, - &data) == Success && nitems > 0) - { - state = *(long *)data; - XFree (data); - } - - return state; -} - -static void -move_window (rp_window *win) -{ - rp_frame *frame; - - if (win->frame_number == EMPTY) - return; - - frame = win_get_frame (win); - - /* X coord. */ - switch (win->gravity) - { - case NorthWestGravity: - case WestGravity: - case SouthWestGravity: - win->x = frame->x; - break; - case NorthGravity: - case CenterGravity: - case SouthGravity: - win->x = frame->x + (frame->width - win->border * 2) / 2 - win->width / 2; - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - win->x = frame->x + frame->width - win->width - win->border; - break; - } - - /* Y coord. */ - switch (win->gravity) - { - case NorthEastGravity: - case NorthGravity: - case NorthWestGravity: - win->y = frame->y; - break; - case EastGravity: - case CenterGravity: - case WestGravity: - win->y = frame->y + (frame->height - win->border * 2) / 2 - win->height / 2; - break; - case SouthEastGravity: - case SouthGravity: - case SouthWestGravity: - win->y = frame->y + frame->height - win->height - win->border; - break; - } -} - -/* Set a transient window's x,y,width,height fields to maximize the - window. */ -static void -maximize_transient (rp_window *win) -{ - rp_frame *frame; - int maxx, maxy; - - frame = win_get_frame (win); - - /* We can't maximize a window if it has no frame. */ - if (frame == NULL) - return; - - /* Set the window's border */ - win->border = defaults.window_border_width; - - /* Always use the window's current width and height for - transients. */ - maxx = win->width; - maxy = win->height; - - /* Fit the window inside its frame (if it has one) */ - if (frame) - { - PRINT_DEBUG (("frame width=%d height=%d\n", - frame->width, frame->height)); - - if (maxx + win->border * 2 > frame->width) maxx = frame->width - win->border * 2; - if (maxy + win->border * 2 > frame->height) maxy = frame->height - win->border * 2; - } - - /* Make sure we maximize to the nearest Resize Increment specified - by the window */ - if (win->hints->flags & PResizeInc) - { - int amount; - int delta; - - /* Avoid a divide by zero if width/height_inc is 0. */ - if (win->hints->width_inc) - { - amount = maxx - win->width; - delta = amount % win->hints->width_inc; - amount -= delta; - if (amount < 0 && delta) amount -= win->hints->width_inc; - maxx = amount + win->width; - } - - if (win->hints->height_inc) - { - amount = maxy - win->height; - delta = amount % win->hints->height_inc; - amount -= delta; - if (amount < 0 && delta) amount -= win->hints->height_inc; - maxy = amount + win->height; - } - } - - PRINT_DEBUG (("maxsize: %d %d\n", maxx, maxy)); - - win->width = maxx; - win->height = maxy; -} - -/* set a good standard window's x,y,width,height fields to maximize - the window. */ -static void -maximize_normal (rp_window *win) -{ - rp_frame *frame; - int maxx, maxy; - - frame = win_get_frame (win); - - /* We can't maximize a window if it has no frame. */ - if (frame == NULL) - return; - - /* Set the window's border */ - win->border = defaults.window_border_width; - - /* Honour the window's maximum size */ - if (win->hints->flags & PMaxSize) - { - maxx = win->hints->max_width; - maxy = win->hints->max_height; - } - else - { - maxx = frame->width - win->border * 2; - maxy = frame->height - win->border * 2; - } - - /* Honour the window's aspect ratio. */ - PRINT_DEBUG (("aspect: %ld\n", win->hints->flags & PAspect)); - if (win->hints->flags & PAspect) - { - float ratio = (float)maxx / maxy; - float min_ratio = (float)win->hints->min_aspect.x / win->hints->min_aspect.y; - float max_ratio = (float)win->hints->max_aspect.x / win->hints->max_aspect.y; - PRINT_DEBUG (("ratio=%f min_ratio=%f max_ratio=%f\n", - ratio,min_ratio,max_ratio)); - if (ratio < min_ratio) - { - maxy = (int) (maxx / min_ratio); - } - else if (ratio > max_ratio) - { - maxx = (int) (maxy * max_ratio); - } - } - - /* Fit the window inside its frame (if it has one) */ - if (frame) - { - PRINT_DEBUG (("frame width=%d height=%d\n", - frame->width, frame->height)); - - if (maxx > frame->width) maxx = frame->width - win->border * 2; - if (maxy > frame->height) maxy = frame->height - win->border * 2; - } - - /* Make sure we maximize to the nearest Resize Increment specified - by the window */ - if (win->hints->flags & PResizeInc) - { - int amount; - int delta; - - if (win->hints->width_inc) - { - amount = maxx - win->width; - delta = amount % win->hints->width_inc; - if (amount < 0 && delta) amount -= win->hints->width_inc; - amount -= delta; - maxx = amount + win->width; - } - - if (win->hints->height_inc) - { - amount = maxy - win->height; - delta = amount % win->hints->height_inc; - if (amount < 0 && delta) amount -= win->hints->height_inc; - amount -= delta; - maxy = amount + win->height; - } - } - - PRINT_DEBUG (("maxsize: %d %d\n", maxx, maxy)); - - win->width = maxx; - win->height = maxy; -} - -/* Maximize the current window if data = 0, otherwise assume it is a - pointer to a window that should be maximized */ -void -maximize (rp_window *win) -{ - if (!win) win = current_window(); - if (!win) return; - - /* Handle maximizing transient windows differently. */ - if (win->transient) - maximize_transient (win); - else - maximize_normal (win); - - /* Reposition the window. */ - move_window (win); - - PRINT_DEBUG (("Resizing window '%s' to x:%d y:%d w:%d h:%d\n", window_name (win), - win->x, win->y, win->width, win->height)); - - - /* Actually do the maximizing. */ - XMoveResizeWindow (dpy, win->w, win->scr->left + win->x, win->scr->top + win->y, win->width, win->height); - XSetWindowBorderWidth (dpy, win->w, win->border); - - XSync (dpy, False); -} - -/* Maximize the current window but don't treat transient windows - differently. */ -void -force_maximize (rp_window *win) -{ - if (!win) win = current_window(); - if (!win) return; - - maximize_normal(win); - - /* Reposition the window. */ - move_window (win); - - /* This little dance is to force a maximize event. If the window is - already "maximized" X11 will optimize away the event since to - geometry changes were made. This initial resize solves the - problem. */ - if (win->hints->flags & PResizeInc) - { - XMoveResizeWindow (dpy, win->w, win->scr->left + win->x, win->scr->top + win->y, - win->width + win->hints->width_inc, - win->height + win->hints->height_inc); - } - else - { - XResizeWindow (dpy, win->w, win->width + 1, win->height + 1); - } - - XSync (dpy, False); - - /* Resize the window to its proper maximum size. */ - XMoveResizeWindow (dpy, win->w, win->scr->left + win->x, win->scr->top + win->y, win->width, win->height); - XSetWindowBorderWidth (dpy, win->w, win->border); - - XSync (dpy, False); -} - -/* map the unmapped window win */ -void -map_window (rp_window *win) -{ - PRINT_DEBUG (("Mapping the unmapped window %s\n", window_name (win))); - - /* Fill in the necessary data about the window */ - update_window_information (win); - win->number = numset_request (rp_window_numset); - grab_top_level_keys (win->w); - - /* Put win in the mapped window list */ - list_del (&win->node); - insert_into_list (win, &rp_mapped_window); - - /* Update all groups. */ - groups_map_window (win); - - /* The window has never been accessed since it was brought back from - the Withdrawn state. */ - win->last_access = 0; - - /* It is now considered iconic and set_active_window can handle the rest. */ - set_state (win, IconicState); - - /* Depending on the rudeness level, actually map the window. */ - if ((rp_honour_transient_map && win->transient) - || (rp_honour_normal_map && !win->transient)) - set_active_window (win); - else - show_rudeness_msg (win, 0); - - hook_run (&rp_new_window_hook); -} - -void -hide_window (rp_window *win) -{ - if (win == NULL) return; - - /* An unmapped window is not inside a frame. */ - win->frame_number = EMPTY; - - /* Ignore the unmap_notify event. */ - XSelectInput(dpy, win->w, WIN_EVENTS&~(StructureNotifyMask)); - XUnmapWindow (dpy, win->w); - XSelectInput (dpy, win->w, WIN_EVENTS); - /* Ensure that the window doesn't have the focused border - color. This is needed by remove_frame and possibly others. */ - XSetWindowBorder (dpy, win->w, win->scr->bw_color); - set_state (win, IconicState); -} - -void -unhide_window (rp_window *win) -{ - if (win == NULL) return; - - /* Always raise the window. */ - XRaiseWindow (dpy, win->w); - - if (win->state != IconicState) return; - - XMapWindow (dpy, win->w); - set_state (win, NormalState); -} - -void -unhide_all_windows (void) -{ - struct list_head *tmp, *iter; - rp_window *win; - - list_for_each_safe_entry (win, iter, tmp, &rp_mapped_window, node) - unhide_window (win); -} - -/* same as unhide_window except that it makes sure the window is mapped - on the bottom of the window stack. */ -void -unhide_window_below (rp_window *win) -{ - if (win == NULL) return; - - /* Always lower the window, but if its not iconic we don't need to - map it since it already is mapped. */ - XLowerWindow (dpy, win->w); - - if (win->state != IconicState) return; - - XMapWindow (dpy, win->w); - set_state (win, NormalState); -} - -void -withdraw_window (rp_window *win) -{ - if (win == NULL) return; - - PRINT_DEBUG (("withdraw_window on '%s'\n", window_name (win))); - - /* Give back the window number. the window will get another one, - if it is remapped. */ - if (win->number == -1) - PRINT_ERROR(("Attempting to withdraw '%s' with number -1!\n", window_name(win))); - - numset_release (rp_window_numset, win->number); - win->number = -1; - - list_move_tail(&win->node, &rp_unmapped_window); - - /* Update the groups. */ - groups_unmap_window (win); - - ignore_badwindow++; - - XRemoveFromSaveSet (dpy, win->w); - set_state (win, WithdrawnState); - XSync (dpy, False); - - ignore_badwindow--; - - /* Call our hook */ - hook_run (&rp_delete_window_hook); -} - -/* Hide all other mapped windows except for win in win's frame. */ -void -hide_others (rp_window *win) -{ - rp_frame *frame; - rp_window *cur; - - if (win == NULL) return; - frame = find_windows_frame (win); - if (frame == NULL) return; - - list_for_each_entry (cur, &rp_mapped_window, node) - { - if (find_windows_frame (cur) - || cur->state != NormalState - || cur->frame_number != frame->number) - continue; - - hide_window (cur); - } -} diff --git a/src/manage.h b/src/manage.h deleted file mode 100644 index 6d5f1f5..0000000 --- a/src/manage.h +++ /dev/null @@ -1,60 +0,0 @@ -/* manage.h - * 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 - */ - -#ifndef _RATPOISON_MANAGE_H -#define _RATPOISON_MANAGE_H 1 - -#include "data.h" - -void clear_unmanaged_list (void); -char *list_unmanaged_windows (void); -void add_unmanaged_window (char *name); -int unmanaged_window (Window w); -rp_screen* current_screen (void); -void scanwins(rp_screen *s); -void unmanage (rp_window *w); -int update_window_name (rp_window *win); -void update_normal_hints (rp_window *win); -void rename_current_window (void); -void send_configure (Window w, int x, int y, int width, int height, int border); -void set_state (rp_window *win, int state); -long get_state (rp_window *win); - -int window_is_transient (rp_window *win); -void update_window_information (rp_window *win); -void map_window (rp_window *win); - -void maximize (rp_window *win); -void force_maximize (rp_window *win); - -void grab_top_level_keys (Window w); -void ungrab_top_level_keys (Window w); -void ungrab_keys_all_wins (void); -void grab_keys_all_wins (void); - -void hide_window (rp_window *win); -void unhide_window (rp_window *win); -void unhide_all_windows (void); -void unhide_window_below (rp_window *win); -void withdraw_window (rp_window *win); -void hide_others (rp_window *win); - -#endif /* ! _RATPOISION_MANAGE_H */ diff --git a/src/messages.h b/src/messages.h deleted file mode 100644 index 47f2563..0000000 --- a/src/messages.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Ratpoison messages. - * 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 - */ - -#ifndef _RATPOISON_MESSAGES_H -#define _RATPOISON_MESSAGES_H 1 - -#include "config.h" - -#define MESSAGE_NO_OTHER_WINDOW "No other window" -#define MESSAGE_NO_OTHER_FRAME "No other frame" -#define MESSAGE_NO_MANAGED_WINDOWS "No managed windows" -#define MESSAGE_UNKNOWN_COMMAND ": unknown command '%s'" -#define MESSAGE_WINDOW_INFORMATION "This is window %d (%s)" - -#define MESSAGE_RAISE_TRANSIENT "Raise request from transient window %d (%s)" -#define MESSAGE_RAISE_WINDOW "Raise request from window %d (%s)" -#define MESSAGE_RAISE_TRANSIENT_GROUP "Raise request from transient window %d (%s) in group %s" -#define MESSAGE_RAISE_WINDOW_GROUP "Raise request from window %d (%s) in group %s" -#define MESSAGE_MAP_TRANSIENT "New transient window %d (%s)" -#define MESSAGE_MAP_WINDOW "New window %d (%s)" -#define MESSAGE_MAP_TRANSIENT_GROUP "New transient window %d (%s) in group %s" -#define MESSAGE_MAP_WINDOW_GROUP "New window %d (%s) in group %s" - -#define MESSAGE_PROMPT_SWITCH_TO_WINDOW "Switch to window: " -#define MESSAGE_PROMPT_NEW_WINDOW_NAME "Set window's title to: " -#define MESSAGE_PROMPT_SHELL_COMMAND "/bin/sh -c " -#define MESSAGE_PROMPT_COMMAND ":" -#define MESSAGE_PROMPT_SWITCH_WM "Switch to wm: " -#define MESSAGE_PROMPT_XTERM_COMMAND MESSAGE_PROMPT_SHELL_COMMAND TERM_PROG " -e " -#define MESSAGE_PROMPT_SWITCH_TO_GROUP "Switch to group: " -#define MESSAGE_PROMPT_SELECT_VAR "Variable: " -#define MESSAGE_PROMPT_VAR_VALUE "Value: " - -#define MESSAGE_WELCOME "Welcome to ratpoison! Hit `%s %s' for help." - -#define EMPTY_FRAME_MESSAGE "Current Frame" - -#endif /* ! _RATPOISON_MESSAGES_H */ diff --git a/src/number.c b/src/number.c deleted file mode 100644 index 332fb06..0000000 --- a/src/number.c +++ /dev/null @@ -1,149 +0,0 @@ -/* handles the handing out of and uniqueness of window numbers. - * 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 <stdlib.h> -#include <stdio.h> - -#include "ratpoison.h" - -/* Initialize a numset structure. */ -static void -numset_init (struct numset *ns) -{ - ns->max_taken = 10; - ns->num_taken = 0; - - ns->numbers_taken = xmalloc (ns->max_taken * sizeof (int)); -} - -static int -numset_num_is_taken (struct numset *ns, int n) -{ - int i; - - for (i=0; i<ns->num_taken; i++) - { - if (ns->numbers_taken[i] == n) return 1; - } - return 0; -} - -/* returns index into numbers_taken that can be used. */ -static int -numset_find_empty_cell (struct numset *ns) -{ - int i; - - for (i=0; i<ns->num_taken; i++) - { - if (ns->numbers_taken[i] == -1) return i; - } - - /* no vacant ones, so grow the array. */ - if (ns->num_taken >= ns->max_taken) - { - ns->max_taken *= 2; - ns->numbers_taken = xrealloc (ns->numbers_taken, sizeof (int) * ns->max_taken); - } - ns->num_taken++; - - return ns->num_taken-1; -} - -int -numset_add_num (struct numset *ns, int n) -{ - int ec; - - PRINT_DEBUG(("ns=%p add_num %d\n", ns, n)); - - if (numset_num_is_taken (ns, n)) - return 0; /* failed. */ - /* numset_find_empty_cell calls realloc on numbers_taken. So store - the ret val in ec then use ec as an index into the array. */ - ec = numset_find_empty_cell(ns); - ns->numbers_taken[ec] = n; - return 1; /* success! */ -} - -/* returns a unique number that can be used as the window number in - the program bar. */ -int -numset_request (struct numset *ns) -{ - int i; - - /* look for a unique number, and add it to the list of taken - numbers. */ - i = 0; - while (!numset_add_num (ns, i)) i++; - - PRINT_DEBUG(("ns=%p request got %d\n", ns, i)); - - return i; -} - -/* When a window is destroyed, it gives back its window number with - this function. */ -void -numset_release (struct numset *ns, int n) -{ - int i; - - PRINT_DEBUG(("ns=%p release %d\n", ns, n)); - - if (n < 0) - PRINT_ERROR(("ns=%p Attempt to release %d!\n", ns, n)); - - for (i=0; i<ns->num_taken; i++) - { - if (ns->numbers_taken[i] == n) - { - ns->numbers_taken[i] = -1; - return; - } - } -} - -/* Create a new numset and return a pointer to it. */ -struct numset * -numset_new (void) -{ - struct numset *ns; - - ns = (struct numset *)xmalloc (sizeof (struct numset)); - numset_init (ns); - return ns; -} - -/* Free a numset structure and it's internal data. */ -void -numset_free (struct numset *ns) -{ - free (ns->numbers_taken); - free (ns); -} - -void -numset_clear (struct numset *ns) -{ - ns->num_taken = 0; -} diff --git a/src/number.h b/src/number.h deleted file mode 100644 index d379aa2..0000000 --- a/src/number.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Function prototypes. - * 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 - */ - -#ifndef _RATPOISON_NUMBER_H -#define _RATPOISON_NUMBER_H 1 - -/* Keep track of a set of numbers. For frames and windows. */ -struct numset -{ - /* A list of the numbers taken. */ - int *numbers_taken; - -/* the number of numbers currently stored in the numbers_taken - array. */ - int num_taken; - -/* the size of the numbers_taken array. */ - int max_taken; -}; - -struct numset *numset_new (void); -void numset_free (struct numset *ns); -void numset_release (struct numset *ns, int n); -int numset_request (struct numset *ns); -int numset_add_num (struct numset *ns, int n); -void numset_clear (struct numset *ns); - -#endif /* ! _RATPOISON_NUMBER_H */ diff --git a/src/ratpoison.h b/src/ratpoison.h deleted file mode 100644 index c307619..0000000 --- a/src/ratpoison.h +++ /dev/null @@ -1,113 +0,0 @@ -/* Standard header for ratpoison. - * 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 - */ - -#ifndef _RATPOISON_H -#define _RATPOISON_H 1 - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif /* HAVE_CONFIG_H */ - -#include <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/Xlocale.h> -#include <fcntl.h> - -/* Some systems don't define the close-on-exec flag in fcntl.h */ -#ifndef FD_CLOEXEC -# define FD_CLOEXEC 1 -#endif - -/* Helper macro for error and debug reporting. */ -#define PRINT_LINE(type) printf (PACKAGE ":%s:%d: %s: ",__FILE__, __LINE__, #type) - -/* Error and debug reporting macros. */ -#define PRINT_ERROR(fmt) \ -do { \ - PRINT_LINE (error); \ - printf fmt; \ - fflush (stdout); \ -} while (0) - -#ifdef DEBUG -#define PRINT_DEBUG(fmt) \ -do { \ - PRINT_LINE (debug); \ - printf fmt; \ - fflush (stdout); \ -} while (0) -#else -#define PRINT_DEBUG(fmt) do {} while (0) -#endif /* DEBUG */ - -extern XGCValues gv; - -#include "conf.h" - -#include "data.h" -#include "globals.h" -#include "manage.h" -#include "window.h" -#include "bar.h" -#include "events.h" -#include "number.h" -#include "input.h" -#include "messages.h" -#include "communications.h" -#include "sbuf.h" -#include "split.h" -#include "frame.h" -#include "screen.h" -#include "group.h" -#include "editor.h" -#include "history.h" -#include "completions.h" -#include "hook.h" -#include "xinerama.h" -#include "format.h" - -void clean_up (void); -rp_screen *find_screen (Window w); - -void set_close_on_exec (FILE *fd); -void read_rc_file (FILE *file); - -void fatal (const char *msg); -void *xmalloc (size_t size); -void *xrealloc (void *ptr, size_t size); -char *xstrdup (const char *s); -char *xsprintf (char *fmt, ...); -char *xvsprintf (char *fmt, va_list ap); -int str_comp (char *s1, char *s2, int len); -char *strtok_ws (char *s); -/* Needed in cmd_tmpwm */ -void check_child_procs (void); -void chld_handler (int signum); -void set_sig_handler (int sig, void (*action)(int)); -/* Font functions. */ -void set_extents_of_fontset (XFontSet font); -XFontSet load_query_font_set (Display *disp, const char *fontset_name); - -#endif /* ! _RATPOISON_H */ diff --git a/src/sbuf.c b/src/sbuf.c deleted file mode 100644 index 8e4556d..0000000 --- a/src/sbuf.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Functions for handling string buffers. - * 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 <string.h> - -#include "ratpoison.h" -#include "sbuf.h" - -struct sbuf * -sbuf_new (size_t initsz) -{ - struct sbuf *b = (struct sbuf*) xmalloc (sizeof (struct sbuf)); - - if (initsz < 1) - initsz = 1; - - b->data = (char*) xmalloc (initsz); - b->maxsz = initsz; - - b->data[0] = '\0'; - b->len = 0; - - return b; -} - -void -sbuf_free (struct sbuf *b) -{ - if (b != NULL) - { - if (b->data != NULL) - free (b->data); - - free (b); - } -} - -/* Free the structure but return the string. */ -char * -sbuf_free_struct (struct sbuf *b) -{ - if (b != NULL) - { - char *tmp; - tmp = b->data; - free (b); - return tmp; - } - - return NULL; -} - -char * -sbuf_nconcat (struct sbuf *b, const char *str, int len) -{ - size_t minsz = b->len + len + 1; - - if (b->maxsz < minsz) - { - b->data = (char*) xrealloc (b->data, minsz); - b->maxsz = minsz; - } - - memcpy (b->data + b->len, str, minsz - b->len - 1); - b->len = minsz - 1; - *(b->data + b->len) = 0; - - return b->data; -} - - -char * -sbuf_concat (struct sbuf *b, const char *str) -{ - return sbuf_nconcat (b, str, strlen (str)); -} - -char * -sbuf_copy (struct sbuf *b, const char *str) -{ - b->len = 0; - return sbuf_concat (b, str); -} - -char * -sbuf_clear (struct sbuf *b) -{ - b->len = 0; - b->data[0] = '\0'; - return b->data; -} - -char * -sbuf_get (struct sbuf *b) -{ - return b->data; -} - -char * -sbuf_printf (struct sbuf *b, char *fmt, ...) -{ - va_list ap; - - free (b->data); - - va_start (ap, fmt); - b->data = xvsprintf (fmt, ap); - va_end (ap); - - return b->data; -} - -char * -sbuf_printf_concat (struct sbuf *b, char *fmt, ...) -{ - char *buffer; - va_list ap; - - va_start (ap, fmt); - buffer = xvsprintf (fmt, ap); - va_end (ap); - - sbuf_concat (b, buffer); - free (buffer); - - return b->data; -} diff --git a/src/sbuf.h b/src/sbuf.h deleted file mode 100644 index ae4ea9c..0000000 --- a/src/sbuf.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Function prototypes for handling string buffers. - * 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 - */ - -#ifndef _RATPOISON_SBUF_H -#define _RATPOISON_SBUF_H 1 - -#include <stdlib.h> - -struct -sbuf -{ - char *data; - size_t len; - size_t maxsz; - - /* sbuf can exist in a list. */ - struct list_head node; -}; - -struct sbuf *sbuf_new (size_t initsz); -void sbuf_free (struct sbuf *b); -char *sbuf_free_struct (struct sbuf *b); -char *sbuf_concat (struct sbuf *b, const char *str); -char *sbuf_nconcat (struct sbuf *b, const char *str, int len); -char *sbuf_copy (struct sbuf *b, const char *str); -char *sbuf_clear (struct sbuf *b); -char *sbuf_get (struct sbuf *b); -char *sbuf_printf (struct sbuf *b, char *fmt, ...); -char *sbuf_printf_concat (struct sbuf *b, char *fmt, ...); - -#endif /* ! _RATPOISON_SBUF_H */ diff --git a/src/screen.c b/src/screen.c deleted file mode 100644 index d843c04..0000000 --- a/src/screen.c +++ /dev/null @@ -1,497 +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 "ratpoison.h" -#include <string.h> -#include <X11/cursorfont.h> - -static void init_screen (rp_screen *s, int screen_num); - -int -screen_width (rp_screen *s) -{ - return s->width - defaults.padding_right - defaults.padding_left; -} - -int -screen_height (rp_screen *s) -{ - return s->height - defaults.padding_bottom - defaults.padding_top; -} - -int -screen_left (rp_screen *s) -{ - return s->left + defaults.padding_left; -} - -int -screen_right (rp_screen *s) -{ - return screen_left (s) + screen_width (s); -} - -int -screen_top (rp_screen *s) -{ - return s->top + defaults.padding_top; -} - -int -screen_bottom (rp_screen *s) -{ - return screen_top (s) + screen_height (s); -} - -/* Returns a pointer to a list of frames. */ -struct list_head * -screen_copy_frameset (rp_screen *s) -{ - struct list_head *head; - rp_frame *cur; - - /* Init our new list. */ - head = xmalloc (sizeof (struct list_head)); - INIT_LIST_HEAD (head); - - /* Copy each frame to our new list. */ - list_for_each_entry (cur, &s->frames, node) - { - list_add_tail (&(frame_copy (cur))->node, head); - } - - return head; -} - -/* Set head as the frameset, deleting the existing one. */ -void -screen_restore_frameset (rp_screen *s, struct list_head *head) -{ - frameset_free (&s->frames); - INIT_LIST_HEAD (&s->frames); - - /* Hook in our new frameset. */ - list_splice (head, &s->frames); -} - - -/* Given a screen, free the frames' numbers from the numset. */ -void -screen_free_nums (rp_screen *s) -{ - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - numset_release (s->frames_numset, cur->number); - } -} - -/* Given a list of frames, free them, but don't remove their numbers - from the numset. */ -void -frameset_free (struct list_head *head) -{ - rp_frame *frame; - struct list_head *iter, *tmp; - - list_for_each_safe_entry (frame, iter, tmp, head, node) - { - /* FIXME: what if frames has memory inside its struct - that needs to be freed? */ - free (frame); - } -} - -rp_frame * -screen_get_frame (rp_screen *s, int frame_num) -{ - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - if (cur->number == frame_num) - return cur; - } - - return NULL; -} - -rp_frame * -screen_find_frame_by_frame (rp_screen *s, rp_frame *f) -{ - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - PRINT_DEBUG (("cur=%p f=%p\n", cur, f)); - if (cur == f) - return cur; - } - - return NULL; -} - -/* Given a root window, return the rp_screen struct */ -rp_screen * -find_screen (Window w) -{ - int i; - - for (i=0; i<num_screens; i++) - if (screens[i].root == w) return &screens[i]; - - return NULL; - } - -/* Return 1 if w is a root window of any of the screens. */ -int -is_a_root_window (unsigned int w) -{ - int i; - for (i=0; i<num_screens; i++) - if (screens[i].root == w) return 1; - - return 0; -} - -void -init_screens (int screen_arg, int screen_num) -{ - int i; - - /* Get the number of screens */ - if (rp_have_xinerama) - num_screens = xine_screen_count; - else - num_screens = ScreenCount (dpy); - - /* make sure the screen specified is valid. */ - if (screen_arg) - { - /* Using just a single Xinerama screen doesn't really make sense. So we - * disable Xinerama in this case. - */ - if (rp_have_xinerama) - { - fprintf (stderr, "Warning: selecting a specific Xinerama screen is not implemented.\n"); - rp_have_xinerama = 0; - screen_num = 0; - num_screens = ScreenCount(dpy); - } - - if (screen_num < 0 || screen_num >= num_screens) - { - fprintf (stderr, "%d is an invalid screen for the display\n", screen_num); - exit (EXIT_FAILURE); - } - - /* we're only going to use one screen. */ - num_screens = 1; - } - - /* Create our global frame numset */ - rp_frame_numset = numset_new(); - - /* Initialize the screens */ - screens = (rp_screen *)xmalloc (sizeof (rp_screen) * num_screens); - PRINT_DEBUG (("%d screens.\n", num_screens)); - - if (screen_arg) - { - init_screen (&screens[0], screen_num); - } - else - { - for (i=0; i<num_screens; i++) - { - init_screen (&screens[i], i); - } - } - -} - -static void -init_rat_cursor (rp_screen *s) -{ - s->rat = XCreateFontCursor( dpy, XC_icon ); -} - -static void -init_screen (rp_screen *s, int screen_num) -{ - XGCValues gcv; - int xine_screen_num; - char *colon; - - /* We use screen_num below to refer to the real X screen number, but - * if we're using Xinerama, it will only be the Xinerama logical screen - * number. So we shuffle it away and replace it with the real one now, - * to cause confusion. -- CP - */ - if (rp_have_xinerama) - { - xine_screen_num = screen_num; - screen_num = DefaultScreen(dpy); - xinerama_get_screen_info(xine_screen_num, - &s->left, &s->top, &s->width, &s->height); - } - else - { - xine_screen_num = screen_num; - s->left = 0; - s->top = 0; - s->width = DisplayWidth(dpy, screen_num); - s->height = DisplayHeight(dpy, screen_num); - } - - /* Select on some events on the root window, if this fails, then - there is already a WM running and the X Error handler will catch - it, terminating ratpoison. */ - XSelectInput(dpy, RootWindow (dpy, screen_num), - PropertyChangeMask | ColormapChangeMask - | SubstructureRedirectMask | SubstructureNotifyMask - | StructureNotifyMask); - XSync (dpy, False); - - /* Set the numset for the frames to our global numset. */ - s->frames_numset = rp_frame_numset; - - /* Build the display string for each screen */ - s->display_string = xmalloc (strlen(DisplayString (dpy)) + 21); - sprintf (s->display_string, "DISPLAY=%s", DisplayString (dpy)); - colon = strrchr (DisplayString (dpy), ':'); - if (colon) - { - char *dot; - - dot = strrchr(s->display_string, '.'); - if (!dot || (strlen(dot) > strlen (colon)) ) - { - /* no dot was found or it belongs to fqdn - append screen_num - to the end */ - dot = s->display_string + strlen (s->display_string); - } - sprintf(dot, ".%i", screen_num); - } - - PRINT_DEBUG (("display string: %s\n", s->display_string)); - - s->screen_num = screen_num; - s->xine_screen_num = xine_screen_num; - s->root = RootWindow (dpy, screen_num); - s->def_cmap = DefaultColormap (dpy, screen_num); - - init_rat_cursor (s); - - s->fg_color = BlackPixel (dpy, s->screen_num); - s->bg_color = WhitePixel (dpy, s->screen_num); - s->fw_color = BlackPixel (dpy, s->screen_num); - s->bw_color = BlackPixel (dpy, s->screen_num); - - /* Setup the GC for drawing the font. */ - gcv.foreground = s->fg_color; - gcv.background = s->bg_color; - gcv.function = GXcopy; - gcv.line_width = 1; - gcv.subwindow_mode = IncludeInferiors; - s->normal_gc = XCreateGC(dpy, s->root, - GCForeground | GCBackground | GCFunction - | GCLineWidth | GCSubwindowMode, - &gcv); - gcv.foreground = s->bg_color; - gcv.background = s->fg_color; - s->inverse_gc = XCreateGC(dpy, s->root, - GCForeground | GCBackground | GCFunction - | GCLineWidth | GCSubwindowMode, - &gcv); - - /* Create the program bar window. */ - s->bar_is_raised = 0; - s->bar_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1, - defaults.bar_border_width, - s->fg_color, s->bg_color); - - /* Setup the window that will receive all keystrokes once the prefix - key has been pressed. */ - s->key_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1, 0, - WhitePixel (dpy, s->screen_num), - BlackPixel (dpy, s->screen_num)); - XSelectInput (dpy, s->key_window, KeyPressMask | KeyReleaseMask); - - /* Create the input window. */ - s->input_window = XCreateSimpleWindow (dpy, s->root, 0, 0, 1, 1, - defaults.bar_border_width, - s->fg_color, s->bg_color); - XSelectInput (dpy, s->input_window, KeyPressMask | KeyReleaseMask); - - /* Create the frame indicator window */ - s->frame_window = XCreateSimpleWindow (dpy, s->root, 1, 1, 1, 1, defaults.bar_border_width, - s->fg_color, s->bg_color); - - /* Create the help window */ - s->help_window = XCreateSimpleWindow (dpy, s->root, s->left, s->top, s->width, - s->height, 0, s->fg_color, s->bg_color); - XSelectInput (dpy, s->help_window, KeyPressMask); - - activate_screen(s); - - XSync (dpy, 0); - -#ifdef USE_XFT_FONT - { - s->xft_font = XftFontOpenName (dpy, screen_num, DEFAULT_XFT_FONT); - if (!s->xft_font) - { - PRINT_ERROR(("Failed to open font\n")); - } - else - { - if (!XftColorAllocName (dpy, DefaultVisual (dpy, screen_num), - DefaultColormap (dpy, screen_num), - defaults.fgcolor_string, &s->xft_fg_color)) - { - PRINT_ERROR(("Failed to allocate font fg color\n")); - XftFontClose (dpy, s->xft_font); - s->xft_font = NULL; - } - if (!XftColorAllocName (dpy, DefaultVisual (dpy, screen_num), - DefaultColormap (dpy, screen_num), - defaults.bgcolor_string, &s->xft_bg_color)) - { - PRINT_ERROR(("Failed to allocate font fg color\n")); - XftFontClose (dpy, s->xft_font); - s->xft_font = NULL; - } - } - } -#endif -} - -void -activate_screen (rp_screen *s) -{ - /* Add netwm support. FIXME: I think this is busted. */ - XChangeProperty (dpy, RootWindow (dpy, s->screen_num), - _net_supported, XA_ATOM, 32, PropModeReplace, - (unsigned char*)&_net_wm_pid, 1); - - /* set window manager name */ - XChangeProperty (dpy, RootWindow (dpy, s->screen_num), - _net_wm_name, xa_utf8_string, 8, PropModeReplace, - (unsigned char*)"ratpoison", 9); - XMapWindow (dpy, s->key_window); -} - -void -deactivate_screen (rp_screen *s) -{ - /* Unmap its key window */ - XUnmapWindow (dpy, s->key_window); - - /* delete everything so noone sees them while we are not there */ - XDeleteProperty (dpy, RootWindow (dpy, s->screen_num), - _net_supported); - XDeleteProperty (dpy, RootWindow (dpy, s->screen_num), - _net_wm_name); -} - -static int -is_rp_window_for_given_screen (Window w, rp_screen *s) -{ - if (w != s->key_window && - w != s->bar_window && - w != s->input_window && - w != s->frame_window && - w != s->help_window) - return 0; - return 1; -} - -int -is_rp_window_for_screen(Window w, rp_screen *s) -{ - int i; - - if (rp_have_xinerama) - { - for (i=0; i<num_screens; i++) - if (is_rp_window_for_given_screen(w, &screens[i])) return 1; - return 0; - } - else - { - return is_rp_window_for_given_screen(w, s); - } -} - -char * -screen_dump (rp_screen *screen) -{ - char *tmp; - struct sbuf *s; - - s = sbuf_new (0); - sbuf_printf (s, "%d %d %d %d %d %d", - (rp_have_xinerama)?screen->xine_screen_num:screen->screen_num, - screen->left, - screen->top, - screen->width, - screen->height, - (current_screen() == screen)?1:0 /* is current? */ - ); - - /* Extract the string and return it, and don't forget to free s. */ - tmp = sbuf_get (s); - free (s); - return tmp; -} - -void -screen_update (rp_screen *s, int width, int height) -{ - rp_frame *f; - int oldwidth,oldheight; - - PRINT_DEBUG (("screen_update(%d,%d)\n", width, height)); - if (rp_have_xinerama) - { - /* TODO: how to do this with xinerama? */ - return; - } - - if (s->width == width && s->height == height) - /* nothing to do */ - return; - - oldwidth = s->width; oldheight = s->height; - s->width = width; s->height = height; - - XResizeWindow (dpy, s->help_window, width, height); - - list_for_each_entry (f, &s->frames, node) - { - f->x = (f->x*width)/oldwidth; - f->width = (f->width*width)/oldwidth; - f->y = (f->y*height)/oldheight; - f->height = (f->height*height)/oldheight; - maximize_all_windows_in_frame (f); - } -} diff --git a/src/screen.h b/src/screen.h deleted file mode 100644 index 6bad555..0000000 --- a/src/screen.h +++ /dev/null @@ -1,48 +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 - */ - -#ifndef SCREEN_H -#define SCREEN_H - -int screen_bottom (rp_screen *s); -int screen_top (rp_screen *s); -int screen_right (rp_screen *s); -int screen_left (rp_screen *s); -int screen_height (rp_screen *s); -int screen_width (rp_screen *s); - -struct list_head *screen_copy_frameset (rp_screen *s); -void screen_restore_frameset (rp_screen *s, struct list_head *head); -void screen_free_nums (rp_screen *s); -void frameset_free (struct list_head *head); -rp_frame *screen_get_frame (rp_screen *s, int frame_num); -rp_frame *screen_find_frame_by_frame (rp_screen *s, rp_frame *f); - -void init_screens (int screen_arg, int screen_num); -void activate_screen (rp_screen *s); -void deactivate_screen (rp_screen *s); - -int is_rp_window_for_screen (Window w, rp_screen *s); -int is_a_root_window (unsigned int w); - -char *screen_dump (rp_screen *screen); - -void screen_update (rp_screen *s, int width, int height); -#endif diff --git a/src/split.c b/src/split.c deleted file mode 100644 index b36b99e..0000000 --- a/src/split.c +++ /dev/null @@ -1,1090 +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 - * - * - * Functions for handling window splitting and tiling. - */ - -#include <unistd.h> -#include <string.h> - -#include "ratpoison.h" - -#define VERTICALLY 0 -#define HORIZONTALLY 1 - -static void -update_last_access (rp_frame *frame) -{ - static int counter = 0; - - frame->last_access = counter; - counter++; -} - -rp_frame * -current_frame (void) -{ - rp_screen *s = current_screen(); - return screen_get_frame (s, s->current_frame); -} - -int -num_frames (rp_screen *s) -{ - int count = 0; - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - count++; - } - - return count; -} - -void -cleanup_frame (rp_frame *frame) -{ - rp_window *win; - rp_screen *screen; - screen = frames_screen(frame); - - win = find_window_other (screen); - if (win == NULL) - { - set_frames_window (frame, NULL); - return; - } - - set_frames_window (frame, win); - - maximize (win); - unhide_window (win); - - - if (!window_is_transient (win)) - hide_others (win); -} - -rp_window * -set_frames_window (rp_frame *frame, rp_window *win) -{ - int last_win; - - last_win = frame->win_number; - if (win) - { - frame->win_number = win->number; - win->frame_number = frame->number; - - /* We need to make sure that win and frame are on the same screen, - * since with Xinerama, windows can move from one screen to another. - */ - win->scr = frames_screen(frame); - } - else - { - frame->win_number = EMPTY; - } - - return find_window_number (last_win); -} - -rp_screen * -frames_screen (rp_frame *frame) -{ - int i; - rp_frame *cur; - - for (i=0; i<num_screens; i++) - list_for_each_entry (cur, &screens[i].frames, node) - { - if (frame == cur) - return &screens[i]; - } - - /* This SHOULD be impossible to get to. FIXME: It'll crash higher up if we - return NULL. */ - return NULL; -} - -void -maximize_all_windows_in_frame (rp_frame *frame) -{ - rp_window *win; - - list_for_each_entry (win, &rp_mapped_window, node) - { - if (win->frame_number == frame->number) - { - maximize (win); - } - } -} - -/* Make the frame occupy the entire screen */ -static void -maximize_frame (rp_frame *frame) -{ - rp_screen *s = frames_screen (frame); - - frame->x = defaults.padding_left; - frame->y = defaults.padding_top; - - frame->width = screen_width (s); - frame->height = screen_height (s); -} - -/* Create a full screen frame */ -static void -create_initial_frame (rp_screen *screen) -{ - rp_frame *frame; - - frame = frame_new (screen); - screen->current_frame = frame->number; - list_add_tail (&frame->node, &screen->frames); - - update_last_access (frame); - - maximize_frame (frame); - set_frames_window (frame, NULL); -} - -void -init_frame_lists (void) -{ - int i; - - for (i=0; i<num_screens; i++) - init_frame_list (&screens[i]); -} - -void -init_frame_list (rp_screen *screen) -{ - INIT_LIST_HEAD (&screen->frames); - - create_initial_frame(screen); -} - -rp_frame * -find_last_frame (void) -{ - rp_frame *cur, *last = NULL; - int last_access = -1; - int i; - - for (i=0; i<num_screens; i++) - { - rp_screen *s = &screens[i]; - - list_for_each_entry (cur, &s->frames, node) - { - if (cur->number != current_screen()->current_frame - && cur->last_access > last_access) - { - last_access = cur->last_access; - last = cur; - } - } - } - - return last; -} - -/* Return the frame that contains the window. */ -rp_frame * -find_windows_frame (rp_window *win) -{ - rp_screen *s; - rp_frame *cur; - - s = win->scr; - - list_for_each_entry (cur, &s->frames, node) - { - if (cur->win_number == win->number) return cur; - } - - return NULL; -} - -rp_frame * -find_frame_next (rp_frame *frame) -{ - if (frame == NULL) return NULL; - return list_next_entry (frame, &frames_screen (frame)->frames, node); -} - -rp_frame * -find_frame_prev (rp_frame *frame) -{ - if (frame == NULL) return NULL; - return list_prev_entry (frame, &frames_screen (frame)->frames, node); -} - -rp_window * -current_window (void) -{ - return find_window_number (current_frame()->win_number); -} - -static int -window_fits_in_frame (rp_window *win, rp_frame *frame) -{ - /* If the window has minimum size hints, make sure they are smaller - than the frame. */ - if (win->hints->flags & PMinSize) - { - if (win->hints->min_width > frame->width - || - win->hints->min_height > frame->height) - { - return 0; - } - } - - return 1; -} - -/* Search the list of mapped windows for a window that will fit in the - specified frame. */ -rp_window * -find_window_for_frame (rp_frame *frame) -{ - rp_screen *s = frames_screen (frame); - int last_access = 0; - rp_window_elem *most_recent = NULL; - rp_window_elem *cur; - - list_for_each_entry (cur, &rp_current_group->mapped_windows, node) - { - if ((cur->win->scr == s || rp_have_xinerama) - && cur->win != current_window() - && !find_windows_frame (cur->win) - && cur->win->last_access >= last_access - && window_fits_in_frame (cur->win, frame) - && cur->win->frame_number == EMPTY) - { - most_recent = cur; - last_access = cur->win->last_access; - } - } - - if (most_recent) - return most_recent->win; - - return NULL; -} - -/* Splits the frame in 2. if way is 0 then split vertically otherwise - split it horizontally. */ -static void -split_frame (rp_frame *frame, int way, int pixels) -{ - rp_screen *s; - rp_window *win; - rp_frame *new_frame; - - s = frames_screen (frame); - - /* Make our new frame. */ - new_frame = frame_new (s); - - /* Add the frame to the frameset. */ - list_add (&new_frame->node, ¤t_frame()->node); - - set_frames_window (new_frame, NULL); - - if (way == HORIZONTALLY) - { - new_frame->x = frame->x; - new_frame->y = frame->y + pixels; - new_frame->width = frame->width; - new_frame->height = frame->height - pixels; - - frame->height = pixels; - } - else - { - new_frame->x = frame->x + pixels; - new_frame->y = frame->y; - new_frame->width = frame->width - pixels; - new_frame->height = frame->height; - - frame->width = pixels; - } - - win = find_window_for_frame (new_frame); - if (win) - { - PRINT_DEBUG (("Found a window for the frame!\n")); - - set_frames_window (new_frame, win); - - maximize (win); - unhide_window (win); - XRaiseWindow (dpy, win->w); - } - else - { - PRINT_DEBUG (("No window fits the frame.\n")); - - set_frames_window (new_frame, NULL); - } - - /* resize the existing frame */ - if (frame->win_number != EMPTY) - { - maximize_all_windows_in_frame (frame); - XRaiseWindow (dpy, find_window_number (frame->win_number)->w); - } - - update_bar (s); - show_frame_indicator(0); -} - -/* Splits the window vertically leaving the original with 'pixels' - pixels . */ -void -v_split_frame (rp_frame *frame, int pixels) -{ - split_frame (frame, VERTICALLY, pixels); -} - -/* Splits the frame horizontally leaving the original with 'pixels' - pixels . */ -void -h_split_frame (rp_frame *frame, int pixels) -{ - split_frame (frame, HORIZONTALLY, pixels); -} - -void -remove_all_splits (void) -{ - struct list_head *tmp, *iter; - rp_screen *s = current_screen(); - rp_frame *frame; - rp_window *win; - - /* Hide all the windows not in the current frame. */ - list_for_each_entry (win, &rp_mapped_window, node) - { - if (win->frame_number != s->current_frame && win->scr == s) - hide_window (win); - } - - /* Delete all the frames except the current one. */ - list_for_each_safe_entry (frame, iter, tmp, &s->frames, node) - { - if (frame->number != s->current_frame) - { - list_del (&frame->node); - frame_free (s, frame); - } - } - - /* Maximize the frame and the windows in the frame. */ - maximize_frame (current_frame()); - maximize_all_windows_in_frame (current_frame()); -} - -/* Shrink the size of the frame to fit it's current window. */ -void -resize_shrink_to_window (rp_frame *frame) -{ - rp_window *win; - - if (frame->win_number == EMPTY) return; - - win = find_window_number (frame->win_number); - - resize_frame_horizontally (frame, win->width + win->border*2 - frame->width); - resize_frame_vertically (frame, win->height + win->border*2 - frame->height); -} - -/* resize_frame is a generic frame resizer that can resize vertically, - horizontally, to the right, to the left, etc. It all depends on the - functions passed to it. Returns -1 if the resize failed, 0 for - success. */ -static int -resize_frame (rp_frame *frame, rp_frame *pusher, int diff, - int (*c1)(rp_frame *), int (c2)(rp_frame *), - int (*c3)(rp_frame *), int (c4)(rp_frame *), - void (*resize1)(rp_frame *, int), - void (*resize2)(rp_frame *, int), - int (*resize3)(rp_frame *, rp_frame *, int)) -{ - rp_screen *s = frames_screen (frame); - rp_frame *cur; - - /* Loop through the frames and determine which ones are affected by - resizing frame. */ - list_for_each_entry (cur, &s->frames, node) - { - if (cur == frame || cur == pusher) continue; - /* If cur is touching frame along the axis that is being - moved then this frame is affected by the resize. */ - if ((*c1)(cur) == (*c3)(frame)) - { - /* If the frame can't get any smaller, then fail. */ - if (diff > 0 - && abs ((*c3)(cur) - (*c1)(cur)) - diff <= defaults.window_border_width * 2) - return -1; - /* Test for this circumstance: - --+ - | |+-+ - |f||c| - | |+-+ - --+ - - In this case, resizing cur will not affect any other - frames, so just do the resize. - */ - if (((*c2)(cur) >= (*c2)(frame)) - && (*c4)(cur) <= (*c4)(frame)) - { - (*resize2)(cur, -diff); - maximize_all_windows_in_frame (cur); - } - /* Otherwise, cur's corners are either strictly outside - frame's corners, or one of them is inside and the other - isn't. In either of these cases, resizing cur will affect - other adjacent frames, so find them and resize them first - (recursive step) and then resize cur. */ - else if (((*c2)(cur) < (*c2)(frame) - && (*c4)(cur) > (*c4)(frame)) - || ((*c2)(cur) >= (*c2)(frame) - && (*c2)(cur) < (*c4)(frame)) - || ((*c4)(cur) > (*c2)(frame) - && (*c4)(cur) <= (*c4)(frame))) - { - /* Attempt to resize cur. */ - if (resize3 (cur, frame, -diff) == -1) - return -1; - } - } - } - - /* Finally, resize the frame and the windows inside. */ - (*resize1) (frame, diff); - maximize_all_windows_in_frame (frame); - - return 0; -} - -static int resize_frame_bottom (rp_frame *frame, rp_frame *pusher, int diff); -static int resize_frame_top (rp_frame *frame, rp_frame *pusher, int diff); -static int resize_frame_left (rp_frame *frame, rp_frame *pusher, int diff); -static int resize_frame_right (rp_frame *frame, rp_frame *pusher, int diff); - -/* Resize frame by moving it's right side. */ -static int -resize_frame_right (rp_frame *frame, rp_frame *pusher, int diff) -{ - return resize_frame (frame, pusher, diff, - frame_left, frame_top, frame_right, frame_bottom, - frame_resize_right, frame_resize_left, resize_frame_left); -} - -/* Resize frame by moving it's left side. */ -static int -resize_frame_left (rp_frame *frame, rp_frame *pusher, int diff) -{ - return resize_frame (frame, pusher, diff, - frame_right, frame_top, frame_left, frame_bottom, - frame_resize_left, frame_resize_right, resize_frame_right); -} - -/* Resize frame by moving it's top side. */ -static int -resize_frame_top (rp_frame *frame, rp_frame *pusher, int diff) -{ - return resize_frame (frame, pusher, diff, - frame_bottom, frame_left, frame_top, frame_right, - frame_resize_up, frame_resize_down, resize_frame_bottom); -} - -/* Resize frame by moving it's bottom side. */ -static int -resize_frame_bottom (rp_frame *frame, rp_frame *pusher, int diff) -{ - return resize_frame (frame, pusher, diff, - frame_top, frame_left, frame_bottom, frame_right, - frame_resize_down, frame_resize_up, resize_frame_top); -} - -/* Resize frame diff pixels by expanding it to the right. If the frame - is against the right side of the screen, expand it to the left. */ -void -resize_frame_horizontally (rp_frame *frame, int diff) -{ - int (*resize_fn)(rp_frame *, rp_frame*, int); - struct list_head *l; - rp_screen *s = frames_screen (frame); - - if (num_frames (s) < 2 || diff == 0) - return; - - if (frame_width (frame) + diff <= defaults.window_border_width * 2) - return; - - /* Find out which resize function to use. */ - if (frame_right (frame) < screen_right (s)) - { - resize_fn = resize_frame_right; - } - else if (frame_left (frame) > screen_left (s)) - { - resize_fn = resize_frame_left; - } - else - { - return; - } - - /* Copy the frameset. If the resize fails, then we restore the - original one. */ - l = screen_copy_frameset (s); - - if ((*resize_fn) (frame, NULL, diff) == -1) - { - screen_restore_frameset (s, l); - } - else - { - frameset_free (l); - } - - /* It's our responsibility to free this. */ - free (l); -} - -/* Resize frame diff pixels by expanding it down. If the frame is - against the bottom of the screen, expand it up. */ -void -resize_frame_vertically (rp_frame *frame, int diff) -{ - int (*resize_fn)(rp_frame *, rp_frame*, int); - struct list_head *l; - rp_screen *s = frames_screen (frame); - - if (num_frames (s) < 2 || diff == 0) - return; - - if (frame_height (frame) + diff <= defaults.window_border_width * 2) - return; - - /* Find out which resize function to use. */ - if (frame_bottom (frame) < screen_bottom (s)) - { - resize_fn = resize_frame_bottom; - } - else if (frame_top (frame) > screen_top (s)) - { - resize_fn = resize_frame_top; - } - else - { - return; - } - - /* Copy the frameset. If the resize fails, then we restore the - original one. */ - l = screen_copy_frameset (s); - - if ((*resize_fn) (frame, NULL, diff) == -1) - { - screen_restore_frameset (s, l); - } - else - { - frameset_free (l); - } - - /* It's our responsibility to free this. */ - free (l); -} - -static int -frame_is_below (rp_frame *src, rp_frame *frame) -{ - if (frame->y > src->y) return 1; - return 0; -} - -static int -frame_is_above (rp_frame *src, rp_frame *frame) -{ - if (frame->y < src->y) return 1; - return 0; -} - -static int -frame_is_left (rp_frame *src, rp_frame *frame) -{ - if (frame->x < src->x) return 1; - return 0; -} - -static int -frame_is_right (rp_frame *src, rp_frame *frame) -{ - if (frame->x > src->x) return 1; - return 0; -} - -static int -total_frame_area (rp_screen *s) -{ - int area = 0; - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - area += cur->width * cur->height; - } - - return area; -} - -/* Return 1 if frames f1 and f2 overlap */ -static int -frames_overlap (rp_frame *f1, rp_frame *f2) -{ - if (f1->x >= f2->x + f2->width - || f1->y >= f2->y + f2->height - || f2->x >= f1->x + f1->width - || f2->y >= f1->y + f1->height) - { - return 0; - } - return 1; -} - -/* Return 1 if w's frame overlaps any other window's frame */ -static int -frame_overlaps (rp_frame *frame) -{ - rp_screen *s; - rp_frame *cur; - - s = frames_screen (frame); - - list_for_each_entry (cur, &s->frames, node) - { - if (cur != frame && frames_overlap (cur, frame)) - { - return 1; - } - } - return 0; -} - -void -remove_frame (rp_frame *frame) -{ - rp_screen *s; - int area; - rp_frame *cur; - rp_window *win; - - if (frame == NULL) return; - - s = frames_screen (frame); - - area = total_frame_area(s); - PRINT_DEBUG (("Total Area: %d\n", area)); - - list_del (&frame->node); - win = find_window_number (frame->win_number); - hide_window (win); - hide_others (win); - - list_for_each_entry (cur, &s->frames, node) - { - rp_frame tmp_frame; - int fits = 0; - -/* if (cur->win_number != EMPTY) */ -/* { */ -/* PRINT_DEBUG (("Trying frame containing window '%s'\n", window_name (cur->win))); */ -/* } */ -/* else */ -/* { */ -/* PRINT_DEBUG (("Trying some empty frame\n")); */ -/* } */ - - /* Backup the frame */ - memcpy (&tmp_frame, cur, sizeof (rp_frame)); - - if (frame_is_below (frame, cur) - || frame_is_above (frame, cur)) - { - if (frame_is_below (frame, cur)) - cur->y = frame->y; - cur->height += frame->height; - } - - PRINT_DEBUG (("Attempting vertical Frame y=%d height=%d\n", cur->y, cur->height)); - PRINT_DEBUG (("New Total Area: %d\n", total_frame_area(s))); - - /* If the area is bigger than before, the frame takes up too - much space. If the current frame and the deleted frame DON'T - overlap then the current window took up just the right amount - of space but didn't take up the space left behind by the - deleted window. If any active frames overlap, it could have - taken up the right amount of space, overlaps with the deleted - frame but obviously didn't fit. */ - if (total_frame_area(s) > area || !frames_overlap (cur, frame) || frame_overlaps (cur)) - { - PRINT_DEBUG (("Didn't fit vertically\n")); - - /* Restore the current window's frame */ - memcpy (cur, &tmp_frame, sizeof (rp_frame)); - } - else - { - PRINT_DEBUG (("It fit vertically!!\n")); - - /* update the frame backup */ - memcpy (&tmp_frame, cur, sizeof (rp_frame)); - fits = 1; - } - - if (frame_is_left (frame, cur) - || frame_is_right (frame, cur)) - { - if (frame_is_right (frame, cur)) - cur->x = frame->x; - cur->width += frame->width; - } - - PRINT_DEBUG (("Attempting horizontal Frame x=%d width=%d\n", cur->x, cur->width)); - PRINT_DEBUG (("New Total Area: %d\n", total_frame_area(s))); - - /* Same test as the vertical test, above. */ - if (total_frame_area(s) > area || !frames_overlap (cur, frame) || frame_overlaps (cur)) - { - PRINT_DEBUG (("Didn't fit horizontally\n")); - - /* Restore the current window's frame */ - memcpy (cur, &tmp_frame, sizeof (rp_frame)); - } - else - { - PRINT_DEBUG (("It fit horizontally!!\n")); - fits = 1; - } - - if (fits) - { - /* The current frame fits into the new space so keep its - new frame parameters and maximize the window to fit - the new frame size. */ - if (cur->win_number != EMPTY) - { - rp_window *new = find_window_number (cur->win_number); - maximize_all_windows_in_frame (cur); - XRaiseWindow (dpy, new->w); - } - } - else - { - memcpy (cur, &tmp_frame, sizeof (rp_frame)); - } - } - - frame_free (s, frame); -} - -/* Switch the input focus to another frame, and therefore a different - window. */ -void -set_active_frame (rp_frame *frame, int force_indicator) -{ - rp_screen *old_s = current_screen(); - rp_screen *s = frames_screen (frame); - int old = current_screen()->current_frame; - rp_window *win, *old_win; - rp_frame *old_frame; - - win = find_window_number (frame->win_number); - old_frame = current_frame(); - if (old_frame) - { - old_win = find_window_number (old_frame->win_number); - } - else - { - old_win = NULL; - } - - /* Make the switch */ - give_window_focus (win, old_win); - update_last_access (frame); - s->current_frame = frame->number; - - /* If frame->win == NULL, then rp_current_screen is not updated. */ - rp_current_screen = s->xine_screen_num; - - update_bar (s); - - /* Possibly show the frame indicator. */ - if ((old != s->current_frame && num_frames(s) > 1) - || s != old_s) - { - show_frame_indicator(force_indicator); - - /* run the frame switch hook. We call it in here because this is - when a frame switch ACTUALLY (for sure) happens. */ - hook_run (&rp_switch_frame_hook); - } - - /* If the frame has no window to give focus to, give the key window - focus. */ - if(frame->win_number == EMPTY) - { - set_window_focus (s->key_window); - } - - /* Call the switchscreen hook, when appropriate. */ - if (s != old_s) - hook_run (&rp_switch_screen_hook); -} - -void -exchange_with_frame (rp_frame *cur, rp_frame *frame) -{ - rp_window *win,*last_win; - - if (frame == NULL || frame == cur) return; - - /* Exchange the windows in the frames */ - win = find_window_number (cur->win_number); - last_win = set_frames_window (frame, win); - set_frames_window (cur, last_win); - - /* Make sure the windows comes up full screen */ - if (last_win) - maximize (last_win); - if (win) - { - maximize (win); - /* Make sure the program bar is always on the top */ - update_window_names (win->scr, defaults.window_fmt); - } - - /* Make the switch */ - update_last_access (frame); - - set_active_frame(frame, 0); -} - - -void -blank_frame (rp_frame *frame) -{ - rp_screen *s; - rp_window *win; - - if (frame->win_number == EMPTY) return; - - s = frames_screen (frame); - - win = find_window_number (frame->win_number); - hide_window (win); - hide_others (win); - - set_frames_window (frame, NULL); - - update_bar (s); - - /* Give the key window focus. */ - set_window_focus (frames_screen(frame)->key_window); -} - -void -hide_frame_indicator (void) -{ - int i; - for (i=0; i<num_screens; i++) - XUnmapWindow (dpy, screens[i].frame_window); -} - -void -show_frame_indicator (int force) -{ - if (num_frames (current_screen()) > 1 || force) - { - hide_frame_indicator (); - show_frame_message (defaults.frame_fmt); - alarm (defaults.frame_indicator_timeout); - } -} - -void -show_frame_message (char *msg) -{ - rp_screen *s = current_screen (); - int width, height; - rp_frame *frame; - rp_window *win; - rp_window_elem *elem = NULL; - struct sbuf *msgbuf; - - frame = current_frame(); - win = current_window (); - if (win) - { - rp_group *g; - - g = groups_find_group_by_window (win); - elem = group_find_window (&g->mapped_windows, win); - } - - /* A frame doesn't always contain a window. */ - msgbuf = sbuf_new (0); - if (elem) - format_string (msg, elem, msgbuf); - else - { - sbuf_concat (msgbuf, EMPTY_FRAME_MESSAGE); - } - - width = defaults.bar_x_padding * 2 - + rp_text_width (s, msgbuf->data, msgbuf->len); - height = (FONT_HEIGHT (s) + defaults.bar_y_padding * 2); - - /* We don't want another frame indicator to be displayed on another - * screen at the same time, so we hide it before bringing it back again. - */ - hide_frame_indicator (); - - XMoveResizeWindow (dpy, s->frame_window, - s->left + frame->x + frame->width / 2 - width / 2, - s->top + frame->y + frame->height / 2 - height / 2, - width, height); - - XMapRaised (dpy, s->frame_window); - XClearWindow (dpy, s->frame_window); - XSync (dpy, False); - - rp_draw_string (s, s->frame_window, STYLE_NORMAL, - defaults.bar_x_padding, - defaults.bar_y_padding + FONT_ASCENT(s), - msgbuf->data, msgbuf->len); - - sbuf_free (msgbuf); -} - -rp_frame * -find_frame_up (rp_frame *frame) -{ - rp_screen *s = frames_screen (frame); - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - if (frame->y == cur->y + cur->height) - { - if (frame->x >= cur->x && frame->x < cur->x + cur->width) - return cur; - } - } - - return NULL; -} - -rp_frame * -find_frame_down (rp_frame *frame) -{ - rp_screen *s = frames_screen (frame); - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - if (frame->y + frame->height == cur->y) - { - if (frame->x >= cur->x && frame->x < cur->x + cur->width) - return cur; - } - } - - return NULL; -} - -rp_frame * -find_frame_left (rp_frame *frame) -{ - rp_screen *s = frames_screen (frame); - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - if (frame->x == cur->x + cur->width) - { - if (frame->y >= cur->y && frame->y < cur->y + cur->height) - return cur; - } - } - - return NULL; -} - -rp_frame * -find_frame_right (rp_frame *frame) -{ - rp_screen *s = frames_screen (frame); - rp_frame *cur; - - list_for_each_entry (cur, &s->frames, node) - { - if (frame->x + frame->width == cur->x) - { - if (frame->y >= cur->y && frame->y < cur->y + cur->height) - return cur; - } - } - - return NULL; -} - -rp_frame * -find_frame_number (int num) -{ - int i; - rp_frame *cur; - - for (i=0; i<num_screens; i++) - { - rp_screen *s = &screens[i]; - - list_for_each_entry (cur, &s->frames, node) - { - if (cur->number == num) - return cur; - } - } - - return NULL; -} diff --git a/src/split.h b/src/split.h deleted file mode 100644 index 87bb660..0000000 --- a/src/split.h +++ /dev/null @@ -1,60 +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 - * - */ - -#ifndef SPLIT_H -#define SPLIT_H - -int num_frames (rp_screen *s); -rp_window *set_frames_window (rp_frame *frame, rp_window *win); -void cleanup_frame (rp_frame *frame); -void maximize_all_windows_in_frame (rp_frame *frame); -void h_split_frame (rp_frame *frame, int pixels); -void v_split_frame (rp_frame *frame, int pixels); -void remove_all_splits (void); -void resize_shrink_to_window (rp_frame *frame); -void resize_frame_horizontally (rp_frame *frame, int diff); -void resize_frame_vertically (rp_frame *frame, int diff); -void remove_frame (rp_frame *frame); -rp_window *find_window_for_frame (rp_frame *frame); -rp_frame *find_windows_frame (rp_window *win); -rp_frame *find_frame_next (rp_frame *frame); -rp_frame *find_frame_prev (rp_frame *frame); -rp_window *current_window (void); -void init_frame_lists (void); -void init_frame_list (rp_screen *screen); -void set_active_frame (rp_frame *frame, int force_indicator); -void exchange_with_frame (rp_frame *cur, rp_frame *frame); -void blank_frame (rp_frame *frame); -void show_frame_indicator (int force); -void hide_frame_indicator (void); - -void show_frame_message (char *msg); - -rp_frame *find_frame_right (rp_frame *frame); -rp_frame *find_frame_left (rp_frame *frame); -rp_frame *find_frame_down (rp_frame *frame); -rp_frame *find_frame_up (rp_frame *frame); -rp_frame *find_last_frame (void); -rp_frame * find_frame_number (int num); - -rp_frame *current_frame (void); - -#endif diff --git a/src/window.c b/src/window.c deleted file mode 100644 index 15024f6..0000000 --- a/src/window.c +++ /dev/null @@ -1,820 +0,0 @@ -/* functions for handling the window list - * 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 - */ - -/* Citing getsid(2) here: - To get the prototype under glibc, define both _XOPEN_SOURCE and - _XOPEN_SOURCE_EXTENDED, or use "#define _XOPEN_SOURCE n" for some - integer n larger than or equal to 500. */ -#define _XOPEN_SOURCE 500 -#include <unistd.h> /* for getsid */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "ratpoison.h" - -LIST_HEAD(rp_unmapped_window); -LIST_HEAD(rp_mapped_window); - -struct numset *rp_window_numset; - -/* Get the mouse position relative to the the specified window */ -static void -get_mouse_position (rp_window *win, int *mouse_x, int *mouse_y) -{ - Window root_win, child_win; - int root_x, root_y; - unsigned int mask; - - XQueryPointer (dpy, win->scr->root, &root_win, &child_win, mouse_x, mouse_y, &root_x, &root_y, &mask); -} - -void -free_window (rp_window *w) -{ - if (w == NULL) return; - - free (w->user_name); - free (w->res_name); - free (w->res_class); - free (w->wm_name); - - XFree (w->hints); - - free (w); -} - -void -update_window_gravity (rp_window *win) -{ -/* if (win->hints->win_gravity == ForgetGravity) */ -/* { */ - if (win->transient) - win->gravity = defaults.trans_gravity; - else if (win->hints->flags & PMaxSize || win->hints->flags & PAspect) - win->gravity = defaults.maxsize_gravity; - else - win->gravity = defaults.win_gravity; -/* } */ -/* else */ -/* { */ -/* win->gravity = win->hints->win_gravity; */ -/* } */ -} - -char * -window_name (rp_window *win) -{ - if (win == NULL) return NULL; - - if (win->named) - return win->user_name; - - switch (defaults.win_name) - { - case WIN_NAME_RES_NAME: - if (win->res_name) - return win->res_name; - else return win->user_name; - - case WIN_NAME_RES_CLASS: - if (win->res_class) - return win->res_class; - else return win->user_name; - - /* if we're not looking for the res name or res class, then - we're looking for the window title. */ - default: - if (win->wm_name) - return win->wm_name; - else return win->user_name; - } - - return NULL; -} - -/* FIXME: we need to verify that the window is running on the same - host as something. otherwise there could be overlapping PIDs. */ -struct rp_child_info * -get_child_info (Window w) -{ - rp_child_info *cur; - int status; - int pid; - Atom type_ret; - int format_ret; - unsigned long nitems; - unsigned long bytes_after; - unsigned char *req; - pid_t sid; - - status = XGetWindowProperty (dpy, w, _net_wm_pid, - 0, 0, False, XA_CARDINAL, - &type_ret, &format_ret, &nitems, &bytes_after, &req); - - if (status != Success || req == NULL) - { - PRINT_DEBUG (("Couldn't get _NET_WM_PID Property\n")); - return NULL; - } - - /* XGetWindowProperty always allocates one extra byte even if - the property is zero length. */ - XFree (req); - - status = XGetWindowProperty (dpy, w, _net_wm_pid, - 0, (bytes_after / 4) + (bytes_after % 4 ? 1 : 0), - False, XA_CARDINAL, &type_ret, &format_ret, &nitems, - &bytes_after, &req); - - if (status != Success || req == NULL) - { - PRINT_DEBUG (("Couldn't get _NET_WM_PID Property\n")); - return NULL; - } - - pid = *((int *)req); - XFree(req); - - PRINT_DEBUG(("pid: %d\n", pid)); - - /* The pids will hopefully be in the same session. */ - sid = getsid (pid); - list_for_each_entry (cur, &rp_children, node) - { - PRINT_DEBUG(("cur->pid=%d sid=%d\n", cur->pid, getsid (cur->pid))); - if (sid == getsid (cur->pid)) - return cur; - } - - return NULL; -} - -/* Allocate a new window and add it to the list of managed windows */ -rp_window * -add_to_window_list (rp_screen *s, Window w) -{ - struct rp_child_info *child_info; - rp_window *new_window; - rp_group *group = NULL; - int frame_num = -1; - - new_window = xmalloc (sizeof (rp_window)); - - new_window->w = w; - new_window->scr = s; - new_window->last_access = 0; - new_window->state = WithdrawnState; - new_window->number = -1; - new_window->frame_number = EMPTY; - new_window->intended_frame_number = -1; - new_window->named = 0; - new_window->hints = XAllocSizeHints (); - new_window->colormap = DefaultColormap (dpy, s->screen_num); - new_window->transient = XGetTransientForHint (dpy, new_window->w, &new_window->transient_for); - PRINT_DEBUG (("transient %d\n", new_window->transient)); - - update_window_gravity (new_window); - - get_mouse_position (new_window, &new_window->mouse_x, &new_window->mouse_y); - - XSelectInput (dpy, new_window->w, WIN_EVENTS); - - new_window->user_name = xstrdup ("Unnamed"); - - new_window->wm_name = NULL; - new_window->res_name = NULL; - new_window->res_class = NULL; - - /* Add the window to the end of the unmapped list. */ - list_add_tail (&new_window->node, &rp_unmapped_window); - - child_info = get_child_info (w); - - if (child_info && !child_info->window_mapped) { - rp_frame *frame = screen_find_frame_by_frame (child_info->screen, child_info->frame); - - PRINT_DEBUG(("frame=%p\n", frame)); - group = groups_find_group_by_group (child_info->group); - if (frame) - frame_num = frame->number; - /* Only map the first window in the launch frame. */ - child_info->window_mapped = 1; - } - - /* Add the window to the group it's pid was launched in or the - current one. */ - if (group) - group_add_window (group, new_window); - else - group_add_window (rp_current_group, new_window); - - PRINT_DEBUG(("frame_num: %d\n", frame_num)); - if (frame_num >= 0) - new_window->intended_frame_number = frame_num; - - return new_window; -} - -/* Check to see if the window is in the list of windows. */ -rp_window * -find_window_in_list (Window w, struct list_head *list) -{ - rp_window *cur; - - list_for_each_entry (cur, list, node) - { - if (cur->w == w) return cur; - } - - return NULL; -} - -/* Check to see if the window is in any of the lists of windows. */ -rp_window * -find_window (Window w) -{ - rp_window *win = NULL; - - - win = find_window_in_list (w, &rp_mapped_window); - - if (!win) - { - win = find_window_in_list (w, &rp_unmapped_window); - if (win) - PRINT_DEBUG (("Window found in unmapped window list\n")); - else - PRINT_DEBUG (("Window not found.\n")); - } - else - { - PRINT_DEBUG (("Window found in mapped window list.\n")); - } - - return win; -} - -void -set_current_window (rp_window *win) -{ - set_frames_window (current_frame(), win); -} - -rp_window * -find_window_number (int n) -{ - rp_window *cur; - - list_for_each_entry (cur,&rp_mapped_window,node) - { -/* if (cur->state == STATE_UNMAPPED) continue; */ - - if (n == cur->number) return cur; - } - - return NULL; -} - -rp_window * -find_window_name (char *name) -{ - rp_window_elem *cur; - - list_for_each_entry (cur, &rp_current_group->mapped_windows, node) - { - if (str_comp (name, window_name (cur->win), strlen (name))) - return cur->win; - } - - /* didn't find it */ - return NULL; -} - -/* Return the previous window in the list. Assumes window is in the - mapped window list. */ -rp_window* -find_window_prev (rp_window *w) -{ - rp_window *cur; - - if (!w) return NULL; - - for (cur = list_prev_entry (w, &rp_mapped_window, node); - cur != w; - cur = list_prev_entry (cur, &rp_mapped_window, node)) - { - if (!find_windows_frame (cur)) - { - return cur; - } - } - - return NULL; -} - -/* Return the next window in the list. Assumes window is in the mapped - window list. */ -rp_window* -find_window_next (rp_window *w) -{ - rp_window *cur; - - if (!w) return NULL; - - for (cur = list_next_entry (w, &rp_mapped_window, node); - cur != w; - cur = list_next_entry (cur, &rp_mapped_window, node)) - { - if (!find_windows_frame (cur)) - { - return cur; - } - } - - return NULL; -} - -rp_window * -find_window_other (rp_screen *screen) -{ - return group_last_window (rp_current_group, screen); -} - - - -/* Assumes the list is sorted by increasing number. Inserts win into - to Right place to keep the list sorted. */ -void -insert_into_list (rp_window *win, struct list_head *list) -{ - rp_window *cur; - - list_for_each_entry (cur, list, node) - { - if (cur->number > win->number) - { - list_add_tail (&win->node, &cur->node); - return; - } - } - - list_add_tail(&win->node, list); -} - -static void -save_mouse_position (rp_window *win) -{ - Window root_win, child_win; - int root_x, root_y; - unsigned int mask; - - /* In the case the XQueryPointer raises a BadWindow error, the - window is not mapped or has been destroyed so it doesn't matter - what we store in mouse_x and mouse_y since they will never be - used again. */ - - ignore_badwindow++; - - XQueryPointer (dpy, win->w, &root_win, &child_win, - &root_x, &root_y, &win->mouse_x, &win->mouse_y, &mask); - - ignore_badwindow--; -} - -/* Takes focus away from last_win and gives focus to win */ -void -give_window_focus (rp_window *win, rp_window *last_win) -{ - /* counter increments every time this function is called. This way - we can track which window was last accessed. */ - static int counter = 1; - - /* Warp the cursor to the window's saved position if last_win and - win are different windows. */ - if (last_win != NULL && win != last_win) - { - save_mouse_position (last_win); - XSetWindowBorder (dpy, last_win->w, last_win->scr->bw_color); - } - - if (win == NULL) return; - - counter++; - win->last_access = counter; - unhide_window (win); - - if (defaults.warp) - { - PRINT_DEBUG (("Warp pointer\n")); - XWarpPointer (dpy, None, win->w, - 0, 0, 0, 0, win->mouse_x, win->mouse_y); - } - - /* Swap colormaps */ - if (last_win != NULL) XUninstallColormap (dpy, last_win->colormap); - XInstallColormap (dpy, win->colormap); - - XSetWindowBorder (dpy, win->w, win->scr->fw_color); - - /* Finally, give the window focus */ - rp_current_screen = win->scr->xine_screen_num; - set_rp_window_focus (win); - - XSync (dpy, False); -} - -#if 0 -void -unhide_transient_for (rp_window *win) -{ - rp_frame *frame; - rp_window *transient_for; - - if (win == NULL) return; - if (!win->transient) return; - frame = find_windows_frame (win); - - transient_for = find_window (win->transient_for); - if (transient_for == NULL) - { - PRINT_DEBUG (("Can't find transient_for for '%s'\n", win->name )); - return; - } - - if (find_windows_frame (transient_for) == NULL) - { - set_frames_window (frame, transient_for); - maximize (transient_for); - - PRINT_DEBUG (("unhide transient window: %s\n", transient_for->name)); - - unhide_window_below (transient_for); - - if (transient_for->transient) - { - unhide_transient_for (transient_for); - } - - set_frames_window (frame, win); - } - else if (transient_for->transient) - { - unhide_transient_for (transient_for); - } -} -#endif - -#if 0 -/* Hide all transient windows for win until we get to last. */ -void -hide_transient_for_between (rp_window *win, rp_window *last) -{ - rp_window *transient_for; - - if (win == NULL) return; - if (!win->transient) return; - - transient_for = find_window (win->transient_for); - if (transient_for == last) - { - PRINT_DEBUG (("Can't find transient_for for '%s'\n", win->name )); - return; - } - - if (find_windows_frame (transient_for) == NULL) - { - PRINT_DEBUG (("hide transient window: %s\n", transient_for->name)); - hide_window (transient_for); - } - - if (transient_for->transient) - { - hide_transient_for (transient_for); - } -} -#endif - -#if 0 -void -hide_transient_for (rp_window *win) -{ - /* Hide ALL the transient windows for win. */ - hide_transient_for_between (win, NULL); -} -#endif - -#if 0 -/* return 1 if transient_for is a transient window for win or one of - win's transient_for ancestors. */ -int -is_transient_ancestor (rp_window *win, rp_window *transient_for) -{ - rp_window *tmp; - - if (win == NULL) return 0; - if (!win->transient) return 0; - if (transient_for == NULL) return 0; - - tmp = win; - - do - { - tmp = find_window (tmp->transient_for); - if (tmp == transient_for) - return 1; - } while (tmp && tmp->transient); - - return 0; -} -#endif - -/* Gets frame from window -- helper to set_active_window_body - * - * While this fct returns a value, it also modifies a param, last_frame, - * which is ugly... but since this is trying to fix ugly code I guess it - * can be a little ugly. - */ -static rp_frame* -get_frame(rp_window *win, rp_frame *last_frame) -{ - rp_frame* frame=NULL; - - /* use the intended frame if we can. */ - if (win->intended_frame_number >= 0) - { - /* With Xinerama, we can move a window over to the current screen; otherwise - * we have to switch to the screen that the window belongs to. - */ - if (rp_have_xinerama) - frame = screen_get_frame (current_screen(), win->intended_frame_number); - else - frame = screen_get_frame (win->scr, win->intended_frame_number); - - win->intended_frame_number = -1; - if (frame != current_frame()) - last_frame = current_frame(); - } - - if (!frame) - { - if (rp_have_xinerama) - frame = screen_get_frame (current_screen(), current_screen()->current_frame); - else - frame = screen_get_frame (win->scr, win->scr->current_frame); - } - - return frame; -} - -/* Finds a non-dedicated frame -- helper to set_active_window_body */ -static void -find_non_dedicated_frame(rp_window *win, rp_frame *frame, rp_frame *last_frame) -{ - /* Try to find a non-dedicated frame. */ - rp_frame *cur; - rp_screen *scr; - int done; - - scr = (rp_have_xinerama)?&screens[rp_current_screen]:win->scr; - done = 0; - - /* Try the only / current screen... */ - for (cur = list_next_entry (frame, &scr->frames, node); - cur != frame; - cur = list_next_entry (cur, &scr->frames, node)) - { - if (!cur->dedicated) - { - set_active_frame (cur, 0); - last_frame = frame; - frame = cur; - break; - } - } - - /* If we have Xinerama, we can check *all* screens... */ - /* TODO: could this be put into yet another function? */ - if (rp_have_xinerama && !done) - { - int i; - - for (i=0; i<num_screens && !done; i++) - { - if (scr == &screens[i]) continue; - list_for_each_entry (cur,&screens[i].frames,node) - { - if (!cur->dedicated) - { - set_active_frame (cur, 0); - last_frame = frame; - frame = cur; - - /* Good case for a goto here? */ - done = 1; /* Break outer loop. */ - break; /* Break inner loop. */ - } - } - } - } -} - -/* In the current frame, set the active window to win. win will have focus. */ -void set_active_window (rp_window *win) -{ - set_active_window_body(win, 0); -} - -void set_active_window_force (rp_window *win) -{ - set_active_window_body(win, 1); -} - -void -set_active_window_body (rp_window *win, int force) -{ - rp_window *last_win; - rp_frame *frame = NULL, *last_frame = NULL; - - if (win == NULL) return; - - PRINT_DEBUG (("intended_frame_number: %d\n", win->intended_frame_number)); - - frame = get_frame(win, last_frame); - - if (frame->dedicated && !force) - find_non_dedicated_frame(win, frame, last_frame); - - last_win = set_frames_window (frame, win); - - if (last_win) PRINT_DEBUG (("last window: %s\n", window_name (last_win))); - PRINT_DEBUG (("new window: %s\n", window_name (win))); - - /* Make sure the window comes up full screen */ - maximize (win); - - /* Focus the window. */ - give_window_focus (win, last_win); - - /* The other windows in the frame will be hidden if this window - doesn't qualify as a transient window (ie dialog box. */ - if (!window_is_transient (win)) - hide_others(win); - - /* Make sure the program bar is always on the top */ - update_window_names (win->scr, defaults.window_fmt); - - XSync (dpy, False); - - /* If we switched frame, go back to the old one. */ - if (last_frame) - set_active_frame (last_frame, 0); - - /* Call the switch window hook */ - hook_run (&rp_switch_win_hook); -} - -/* Go to the window, switching frames if the window is already in a - frame. */ -void -goto_window (rp_window *win) -{ - rp_frame *frame; - - /* There is nothing to do if it is already the current window. */ - if (current_window() == win) - return; - - frame = find_windows_frame (win); - if (frame) - { - set_active_frame (frame, 0); - } - else - { - set_active_window (win); - } -} - -void -print_window_information (rp_group *group, rp_window *win) -{ - rp_window_elem *win_elem; - /* Display the window's number in group. This gives the possibility - of windows existing in multiple groups. */ - win_elem = group_find_window (&group->mapped_windows, win); - if (win_elem) - marked_message_printf (0, 0, MESSAGE_WINDOW_INFORMATION, - win_elem->number, window_name (win)); - else - marked_message_printf (0, 0, "%s doesn't exist in group %d\n", - window_name(win), group->number); -} - -/* get the window list and store it in buffer delimiting each window - with delim. mark_start and mark_end will be filled with the text - positions for the start and end of the current window. */ -void -get_window_list (char *fmt, char *delim, struct sbuf *buffer, - int *mark_start, int *mark_end) -{ - rp_window_elem *we; - - if (buffer == NULL) return; - - sbuf_clear (buffer); - find_window_other (current_screen()); - - /* We only loop through the current group to look for windows. */ - list_for_each_entry (we,&rp_current_group->mapped_windows,node) - { - PRINT_DEBUG (("%d-%s\n", we->number, window_name (we->win))); - - if (we->win == current_window()) - *mark_start = strlen (sbuf_get (buffer)); - - /* A hack, pad the window with a space at the beginning and end - if there is no delimiter. */ - if (!delim) - sbuf_concat (buffer, " "); - - format_string (fmt, we, buffer); - - /* A hack, pad the window with a space at the beginning and end - if there is no delimiter. */ - if (!delim) - sbuf_concat (buffer, " "); - - /* Only put the delimiter between the windows, and not after the the last - window. */ - if (delim && we->node.next != &rp_current_group->mapped_windows) - sbuf_concat (buffer, delim); - - if (we->win == current_window()) - { - *mark_end = strlen (sbuf_get (buffer)); - } - } - - if (!strcmp (sbuf_get (buffer), "")) - { - sbuf_copy (buffer, MESSAGE_NO_MANAGED_WINDOWS); - } -} - -void -init_window_stuff (void) -{ - rp_window_numset = numset_new (); -} - -void -free_window_stuff (void) -{ - rp_window *cur; - struct list_head *tmp, *iter; - - list_for_each_safe_entry (cur, iter, tmp, &rp_unmapped_window, node) - { - list_del (&cur->node); - groups_del_window (cur); - free_window (cur); - } - - list_for_each_safe_entry (cur, iter, tmp, &rp_mapped_window, node) - { - list_del (&cur->node); - groups_unmap_window (cur); - groups_del_window (cur); - free_window (cur); - } - - numset_free (rp_window_numset); -} - -rp_frame * -win_get_frame (rp_window *win) -{ - if (win->frame_number != EMPTY) - return screen_get_frame (win->scr, win->frame_number); - else - return NULL; -} diff --git a/src/window.h b/src/window.h deleted file mode 100644 index 922200b..0000000 --- a/src/window.h +++ /dev/null @@ -1,73 +0,0 @@ -/* functions for managing the window list - * 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 - */ - -#ifndef _RATPOISON_LIST_H -#define _RATPOISON_LIST_H 1 - -#include "sbuf.h" - -void free_window (rp_window *w); -rp_window *add_to_window_list (rp_screen *s, Window w); -void last_window (void); -rp_window *find_window_in_list (Window w, struct list_head *list); -rp_window *find_window (Window w); -void maximize_current_window (void); -void give_window_focus (rp_window *win, rp_window *last_win); -void set_active_window (rp_window *win); -void goto_window (rp_window *win); -void set_current_window (rp_window *win); -void update_window_gravity (rp_window *win); -char *window_name (rp_window *win); - -#if 0 -void unhide_transient_for (rp_window *win); -void hide_transient_for (rp_window *win); -void hide_transient_for_between (rp_window *win, rp_window *last); -int is_transient_ancestor (rp_window *win, rp_window *transient_for); -#endif - -/* int goto_window_name (char *name); */ -rp_window *find_window_other (rp_screen *screen); -rp_window *find_window_by_number (int n); -rp_window *find_window_name (char *name); -rp_window *find_window_prev (rp_window *w); -rp_window *find_window_prev_with_frame (rp_window *w); -rp_window *find_window_next (rp_window *w); -rp_window *find_window_next_with_frame (rp_window *w); -rp_window *find_window_number (int n); -void sort_window_list_by_number (void); - -void insert_into_list (rp_window *win, struct list_head *list); - -void print_window_information (rp_group *group, rp_window *win); -void get_window_list (char *fmt, char *delim, struct sbuf *buffer, - int *mark_start, int *mark_end); -void init_window_stuff (void); -void free_window_stuff (void); - -rp_frame *win_get_frame (rp_window *win); - -void set_active_window_force (rp_window *win); -void set_active_window_body (rp_window *win, int force); - -struct rp_child_info *get_child_info (Window w); - -#endif /* ! _RATPOISON_LIST_H */ diff --git a/src/xinerama.c b/src/xinerama.c deleted file mode 100644 index 51d51b3..0000000 --- a/src/xinerama.c +++ /dev/null @@ -1,99 +0,0 @@ -/* functions for grabbing information about Xinerama screens - * Copyright (C) 2003 Cameron Patrick - * - * 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 "ratpoison.h" - -#ifdef HAVE_X11_EXTENSIONS_XINERAMA_H -# include <X11/extensions/Xinerama.h> -# define XINERAMA -#endif - -int rp_have_xinerama = 0; -int xine_screen_count; - -#ifdef XINERAMA -static XineramaScreenInfo *xine_screens = NULL; -#endif - -void -init_xinerama(void) -{ -#ifdef XINERAMA - int evbase, errbase, major, minor; - - rp_have_xinerama = 0; - - if (xine_screens) XFree(xine_screens); - - if (!XineramaQueryExtension(dpy, &evbase, &errbase)) { - return; - } - - if (!XineramaQueryVersion(dpy, &major, &minor) != Success) { - return; - } - - if (major != 1) { - fprintf (stderr, "Warning: Xinerama version %d.%d not supported\n", major, minor); - return; - } - - if (!XineramaIsActive(dpy)) { - return; - } - - xine_screens = XineramaQueryScreens(dpy, &xine_screen_count); - if ((xine_screens == NULL) || (xine_screen_count < 2)) { - return; - } - - rp_have_xinerama = 1; -#else - rp_have_xinerama = 0; -#endif -} - -#ifdef XINERAMA -void xinerama_get_screen_info(int sc, int *x, int *y, int *w, int *h) -{ - if ((sc < xine_screen_count) && (sc >= 0)) { - *x = xine_screens[sc].x_org; - *y = xine_screens[sc].y_org; - *w = xine_screens[sc].width; - *h = xine_screens[sc].height; - } -} -#else -void xinerama_get_screen_info(int sc UNUSED, int *x UNUSED, int *y UNUSED, int *w UNUSED, int *h UNUSED) -{ -} -#endif - -void -free_xinerama(void) -{ -#ifdef XINERAMA - if (xine_screens) { - XFree(xine_screens); - } - rp_have_xinerama = 0; -#endif -} diff --git a/src/xinerama.h b/src/xinerama.h deleted file mode 100644 index 233ec46..0000000 --- a/src/xinerama.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2003 Cameron Patrick - * - * 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 - */ - -#ifndef XINERAMA_H -#define XINERAMA_H - -void init_xinerama(void); -void free_xinerama(void); -void xinerama_get_screen_info(int sc, int *x, int *y, int *w, int *h); - -#endif |