/* xkeycaps, Copyright (c) 1991, 1992, 1993, 1996, 1997
* Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*/
#include <stdio.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/StringDefs.h>
#include <X11/Intrinsic.h>
#include <X11/Xaw/Simple.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Box.h>
#include "KbdWidgetP.h"
#include "KeyWidgetP.h"
#include "xkeycaps.h"
struct info_labels {
Widget info;
#ifdef MULTIPLE_WIDGETS
Widget keycode [5];
Widget keysym [9];
Widget ascii [5];
Widget modifiers [2];
Widget autorepeat [2];
#else
Widget keycode;
Widget keysym;
Widget ascii;
Widget modifiers;
Widget autorepeat;
#endif
Widget message;
Widget message2;
};
Widget
#ifdef __STDC__
make_label_1 (Widget parent,
char *name, char *string,
Widget left, Widget top,
WidgetClass class,
XtCallbackProc callback,
XtPointer data)
#else /* ! __STDC__ */
make_label_1 (parent, name, string, left, top, class, callback, data)
Widget parent;
char *name, *string;
Widget left, top;
WidgetClass class;
XtCallbackProc callback;
XtPointer data;
#endif /* ! __STDC__ */
{
Arg av [20];
int ac = 0;
Widget w;
XtSetArg (av[ac], XtNleft, XtChainLeft); ac++;
XtSetArg (av[ac], XtNright, XtChainLeft); ac++;
XtSetArg (av[ac], XtNtop, XtChainTop); ac++;
XtSetArg (av[ac], XtNbottom, XtChainTop); ac++;
XtSetArg (av[ac], XtNjustify, XtJustifyLeft); ac++;
XtSetArg (av[ac], XtNresize, True); ac++;
if (string) XtSetArg (av[ac], XtNlabel, string), ac++;
if (left) XtSetArg (av[ac], XtNfromHoriz, left), ac++;
if (top) XtSetArg (av[ac], XtNfromVert, top), ac++;
w = XtCreateManagedWidget (name, class, parent, av, ac);
if (callback) XtAddCallback (w, XtNcallback, callback, data);
return w;
}
Widget
#ifdef __STDC__
make_label (Widget parent,
char *name, char *string,
Widget left, Widget top)
#else /* ! __STDC__ */
make_label (parent, name, string, left, top)
Widget parent;
char *name, *string;
Widget left, top;
#endif /* ! __STDC__ */
{
return make_label_1 (parent, name, string, left, top, labelWidgetClass, 0,0);
}
#ifdef MULTIPLE_WIDGETS
struct info_labels *
#ifdef __STDC__
make_info_widget (Widget parent, Widget parent_left)
#else /* ! __STDC__ */
make_info_widget (parent, parent_left)
Widget parent, parent_left;
#endif /* ! __STDC__ */
{
Widget info, left, farleft;
Widget label_col, line_widget;
struct info_labels *labels =
(struct info_labels *) malloc (sizeof (struct info_labels));
Arg av [10];
int ac = 0;
XtSetArg (av[ac], XtNleft, XtChainLeft); ac++;
XtSetArg (av[ac], XtNright, XtChainLeft); ac++;
XtSetArg (av[ac], XtNtop, XtChainTop); ac++;
XtSetArg (av[ac], XtNbottom, XtChainTop); ac++;
if (parent_left) XtSetArg (av[ac], XtNfromHoriz, parent_left), ac++;
info = XtCreateManagedWidget ("info", formWidgetClass, parent, av, ac);
ac = 0;
XtSetArg (av[ac], XtNleft, XtChainLeft); ac++;
XtSetArg (av[ac], XtNright, XtChainLeft); ac++;
XtSetArg (av[ac], XtNtop, XtChainTop); ac++;
XtSetArg (av[ac], XtNbottom, XtChainTop); ac++;
label_col = XtCreateManagedWidget ("labels", formWidgetClass, info, av, ac);
farleft = 0;
#define NEWLABEL(store, name,val) \
{ ac = 0; \
XtSetArg (av[ac], XtNfromHoriz, label_col), ac++; \
XtSetArg (av[ac], XtNorientation, "horizontal"), ac++; \
XtSetArg (av[ac], XtNleft, XtChainLeft); ac++; \
XtSetArg (av[ac], XtNright, XtChainRight); ac++; \
XtSetArg (av[ac], XtNtop, XtChainTop); ac++; \
XtSetArg (av[ac], XtNbottom, XtChainTop); ac++; \
if (farleft) XtSetArg (av[ac], XtNfromVert, farleft), ac++; \
line_widget = XtCreateManagedWidget("line",boxWidgetClass, info, av, ac); \
farleft = make_label (label_col, (name),(val),0, farleft); \
left = 0; \
store = farleft; \
}
#define NEWVALUE(store, name) \
{ left = make_label (line_widget, (name),"",0, 0); \
store = left; \
}
NEWLABEL (labels->keycode [0], "label", "KeyCode:");
NEWVALUE (labels->keycode [1], "keycode");
NEWVALUE (labels->keycode [2], "keycode16");
NEWVALUE (labels->keycode [3], "keycode10");
NEWVALUE (labels->keycode [4], "keycode8");
NEWLABEL (labels->keysym [0], "label", "KeySym:");
NEWVALUE (labels->keysym [1], "keysym");
NEWVALUE (labels->keysym [2], "keysym");
NEWVALUE (labels->keysym [3], "keysym");
NEWVALUE (labels->keysym [4], "keysym");
NEWVALUE (labels->keysym [5], "keysym");
NEWVALUE (labels->keysym [6], "keysym");
NEWVALUE (labels->keysym [7], "keysym");
NEWVALUE (labels->keysym [8], "keysym");
NEWLABEL (labels->ascii [0], "label","ASCII:");
NEWVALUE (labels->ascii [1], "ascii");
NEWVALUE (labels->ascii [2], "ascii16");
NEWVALUE (labels->ascii [3], "ascii10");
NEWVALUE (labels->ascii [4], "ascii8");
NEWLABEL (labels->modifiers [0], "label", "Modifiers:");
NEWVALUE (labels->modifiers [1], "modifiers");
NEWLABEL (labels->autorepeat [0], "label", "AutoRepeat:");
NEWVALUE (labels->autorepeat [1], "autoRepeat");
labels->message = make_label (info, "message", "", info,
labels->autorepeat [0]);
labels->message2 = make_label (info, "message2", "", info,
labels->message);
#undef NEWLABEL
#undef NEWVALUE
labels->info = info;
return labels;
}
#else /* !MULTIPLE_WIDGETS */
struct info_labels *
#ifdef __STDC__
make_info_widget (Widget parent, Widget parent_left)
#else /* ! __STDC__ */
make_info_widget (parent, parent_left)
Widget parent, parent_left;
#endif /* ! __STDC__ */
{
Widget info, left, farleft;
Widget label_col, line_widget;
struct info_labels *labels =
(struct info_labels *) malloc (sizeof (struct info_labels));
Arg av [10];
int ac = 0;
XtSetArg (av[ac], XtNleft, XtChainLeft); ac++;
XtSetArg (av[ac], XtNright, XtChainLeft); ac++;
XtSetArg (av[ac], XtNtop, XtChainTop); ac++;
XtSetArg (av[ac], XtNbottom, XtChainTop); ac++;
if (parent_left) XtSetArg (av[ac], XtNfromHoriz, parent_left), ac++;
info = XtCreateManagedWidget ("info", formWidgetClass, parent, av, ac);
ac = 0;
XtSetArg (av[ac], XtNleft, XtChainLeft); ac++;
XtSetArg (av[ac], XtNright, XtChainLeft); ac++;
XtSetArg (av[ac], XtNtop, XtChainTop); ac++;
XtSetArg (av[ac], XtNbottom, XtChainTop); ac++;
label_col = XtCreateManagedWidget ("labels", formWidgetClass, info, av, ac);
farleft = 0;
#define NEWLABEL(name,val) \
{ ac = 0; \
XtSetArg (av[ac], XtNfromHoriz, label_col), ac++; \
XtSetArg (av[ac], XtNorientation, "horizontal"), ac++; \
XtSetArg (av[ac], XtNleft, XtChainLeft); ac++; \
XtSetArg (av[ac], XtNright, XtChainRight); ac++; \
XtSetArg (av[ac], XtNtop, XtChainTop); ac++; \
XtSetArg (av[ac], XtNbottom, XtChainTop); ac++; \
if (farleft) XtSetArg (av[ac], XtNfromVert, farleft), ac++; \
line_widget = XtCreateManagedWidget("line",boxWidgetClass, info, av, ac); \
farleft = make_label (label_col, (name),(val),0, farleft); \
left = 0; \
}
#define NEWVALUE(store, name) \
{ left = make_label (line_widget, (name),"",0, 0); \
store = left; \
}
NEWLABEL ("keycode", "KeyCode:");
NEWVALUE (labels->keycode, "keycode");
NEWLABEL ("keysym", "KeySym:");
NEWVALUE (labels->keysym, "keysym");
NEWLABEL ("ascii","ASCII:");
NEWVALUE (labels->ascii, "ascii");
NEWLABEL ("modifiers", "Modifiers:");
NEWVALUE (labels->modifiers, "modifiers");
NEWLABEL ("autoRepeat", "AutoRepeat:");
NEWVALUE (labels->autorepeat, "autoRepeat");
NEWLABEL ("message", "");
NEWVALUE (labels->message, "message");
NEWLABEL ("message2", "");
NEWVALUE (labels->message2, "message2");
#undef NEWLABEL
#undef NEWVALUE
labels->info = info;
return labels;
}
#endif /* !MULTIPLE_WIDGETS */
void
#ifdef __STDC__
message (KeyboardWidget widget, char *str)
#else /* ! __STDC__ */
message (widget, str)
KeyboardWidget widget;
char *str;
#endif /* ! __STDC__ */
{
Arg av[10];
int ac = 0;
XtSetArg (av [ac], XtNlabel, str); ac++;
XtSetValues (widget->keyboard.label_widgets->message, av, ac);
message2 (widget, "");
}
void
#ifdef __STDC__
message2 (KeyboardWidget widget, char *str)
#else /* ! __STDC__ */
message2 (widget, str)
KeyboardWidget widget;
char *str;
#endif /* ! __STDC__ */
{
Arg av[10];
int ac = 0;
XtSetArg (av [ac], XtNlabel, str); ac++;
XtSetValues (widget->keyboard.label_widgets->message2, av, ac);
}
static void
#ifdef __STDC__
key_to_ascii (KeyWidget widget,
char *string, char *pretty,
KeySym *keysym,
XFontStruct *font)
#else /* ! __STDC__ */
key_to_ascii (widget, string, pretty, keysym, font)
KeyWidget widget;
char *string, *pretty;
KeySym *keysym;
XFontStruct *font;
#endif /* ! __STDC__ */
{
XEvent event;
char *p = pretty;
int i, size;
key_to_event (widget, &event, 1);
/* We can't really pass in an XComposeStatus structure here, because we call
XLookupString() as a result of mouse-motion as well as keypresses, and if
the user moved the mouse over Multi_key, things would get all confused.
Actually, I've been told that the Xlib that comes with OpenWindows 3 does
compose processing even if you pass 0 as the XComposeStatus argument to
XLookupString(), so no doubt things will be confused on that system
anyway. (Yeah, big surprise...)
*/
size = XLookupString ((XKeyEvent *) &event, string, 50, keysym, 0);
string [size] = 0;
for (i = 0; i < size; i++)
{
unsigned char c = (unsigned char) string [i];
unsigned char hic = 0;
if (c >= 0200)
{
*p++ = 'M';
*p++ = '-';
hic = c;
c -= 0200;
}
if (c < 040)
{
*p++ = '^';
*p++ = c + ('A'-1);
if (! hic) hic = c;
}
else if (c == 0177)
{
*p++ = '^';
*p++ = '?';
if (! hic) hic = c;
}
else
*p++ = c;
if (hic && font && size == 1 &&
hic != '\n' && hic != ' ' &&
hic >= font->min_char_or_byte2 &&
hic <= font->max_char_or_byte2 &&
(!font->per_char ||
font->per_char [hic - font->min_char_or_byte2].width))
{
*p++ = ' ';
*p++ = '(';
*p++ = hic;
*p++ = ')';
}
}
*p = 0;
}
void
#ifdef __STDC__
describe_key (KeyWidget widget)
#else /* ! __STDC__ */
describe_key (widget)
KeyWidget widget;
#endif /* ! __STDC__ */
{
KeyboardWidget keyboard = (KeyboardWidget) widget->core.parent;
struct info_labels *labels = keyboard->keyboard.label_widgets;
Arg av [10];
int i, ac = 0;
KeySym keysym, *keysyms;
int syms_per_code;
XFontStruct *ascii_font = 0;
char buf [255];
char buf2 [255];
char *b;
int ascii = 0;
XtSetArg (av[0], XtNfont, &ascii_font); ac++;
XtGetValues (labels->ascii, av, ac);
if (! ascii_font) exit (-69);
#define SETLABEL(label,string) \
XtSetArg (av[0], XtNlabel, string); \
XtSetValues (label, av, 1);
keysyms = 0;
if (widget->key.keycode)
keysyms = XGetKeyboardMapping (XtDisplay (widget),
widget->key.keycode,
1, &syms_per_code);
if (! keysyms) syms_per_code = 0;
for (; syms_per_code && (!keysyms[syms_per_code-1]); syms_per_code--)
;
key_to_ascii (widget, buf, buf2, &keysym, ascii_font);
ascii = (unsigned char) buf[0];
sprintf (buf, "%s 0x%02X %u 0%02o",
widget->key.key_name,
widget->key.keycode,
widget->key.keycode,
widget->key.keycode);
SETLABEL (labels->keycode, buf);
b = buf;
*b = 0;
for (i = 0; i < syms_per_code; i++)
{
char yabuf [255];
char *b2;
int j;
if (! keysyms [i])
b2 = "NoSymbol";
else
{
b2 = XKeysymToString (keysyms [i]);
#if defined(sun) || defined(__sun)
/* What is *up* with that damn OpenWindows libX, anyway??
It knows these, and then after a while forgets about them.
The loaded XKeysymDB must be getting corrupted. */
if (b2) ;
else if (keysyms [i] == 0x1005FF10) b2 = "SunXK_F36";
else if (keysyms [i] == 0x1005FF11) b2 = "SunXK_F37";
else if (keysyms [i] == 0x1005FF75) b2 = "SunXK_Cut";
else if (keysyms [i] == 0x1005FF70) b2 = "SunXK_Props";
else if (keysyms [i] == 0x1005FF71) b2 = "SunXK_Front";
else if (keysyms [i] == 0x1005FF72) b2 = "SunXK_Copy";
else if (keysyms [i] == 0x1005FF73) b2 = "SunXK_Open";
else if (keysyms [i] == 0x1005FF74) b2 = "SunXK_Paste";
else
#endif
if (! b2)
{
sprintf (yabuf, "unknown_keysym_0x%02X", (int) keysyms [i]);
b2 = yabuf;
}
}
j = strlen (b2);
if (b != buf) {
b [0] = ' '; b++;
b [0] = ' '; b++;
}
strncpy (b, b2, j+1);
b += j;
}
SETLABEL (labels->keysym, buf);
if (ascii)
sprintf (buf, "%s 0x%02X %u 0%02o", buf2, ascii, ascii, ascii);
else
*buf = 0;
SETLABEL (labels->ascii, buf);
sprintf (buf, "%s%s%s%s%s%s%s%s",
((widget->key.modifier_bits & ShiftMask) ? "Shift " : ""),
((widget->key.modifier_bits & LockMask) ? "Lock " : ""),
((widget->key.modifier_bits & ControlMask) ? "Control " : ""),
((widget->key.modifier_bits & Mod1Mask) ? "Mod1 " : ""),
((widget->key.modifier_bits & Mod2Mask) ? "Mod2 " : ""),
((widget->key.modifier_bits & Mod3Mask) ? "Mod3 " : ""),
((widget->key.modifier_bits & Mod4Mask) ? "Mod4 " : ""),
((widget->key.modifier_bits & Mod5Mask) ? "Mod5 " : ""));
SETLABEL (labels->modifiers, buf);
SETLABEL (labels->autorepeat, (widget->key.auto_repeat_p ? "yes" : "no"));
#undef SETLABEL
if (keysyms) XFree ((char *) keysyms);
}