xkbevd.c revision a67f45c3
176910425Smrg/************************************************************ 276910425Smrg Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. 376910425Smrg 476910425Smrg Permission to use, copy, modify, and distribute this 576910425Smrg software and its documentation for any purpose and without 676910425Smrg fee is hereby granted, provided that the above copyright 776910425Smrg notice appear in all copies and that both that copyright 876910425Smrg notice and this permission notice appear in supporting 99ff100acSmrg documentation, and that the name of Silicon Graphics not be 109ff100acSmrg used in advertising or publicity pertaining to distribution 1176910425Smrg of the software without specific prior written permission. 129ff100acSmrg Silicon Graphics makes no representation about the suitability 1376910425Smrg of this software for any purpose. It is provided "as is" 1476910425Smrg without any express or implied warranty. 159ff100acSmrg 169ff100acSmrg SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 179ff100acSmrg SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 1876910425Smrg AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 199ff100acSmrg GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 209ff100acSmrg DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 219ff100acSmrg DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 2276910425Smrg OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 2376910425Smrg THE USE OR PERFORMANCE OF THIS SOFTWARE. 2476910425Smrg 2576910425Smrg ********************************************************/ 2676910425Smrg 2776910425Smrg#include <X11/Xosdefs.h> 2876910425Smrg#include <stdlib.h> 2976910425Smrg#include "xkbevd.h" 3076910425Smrg 3176910425Smrg/***====================================================================***/ 3276910425Smrg 3376910425Smrg#ifndef DFLT_XKBEVD_CONFIG 3476910425Smrg#define DFLT_XKBEVD_CONFIG "%s/.xkb/xkbevd.cf" 3576910425Smrg#endif /* DFLT_XKBEVD_CONFIG */ 3676910425Smrg 3776910425Smrg#ifndef DFLT_XKB_CONFIG_ROOT 38a67f45c3Smrg#define DFLT_XKB_CONFIG_ROOT "/usr/share/X11/xkb" 3976910425Smrg#endif 4076910425Smrg 4176910425Smrg#ifndef DFLT_SYS_XKBEVD_CONFIG 4276910425Smrg#define DFLT_SYS_XKBEVD_CONFIG "%s/xkbevd.cf" 4376910425Smrg#endif /* DFLT_SYS_XKBEVD_CONFIG */ 4476910425Smrg 4576910425Smrg#ifndef DFLT_SOUND_CMD 4676910425Smrg#define DFLT_SOUND_CMD "/usr/sbin/sfplay -q" 4776910425Smrg#endif /* DFLT_SOUND_CMD */ 4876910425Smrg 4976910425Smrg#ifndef DFLT_SOUND_DIR 5076910425Smrg#define DFLT_SOUND_DIR "/usr/share/data/sounds/prosonus/" 5176910425Smrg#endif /* DFLT_SOUND_DIR */ 5276910425Smrg 5376910425Smrg/***====================================================================***/ 5476910425Smrg 559ff100acSmrgstatic char * dpyName = NULL; 569ff100acSmrgDisplay * dpy = NULL; 579ff100acSmrgstatic const char *cfgFileName = NULL; 589ff100acSmrgint xkbOpcode = 0; 599ff100acSmrgint xkbEventCode = 0; 609ff100acSmrgBool detectableRepeat = False; 6176910425Smrg 629ff100acSmrgstatic CfgEntryPtr config = NULL; 639ff100acSmrgstatic unsigned long eventMask = 0; 6476910425Smrg 659ff100acSmrgstatic Bool synch = False; 669ff100acSmrgstatic int verbose = 0; 679ff100acSmrgstatic Bool background = False; 6876910425Smrg 699ff100acSmrgstatic const char *soundCmd = NULL; 709ff100acSmrgstatic const char *soundDir = NULL; 7176910425Smrg 729ff100acSmrgXkbDescPtr xkb = NULL; 7376910425Smrg 7476910425Smrg/***====================================================================***/ 7576910425Smrg 7676910425Smrgstatic void 7776910425SmrgUsage(int argc, char *argv[]) 7876910425Smrg{ 799ff100acSmrg fprintf(stderr, "Usage: %s [options]...\n%s", argv[0], 809ff100acSmrg "Legal options:\n" 819ff100acSmrg "-?, -help Print this message\n" 829ff100acSmrg "-cfg <file> Specify a config file\n" 839ff100acSmrg "-sc <cmd> Specify the command to play sounds\n" 849ff100acSmrg "-sd <dir> Specify the root directory for sound files\n" 859ff100acSmrg "-d[isplay] <dpy> Specify the display to watch\n" 869ff100acSmrg "-bg Run in background\n" 879ff100acSmrg "-synch Force synchronization\n" 889ff100acSmrg "-v Print verbose messages\n" 899ff100acSmrg "-version Print program version\n" 909ff100acSmrg ); 9176910425Smrg return; 9276910425Smrg} 9376910425Smrg 9476910425Smrg/***====================================================================***/ 9576910425Smrg 9676910425Smrgstatic Bool 9776910425SmrgparseArgs(int argc, char *argv[]) 9876910425Smrg{ 999ff100acSmrg register int i; 1009ff100acSmrg 1019ff100acSmrg for (i = 1; i < argc; i++) { 1029ff100acSmrg if (strcmp(argv[i], "-bg") == 0) { 1039ff100acSmrg background = True; 1049ff100acSmrg } 1059ff100acSmrg else if (strcmp(argv[i], "-cfg") == 0) { 1069ff100acSmrg if (i >= (argc - 1)) { 1079ff100acSmrg uError("No configuration file specified on command line\n"); 1089ff100acSmrg uAction("Trailing %s argument ignored\n", argv[i]); 1099ff100acSmrg } 1109ff100acSmrg else { 1119ff100acSmrg char *name = argv[++i]; 1129ff100acSmrg 1139ff100acSmrg if (cfgFileName != NULL) { 1149ff100acSmrg if (uStringEqual(cfgFileName, name)) 1159ff100acSmrg uWarning("Config file \"%s\" specified twice!\n", name); 1169ff100acSmrg else { 1179ff100acSmrg uWarning("Multiple config files on command line\n"); 1189ff100acSmrg uAction("Using \"%s\", ignoring \"%s\"\n", name, 1199ff100acSmrg cfgFileName); 1209ff100acSmrg } 1219ff100acSmrg } 1229ff100acSmrg cfgFileName = name; 1239ff100acSmrg } 1249ff100acSmrg } 1259ff100acSmrg else if ((strcmp(argv[i], "-d") == 0) || 1269ff100acSmrg (strcmp(argv[i], "-display") == 0)) { 1279ff100acSmrg if (i >= (argc - 1)) { 1289ff100acSmrg uError("No display specified on command line\n"); 1299ff100acSmrg uAction("Trailing %s argument ignored\n", argv[i]); 1309ff100acSmrg } 1319ff100acSmrg else { 1329ff100acSmrg char *name = argv[++i]; 1339ff100acSmrg 1349ff100acSmrg if (dpyName != NULL) { 1359ff100acSmrg if (uStringEqual(dpyName, name)) 1369ff100acSmrg uWarning("Display \"%s\" specified twice!\n", name); 1379ff100acSmrg else { 1389ff100acSmrg uWarning("Multiple displays on command line\n"); 1399ff100acSmrg uAction("Using \"%s\", ignoring \"%s\"\n", name, 1409ff100acSmrg dpyName); 1419ff100acSmrg } 1429ff100acSmrg } 1439ff100acSmrg dpyName = name; 1449ff100acSmrg } 1459ff100acSmrg } 1469ff100acSmrg else if (strcmp(argv[i], "-sc") == 0) { 1479ff100acSmrg if (i >= (argc - 1)) { 1489ff100acSmrg uError("No sound command specified on command line\n"); 1499ff100acSmrg uAction("Trailing %s argument ignored\n", argv[i]); 1509ff100acSmrg } 1519ff100acSmrg else { 1529ff100acSmrg char *name = argv[++i]; 1539ff100acSmrg 1549ff100acSmrg if (soundCmd != NULL) { 1559ff100acSmrg if (uStringEqual(soundCmd, name)) 1569ff100acSmrg uWarning("Sound command \"%s\" specified twice!\n", 1579ff100acSmrg name); 1589ff100acSmrg else { 1599ff100acSmrg uWarning("Multiple sound commands on command line\n"); 1609ff100acSmrg uAction("Using \"%s\", ignoring \"%s\"\n", name, 1619ff100acSmrg soundCmd); 1629ff100acSmrg } 1639ff100acSmrg } 1649ff100acSmrg soundCmd = name; 1659ff100acSmrg } 1669ff100acSmrg } 1679ff100acSmrg else if (strcmp(argv[i], "-sd") == 0) { 1689ff100acSmrg if (i >= (argc - 1)) { 1699ff100acSmrg uError("No sound directory specified on command line\n"); 1709ff100acSmrg uAction("Trailing %s argument ignored\n", argv[i]); 1719ff100acSmrg } 1729ff100acSmrg else { 1739ff100acSmrg char *name = argv[++i]; 1749ff100acSmrg 1759ff100acSmrg if (soundDir != NULL) { 1769ff100acSmrg if (uStringEqual(soundDir, name)) 1779ff100acSmrg uWarning("Sound directory \"%s\" specified twice!\n", 1789ff100acSmrg name); 1799ff100acSmrg else { 1809ff100acSmrg uWarning("Multiple sound dirs on command line\n"); 1819ff100acSmrg uAction("Using \"%s\", ignoring \"%s\"\n", name, 1829ff100acSmrg soundDir); 1839ff100acSmrg } 1849ff100acSmrg } 1859ff100acSmrg soundDir = name; 1869ff100acSmrg } 1879ff100acSmrg } 1889ff100acSmrg else if ((strcmp(argv[i], "-synch") == 0) || 1899ff100acSmrg (strcmp(argv[i], "-s") == 0)) { 1909ff100acSmrg synch = True; 1919ff100acSmrg } 1929ff100acSmrg else if (strcmp(argv[i], "-v") == 0) { 1939ff100acSmrg verbose++; 1949ff100acSmrg } 1959ff100acSmrg else if (strcmp(argv[i], "-version") == 0) { 1969ff100acSmrg puts(PACKAGE_STRING); 1979ff100acSmrg exit(0); 1989ff100acSmrg } 1999ff100acSmrg else if ((strcmp(argv[i], "-?") == 0) || 2009ff100acSmrg (strcmp(argv[i], "-help") == 0)) { 2019ff100acSmrg Usage(argc, argv); 2029ff100acSmrg exit(0); 2039ff100acSmrg } 2049ff100acSmrg else { 2059ff100acSmrg uError("Unknown flag \"%s\" on command line\n", argv[i]); 2069ff100acSmrg Usage(argc, argv); 2079ff100acSmrg return False; 2089ff100acSmrg } 20976910425Smrg } 210db17cd6dSmrg if (background == False) { 2119ff100acSmrg eventMask = XkbAllEventsMask; 2129ff100acSmrg verbose++; 213db17cd6dSmrg } 214db17cd6dSmrg 21576910425Smrg return True; 21676910425Smrg} 21776910425Smrg 21876910425Smrgstatic Display * 219a67f45c3SmrgGetDisplay(const char *program, const char *displayName, 220a67f45c3Smrg int *opcodeRtrn, int *evBaseRtrn) 22176910425Smrg{ 2229ff100acSmrg int mjr, mnr, error; 223a67f45c3Smrg Display *display; 2249ff100acSmrg 2259ff100acSmrg mjr = XkbMajorVersion; 2269ff100acSmrg mnr = XkbMinorVersion; 227a67f45c3Smrg display = XkbOpenDisplay(displayName, evBaseRtrn, NULL, &mjr, &mnr, &error); 228a67f45c3Smrg if (display == NULL) { 2299ff100acSmrg switch (error) { 2309ff100acSmrg case XkbOD_BadLibraryVersion: 2319ff100acSmrg uInformation("%s was compiled with XKB version %d.%02d\n", 2329ff100acSmrg program, XkbMajorVersion, XkbMinorVersion); 2339ff100acSmrg uError("X library supports incompatible version %d.%02d\n", 2349ff100acSmrg mjr, mnr); 2359ff100acSmrg break; 2369ff100acSmrg case XkbOD_ConnectionRefused: 237a67f45c3Smrg uError("Cannot open display \"%s\"\n", displayName); 2389ff100acSmrg break; 2399ff100acSmrg case XkbOD_NonXkbServer: 240a67f45c3Smrg uError("XKB extension not present on %s\n", displayName); 2419ff100acSmrg break; 2429ff100acSmrg case XkbOD_BadServerVersion: 2439ff100acSmrg uInformation("%s was compiled with XKB version %d.%02d\n", 2449ff100acSmrg program, XkbMajorVersion, XkbMinorVersion); 2459ff100acSmrg uError("Server %s uses incompatible version %d.%02d\n", 246a67f45c3Smrg displayName, mjr, mnr); 2479ff100acSmrg break; 2489ff100acSmrg default: 2499ff100acSmrg uInternalError("Unknown error %d from XkbOpenDisplay\n", error); 2509ff100acSmrg } 25176910425Smrg } 25276910425Smrg else if (synch) 253a67f45c3Smrg XSynchronize(display, True); 25476910425Smrg if (opcodeRtrn) 255a67f45c3Smrg XkbQueryExtension(display, opcodeRtrn, evBaseRtrn, NULL, &mjr, &mnr); 256a67f45c3Smrg return display; 25776910425Smrg} 25876910425Smrg 25976910425Smrg/***====================================================================***/ 26076910425Smrg 26176910425Smrgvoid 26276910425SmrgInterpretConfigs(CfgEntryPtr cfg) 26376910425Smrg{ 2649ff100acSmrg config = cfg; 2659ff100acSmrg while (cfg != NULL) { 266a67f45c3Smrg char *name = cfg->name.str; 2679ff100acSmrg if (cfg->entry_type == VariableDef) { 2689ff100acSmrg if (uStrCaseEqual(name, "sounddirectory") || 2699ff100acSmrg uStrCaseEqual(name, "sounddir")) { 2709ff100acSmrg if (soundDir == NULL) { 2719ff100acSmrg soundDir = cfg->action.text; 2729ff100acSmrg cfg->name.str = NULL; 2739ff100acSmrg cfg->action.text = NULL; 2749ff100acSmrg } 2759ff100acSmrg } 2769ff100acSmrg else if (uStrCaseEqual(name, "soundcommand") || 2779ff100acSmrg uStrCaseEqual(name, "soundcmd")) { 2789ff100acSmrg if (soundCmd == NULL) { 2799ff100acSmrg soundCmd = cfg->action.text; 2809ff100acSmrg cfg->name.str = NULL; 2819ff100acSmrg cfg->action.text = NULL; 2829ff100acSmrg } 2839ff100acSmrg } 2849ff100acSmrg else { 2859ff100acSmrg uWarning("Assignment to unknown variable \"%s\"\n", name); 2869ff100acSmrg uAction("Ignored\n"); 2879ff100acSmrg } 2889ff100acSmrg } 289a67f45c3Smrg else if (cfg->entry_type == EventDef) { 290a67f45c3Smrg unsigned int priv; 291a67f45c3Smrg 2929ff100acSmrg switch (cfg->event_type) { 2939ff100acSmrg case XkbBellNotify: 2949ff100acSmrg if (name != NULL) 2959ff100acSmrg cfg->name.atom = XInternAtom(dpy, name, False); 2969ff100acSmrg else 2979ff100acSmrg cfg->name.atom = None; 2989ff100acSmrg if (name) 2999ff100acSmrg free(name); 3009ff100acSmrg break; 3019ff100acSmrg case XkbAccessXNotify: 3029ff100acSmrg priv = 0; 3039ff100acSmrg if (name == NULL) 3049ff100acSmrg priv = XkbAllNewKeyboardEventsMask; 3059ff100acSmrg else if (uStrCaseEqual(name, "skpress")) 3069ff100acSmrg priv = XkbAXN_SKPressMask; 3079ff100acSmrg else if (uStrCaseEqual(name, "skaccept")) 3089ff100acSmrg priv = XkbAXN_SKAcceptMask; 3099ff100acSmrg else if (uStrCaseEqual(name, "skreject")) 3109ff100acSmrg priv = XkbAXN_SKRejectMask; 3119ff100acSmrg else if (uStrCaseEqual(name, "skrelease")) 3129ff100acSmrg priv = XkbAXN_SKReleaseMask; 3139ff100acSmrg else if (uStrCaseEqual(name, "bkaccept")) 3149ff100acSmrg priv = XkbAXN_BKAcceptMask; 3159ff100acSmrg else if (uStrCaseEqual(name, "bkreject")) 3169ff100acSmrg priv = XkbAXN_BKRejectMask; 3179ff100acSmrg else if (uStrCaseEqual(name, "warning")) 3189ff100acSmrg priv = XkbAXN_AXKWarningMask; 3199ff100acSmrg if (name) 3209ff100acSmrg free(name); 3219ff100acSmrg cfg->name.priv = priv; 3229ff100acSmrg break; 3239ff100acSmrg case XkbActionMessage: 3249ff100acSmrg /* nothing to do */ 3259ff100acSmrg break; 3269ff100acSmrg } 327a67f45c3Smrg } 3289ff100acSmrg eventMask |= (1L << cfg->event_type); 3299ff100acSmrg cfg = cfg->next; 33076910425Smrg } 3319ff100acSmrg while ((config) && (config->entry_type != EventDef)) { 3329ff100acSmrg CfgEntryPtr next; 3339ff100acSmrg 3349ff100acSmrg if (config->name.str) 3359ff100acSmrg free(config->name.str); 3369ff100acSmrg if (config->action.text) 3379ff100acSmrg free(config->action.text); 3389ff100acSmrg config->name.str = NULL; 3399ff100acSmrg config->action.text = NULL; 3409ff100acSmrg next = config->next; 3419ff100acSmrg free(config); 3429ff100acSmrg config = next; 34376910425Smrg } 3449ff100acSmrg cfg = config; 3459ff100acSmrg while ((cfg != NULL) && (cfg->next != NULL)) { 3469ff100acSmrg CfgEntryPtr next; 3479ff100acSmrg 3489ff100acSmrg next = cfg->next; 3499ff100acSmrg if (next->entry_type != EventDef) { 3509ff100acSmrg if (next->name.str) 3519ff100acSmrg free(config->name.str); 3529ff100acSmrg if (next->action.text) 3539ff100acSmrg free(config->action.text); 3549ff100acSmrg next->name.str = NULL; 3559ff100acSmrg next->action.text = NULL; 3569ff100acSmrg cfg->next = next->next; 3579ff100acSmrg next->next = NULL; 3589ff100acSmrg free(next); 3599ff100acSmrg } 3609ff100acSmrg else 3619ff100acSmrg cfg = next; 36276910425Smrg } 36376910425Smrg return; 36476910425Smrg} 36576910425Smrg 36676910425Smrgstatic CfgEntryPtr 3679ff100acSmrgFindMatchingConfig(XkbEvent * ev) 36876910425Smrg{ 3699ff100acSmrg CfgEntryPtr cfg, dflt; 3709ff100acSmrg 3719ff100acSmrg dflt = NULL; 3729ff100acSmrg for (cfg = config; (cfg != NULL); cfg = cfg->next) { 3739ff100acSmrg if ((ev->type != xkbEventCode) || (cfg->event_type != ev->any.xkb_type)) 3749ff100acSmrg continue; 3759ff100acSmrg switch (ev->any.xkb_type) { 3769ff100acSmrg case XkbBellNotify: 3779ff100acSmrg if (ev->bell.name == cfg->name.atom) 3789ff100acSmrg return cfg; 3799ff100acSmrg else if ((cfg->name.atom == None) && (dflt == NULL)) 3809ff100acSmrg dflt = cfg; 3819ff100acSmrg break; 3829ff100acSmrg case XkbAccessXNotify: 3839ff100acSmrg if (cfg->name.priv & (1L << ev->accessx.detail)) 3849ff100acSmrg return cfg; 3859ff100acSmrg break; 3869ff100acSmrg case XkbActionMessage: 3879ff100acSmrg if (cfg->name.str == NULL) 3889ff100acSmrg dflt = cfg; 3899ff100acSmrg else if (strncmp(cfg->name.str, ev->message.message, 3909ff100acSmrg XkbActionMessageLength) == 0) 3919ff100acSmrg return cfg; 3929ff100acSmrg break; 3939ff100acSmrg default: 3949ff100acSmrg uInternalError("Can't handle type %d XKB events yet, Sorry.\n", 3959ff100acSmrg ev->any.xkb_type); 3969ff100acSmrg break; 3979ff100acSmrg } 39876910425Smrg } 39976910425Smrg return dflt; 40076910425Smrg} 40176910425Smrg 40276910425Smrgstatic Bool 4039ff100acSmrgProcessMatchingConfig(XkbEvent * ev) 40476910425Smrg{ 4059ff100acSmrg CfgEntryPtr cfg; 4069ff100acSmrg char buf[1024], *cmd; 4079ff100acSmrg int ok; 40876910425Smrg 4099ff100acSmrg cfg = FindMatchingConfig(ev); 410db17cd6dSmrg if (!cfg) { 4119ff100acSmrg if (verbose) 4129ff100acSmrg PrintXkbEvent(stdout, ev); 4139ff100acSmrg return False; 414db17cd6dSmrg } 4159ff100acSmrg if (cfg->action.type == UnknownAction) { 4169ff100acSmrg if (cfg->action.text == NULL) 4179ff100acSmrg cfg->action.type = NoAction; 4189ff100acSmrg else if (cfg->action.text[0] == '!') { 4199ff100acSmrg char *tmp; 4209ff100acSmrg 4219ff100acSmrg cfg->action.type = ShellAction; 4229ff100acSmrg tmp = uStringDup(&cfg->action.text[1]); 4239ff100acSmrg free(cfg->action.text); 4249ff100acSmrg cfg->action.text = tmp; 4259ff100acSmrg } 4269ff100acSmrg else 4279ff100acSmrg cfg->action.type = SoundAction; 42876910425Smrg } 42976910425Smrg switch (cfg->action.type) { 4309ff100acSmrg case NoAction: 4319ff100acSmrg return True; 4329ff100acSmrg case EchoAction: 4339ff100acSmrg if (cfg->action.text != NULL) { 4349ff100acSmrg snprintf(buf, sizeof(buf), "%s", cfg->action.text); 4359ff100acSmrg cmd = SubstituteEventArgs(buf, ev); 4369ff100acSmrg printf("%s", cmd); 4379ff100acSmrg } 4389ff100acSmrg return True; 4399ff100acSmrg case PrintEvAction: 4409ff100acSmrg PrintXkbEvent(stdout, ev); 4419ff100acSmrg return True; 4429ff100acSmrg case ShellAction: 4439ff100acSmrg if (cfg->action.text == NULL) { 4449ff100acSmrg uWarning("Empty shell command!\n"); 4459ff100acSmrg uAction("Ignored\n"); 4469ff100acSmrg return True; 4479ff100acSmrg } 4489ff100acSmrg cmd = cfg->action.text; 4499ff100acSmrg break; 4509ff100acSmrg case SoundAction: 4519ff100acSmrg if (cfg->action.text == NULL) { 4529ff100acSmrg uWarning("Empty sound command!\n"); 4539ff100acSmrg uAction("Ignored\n"); 4549ff100acSmrg return True; 4559ff100acSmrg } 4569ff100acSmrg snprintf(buf, sizeof(buf), "%s %s%s", soundCmd, soundDir, 4579ff100acSmrg cfg->action.text); 4589ff100acSmrg cmd = buf; 4599ff100acSmrg break; 4609ff100acSmrg default: 4619ff100acSmrg uInternalError("Unknown error action type %d\n", cfg->action.type); 4629ff100acSmrg return False; 46376910425Smrg } 4649ff100acSmrg cmd = SubstituteEventArgs(cmd, ev); 46576910425Smrg if (verbose) 4669ff100acSmrg uInformation("Executing shell command \"%s\"\n", cmd); 4679ff100acSmrg ok = (system(cmd) == 0); 46876910425Smrg return ok; 46976910425Smrg} 47076910425Smrg 47176910425Smrg/***====================================================================***/ 47276910425Smrg 47376910425Smrgint 47476910425Smrgmain(int argc, char *argv[]) 47576910425Smrg{ 4769ff100acSmrg FILE * file; 4779ff100acSmrg static char buf[1024]; 4789ff100acSmrg XkbEvent ev; 4799ff100acSmrg Bool ok; 48076910425Smrg 48176910425Smrg yyin = stdin; 48276910425Smrg uSetErrorFile(NullString); 48376910425Smrg 4849ff100acSmrg if (!parseArgs(argc, argv)) 4859ff100acSmrg exit(1); 4869ff100acSmrg file = NULL; 48776910425Smrg XkbInitAtoms(NULL); 4889ff100acSmrg if (cfgFileName == NULL) { 4899ff100acSmrg char *home = getenv("HOME"); 4909ff100acSmrg snprintf(buf, sizeof(buf), DFLT_XKBEVD_CONFIG, (home ? home : "")); 4919ff100acSmrg cfgFileName = buf; 49276910425Smrg } 4939ff100acSmrg if (uStringEqual(cfgFileName, "-")) { 4949ff100acSmrg static const char *in = "stdin"; 4959ff100acSmrg 4969ff100acSmrg file = stdin; 4979ff100acSmrg cfgFileName = in; 49876910425Smrg } 49976910425Smrg else { 5009ff100acSmrg file = fopen(cfgFileName, "r"); 5019ff100acSmrg if (file == NULL) { /* no personal config, try for a system one */ 5029ff100acSmrg if (cfgFileName != buf) { /* user specified a file. bail */ 5039ff100acSmrg uError("Can't open config file \"%s\n", cfgFileName); 5049ff100acSmrg uAction("Exiting\n"); 5059ff100acSmrg exit(1); 5069ff100acSmrg } 5079ff100acSmrg snprintf(buf, sizeof(buf), DFLT_SYS_XKBEVD_CONFIG, 5089ff100acSmrg DFLT_XKB_CONFIG_ROOT); 5099ff100acSmrg file = fopen(cfgFileName, "r"); 5109ff100acSmrg if (file == NULL && !eventMask) { 5119ff100acSmrg if (verbose) { 5129ff100acSmrg uError("Couldn't find a config file anywhere\n"); 5139ff100acSmrg uAction("Exiting\n"); 5149ff100acSmrg exit(1); 5159ff100acSmrg } 5169ff100acSmrg exit(0); 5179ff100acSmrg } 5189ff100acSmrg } 51976910425Smrg } 52076910425Smrg 52176910425Smrg if (background) { 5229ff100acSmrg if (fork() != 0) { 5239ff100acSmrg if (verbose) 5249ff100acSmrg uInformation("Running in the background\n"); 5259ff100acSmrg exit(0); 5269ff100acSmrg } 52776910425Smrg } 5289ff100acSmrg dpy = GetDisplay(argv[0], dpyName, &xkbOpcode, &xkbEventCode); 52976910425Smrg if (!dpy) 5309ff100acSmrg goto BAILOUT; 5319ff100acSmrg ok = True; 5329ff100acSmrg setScanState(cfgFileName, 1); 53376910425Smrg CFGParseFile(file); 534db17cd6dSmrg if (!config && !eventMask) { 5359ff100acSmrg uError("No configuration specified in \"%s\"\n", cfgFileName); 5369ff100acSmrg goto BAILOUT; 53776910425Smrg } 5389ff100acSmrg if (eventMask == 0) { 5399ff100acSmrg uError("No events to watch in \"%s\"\n", cfgFileName); 5409ff100acSmrg goto BAILOUT; 54176910425Smrg } 5429ff100acSmrg if (!XkbSelectEvents(dpy, XkbUseCoreKbd, eventMask, eventMask)) { 5439ff100acSmrg uError("Couldn't select desired XKB events\n"); 5449ff100acSmrg goto BAILOUT; 54576910425Smrg } 5469ff100acSmrg xkb = XkbGetKeyboard(dpy, XkbGBN_AllComponentsMask, XkbUseCoreKbd); 5479ff100acSmrg if (eventMask & XkbBellNotifyMask) { 5489ff100acSmrg unsigned ctrls, vals; 5499ff100acSmrg 5509ff100acSmrg if (verbose) 5519ff100acSmrg uInformation("Temporarily disabling the audible bell\n"); 5529ff100acSmrg if (!XkbChangeEnabledControls 5539ff100acSmrg (dpy, XkbUseCoreKbd, XkbAudibleBellMask, 0)) { 5549ff100acSmrg uError("Couldn't disable audible bell\n"); 5559ff100acSmrg goto BAILOUT; 5569ff100acSmrg } 5579ff100acSmrg ctrls = vals = XkbAudibleBellMask; 5589ff100acSmrg if (!XkbSetAutoResetControls(dpy, XkbAudibleBellMask, &ctrls, &vals)) { 5599ff100acSmrg uWarning("Couldn't configure audible bell to reset on exit\n"); 5609ff100acSmrg uAction("Audible bell might remain off\n"); 5619ff100acSmrg } 56276910425Smrg } 5639ff100acSmrg if (soundCmd == NULL) 5649ff100acSmrg soundCmd = DFLT_SOUND_CMD; 5659ff100acSmrg if (soundDir == NULL) 5669ff100acSmrg soundDir = DFLT_SOUND_DIR; 5679ff100acSmrg XkbStdBellEvent(dpy, None, 0, XkbBI_ImAlive); 56876910425Smrg while (1) { 5699ff100acSmrg XNextEvent(dpy, &ev.core); 5709ff100acSmrg if ((!ProcessMatchingConfig(&ev)) && (ev.type == xkbEventCode) && 5719ff100acSmrg (ev.any.xkb_type == XkbBellNotify)) { 5729ff100acSmrg XkbForceDeviceBell(dpy, ev.bell.device, 5739ff100acSmrg ev.bell.bell_class, ev.bell.bell_id, 5749ff100acSmrg ev.bell.percent); 5759ff100acSmrg } 57676910425Smrg } 57776910425Smrg 57876910425Smrg XCloseDisplay(dpy); 5799ff100acSmrg return (ok == 0); 5809ff100acSmrg BAILOUT: 58176910425Smrg uAction("Exiting\n"); 5829ff100acSmrg if (dpy != NULL) 5839ff100acSmrg XCloseDisplay(dpy); 58476910425Smrg exit(1); 58576910425Smrg} 586