/*************************************************************************** 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 "config.h" #include #include #include #include #include #include "options.h" #include "xbindkeys.h" #include "keys.h" #include "grab_key.h" #ifdef GUILE_FLAG #include #endif char *display_name = NULL; char rc_file[512]; #ifdef GUILE_FLAG char rc_guile_file[512]; #endif int verbose = 0; int poll_rc = 0; int have_to_show_binding = 0; int have_to_get_binding = 0; int have_to_start_as_daemon = 1; int detectable_ar = 0; 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], "-p") == 0 || strcmp (argv[i], "--poll-rc") == 0) { poll_rc = 1; } 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 if (strcmp (argv[i], "-sd") == 0 || strcmp (argv[i], "--detectable-ar") == 0) { detectable_ar = 1; } else { show_help (); exit (1); } } if (strcmp (rc_file, "") == 0) { home = getenv ("HOME"); if (rc_file != NULL) { strncpy (rc_file, home, sizeof (rc_file) - 20); strncat (rc_file, "/.xbindkeysrc", 20); } } #ifdef GUILE_FLAG if (strcmp (rc_guile_file, "") == 0) { home = getenv ("HOME"); if (rc_guile_file != NULL) { strncpy (rc_guile_file, home, sizeof (rc_guile_file) - 20); strncat (rc_guile_file, "/.xbindkeysrc.scm", 20); } } #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, " -p, --poll-rc Poll the rc/guile configs for updates\n"); 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_from_locale_string(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 modifier. //So copy it: //Guile strings are not \0 terminated. hence we must copy. if (scm_is_true(scm_symbol_p(SCM_CAR(key)))) { SCM newkey = scm_symbol_to_string(SCM_CAR(key)); str = scm_to_locale_string(newkey); } else { str = scm_to_locale_string(SCM_CAR(key)); } len = strlen(str); /*str = scm_to_locale_string(SCM_CAR(key));*/ 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. if (scm_is_true(scm_symbol_p(key))) { SCM newkey = scm_symbol_to_string(key); str = scm_to_locale_string(newkey); } else { str = scm_to_locale_string(key); } len = strlen(str); 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 = scm_to_locale_string(cmd); 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 tab_scm[2]; 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; } tab_scm[0] = fun; if (add_key (type, event_type, keysym, keycode, button, modifier, NULL, tab_scm[0]) != 0) { printf("add_key didn't return 0!!!\n"); return SCM_BOOL_F; } else { printf ("add_key ok!!! fun=%d\n", (scm_procedure_p (fun) == SCM_BOOL_T)); } //scm_permanent_object (tab_scm[0]); scm_remember_upto_here_1 (tab_scm[0]); 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 = scm_to_locale_string(command); 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