summaryrefslogtreecommitdiff
path: root/src/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input.c')
-rw-r--r--src/input.c622
1 files changed, 0 insertions, 622 deletions
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;
-}