1010cdda0Smrg/************************************************************
2010cdda0SmrgCopyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3010cdda0Smrg
4010cdda0SmrgPermission to use, copy, modify, and distribute this
5010cdda0Smrgsoftware and its documentation for any purpose and without
6010cdda0Smrgfee is hereby granted, provided that the above copyright
7010cdda0Smrgnotice appear in all copies and that both that copyright
8010cdda0Smrgnotice and this permission notice appear in supporting
9010cdda0Smrgdocumentation, and that the name of Silicon Graphics not be
10010cdda0Smrgused in advertising or publicity pertaining to distribution
11010cdda0Smrgof the software without specific prior written permission.
12010cdda0SmrgSilicon Graphics makes no representation about the suitability
13010cdda0Smrgof this software for any purpose. It is provided "as is"
14010cdda0Smrgwithout any express or implied warranty.
15010cdda0Smrg
16010cdda0SmrgSILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17010cdda0SmrgSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18010cdda0SmrgAND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19010cdda0SmrgGRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20010cdda0SmrgDAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21010cdda0SmrgDATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22010cdda0SmrgOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23010cdda0SmrgTHE USE OR PERFORMANCE OF THIS SOFTWARE.
24010cdda0Smrg
25010cdda0Smrg********************************************************/
26b4485a66Smrg
27b4485a66Smrg#ifdef HAVE_CONFIG_H
28b4485a66Smrg# include       "config.h"
29b4485a66Smrg#endif
30010cdda0Smrg
31010cdda0Smrg#include <stdio.h>
32b4485a66Smrg#include <stdlib.h>
33010cdda0Smrg#include <string.h>
34010cdda0Smrg#include <X11/Xproto.h>
35010cdda0Smrg#include <X11/Xlib.h>
36010cdda0Smrg#include <X11/X.h>
37010cdda0Smrg#include <X11/XKBlib.h>
38010cdda0Smrg#include <X11/extensions/XI.h>
39010cdda0Smrg
40b4485a66Smrgstatic char *dpyName = NULL;
41b4485a66Smrgstatic int volume = 0;
42b4485a66Smrgstatic int devSpec = XkbUseCoreKbd;
43b4485a66Smrgstatic int class = -1;
44b4485a66Smrgstatic int id = -1;
45b4485a66Smrgstatic char *bellName;
46b4485a66Smrgstatic Atom nameAtom = None;
47b4485a66Smrgstatic int synch = 0;
48b4485a66Smrgstatic int win = None;
49b4485a66Smrgstatic int force = 0;
50b4485a66Smrgstatic int nobeep = 0;
51010cdda0Smrg
52010cdda0Smrgstatic int
53010cdda0SmrgparseArgs(int argc, char *argv[])
54010cdda0Smrg{
55b4485a66Smrg    int i;
56010cdda0Smrg
57b4485a66Smrg    for (i = 1; i < argc; i++) {
58b4485a66Smrg        if (strcmp(argv[i], "-display") == 0) {
59b4485a66Smrg            if (++i < argc)
60b4485a66Smrg                dpyName = argv[i];
61b4485a66Smrg            else {
62b4485a66Smrg                fprintf(stderr,
63b4485a66Smrg                        "Must specify a display with -display option\n");
64b4485a66Smrg                return 0;
65b4485a66Smrg            }
66b4485a66Smrg        }
67b4485a66Smrg        else if ((strcmp(argv[i], "-help") == 0) ||
68b4485a66Smrg                 (strcmp(argv[i], "-usage") == 0)) {
69b4485a66Smrg            return 0;
70b4485a66Smrg        }
71b4485a66Smrg        else if (strcmp(argv[i], "-version") == 0) {
72b4485a66Smrg            printf("xkbbell (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
73b4485a66Smrg            exit(0);
74b4485a66Smrg        }
75b4485a66Smrg        else if (strcmp(argv[i], "-synch") == 0) {
76b4485a66Smrg            synch = 1;
77b4485a66Smrg        }
78b4485a66Smrg        else if (strcmp(argv[i], "-force") == 0) {
79b4485a66Smrg            force = 1;
80b4485a66Smrg        }
81b4485a66Smrg        else if (strcmp(argv[i], "-nobeep") == 0) {
82b4485a66Smrg            nobeep = 1;
83b4485a66Smrg        }
84b4485a66Smrg        else if (strcmp(argv[i], "-dev") == 0) {
85b4485a66Smrg            if (++i < argc) {
86b4485a66Smrg                if (sscanf(argv[i], " %i ", &devSpec) != 1) {
87b4485a66Smrg                    fprintf(stderr, "Device ID must be an integer\n");
88b4485a66Smrg                    return 0;
89b4485a66Smrg                }
90b4485a66Smrg            }
91b4485a66Smrg            else {
92b4485a66Smrg                fprintf(stderr, "Must specify a device ID with -dev option\n");
93b4485a66Smrg                return 0;
94b4485a66Smrg            }
95b4485a66Smrg        }
96b4485a66Smrg        else if (strcmp(argv[i], "-kf") == 0) {
97b4485a66Smrg            if (++i < argc) {
98b4485a66Smrg                if (sscanf(argv[i], " %i ", &id) != 1) {
99b4485a66Smrg                    fprintf(stderr,
100b4485a66Smrg                            "Keyboard feedback ID must be an integer\n");
101b4485a66Smrg                    return 0;
102b4485a66Smrg                }
103b4485a66Smrg                class = KbdFeedbackClass;
104b4485a66Smrg            }
105b4485a66Smrg            else {
106b4485a66Smrg                fprintf(stderr,
107b4485a66Smrg                        "Must specify a keyboard feedback ID for -kf\n");
108b4485a66Smrg                return 0;
109b4485a66Smrg            }
110b4485a66Smrg        }
111b4485a66Smrg        else if (strcmp(argv[i], "-bf") == 0) {
112b4485a66Smrg            if (++i < argc) {
113b4485a66Smrg                if (sscanf(argv[i], " %i ", &id) != 1) {
114b4485a66Smrg                    fprintf(stderr, "Bell feedback ID must be an integer\n");
115b4485a66Smrg                    return 0;
116b4485a66Smrg                }
117b4485a66Smrg                class = BellFeedbackClass;
118b4485a66Smrg            }
119b4485a66Smrg            else {
120b4485a66Smrg                fprintf(stderr, "Must specify a bell feedback ID for -bf\n");
121b4485a66Smrg                return 0;
122b4485a66Smrg            }
123b4485a66Smrg        }
124b4485a66Smrg        else if (strcmp(argv[i], "-v") == 0) {
125b4485a66Smrg            if (++i < argc) {
126b4485a66Smrg                if ((sscanf(argv[i], " %i ", &volume) != 1) ||
127b4485a66Smrg                    (volume < -100) || (volume > 100)) {
128b4485a66Smrg                    fprintf(stderr, "Volume must be in the range -100..100\n");
129b4485a66Smrg                    return 0;
130b4485a66Smrg                }
131b4485a66Smrg            }
132b4485a66Smrg            else {
133b4485a66Smrg                fprintf(stderr, "Must specify volume for -v\n");
134b4485a66Smrg                return 0;
135b4485a66Smrg            }
136b4485a66Smrg        }
137b4485a66Smrg        else if (strcmp(argv[i], "-w") == 0) {
138b4485a66Smrg            if (++i < argc) {
139b4485a66Smrg                if (sscanf(argv[i], " %i ", &win) != 1) {
140b4485a66Smrg                    fprintf(stderr, "Must specify a numeric window ID\n");
141b4485a66Smrg                    return 0;
142b4485a66Smrg                }
143b4485a66Smrg            }
144b4485a66Smrg            else {
145b4485a66Smrg                fprintf(stderr, "Must specify a window ID for -w\n");
146b4485a66Smrg                return 0;
147b4485a66Smrg            }
148b4485a66Smrg        }
149b4485a66Smrg        else {
150b4485a66Smrg            if (i < argc - 1) {
151b4485a66Smrg                fprintf(stderr, "Bell name must be the last argument\n");
152b4485a66Smrg                return 0;
153b4485a66Smrg            }
154b4485a66Smrg            bellName = argv[i];
155b4485a66Smrg        }
156010cdda0Smrg    }
157010cdda0Smrg    return 1;
158010cdda0Smrg}
159010cdda0Smrg
160010cdda0Smrgint
161010cdda0Smrgmain(int argc, char *argv[])
162010cdda0Smrg{
163b4485a66Smrg    Display *dpy;
164b4485a66Smrg
165b4485a66Smrg    int i1, i2, i3, i4, i5;
166010cdda0Smrg
167b4485a66Smrg    if (!parseArgs(argc, argv)) {
168b4485a66Smrg        fprintf(stderr, "Usage: %s [ <options> ] <name>\n", argv[0]);
169b4485a66Smrg        fprintf(stderr, "Where legal options are:\n"
170b4485a66Smrg                "-help              print this message\n"
171b4485a66Smrg                "-usage             print this message\n"
172b4485a66Smrg                "-version           print the program version\n"
173b4485a66Smrg                "-display <dpy>     specifies display to use\n"
174b4485a66Smrg                "-synch             turn on synchronization\n"
175b4485a66Smrg                "-dev <id>          specifies device to use\n"
176b4485a66Smrg                "-force             force audible bell\n"
177b4485a66Smrg                "-nobeep            suppress server bell, event only\n"
178b4485a66Smrg                "-bf <id>           specifies bell feedback to use\n"
179b4485a66Smrg                "-kf <id>           specifies keyboard feedback to use\n"
180b4485a66Smrg                "-v <volume>        specifies volume to use\n"
181b4485a66Smrg                "-w <id>            specifies window to use\n");
182b4485a66Smrg        fprintf(stderr,
183b4485a66Smrg                "If neither device nor feedback are specified, %s uses the\n"
184b4485a66Smrg                "default values for the core keyboard device.\n",
185b4485a66Smrg                argv[0]);
186b4485a66Smrg        return 1;
187010cdda0Smrg    }
188010cdda0Smrg    dpy = XOpenDisplay(dpyName);
189b4485a66Smrg    if (!dpy) {
190b4485a66Smrg        fprintf(stderr, "Couldn't open display \"%s\"\n",
191b4485a66Smrg                XDisplayName(dpyName));
192b4485a66Smrg        return 1;
193010cdda0Smrg    }
194010cdda0Smrg    if (synch)
195b4485a66Smrg        XSynchronize(dpy, 1);
196b4485a66Smrg    i1 = XkbMajorVersion;
197b4485a66Smrg    i2 = XkbMinorVersion;
198b4485a66Smrg    if (!XkbLibraryVersion(&i1, &i2)) {
199b4485a66Smrg        fprintf(stderr, "Warning! X library built with XKB version %d.%02d\n",
200b4485a66Smrg                i1, i2);
201b4485a66Smrg        fprintf(stderr, "         but %s was built with %d.%02d\n", argv[0],
202b4485a66Smrg                XkbMajorVersion, XkbMinorVersion);
203b4485a66Smrg        fprintf(stderr, "         Trying anyway\n");
204010cdda0Smrg    }
205500f9a20Sjoerg    if (!XkbQueryExtension(dpy, &i1, &i2, &i3, &i4, &i5)) {
206b4485a66Smrg        if ((i4 != 0) || (i5 != 0))
207b4485a66Smrg            fprintf(stderr,
208b4485a66Smrg                    "server supports incompatible XKB version %d.%02d\n", i4,
209b4485a66Smrg                    i5);
210b4485a66Smrg        else
211b4485a66Smrg            fprintf(stderr, "XkbQueryExtension failed\n");
212b4485a66Smrg        fprintf(stderr, "Trying anyway\n");
213010cdda0Smrg    }
214b4485a66Smrg    if (force && (nameAtom != None))
215b4485a66Smrg        fprintf(stderr, "Warning! Name ignored for forced bell requests\n");
216b4485a66Smrg    if (bellName != NULL)
217b4485a66Smrg        nameAtom = XInternAtom(dpy, bellName, 0);
218b4485a66Smrg    if ((devSpec == XkbUseCoreKbd) && (class < 0)) {
219b4485a66Smrg        Bool ok;
220b4485a66Smrg
221b4485a66Smrg        if (force)
222b4485a66Smrg            ok = XkbForceBell(dpy, volume);
223b4485a66Smrg        else if (nobeep)
224b4485a66Smrg            ok = XkbBellEvent(dpy, win, volume, nameAtom);
225b4485a66Smrg        else
226b4485a66Smrg            ok = XkbBell(dpy, win, volume, nameAtom);
227b4485a66Smrg        if (!ok)
228b4485a66Smrg            fprintf(stderr, "XkbBell request failed\n");
229010cdda0Smrg    }
230010cdda0Smrg    else {
231b4485a66Smrg        Bool ok;
232b4485a66Smrg
233b4485a66Smrg        if (class < 0)
234b4485a66Smrg            class = KbdFeedbackClass;
235b4485a66Smrg        if (id < 0)
236b4485a66Smrg            id = 0;
237b4485a66Smrg        if (force)
238b4485a66Smrg            ok = XkbForceDeviceBell(dpy, devSpec, class, id, volume);
239b4485a66Smrg        else if (nobeep)
240b4485a66Smrg            ok = XkbDeviceBellEvent(dpy, win, devSpec, class, id, volume,
241b4485a66Smrg                                    nameAtom);
242b4485a66Smrg        else
243b4485a66Smrg            ok = XkbDeviceBell(dpy, win, devSpec, class, id, volume, nameAtom);
244b4485a66Smrg        if (!ok)
245b4485a66Smrg            fprintf(stderr, "XkbDeviceBell request failed\n");
246010cdda0Smrg    }
247010cdda0Smrg/* BAIL: */
248010cdda0Smrg    XCloseDisplay(dpy);
249010cdda0Smrg    return 0;
250010cdda0Smrg}
251