diff options
author | Philippe Brochard <pbrochard@common-lisp.net> | 2009-05-18 15:28:11 +0200 |
---|---|---|
committer | Philippe Brochard <pbrochard@common-lisp.net> | 2009-05-18 15:28:11 +0200 |
commit | 0d5a90f36acc602d993075bbccaebb44e671dca6 (patch) | |
tree | 71f73266ef446b8f030f7182544ef21593318fb1 /options.c | |
parent | be5b5354a2af10580bde41d3cbf6d2c9db72bb9b (diff) | |
download | xbindkeys-0d5a90f36acc602d993075bbccaebb44e671dca6.tar.gz |
Initial import
Diffstat (limited to 'options.c')
-rw-r--r-- | options.c | 1119 |
1 files changed, 1119 insertions, 0 deletions
diff --git a/options.c b/options.c new file mode 100644 index 0000000..be678a7 --- /dev/null +++ b/options.c @@ -0,0 +1,1119 @@ +/*************************************************************************** + xbindkeys : a program to bind keys to commands under X11. + ------------------- + begin : Sat Oct 13 14:11:34 CEST 2001 + copyright : (C) 2001 by Philippe Brochard + email : hocwp@free.fr + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <X11/keysym.h> +#include <ctype.h> +#include "options.h" +#include "xbindkeys.h" +#include "keys.h" +#include "grab_key.h" +#ifdef GUILE_FLAG +#include <libguile.h> +#endif +#include "config.h" + +char *display_name = NULL; + +char rc_file[512]; +#ifdef GUILE_FLAG +char rc_guile_file[512]; +#endif + +int verbose = 0; +int have_to_show_binding = 0; +int have_to_get_binding = 0; +int have_to_start_as_daemon = 1; + +char *geom = NULL; + + +static void show_version (void); +static void show_help (void); +static void show_defaults_rc (void); +#ifdef GUILE_FLAG +static void show_defaults_guile_rc (void); +int init_xbk_guile_fns (void); +SCM set_numlock_wrapper (SCM x); +SCM set_scrolllock_wrapper (SCM x); +SCM set_capslock_wrapper (SCM x); +SCM xbindkey_wrapper(SCM key, SCM cmd); +SCM xbindkey_function_wrapper(SCM key, SCM fun); +SCM remove_xbindkey_wrapper(SCM key); +SCM run_command_wrapper (SCM command); +SCM grab_all_keys_wrapper (void); +SCM ungrab_all_keys_wrapper (void); +SCM remove_all_keys_wrapper (void); +SCM debug_info_wrapper (void); +#endif + + + +void +get_options (int argc, char **argv) +{ + int i; + char *home; + + strncpy (rc_file, "", sizeof(rc_file)); +#ifdef GUILE_FLAG + strncpy (rc_guile_file, "", sizeof (rc_guile_file)); +#endif + + verbose = 0; + have_to_show_binding = 0; + have_to_get_binding = 0; + have_to_start_as_daemon = 1; + + + for (i = 1; i < argc; i++) + { + if (strcmp (argv[i], "-V") == 0 || strcmp (argv[i], "--version") == 0) + { + show_version (); + exit (1); + } + else if ((strcmp (argv[i], "-X") == 0 + || strcmp (argv[i], "--display") == 0) && i + 1 < argc) + { + display_name = argv[++i]; + } + else if ((strcmp (argv[i], "-f") == 0 + || strcmp (argv[i], "--file") == 0) && i + 1 < argc) + { + strncpy (rc_file, argv[++i], sizeof (rc_file) - 1); + } +#ifdef GUILE_FLAG + else if ((strcmp (argv[i], "-fg") == 0 + || strcmp (argv[i], "--guile-file") == 0) && i + 1 < argc) + { + strncpy (rc_guile_file, argv[++i], sizeof (rc_guile_file) - 1); + } +#endif + else if (strcmp (argv[i], "-s") == 0 || strcmp (argv[i], "--show") == 0) + { + have_to_show_binding = 1; + } + else if (strcmp (argv[i], "-k") == 0 || strcmp (argv[i], "--key") == 0) + { + have_to_get_binding = 1; + } + else if (strcmp (argv[i], "-mk") == 0 + || strcmp (argv[i], "--multikey") == 0) + { + have_to_get_binding = 2; + } + else if (strcmp (argv[i], "-v") == 0 + || strcmp (argv[i], "--verbose") == 0) + { + verbose = 1; + have_to_start_as_daemon = 0; + } + else if (strcmp (argv[i], "-d") == 0 + || strcmp (argv[i], "--defaults") == 0) + { + show_defaults_rc (); + } +#ifdef GUILE_FLAG + else if (strcmp (argv[i], "-dg") == 0 + || strcmp (argv[i], "--defaults-guile") == 0) + { + show_defaults_guile_rc (); + } +#endif + else if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "--help") == 0) + { + show_help (); + exit (1); + } + else if ((strcmp (argv[i], "-g") == 0 + || strcmp (argv[i], "--geometry") == 0) && i + 1 < argc) + { + geom = argv[++i]; + } + else if (strcmp (argv[i], "-n") == 0 + || strcmp (argv[i], "--nodaemon") == 0) + { + have_to_start_as_daemon = 0; + } + else + { + show_help (); + exit (1); + } + } + + if (strcmp (rc_file, "") == 0) + { + home = getenv ("HOME"); + + if (rc_file) + { + strncpy (rc_file, home, sizeof (rc_file) - 20); + strncat (rc_file, "/.xbindkeysrc", sizeof (rc_file)); + } + } + +#ifdef GUILE_FLAG + if (strcmp (rc_guile_file, "") == 0) + { + home = getenv ("HOME"); + + if (rc_guile_file) + { + strncpy (rc_guile_file, home, sizeof (rc_guile_file) - 20); + strncat (rc_guile_file, "/.xbindkeysrc.scm", sizeof (rc_guile_file)); + } + } +#endif +} + +void +show_options (void) +{ + if (verbose) + { + printf ("displayName = %s\n", display_name); + printf ("rc file = %s\n", rc_file); +#ifdef GUILE_FLAG + printf ("rc guile file = %s\n", rc_guile_file); +#endif + } +} + + +static void +show_version (void) +{ + fprintf (stderr, "xbindkeys %s by Philippe Brochard\n", PACKAGE_VERSION); +} + +static void +show_help (void) +{ + show_version (); + + fprintf (stderr, "usage: xbindkeys [options]\n"); + fprintf (stderr, " where options are:\n"); + + fprintf (stderr, " -V, --version Print version and exit\n"); + fprintf (stderr, " -d, --defaults Print a default rc file\n"); +#ifdef GUILE_FLAG + fprintf (stderr, " -dg, --defaults-guile Print a default guile configuration file\n"); +#endif + fprintf (stderr, " -f, --file Use an alternative rc file\n"); +#ifdef GUILE_FLAG + fprintf (stderr, " -fg, --file-guile Use an alternative guile configuration file\n"); +#endif + fprintf (stderr, " -h, --help This help!\n"); + fprintf (stderr, " -X, --display Set X display to use\n"); + fprintf (stderr, + " -v, --verbose More information on xbindkeys when it run\n"); + fprintf (stderr, " -s, --show Show the actual keybinding\n"); + fprintf (stderr, " -k, --key Identify one key pressed\n"); + fprintf (stderr, " -mk, --multikey Identify multi key pressed\n"); + fprintf (stderr, + " -g, --geometry size and position of window open with -k|-mk option\n"); + fprintf (stderr, " -n, --nodaemon don't start as daemon\n"); +} + + +static void +show_defaults_rc (void) +{ + printf ("# For the benefit of emacs users: -*- shell-script -*-\n"); + printf ("###########################\n"); + printf ("# xbindkeys configuration #\n"); + printf ("###########################\n"); + printf ("#\n"); + printf ("# Version: %s\n", PACKAGE_VERSION); + printf ("#\n"); + printf ("# If you edit this file, do not forget to uncomment any lines\n"); + printf ("# that you change.\n"); + printf ("# The pound(#) symbol may be used anywhere for comments.\n"); + printf ("#\n"); + + printf ("# To specify a key, you can use 'xbindkeys --key' or\n"); + printf + ("# 'xbindkeys --multikey' and put one of the two lines in this file.\n"); + printf ("#\n"); + printf ("# The format of a command line is:\n"); + printf ("# \"command to start\"\n"); + printf ("# associated key\n"); + printf ("#\n"); + printf ("#\n"); + printf ("# A list of keys is in /usr/include/X11/keysym.h and in\n"); + printf ("# /usr/include/X11/keysymdef.h\n"); + printf ("# The XK_ is not needed.\n"); + printf ("#\n"); + printf ("# List of modifier:\n"); + printf ("# Release, Control, Shift, Mod1 (Alt), Mod2 (NumLock),\n"); + printf ("# Mod3 (CapsLock), Mod4, Mod5 (Scroll).\n"); + printf ("#\n"); + printf ("\n"); + printf ("# The release modifier is not a standard X modifier, but you can\n"); + printf ("# use it if you want to catch release events instead of press events\n"); + printf ("\n"); + printf + ("# By defaults, xbindkeys does not pay attention with the modifiers\n"); + printf ("# NumLock, CapsLock and ScrollLock.\n"); + printf + ("# Uncomment the lines above if you want to pay attention to them.\n"); + printf ("\n"); + printf ("#keystate_numlock = enable\n"); + printf ("#keystate_capslock = enable\n"); + printf ("#keystate_scrolllock= enable\n"); + printf ("\n"); + printf ("# Examples of commands:\n"); + printf ("\n"); + + printf ("\"xbindkeys_show\" \n"); + printf (" control+shift + q\n"); + printf ("\n"); + printf ("# set directly keycode (here control + f with my keyboard)\n"); + printf ("\"xterm\"\n"); + printf (" c:41 + m:0x4\n"); + printf ("\n"); + printf ("# specify a mouse button\n"); + printf ("\"xterm\"\n"); + printf (" control + b:2\n"); + printf ("\n"); + printf ("#\"xterm -geom 50x20+20+20\"\n"); + printf ("# Shift+Mod2+alt + s\n"); + printf ("#\n"); + printf + ("## set directly keycode (here control+alt+mod2 + f with my keyboard)\n"); + printf ("#\"xterm\"\n"); + printf ("# alt + c:0x29 + m:4 + mod2\n"); + printf ("#\n"); + printf ("## Control+Shift+a release event starts rxvt\n"); + printf ("#\"rxvt\"\n"); + printf ("# release+control+shift + a\n"); + printf ("#\n"); + printf ("## Control + mouse button 2 release event starts rxvt\n"); + printf ("#\"rxvt\"\n"); + printf ("# Control + b:2 + Release\n"); + + printf ("\n"); + printf ("##################################\n"); + printf ("# End of xbindkeys configuration #\n"); + printf ("##################################\n"); + + exit (1); +} + + +#ifdef GUILE_FLAG +static void +show_defaults_guile_rc (void) +{ + printf (";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); + printf (";; Start of xbindkeys guile configuration ;;\n"); + printf (";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); + printf (";; This configuration is guile based.\n"); + printf (";; http://www.gnu.org/software/guile/guile.html\n"); + printf (";; any functions that work in guile will work here.\n"); + printf (";; see EXTRA FUNCTIONS:\n"); + printf ("\n"); + printf (";; Version: %s\n", PACKAGE_VERSION); + printf ("\n"); + printf (";; If you edit this file, do not forget to uncomment any lines\n"); + printf (";; that you change.\n"); + printf (";; The semicolon(;) symbol may be used anywhere for comments.\n"); + printf ("\n"); + printf (";; To specify a key, you can use 'xbindkeys --key' or\n"); + printf (";; 'xbindkeys --multikey' and put one of the two lines in this file.\n"); + printf ("\n"); + printf (";; A list of keys is in /usr/include/X11/keysym.h and in\n"); + printf (";; /usr/include/X11/keysymdef.h\n"); + printf (";; The XK_ is not needed.\n"); + printf ("\n"); + printf (";; List of modifier:\n"); + printf (";; Release, Control, Shift, Mod1 (Alt), Mod2 (NumLock),\n"); + printf (";; Mod3 (CapsLock), Mod4, Mod5 (Scroll).\n"); + printf ("\n"); + printf ("\n"); + printf (";; The release modifier is not a standard X modifier, but you can\n"); + printf (";; use it if you want to catch release instead of press events\n"); + printf ("\n"); + printf (";; By defaults, xbindkeys does not pay attention to modifiers\n"); + printf (";; NumLock, CapsLock and ScrollLock.\n"); + printf (";; Uncomment the lines below if you want to use them.\n"); + printf (";; To dissable them, call the functions with #f\n"); + printf ("\n"); + printf ("\n"); + printf (";;;;EXTRA FUNCTIONS: Enable numlock, scrolllock or capslock usage\n"); + printf (";;(set-numlock! #t)\n"); + printf (";;(set-scrolllock! #t)\n"); + printf (";;(set-capslock! #t)\n"); + printf ("\n"); + printf (";;;;; Scheme API reference\n"); + printf (";;;;\n"); + printf (";; Optional modifier state:\n"); + printf (";; (set-numlock! #f or #t)\n"); + printf (";; (set-scrolllock! #f or #t)\n"); + printf (";; (set-capslock! #f or #t)\n"); + printf (";; \n"); + printf (";; Shell command key:\n"); + printf (";; (xbindkey key \"foo-bar-command [args]\")\n"); + printf (";; (xbindkey '(modifier* key) \"foo-bar-command [args]\")\n"); + printf (";; \n"); + printf (";; Scheme function key:\n"); + printf (";; (xbindkey-function key function-name-or-lambda-function)\n"); + printf (";; (xbindkey-function '(modifier* key) function-name-or-lambda-function)\n"); + printf (";; \n"); + printf (";; Other functions:\n"); + printf (";; (remove-xbindkey key)\n"); + printf (";; (run-command \"foo-bar-command [args]\")\n"); + printf (";; (grab-all-keys)\n"); + printf (";; (ungrab-all-keys)\n"); + printf (";; (remove-all-keys)\n"); + printf (";; (debug)\n"); + printf ("\n"); + printf ("\n"); + printf (";; Examples of commands:\n"); + printf ("\n"); + printf ("(xbindkey '(control shift q) \"xbindkeys_show\")\n"); + printf ("\n"); + printf (";; set directly keycode (here control + f with my keyboard)\n"); + printf ("(xbindkey '(\"m:0x4\" \"c:41\") \"xterm\")\n"); + printf ("\n"); + printf (";; specify a mouse button\n"); + printf ("(xbindkey '(control \"b:2\") \"xterm\")\n"); + printf ("\n"); + printf (";;(xbindkey '(shift mod2 alt s) \"xterm -geom 50x20+20+20\")\n"); + printf ("\n"); + printf (";; set directly keycode (control+alt+mod2 + f with my keyboard)\n"); + printf ("(xbindkey '(alt \"m:4\" mod2 \"c:0x29\") \"xterm\")\n"); + printf ("\n"); + printf (";; Control+Shift+a release event starts rxvt\n"); + printf (";;(xbindkey '(release control shift a) \"rxvt\")\n"); + printf ("\n"); + printf (";; Control + mouse button 2 release event starts rxvt\n"); + printf (";;(xbindkey '(releace control \"b:2\") \"rxvt\")\n"); + printf ("\n"); + printf ("\n"); + printf (";; Extra features\n"); + printf ("(xbindkey-function '(control a)\n"); + printf (" (lambda ()\n"); + printf (" (display \"Hello from Scheme!\")\n"); + printf (" (newline)))\n"); + printf ("\n"); + printf ("(xbindkey-function '(shift p)\n"); + printf (" (lambda ()\n"); + printf (" (run-command \"xterm\")))\n"); + printf ("\n"); + printf ("\n"); + printf (";; Double click test\n"); + printf ("(xbindkey-function '(control w)\n"); + printf (" (let ((count 0))\n"); + printf (" (lambda ()\n"); + printf (" (set! count (+ count 1))\n"); + printf (" (if (> count 1)\n"); + printf (" (begin\n"); + printf (" (set! count 0)\n"); + printf (" (run-command \"xterm\"))))))\n"); + printf ("\n"); + printf (";; Time double click test:\n"); + printf (";; - short double click -> run an xterm\n"); + printf (";; - long double click -> run an rxvt\n"); + printf ("(xbindkey-function '(shift w)\n"); + printf (" (let ((time (current-time))\n"); + printf (" (count 0))\n"); + printf (" (lambda ()\n"); + printf (" (set! count (+ count 1))\n"); + printf (" (if (> count 1)\n"); + printf (" (begin\n"); + printf (" (if (< (- (current-time) time) 1)\n"); + printf (" (run-command \"xterm\")\n"); + printf (" (run-command \"rxvt\"))\n"); + printf (" (set! count 0)))\n"); + printf (" (set! time (current-time)))))\n"); + printf ("\n"); + printf ("\n"); + printf (";; Chording keys test: Start differents program if only one key is\n"); + printf (";; pressed or another if two keys are pressed.\n"); + printf (";; If key1 is pressed start cmd-k1\n"); + printf (";; If key2 is pressed start cmd-k2\n"); + printf (";; If both are pressed start cmd-k1-k2 or cmd-k2-k1 following the\n"); + printf (";; release order\n"); + printf ("(define (define-chord-keys key1 key2 cmd-k1 cmd-k2 cmd-k1-k2 cmd-k2-k1)\n"); + printf (" \"Define chording keys\"\n"); + printf (" (let ((k1 #f) (k2 #f))\n"); + printf (" (xbindkey-function key1 (lambda () (set! k1 #t)))\n"); + printf (" (xbindkey-function key2 (lambda () (set! k2 #t)))\n"); + printf (" (xbindkey-function (cons 'release key1)\n"); + printf (" (lambda ()\n"); + printf (" (if (and k1 k2)\n"); + printf (" (run-command cmd-k1-k2)\n"); + printf (" (if k1 (run-command cmd-k1)))\n"); + printf (" (set! k1 #f) (set! k2 #f)))\n"); + printf (" (xbindkey-function (cons 'release key2)\n"); + printf (" (lambda ()\n"); + printf (" (if (and k1 k2)\n"); + printf (" (run-command cmd-k2-k1)\n"); + printf (" (if k2 (run-command cmd-k2)))\n"); + printf (" (set! k1 #f) (set! k2 #f)))))\n"); + printf ("\n"); + printf ("\n"); + printf (";; Example:\n"); + printf (";; Shift + b:1 start an xterm\n"); + printf (";; Shift + b:3 start an rxvt\n"); + printf (";; Shift + b:1 then Shift + b:3 start gv\n"); + printf (";; Shift + b:3 then Shift + b:1 start xpdf\n"); + printf ("\n"); + printf ("(define-chord-keys '(shift \"b:1\") '(shift \"b:3\")\n"); + printf (" \"xterm\" \"rxvt\" \"gv\" \"xpdf\")\n"); + printf ("\n"); + printf (";; Here the release order have no importance\n"); + printf (";; (the same program is started in both case)\n"); + printf ("(define-chord-keys '(alt \"b:1\") '(alt \"b:3\")\n"); + printf (" \"gv\" \"xpdf\" \"xterm\" \"xterm\")\n"); + printf ("\n"); + printf ("\n"); + printf (";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); + printf (";; End of xbindkeys guile configuration ;;\n"); + printf (";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); + + exit (1); +} +#endif + + + +static int +file_exist (char * filename) +{ + FILE * stream; + + if ((stream = fopen (filename, "r")) == NULL) + return 0; + + fclose (stream); + return 1; +} + + +int +rc_file_exist (void) +{ +#ifdef GUILE_FLAG + if (file_exist (rc_guile_file)) + return 1; +#endif + + if (!file_exist (rc_file)) + { + fprintf (stderr, "Error : %s not found or reading not allowed.\n", + rc_file); + fprintf (stderr, + "please, create one with 'xbindkeys --defaults > %s'.\n", + rc_file); +#ifdef GUILE_FLAG + fprintf (stderr, + "or, if you want scheme configuration style,\n"); + fprintf (stderr, + "with 'xbindkeys --defaults-guile > %s'.\n", + rc_guile_file); +#endif + return 0; + } + + return 1; +} + + + + + +int +get_rc_file (void) +{ + char line[1024]; + char line2[1024]; + char command[1024]; + KeyType_t type; + EventType_t event_type; + KeySym keysym; + KeyCode keycode; + unsigned int button; + unsigned int modifier; + FILE *stream = NULL; + char *pos1; + char *pos2; + char *p; + int i; + + + if (init_keys () != 0) + return (-1); + + /* Open RC File */ + if ((stream = fopen (rc_file, "r")) == NULL) + { + fprintf (stderr, "Error : %s not found or reading not allowed.\n", + rc_file); + fprintf (stderr, + "please, create one with 'xbindkeys --defaults > %s'.\n", + rc_file); + return (-1); + } + + + /* Read RC file */ + while (fgets (line, sizeof (line), stream)) + { + /* search for keystate options */ + if (strstr (line, "keystate_numlock") != NULL) + { + /* search for comment or command line */ + pos1 = strchr (line, '"'); + pos2 = strchr (line, '#'); + if (!pos1 && !pos2) + { + if (strstr (line, "enable") != NULL) + { + numlock_mask = 0; + } + if (verbose) + printf ("keystate_numlock: %s\n", + numlock_mask == 0 ? "Enabled" : "Disabled"); + + continue; + } + } + + if (strstr (line, "keystate_capslock") != NULL) + { + /* search for comment or command line */ + pos1 = strchr (line, '"'); + pos2 = strchr (line, '#'); + if (!pos1 && !pos2) + { + if (strstr (line, "enable") != NULL) + { + capslock_mask = 0; + } + if (verbose) + printf ("keystate_capslock: %s\n", + capslock_mask == 0 ? "Enabled" : "Disabled"); + + continue; + } + } + + if (strstr (line, "keystate_scrolllock") != NULL) + { + /* search for comment or command line */ + pos1 = strchr (line, '"'); + pos2 = strchr (line, '#'); + if (!pos1 && !pos2) + { + if (strstr (line, "enable") != NULL) + { + scrolllock_mask = 0; + } + if (verbose) + printf ("keystate_scrolllock: %s\n", + scrolllock_mask == 0 ? "Enabled" : "Disabled"); + + continue; + } + } + + + pos1 = strchr (line, '"'); + if (pos1) + { + pos2 = strchr (line, '#'); + + if (!pos2 || pos2 > pos1) + { + /* search for command line */ + pos2 = strrchr (line, '"'); + if (pos2 && pos1 < pos2) + { + command[0] = '\0'; + type = SYM; + event_type = PRESS; + keysym = 0; + keycode = 0; + button = 0; + modifier = 0; + + for (p = pos1 + 1, i = 0; + p < pos2 && i < sizeof (command); p++, i++) + { + command[i] = *p; + } + command[i] = '\0'; + + /* get associated keys */ + if (fgets (line, sizeof (line), stream)) + { + pos1 = line; + + while (*pos1 != '\n') + { + /* jump space */ + for (; *pos1 == '+' || *pos1 == ' ' + || *pos1 == '\t'; pos1++); + + /* find corresponding + or \n */ + pos2 = strchr (pos1, '+'); + if (!pos2) + { + for (pos2 = pos1; *pos2 != '\n'; pos2++); + } + + /* copy string in line2 */ + for (p = pos1, i = 0; + p < pos2 && i < sizeof (line2) + && *p != '+' && *p != ' ' && *p != '\t'; + p++, i++) + { + line2[i] = *p; + } + line2[i] = '\0'; + + /* is a numeric keycode (c:nnn) ? */ + if (line2[0] == 'c' && line2[1] == ':') + { + if (isdigit (line2[2])) + { + type = CODE; + keycode = strtol (line2+2, (char **) NULL, 0); + } + else + { + keysym = 0; + keycode = 0; + button = 0; + break; + } + } + else + /* is a numeric modifier (m:nnn) ? */ + if (line2[0] == 'm' && line2[1] == ':') + { + if (isdigit (line2[2])) + { + modifier |= strtol (line2+2, (char **) NULL, 0); + } + else + { + keysym = 0; + keycode = 0; + button = 0; + break; + } + } + else + /* is a mouse button (b:nnn) ? */ + if (line2[0] == 'b' && line2[1] == ':') + { + if (isdigit (line2[2])) + { + type = BUTTON; + button = strtol (line2+2, (char **) NULL, 0); + } + else + { + keysym = 0; + keycode = 0; + button = 0; + break; + } + } + else + { + /* apply to modifier, release/press or key */ + if (strcasecmp (line2, "control") == 0) + modifier |= ControlMask; + else if (strcasecmp (line2, "shift") == 0) + modifier |= ShiftMask; + else if (strcasecmp (line2, "mod1") == 0 + || strcasecmp (line2, "alt") == 0) + modifier |= Mod1Mask; + else if (strcasecmp (line2, "mod2") == 0) + modifier |= Mod2Mask; + else if (strcasecmp (line2, "mod3") == 0) + modifier |= Mod3Mask; + else if (strcasecmp (line2, "mod4") == 0) + modifier |= Mod4Mask; + else if (strcasecmp (line2, "mod5") == 0) + modifier |= Mod5Mask; + else if (strcasecmp (line2, "release") == 0) + event_type = RELEASE; + else + { + type = SYM; + keysym = XStringToKeysym (line2); + if (keysym == 0) + break; + } + } + + pos1 = pos2; + } + } + + if (add_key (type, event_type, keysym, keycode, + button, modifier, command, 0) != 0) + break; + } + } + } + } + + + /* Close RC File */ + if (stream != NULL) + fclose (stream); + + if (keys == NULL) + { + fprintf (stderr, "Error in alocation of keys\n"); + return (-1); + } + + /* Verify if all is good (like my english) */ + for (i = 0; i < nb_keys; i++) + { + if (keys[i].key.sym == 0 || keys[i].command == NULL) + { + fprintf (stderr, "Error in RC file : %s\n", rc_file); + return (-1); + } + } + + if (verbose) + printf ("%d keys in %s\n", nb_keys, rc_file); + + return (0); +} + + + +//Everything from here on out has been changed by MMH +#ifdef GUILE_FLAG +int +init_xbk_guile_fns (void) +{ + if (verbose) + printf("initializing guile fns...\n"); + scm_c_define_gsubr("set-numlock!", 1, 0, 0, set_numlock_wrapper); + scm_c_define_gsubr("set-scrolllock!", 1, 0, 0, set_scrolllock_wrapper); + scm_c_define_gsubr("set-capslock!", 1, 0, 0, set_capslock_wrapper); + scm_c_define_gsubr("xbindkey", 2, 0, 0, xbindkey_wrapper); + scm_c_define_gsubr("xbindkey-function", 2, 0, 0, xbindkey_function_wrapper); + scm_c_define_gsubr("remove-xbindkey", 1, 0, 0, remove_xbindkey_wrapper); + scm_c_define_gsubr("run-command", 1, 0, 0, run_command_wrapper); + scm_c_define_gsubr("grab-all-keys", 0, 0, 0, grab_all_keys_wrapper); + scm_c_define_gsubr("ungrab-all-keys", 0, 0, 0, ungrab_all_keys_wrapper); + scm_c_define_gsubr("remove-all-keys", 0, 0, 0, remove_all_keys_wrapper); + scm_c_define_gsubr("debug", 0, 0, 0, debug_info_wrapper); + return 0; +} + +int +get_rc_guile_file (void) +{ + FILE *stream; + + if (verbose) + printf("getting rc guile file %s.\n", rc_guile_file); + + if (init_keys () != 0) + return (-1); + + /* Open RC File */ + if ((stream = fopen (rc_guile_file, "r")) == NULL) + { + if (verbose) + fprintf (stderr, "WARNING : %s not found or reading not allowed.\n", + rc_guile_file); + return (-1); + } + fclose (stream); + + init_xbk_guile_fns(); + scm_primitive_load(scm_take0str(rc_guile_file)); + return 0; +} + +#define MAKE_MASK_WRAPPER(name, mask_name) \ +SCM name (SCM val) \ +{ \ + if (verbose) \ + printf("Running mask cmd!\n"); \ + mask_name = SCM_FALSEP(val); \ + return SCM_UNSPECIFIED; \ +} + +MAKE_MASK_WRAPPER(set_numlock_wrapper, numlock_mask); +MAKE_MASK_WRAPPER(set_scrolllock_wrapper, scrolllock_mask); +MAKE_MASK_WRAPPER(set_capslock_wrapper, capslock_mask); + + + +SCM extract_key (SCM key, KeyType_t *type, EventType_t *event_type, + KeySym *keysym, KeyCode *keycode, + unsigned int *button, unsigned int *modifier) +{ + char *str; + int len; + + while(SCM_CONSP(key)){ //Iterate through the list (If it is a list) + if(!SCM_CONSP(SCM_CDR(key))){ //if this is the last item + key = SCM_CAR(key); //go to that + break; //and continue + } + //Otherwise, this is a modifyer. + + //So copy it: + //Guile strings are not \0 terminated. hence we must copy. + len = SCM_LENGTH(SCM_CAR(key)); + str = malloc(sizeof(char)*(len+1)); + strncpy(str, SCM_CHARS(SCM_CAR(key)), len); + str[len] = '\0'; + + if(verbose) //extra verbosity here. + printf("xbindkey_wrapper debug: modifier = %s.\n", str); + + //copied directly with some substitutions. ie. line2 -> str + //Do whatever needs to be done with modifiers. + if (strncasecmp (str, "control", len) == 0) + *modifier |= ControlMask; + else if (strncasecmp (str, "shift", len) == 0) + *modifier |= ShiftMask; + else if (strncasecmp (str, "mod1", len) == 0 + || strncasecmp (str, "alt", len) == 0) + *modifier |= Mod1Mask; + else if (strncasecmp (str, "mod2", len) == 0) + *modifier |= Mod2Mask; + else if (strncasecmp (str, "mod3", len) == 0) + *modifier |= Mod3Mask; + else if (strncasecmp (str, "mod4", len) == 0) + *modifier |= Mod4Mask; + else if (strncasecmp (str, "mod5", len) == 0) + *modifier |= Mod5Mask; + else if (strncasecmp (str, "release", len) == 0) + *event_type = RELEASE; + else if(strlen (str) > 2 && str[0] == 'm' && str[1] == ':'){ + *modifier |= strtol (str+2, (char **) NULL, 0); + //this break have nothing to do here! + //break + }else{ + printf("Bad modifier:\n%s\n", str); //or error + return SCM_BOOL_F; //and return false + } + free(str); //we copied, so we must destroy this + str=NULL; + key = SCM_CDR(key); //and go a step down the list + } + //So this was either the only or last item of the 1st arg + //Hence it is the key + + //So copy it: + //Guile strings are not \0 terminated. hence we must copy. + len = SCM_LENGTH(key); + str = malloc(sizeof(char)*(len+1)); + strncpy(str, SCM_CHARS(key), len); + str[len] = '\0'; + if(verbose) + printf("xbindkey_wrapper debug: key = %s\n", str); + + //Check for special numeric stuff. + //This way is really far nicer looking and more efficient than + //having three copies of the code. + if(strlen (str) > 2 && str[1] == ':' && isdigit (str[2])) + { + switch (str[0]) + { + case 'b': + *type = BUTTON; + *button = strtol (str+2, (char **) NULL, 0); + break; + case 'c': + *type = CODE; + *keycode = strtol (str+2, (char **) NULL, 0); + break; + case 'm': //is a modifier so it is in the other part. + printf("bad modifyer: %s.", str); + printf("m: modifiers need be applied to keys\n"); + return SCM_BOOL_F; + default: + printf("bad modifyer: %c: shoud be b:, c: or m: .\n", str[0]); + return SCM_BOOL_F; + } + } + else //regular key + { + *type = SYM; + *keysym = XStringToKeysym (str); + if (*keysym == 0){ + printf("No keysym for key: %s\n", str); + return SCM_BOOL_F; + } + } + + free(str); //these were used by add key and copied. + + return SCM_BOOL_T; +} + + + +SCM xbindkey_wrapper(SCM key, SCM cmd) +{ + KeyType_t type = SYM; + EventType_t event_type = PRESS; + KeySym keysym = 0; + KeyCode keycode = 0; + unsigned int button = 0; + unsigned int modifier = 0; + char *cmdstr; + + //Guile strings are not \0 terminated. hence we must copy. + cmdstr = malloc(sizeof(char) * SCM_LENGTH(cmd) + 1); + strncpy(cmdstr, SCM_CHARS(cmd), SCM_LENGTH(cmd)); + cmdstr[SCM_LENGTH(cmd)] = '\0'; + if(verbose) + printf("xbindkey_wrapper debug: cmd=%s.\n", cmdstr); + + if (extract_key (key, &type, &event_type, &keysym, &keycode, + &button, &modifier) == SCM_BOOL_F) + { + return SCM_BOOL_F; + } + + if (add_key (type, event_type, keysym, keycode, + button, modifier, cmdstr, 0) != 0) + { + printf("add_key didn't return 0!!!\n"); + return SCM_BOOL_F; + } + + free(cmdstr); //we may get rid of them! + + return SCM_UNSPECIFIED; +} + + +SCM xbindkey_function_wrapper (SCM key, SCM fun) +{ + KeyType_t type = SYM; + EventType_t event_type = PRESS; + KeySym keysym = 0; + KeyCode keycode = 0; + unsigned int button = 0; + unsigned int modifier = 0; + + if (extract_key (key, &type, &event_type, &keysym, &keycode, + &button, &modifier) == SCM_BOOL_F) + { + return SCM_BOOL_F; + } + + if (add_key (type, event_type, keysym, keycode, + button, modifier, NULL, fun) != 0) + { + printf("add_key didn't return 0!!!\n"); + return SCM_BOOL_F; + } + + return SCM_UNSPECIFIED; +} + + + +SCM remove_xbindkey_wrapper (SCM key) +{ + KeyType_t type = SYM; + EventType_t event_type = PRESS; + KeySym keysym = 0; + KeyCode keycode = 0; + unsigned int button = 0; + unsigned int modifier = 0; + + if (extract_key (key, &type, &event_type, &keysym, &keycode, + &button, &modifier) == SCM_BOOL_F) + { + return SCM_BOOL_F; + } + + if (remove_key (type, event_type, keysym, keycode, button, modifier) != 0) + { + printf("remove_key didn't return 0!!!\n"); + return SCM_BOOL_F; + } + + + return SCM_UNSPECIFIED; +} + + +SCM run_command_wrapper (SCM command) +{ + char *cmdstr; + + cmdstr = malloc(sizeof(char) * SCM_LENGTH(command) + 1); + strncpy(cmdstr, SCM_CHARS(command), SCM_LENGTH(command)); + cmdstr[SCM_LENGTH(command)] = '\0'; + + run_command (cmdstr); + + free(cmdstr); + + return SCM_UNSPECIFIED; +} + +SCM grab_all_keys_wrapper (void) +{ + grab_keys (current_display); + + return SCM_UNSPECIFIED; +} + + +SCM ungrab_all_keys_wrapper (void) +{ + ungrab_all_keys (current_display); + + return SCM_UNSPECIFIED; +} + +SCM remove_all_keys_wrapper (void) +{ + close_keys (); + + return SCM_UNSPECIFIED; +} + + +SCM debug_info_wrapper (void) +{ + printf ("\nKeys = %p\n", keys); + printf ("nb_keys = %d\n", nb_keys); + + return SCM_UNSPECIFIED; +} + +#endif |