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; 6076910425Smrg 619ff100acSmrgstatic CfgEntryPtr config = NULL; 629ff100acSmrgstatic unsigned long eventMask = 0; 6376910425Smrg 649ff100acSmrgstatic Bool synch = False; 659ff100acSmrgstatic int verbose = 0; 669ff100acSmrgstatic Bool background = False; 6776910425Smrg 689ff100acSmrgstatic const char *soundCmd = NULL; 699ff100acSmrgstatic const char *soundDir = NULL; 7076910425Smrg 719ff100acSmrgXkbDescPtr xkb = NULL; 7276910425Smrg 7376910425Smrg/***====================================================================***/ 7476910425Smrg 7576910425Smrgstatic void 7676910425SmrgUsage(int argc, char *argv[]) 7776910425Smrg{ 789ff100acSmrg fprintf(stderr, "Usage: %s [options]...\n%s", argv[0], 799ff100acSmrg "Legal options:\n" 809ff100acSmrg "-?, -help Print this message\n" 819ff100acSmrg "-cfg <file> Specify a config file\n" 829ff100acSmrg "-sc <cmd> Specify the command to play sounds\n" 839ff100acSmrg "-sd <dir> Specify the root directory for sound files\n" 849ff100acSmrg "-d[isplay] <dpy> Specify the display to watch\n" 859ff100acSmrg "-bg Run in background\n" 869ff100acSmrg "-synch Force synchronization\n" 879ff100acSmrg "-v Print verbose messages\n" 889ff100acSmrg "-version Print program version\n" 899ff100acSmrg ); 9076910425Smrg return; 9176910425Smrg} 9276910425Smrg 9376910425Smrg/***====================================================================***/ 9476910425Smrg 9576910425Smrgstatic Bool 9676910425SmrgparseArgs(int argc, char *argv[]) 9776910425Smrg{ 989ff100acSmrg register int i; 999ff100acSmrg 1009ff100acSmrg for (i = 1; i < argc; i++) { 1019ff100acSmrg if (strcmp(argv[i], "-bg") == 0) { 1029ff100acSmrg background = True; 1039ff100acSmrg } 1049ff100acSmrg else if (strcmp(argv[i], "-cfg") == 0) { 1059ff100acSmrg if (i >= (argc - 1)) { 1069ff100acSmrg uError("No configuration file specified on command line\n"); 1079ff100acSmrg uAction("Trailing %s argument ignored\n", argv[i]); 1089ff100acSmrg } 1099ff100acSmrg else { 1109ff100acSmrg char *name = argv[++i]; 1119ff100acSmrg 1129ff100acSmrg if (cfgFileName != NULL) { 1139ff100acSmrg if (uStringEqual(cfgFileName, name)) 1149ff100acSmrg uWarning("Config file \"%s\" specified twice!\n", name); 1159ff100acSmrg else { 1169ff100acSmrg uWarning("Multiple config files on command line\n"); 1179ff100acSmrg uAction("Using \"%s\", ignoring \"%s\"\n", name, 1189ff100acSmrg cfgFileName); 1199ff100acSmrg } 1209ff100acSmrg } 1219ff100acSmrg cfgFileName = name; 1229ff100acSmrg } 1239ff100acSmrg } 1249ff100acSmrg else if ((strcmp(argv[i], "-d") == 0) || 1259ff100acSmrg (strcmp(argv[i], "-display") == 0)) { 1269ff100acSmrg if (i >= (argc - 1)) { 1279ff100acSmrg uError("No display specified on command line\n"); 1289ff100acSmrg uAction("Trailing %s argument ignored\n", argv[i]); 1299ff100acSmrg } 1309ff100acSmrg else { 1319ff100acSmrg char *name = argv[++i]; 1329ff100acSmrg 1339ff100acSmrg if (dpyName != NULL) { 1349ff100acSmrg if (uStringEqual(dpyName, name)) 1359ff100acSmrg uWarning("Display \"%s\" specified twice!\n", name); 1369ff100acSmrg else { 1379ff100acSmrg uWarning("Multiple displays on command line\n"); 1389ff100acSmrg uAction("Using \"%s\", ignoring \"%s\"\n", name, 1399ff100acSmrg dpyName); 1409ff100acSmrg } 1419ff100acSmrg } 1429ff100acSmrg dpyName = name; 1439ff100acSmrg } 1449ff100acSmrg } 1459ff100acSmrg else if (strcmp(argv[i], "-sc") == 0) { 1469ff100acSmrg if (i >= (argc - 1)) { 1479ff100acSmrg uError("No sound command specified on command line\n"); 1489ff100acSmrg uAction("Trailing %s argument ignored\n", argv[i]); 1499ff100acSmrg } 1509ff100acSmrg else { 1519ff100acSmrg char *name = argv[++i]; 1529ff100acSmrg 1539ff100acSmrg if (soundCmd != NULL) { 1549ff100acSmrg if (uStringEqual(soundCmd, name)) 1559ff100acSmrg uWarning("Sound command \"%s\" specified twice!\n", 1569ff100acSmrg name); 1579ff100acSmrg else { 1589ff100acSmrg uWarning("Multiple sound commands on command line\n"); 1599ff100acSmrg uAction("Using \"%s\", ignoring \"%s\"\n", name, 1609ff100acSmrg soundCmd); 1619ff100acSmrg } 1629ff100acSmrg } 1639ff100acSmrg soundCmd = name; 1649ff100acSmrg } 1659ff100acSmrg } 1669ff100acSmrg else if (strcmp(argv[i], "-sd") == 0) { 1679ff100acSmrg if (i >= (argc - 1)) { 1689ff100acSmrg uError("No sound directory specified on command line\n"); 1699ff100acSmrg uAction("Trailing %s argument ignored\n", argv[i]); 1709ff100acSmrg } 1719ff100acSmrg else { 1729ff100acSmrg char *name = argv[++i]; 1739ff100acSmrg 1749ff100acSmrg if (soundDir != NULL) { 1759ff100acSmrg if (uStringEqual(soundDir, name)) 1769ff100acSmrg uWarning("Sound directory \"%s\" specified twice!\n", 1779ff100acSmrg name); 1789ff100acSmrg else { 1799ff100acSmrg uWarning("Multiple sound dirs on command line\n"); 1809ff100acSmrg uAction("Using \"%s\", ignoring \"%s\"\n", name, 1819ff100acSmrg soundDir); 1829ff100acSmrg } 1839ff100acSmrg } 1849ff100acSmrg soundDir = name; 1859ff100acSmrg } 1869ff100acSmrg } 1879ff100acSmrg else if ((strcmp(argv[i], "-synch") == 0) || 1889ff100acSmrg (strcmp(argv[i], "-s") == 0)) { 1899ff100acSmrg synch = True; 1909ff100acSmrg } 1919ff100acSmrg else if (strcmp(argv[i], "-v") == 0) { 1929ff100acSmrg verbose++; 1939ff100acSmrg } 1948bfe6addSmrg else if ((strcmp(argv[i], "-version") == 0) || 1958bfe6addSmrg (strcmp(argv[i], "--version") == 0)) { 1969ff100acSmrg puts(PACKAGE_STRING); 1979ff100acSmrg exit(0); 1989ff100acSmrg } 1999ff100acSmrg else if ((strcmp(argv[i], "-?") == 0) || 2008bfe6addSmrg (strcmp(argv[i], "-help") == 0) || 2018bfe6addSmrg (strcmp(argv[i], "--help") == 0)) { 2029ff100acSmrg Usage(argc, argv); 2039ff100acSmrg exit(0); 2049ff100acSmrg } 2059ff100acSmrg else { 2069ff100acSmrg uError("Unknown flag \"%s\" on command line\n", argv[i]); 2079ff100acSmrg Usage(argc, argv); 2089ff100acSmrg return False; 2099ff100acSmrg } 21076910425Smrg } 211db17cd6dSmrg if (background == False) { 2129ff100acSmrg eventMask = XkbAllEventsMask; 2139ff100acSmrg verbose++; 214db17cd6dSmrg } 215db17cd6dSmrg 21676910425Smrg return True; 21776910425Smrg} 21876910425Smrg 21976910425Smrgstatic Display * 220a67f45c3SmrgGetDisplay(const char *program, const char *displayName, 221a67f45c3Smrg int *opcodeRtrn, int *evBaseRtrn) 22276910425Smrg{ 2239ff100acSmrg int mjr, mnr, error; 224a67f45c3Smrg Display *display; 2259ff100acSmrg 2269ff100acSmrg mjr = XkbMajorVersion; 2279ff100acSmrg mnr = XkbMinorVersion; 228a67f45c3Smrg display = XkbOpenDisplay(displayName, evBaseRtrn, NULL, &mjr, &mnr, &error); 229a67f45c3Smrg if (display == NULL) { 2309ff100acSmrg switch (error) { 2319ff100acSmrg case XkbOD_BadLibraryVersion: 2329ff100acSmrg uInformation("%s was compiled with XKB version %d.%02d\n", 2339ff100acSmrg program, XkbMajorVersion, XkbMinorVersion); 2349ff100acSmrg uError("X library supports incompatible version %d.%02d\n", 2359ff100acSmrg mjr, mnr); 2369ff100acSmrg break; 2379ff100acSmrg case XkbOD_ConnectionRefused: 238a67f45c3Smrg uError("Cannot open display \"%s\"\n", displayName); 2399ff100acSmrg break; 2409ff100acSmrg case XkbOD_NonXkbServer: 241a67f45c3Smrg uError("XKB extension not present on %s\n", displayName); 2429ff100acSmrg break; 2439ff100acSmrg case XkbOD_BadServerVersion: 2449ff100acSmrg uInformation("%s was compiled with XKB version %d.%02d\n", 2459ff100acSmrg program, XkbMajorVersion, XkbMinorVersion); 2469ff100acSmrg uError("Server %s uses incompatible version %d.%02d\n", 247a67f45c3Smrg displayName, mjr, mnr); 2489ff100acSmrg break; 2499ff100acSmrg default: 2509ff100acSmrg uInternalError("Unknown error %d from XkbOpenDisplay\n", error); 2519ff100acSmrg } 25276910425Smrg } 25376910425Smrg else if (synch) 254a67f45c3Smrg XSynchronize(display, True); 25576910425Smrg if (opcodeRtrn) 256a67f45c3Smrg XkbQueryExtension(display, opcodeRtrn, evBaseRtrn, NULL, &mjr, &mnr); 257a67f45c3Smrg return display; 25876910425Smrg} 25976910425Smrg 26076910425Smrg/***====================================================================***/ 26176910425Smrg 26276910425Smrgvoid 26376910425SmrgInterpretConfigs(CfgEntryPtr cfg) 26476910425Smrg{ 2659ff100acSmrg config = cfg; 2669ff100acSmrg while (cfg != NULL) { 267a67f45c3Smrg char *name = cfg->name.str; 2689ff100acSmrg if (cfg->entry_type == VariableDef) { 2699ff100acSmrg if (uStrCaseEqual(name, "sounddirectory") || 2709ff100acSmrg uStrCaseEqual(name, "sounddir")) { 2719ff100acSmrg if (soundDir == NULL) { 2729ff100acSmrg soundDir = cfg->action.text; 2739ff100acSmrg cfg->name.str = NULL; 2749ff100acSmrg cfg->action.text = NULL; 2759ff100acSmrg } 2769ff100acSmrg } 2779ff100acSmrg else if (uStrCaseEqual(name, "soundcommand") || 2789ff100acSmrg uStrCaseEqual(name, "soundcmd")) { 2799ff100acSmrg if (soundCmd == NULL) { 2809ff100acSmrg soundCmd = cfg->action.text; 2819ff100acSmrg cfg->name.str = NULL; 2829ff100acSmrg cfg->action.text = NULL; 2839ff100acSmrg } 2849ff100acSmrg } 2859ff100acSmrg else { 2869ff100acSmrg uWarning("Assignment to unknown variable \"%s\"\n", name); 2879ff100acSmrg uAction("Ignored\n"); 2889ff100acSmrg } 2899ff100acSmrg } 290a67f45c3Smrg else if (cfg->entry_type == EventDef) { 291a67f45c3Smrg unsigned int priv; 292a67f45c3Smrg 2939ff100acSmrg switch (cfg->event_type) { 2949ff100acSmrg case XkbBellNotify: 2959ff100acSmrg if (name != NULL) 2969ff100acSmrg cfg->name.atom = XInternAtom(dpy, name, False); 2979ff100acSmrg else 2989ff100acSmrg cfg->name.atom = None; 2999ff100acSmrg if (name) 3009ff100acSmrg free(name); 3019ff100acSmrg break; 3029ff100acSmrg case XkbAccessXNotify: 3039ff100acSmrg priv = 0; 3049ff100acSmrg if (name == NULL) 3059ff100acSmrg priv = XkbAllNewKeyboardEventsMask; 3069ff100acSmrg else if (uStrCaseEqual(name, "skpress")) 3079ff100acSmrg priv = XkbAXN_SKPressMask; 3089ff100acSmrg else if (uStrCaseEqual(name, "skaccept")) 3099ff100acSmrg priv = XkbAXN_SKAcceptMask; 3109ff100acSmrg else if (uStrCaseEqual(name, "skreject")) 3119ff100acSmrg priv = XkbAXN_SKRejectMask; 3129ff100acSmrg else if (uStrCaseEqual(name, "skrelease")) 3139ff100acSmrg priv = XkbAXN_SKReleaseMask; 3149ff100acSmrg else if (uStrCaseEqual(name, "bkaccept")) 3159ff100acSmrg priv = XkbAXN_BKAcceptMask; 3169ff100acSmrg else if (uStrCaseEqual(name, "bkreject")) 3179ff100acSmrg priv = XkbAXN_BKRejectMask; 3189ff100acSmrg else if (uStrCaseEqual(name, "warning")) 3199ff100acSmrg priv = XkbAXN_AXKWarningMask; 3209ff100acSmrg if (name) 3219ff100acSmrg free(name); 3229ff100acSmrg cfg->name.priv = priv; 3239ff100acSmrg break; 3249ff100acSmrg case XkbActionMessage: 3259ff100acSmrg /* nothing to do */ 3269ff100acSmrg break; 3279ff100acSmrg } 328a67f45c3Smrg } 3299ff100acSmrg eventMask |= (1L << cfg->event_type); 3309ff100acSmrg cfg = cfg->next; 33176910425Smrg } 3329ff100acSmrg while ((config) && (config->entry_type != EventDef)) { 3339ff100acSmrg CfgEntryPtr next; 3349ff100acSmrg 3359ff100acSmrg if (config->name.str) 3369ff100acSmrg free(config->name.str); 3379ff100acSmrg if (config->action.text) 3389ff100acSmrg free(config->action.text); 3399ff100acSmrg config->name.str = NULL; 3409ff100acSmrg config->action.text = NULL; 3419ff100acSmrg next = config->next; 3429ff100acSmrg free(config); 3439ff100acSmrg config = next; 34476910425Smrg } 3459ff100acSmrg cfg = config; 3469ff100acSmrg while ((cfg != NULL) && (cfg->next != NULL)) { 3479ff100acSmrg CfgEntryPtr next; 3489ff100acSmrg 3499ff100acSmrg next = cfg->next; 3509ff100acSmrg if (next->entry_type != EventDef) { 3519ff100acSmrg if (next->name.str) 3529ff100acSmrg free(config->name.str); 3539ff100acSmrg if (next->action.text) 3549ff100acSmrg free(config->action.text); 3559ff100acSmrg next->name.str = NULL; 3569ff100acSmrg next->action.text = NULL; 3579ff100acSmrg cfg->next = next->next; 3589ff100acSmrg next->next = NULL; 3599ff100acSmrg free(next); 3609ff100acSmrg } 3619ff100acSmrg else 3629ff100acSmrg cfg = next; 36376910425Smrg } 36476910425Smrg return; 36576910425Smrg} 36676910425Smrg 36776910425Smrgstatic CfgEntryPtr 3689ff100acSmrgFindMatchingConfig(XkbEvent * ev) 36976910425Smrg{ 3709ff100acSmrg CfgEntryPtr cfg, dflt; 3719ff100acSmrg 3729ff100acSmrg dflt = NULL; 3739ff100acSmrg for (cfg = config; (cfg != NULL); cfg = cfg->next) { 3749ff100acSmrg if ((ev->type != xkbEventCode) || (cfg->event_type != ev->any.xkb_type)) 3759ff100acSmrg continue; 3769ff100acSmrg switch (ev->any.xkb_type) { 3779ff100acSmrg case XkbBellNotify: 3789ff100acSmrg if (ev->bell.name == cfg->name.atom) 3799ff100acSmrg return cfg; 3809ff100acSmrg else if ((cfg->name.atom == None) && (dflt == NULL)) 3819ff100acSmrg dflt = cfg; 3829ff100acSmrg break; 3839ff100acSmrg case XkbAccessXNotify: 3849ff100acSmrg if (cfg->name.priv & (1L << ev->accessx.detail)) 3859ff100acSmrg return cfg; 3869ff100acSmrg break; 3879ff100acSmrg case XkbActionMessage: 3889ff100acSmrg if (cfg->name.str == NULL) 3899ff100acSmrg dflt = cfg; 3909ff100acSmrg else if (strncmp(cfg->name.str, ev->message.message, 3919ff100acSmrg XkbActionMessageLength) == 0) 3929ff100acSmrg return cfg; 3939ff100acSmrg break; 3949ff100acSmrg default: 3959ff100acSmrg uInternalError("Can't handle type %d XKB events yet, Sorry.\n", 3969ff100acSmrg ev->any.xkb_type); 3979ff100acSmrg break; 3989ff100acSmrg } 39976910425Smrg } 40076910425Smrg return dflt; 40176910425Smrg} 40276910425Smrg 40376910425Smrgstatic Bool 4049ff100acSmrgProcessMatchingConfig(XkbEvent * ev) 40576910425Smrg{ 4069ff100acSmrg CfgEntryPtr cfg; 4078bfe6addSmrg char buf[1024]; 4088bfe6addSmrg const char *cmd; 4099ff100acSmrg int ok; 41076910425Smrg 4119ff100acSmrg cfg = FindMatchingConfig(ev); 412db17cd6dSmrg if (!cfg) { 4139ff100acSmrg if (verbose) 4149ff100acSmrg PrintXkbEvent(stdout, ev); 4159ff100acSmrg return False; 416db17cd6dSmrg } 4179ff100acSmrg if (cfg->action.type == UnknownAction) { 4189ff100acSmrg if (cfg->action.text == NULL) 4199ff100acSmrg cfg->action.type = NoAction; 4209ff100acSmrg else if (cfg->action.text[0] == '!') { 4219ff100acSmrg char *tmp; 4229ff100acSmrg 4239ff100acSmrg cfg->action.type = ShellAction; 4249ff100acSmrg tmp = uStringDup(&cfg->action.text[1]); 4259ff100acSmrg free(cfg->action.text); 4269ff100acSmrg cfg->action.text = tmp; 4279ff100acSmrg } 4289ff100acSmrg else 4299ff100acSmrg cfg->action.type = SoundAction; 43076910425Smrg } 43176910425Smrg switch (cfg->action.type) { 4329ff100acSmrg case NoAction: 4339ff100acSmrg return True; 4349ff100acSmrg case EchoAction: 4359ff100acSmrg if (cfg->action.text != NULL) { 4369ff100acSmrg snprintf(buf, sizeof(buf), "%s", cfg->action.text); 4379ff100acSmrg cmd = SubstituteEventArgs(buf, ev); 4389ff100acSmrg printf("%s", cmd); 4399ff100acSmrg } 4409ff100acSmrg return True; 4419ff100acSmrg case PrintEvAction: 4429ff100acSmrg PrintXkbEvent(stdout, ev); 4439ff100acSmrg return True; 4449ff100acSmrg case ShellAction: 4459ff100acSmrg if (cfg->action.text == NULL) { 4469ff100acSmrg uWarning("Empty shell command!\n"); 4479ff100acSmrg uAction("Ignored\n"); 4489ff100acSmrg return True; 4499ff100acSmrg } 4509ff100acSmrg cmd = cfg->action.text; 4519ff100acSmrg break; 4529ff100acSmrg case SoundAction: 4539ff100acSmrg if (cfg->action.text == NULL) { 4549ff100acSmrg uWarning("Empty sound command!\n"); 4559ff100acSmrg uAction("Ignored\n"); 4569ff100acSmrg return True; 4579ff100acSmrg } 4589ff100acSmrg snprintf(buf, sizeof(buf), "%s %s%s", soundCmd, soundDir, 4599ff100acSmrg cfg->action.text); 4609ff100acSmrg cmd = buf; 4619ff100acSmrg break; 4629ff100acSmrg default: 4639ff100acSmrg uInternalError("Unknown error action type %d\n", cfg->action.type); 4649ff100acSmrg return False; 46576910425Smrg } 4669ff100acSmrg cmd = SubstituteEventArgs(cmd, ev); 46776910425Smrg if (verbose) 4689ff100acSmrg uInformation("Executing shell command \"%s\"\n", cmd); 4699ff100acSmrg ok = (system(cmd) == 0); 47076910425Smrg return ok; 47176910425Smrg} 47276910425Smrg 47376910425Smrg/***====================================================================***/ 47476910425Smrg 47576910425Smrgint 47676910425Smrgmain(int argc, char *argv[]) 47776910425Smrg{ 4789ff100acSmrg FILE * file; 4799ff100acSmrg static char buf[1024]; 4809ff100acSmrg XkbEvent ev; 4819ff100acSmrg Bool ok; 48276910425Smrg 48376910425Smrg yyin = stdin; 48476910425Smrg uSetErrorFile(NullString); 48576910425Smrg 4869ff100acSmrg if (!parseArgs(argc, argv)) 4879ff100acSmrg exit(1); 4889ff100acSmrg file = NULL; 48976910425Smrg XkbInitAtoms(NULL); 4909ff100acSmrg if (cfgFileName == NULL) { 4919ff100acSmrg char *home = getenv("HOME"); 4929ff100acSmrg snprintf(buf, sizeof(buf), DFLT_XKBEVD_CONFIG, (home ? home : "")); 4939ff100acSmrg cfgFileName = buf; 49476910425Smrg } 4959ff100acSmrg if (uStringEqual(cfgFileName, "-")) { 4969ff100acSmrg static const char *in = "stdin"; 4979ff100acSmrg 4989ff100acSmrg file = stdin; 4999ff100acSmrg cfgFileName = in; 50076910425Smrg } 50176910425Smrg else { 5029ff100acSmrg file = fopen(cfgFileName, "r"); 5039ff100acSmrg if (file == NULL) { /* no personal config, try for a system one */ 5049ff100acSmrg if (cfgFileName != buf) { /* user specified a file. bail */ 5059ff100acSmrg uError("Can't open config file \"%s\n", cfgFileName); 5069ff100acSmrg uAction("Exiting\n"); 5079ff100acSmrg exit(1); 5089ff100acSmrg } 5099ff100acSmrg snprintf(buf, sizeof(buf), DFLT_SYS_XKBEVD_CONFIG, 5109ff100acSmrg DFLT_XKB_CONFIG_ROOT); 5119ff100acSmrg file = fopen(cfgFileName, "r"); 5129ff100acSmrg if (file == NULL && !eventMask) { 5139ff100acSmrg if (verbose) { 5149ff100acSmrg uError("Couldn't find a config file anywhere\n"); 5159ff100acSmrg uAction("Exiting\n"); 5169ff100acSmrg exit(1); 5179ff100acSmrg } 5189ff100acSmrg exit(0); 5199ff100acSmrg } 5209ff100acSmrg } 52176910425Smrg } 52276910425Smrg 52376910425Smrg if (background) { 5249ff100acSmrg if (fork() != 0) { 5259ff100acSmrg if (verbose) 5269ff100acSmrg uInformation("Running in the background\n"); 5279ff100acSmrg exit(0); 5289ff100acSmrg } 52976910425Smrg } 5309ff100acSmrg dpy = GetDisplay(argv[0], dpyName, &xkbOpcode, &xkbEventCode); 53176910425Smrg if (!dpy) 5329ff100acSmrg goto BAILOUT; 5339ff100acSmrg ok = True; 5349ff100acSmrg setScanState(cfgFileName, 1); 53576910425Smrg CFGParseFile(file); 536db17cd6dSmrg if (!config && !eventMask) { 5379ff100acSmrg uError("No configuration specified in \"%s\"\n", cfgFileName); 5389ff100acSmrg goto BAILOUT; 53976910425Smrg } 5409ff100acSmrg if (eventMask == 0) { 5419ff100acSmrg uError("No events to watch in \"%s\"\n", cfgFileName); 5429ff100acSmrg goto BAILOUT; 54376910425Smrg } 5449ff100acSmrg if (!XkbSelectEvents(dpy, XkbUseCoreKbd, eventMask, eventMask)) { 5459ff100acSmrg uError("Couldn't select desired XKB events\n"); 5469ff100acSmrg goto BAILOUT; 54776910425Smrg } 5489ff100acSmrg xkb = XkbGetKeyboard(dpy, XkbGBN_AllComponentsMask, XkbUseCoreKbd); 5499ff100acSmrg if (eventMask & XkbBellNotifyMask) { 5509ff100acSmrg unsigned ctrls, vals; 5519ff100acSmrg 5529ff100acSmrg if (verbose) 5539ff100acSmrg uInformation("Temporarily disabling the audible bell\n"); 5549ff100acSmrg if (!XkbChangeEnabledControls 5559ff100acSmrg (dpy, XkbUseCoreKbd, XkbAudibleBellMask, 0)) { 5569ff100acSmrg uError("Couldn't disable audible bell\n"); 5579ff100acSmrg goto BAILOUT; 5589ff100acSmrg } 5599ff100acSmrg ctrls = vals = XkbAudibleBellMask; 5609ff100acSmrg if (!XkbSetAutoResetControls(dpy, XkbAudibleBellMask, &ctrls, &vals)) { 5619ff100acSmrg uWarning("Couldn't configure audible bell to reset on exit\n"); 5629ff100acSmrg uAction("Audible bell might remain off\n"); 5639ff100acSmrg } 56476910425Smrg } 5659ff100acSmrg if (soundCmd == NULL) 5669ff100acSmrg soundCmd = DFLT_SOUND_CMD; 5679ff100acSmrg if (soundDir == NULL) 5689ff100acSmrg soundDir = DFLT_SOUND_DIR; 5699ff100acSmrg XkbStdBellEvent(dpy, None, 0, XkbBI_ImAlive); 57076910425Smrg while (1) { 5719ff100acSmrg XNextEvent(dpy, &ev.core); 5729ff100acSmrg if ((!ProcessMatchingConfig(&ev)) && (ev.type == xkbEventCode) && 5739ff100acSmrg (ev.any.xkb_type == XkbBellNotify)) { 5749ff100acSmrg XkbForceDeviceBell(dpy, ev.bell.device, 5759ff100acSmrg ev.bell.bell_class, ev.bell.bell_id, 5769ff100acSmrg ev.bell.percent); 5779ff100acSmrg } 57876910425Smrg } 57976910425Smrg 58076910425Smrg XCloseDisplay(dpy); 5819ff100acSmrg return (ok == 0); 5829ff100acSmrg BAILOUT: 58376910425Smrg uAction("Exiting\n"); 5849ff100acSmrg if (dpy != NULL) 5859ff100acSmrg XCloseDisplay(dpy); 58676910425Smrg exit(1); 58776910425Smrg} 588