#include "tkInt.h"
void
Tk_SetCaretPos(tkwin, x, y, height)
Tk_Window tkwin;
int
x;
int
y;
int
height;
{
TkCaret *caretPtr = &(((TkWindow *) tkwin)->dispPtr->caret);
caretPtr->winPtr = ((TkWindow *) tkwin);
caretPtr->x = x;
caretPtr->y = y;
caretPtr->height = height;
}
char
*
TkpGetString(winPtr, eventPtr, dsPtr)
TkWindow *winPtr;
XEvent *eventPtr;
Tcl_DString *dsPtr;
{
int
len;
Tcl_DString buf;
Status status;
#ifdef TK_USE_INPUT_METHODS
TkDisplay *dispPtr = winPtr->dispPtr;
#endif
#ifdef TK_USE_INPUT_METHODS
if
((dispPtr->flags & TK_DISPLAY_USE_IM)
&& (winPtr->inputContext != NULL)
&& (eventPtr->type == KeyPress)) {
#if TK_XIM_SPOT
XVaNestedList preedit_attr;
XPoint spot;
#endif
#ifdef X_HAVE_UTF8_STRING
Tcl_DStringInit(dsPtr);
Tcl_DStringSetLength(dsPtr, TCL_DSTRING_STATIC_SIZE-1);
len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey,
Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr),
(KeySym *) NULL, &status);
#else
Tcl_DStringInit(&buf);
Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1);
len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey,
Tcl_DStringValue(&buf), Tcl_DStringLength(&buf),
(KeySym *) NULL, &status);
#endif
if
(status == XBufferOverflow) {
#ifdef X_HAVE_UTF8_STRING
Tcl_DStringSetLength(dsPtr, len);
len = Xutf8LookupString(winPtr->inputContext, &eventPtr->xkey,
Tcl_DStringValue(dsPtr), len, (KeySym *) NULL, &status);
#else
Tcl_DStringSetLength(&buf, len);
len = XmbLookupString(winPtr->inputContext, &eventPtr->xkey,
Tcl_DStringValue(&buf), len, (KeySym *) NULL, &status);
#endif
}
if
((status != XLookupChars) && (status != XLookupBoth)) {
len = 0;
}
#if TK_XIM_SPOT
if
(dispPtr->flags & TK_DISPLAY_XIM_SPOT) {
spot.x = dispPtr->caret.x;
spot.y = dispPtr->caret.y + dispPtr->caret.height;
preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
XSetICValues(winPtr->inputContext,
XNPreeditAttributes, preedit_attr, NULL);
XFree(preedit_attr);
}
#endif
#ifdef X_HAVE_UTF8_STRING
Tcl_DStringSetLength(dsPtr, len);
return
Tcl_DStringValue(dsPtr);
#endif
}
else
{
Tcl_DStringInit(&buf);
Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1);
len = XLookupString(&eventPtr->xkey, Tcl_DStringValue(&buf),
Tcl_DStringLength(&buf), (KeySym *) NULL,
(XComposeStatus *) NULL);
}
#else /* TK_USE_INPUT_METHODS */
Tcl_DStringInit(&buf);
Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1);
len = XLookupString(&eventPtr->xkey, Tcl_DStringValue(&buf),
Tcl_DStringLength(&buf), (KeySym *) NULL,
(XComposeStatus *) NULL);
#endif /* TK_USE_INPUT_METHODS */
Tcl_DStringSetLength(&buf, len);
Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buf), len, dsPtr);
Tcl_DStringFree(&buf);
return
Tcl_DStringValue(dsPtr);
}
void
TkpSetKeycodeAndState(tkwin, keySym, eventPtr)
Tk_Window tkwin;
KeySym keySym;
XEvent *eventPtr;
{
Display *display;
int
state;
KeyCode keycode;
display = Tk_Display(tkwin);
if
(keySym == NoSymbol) {
keycode = 0;
}
else
{
keycode = XKeysymToKeycode(display, keySym);
}
if
(keycode != 0) {
for
(state = 0; state < 4; state++) {
if
(XKeycodeToKeysym(display, keycode, state) == keySym) {
if
(state & 1) {
eventPtr->xkey.state |= ShiftMask;
}
if
(state & 2) {
TkDisplay *dispPtr;
dispPtr = ((TkWindow *) tkwin)->dispPtr;
eventPtr->xkey.state |= dispPtr->modeModMask;
}
break
;
}
}
}
eventPtr->xkey.keycode = keycode;
}
KeySym
TkpGetKeySym(dispPtr, eventPtr)
TkDisplay *dispPtr;
XEvent *eventPtr;
{
KeySym sym;
int
index;
if
(dispPtr->bindInfoStale) {
TkpInitKeymapInfo(dispPtr);
}
index = 0;
if
(eventPtr->xkey.state & dispPtr->modeModMask) {
index = 2;
}
if
((eventPtr->xkey.state & ShiftMask)
|| ((dispPtr->lockUsage != LU_IGNORE)
&& (eventPtr->xkey.state & LockMask))) {
index += 1;
}
sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index);
if
((index & 1) && !(eventPtr->xkey.state & ShiftMask)
&& (dispPtr->lockUsage == LU_CAPS)) {
if
(!(((sym >= XK_A) && (sym <= XK_Z))
|| ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
|| ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) {
index &= ~1;
sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
index);
}
}
if
((index & 1) && (sym == NoSymbol)) {
sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode,
index & ~1);
}
return
sym;
}
void
TkpInitKeymapInfo(dispPtr)
TkDisplay *dispPtr;
{
XModifierKeymap *modMapPtr;
KeyCode *codePtr;
KeySym keysym;
int
count, i, j, max, arraySize;
#define KEYCODE_ARRAY_SIZE 20
dispPtr->bindInfoStale = 0;
modMapPtr = XGetModifierMapping(dispPtr->display);
dispPtr->lockUsage = LU_IGNORE;
codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex;
for
(count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) {
if
(*codePtr == 0) {
continue
;
}
keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
if
(keysym == XK_Shift_Lock) {
dispPtr->lockUsage = LU_SHIFT;
break
;
}
if
(keysym == XK_Caps_Lock) {
dispPtr->lockUsage = LU_CAPS;
break
;
}
}
dispPtr->modeModMask = 0;
dispPtr->metaModMask = 0;
dispPtr->altModMask = 0;
codePtr = modMapPtr->modifiermap;
max = 8*modMapPtr->max_keypermod;
for
(i = 0; i < max; i++, codePtr++) {
if
(*codePtr == 0) {
continue
;
}
keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0);
if
(keysym == XK_Mode_switch) {
dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
}
if
((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) {
dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
}
if
((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) {
dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod);
}
}
if
(dispPtr->modKeyCodes != NULL) {
ckfree((
char
*) dispPtr->modKeyCodes);
}
dispPtr->numModKeyCodes = 0;
arraySize = KEYCODE_ARRAY_SIZE;
dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned)
(KEYCODE_ARRAY_SIZE *
sizeof
(KeyCode)));
for
(i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) {
if
(*codePtr == 0) {
continue
;
}
for
(j = 0; j < dispPtr->numModKeyCodes; j++) {
if
(dispPtr->modKeyCodes[j] == *codePtr) {
goto
nextModCode;
}
}
if
(dispPtr->numModKeyCodes >= arraySize) {
KeyCode *
new
;
arraySize *= 2;
new
= (KeyCode *) ckalloc((unsigned)
(arraySize *
sizeof
(KeyCode)));
memcpy
((
VOID
*)
new
, (
VOID
*) dispPtr->modKeyCodes,
(dispPtr->numModKeyCodes *
sizeof
(KeyCode)));
ckfree((
char
*) dispPtr->modKeyCodes);
dispPtr->modKeyCodes =
new
;
}
dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr;
dispPtr->numModKeyCodes++;
nextModCode:
continue
;
}
XFreeModifiermap(modMapPtr);
}