/efte-1.1/src/con_i18n.cpp
C++ | 413 lines | 249 code | 47 blank | 117 comment | 107 complexity | a086a1b5d47606482dc6c3a70b8ab217 MD5 | raw file
Possible License(s): GPL-2.0
- /*
- * con_i18n.cpp
- *
- * Copyright (c) 2008, eFTE SF Group (see AUTHORS file)
- * Copyright (c) 1998, Zdenek Kabelac
- *
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the README file.
- *
- * I18N support by kabi@fi.muni.cz
- *
- * written as plain 'C' module and might be used
- * in other programs to implement I18N support
- */
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/keysym.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "con_i18n.h"
- #define KEYMASK 0xff
- #define KEYBYTEMAX 0xf00
- #ifdef USE_HARD_REMAP
- /*
- * This part is used when your Xserver doesn't work well with XKB extension
- */
- /* Keyboard definition file - currently only Czech national keyboard
- * write your own keyboard for your language
- * And remember - this is supposed to be used only if your Xserver
- * is not supporting keyboard extension
- */
- #include "con_ikcz.h"
- /*
- * Quite a complex function to convert normal keys
- * to dead-keys and remapped keys
- */
- static int i18n_key_analyze(XKeyEvent * keyEvent, KeySym * key, /*FOLD00*/
- char *keyName, int nbytes) {
- static long prev_state = 0, local_switch = 0,
- keypos = 0, last_keypos = 0, remap = 0;
- long i;
- struct keyboardRec *kbdActual;
- /* Find the state of keyboard
- * Check for different ISO group or modifier 5
- * So to activate remaping, you need to press at least
- * ScrollLock which is usually mapped as modifier 5
- */
- i = ((keyEvent->state | local_switch) & 0xFFA0);
- if (i != prev_state) {
- /* reset table position */
- last_keypos = keypos = 0;
- prev_state = i;
- }
- if (keyEvent->type == KeyPress) {
- if (i && ((*key == XK_Pause) || (*key == XK_F21))) {
- remap = !remap;
- return 0;
- } else if (*key == XK_F23) {
- local_switch ^= (1UL << 12);
- return 0;
- }
- }
- /*
- * Check for already remapped ISO8859-X keys
- * this should not normaly happen :-)
- * as we need to use this hack
- */
- if ((*key > KEYMASK) && (*key < KEYBYTEMAX) || (*key > 0xffffff00)) {
- *key &= KEYMASK;
- keyName[0] = (char) * key;
- return 1;
- }
- /* Select keyboard map */
- if (!i)
- kbdActual = nationalKey[0];
- else if (!remap)
- kbdActual = nationalKey[1];
- else
- kbdActual = nationalKey[2];
- if (keyEvent->type == KeyPress) {
- long i = last_keypos;
- /*
- * Search for DeadKey -> do loop over all tables.
- *
- * Note: We can define ONE DeadKey and use
- * it for several tables sequentially
- */
- for (;;) {
- i++;
- if ((kbdActual[0].tab == NULL) || kbdActual[i].tab == NULL) {
- i = 0;
- if (kbdActual[i].tab == NULL) {
- /* Looks like empty table -> IGNORE */
- keypos = i;
- return nbytes;
- }
- }
- if (i == last_keypos)
- break;
- if (kbdActual[i].deadkey == *key) {
- keypos = kbdActual[i].next;
- /* Found DeadKey -> delete it
- * and mark actual position for next search */
- last_keypos = i;
- keyName[0] = *key = 0;
- return 0;
- }
- }
- } else if (keypos)
- return 0; /* ignore key release */
- /* Now we know it is not a DeadKey and we
- * are in selected remaping keyboard table */
- /* printf("** key:%5d\tstatus:0x%x\n", *key, prev_state); */
- if (*key < KEYBYTEMAX) {
- /*
- * this is selected constant and will change when
- * this editor will be able to write in japan :-)
- */
- int i = 0;
- /* remaping only real keys */
- while (kbdActual[keypos].tab[i].key_english != 0) {
- if (*key == kbdActual[keypos].tab[i].key_english) {
- *key = kbdActual[keypos].tab[i].key_remap;
- break;
- }
- i++;
- }
- last_keypos = keypos = kbdActual[keypos].next;
- /* printf("** remap: %3d %3d\n", keypos, *key); */
- keyName[0] = *key && KEYMASK;
- return 1;
- }
- return 0;
- }
- /*FOLD00*/
- #else
- /*********************************************
- * *
- * Standart methods for reading Keyboard *
- * *
- *********************************************/
- /* ISO-8859-2 key-change
- * All these functions are for keyboard reading.
- * Correct displaing of this text is another thing,
- * but as I only need ISO-8859 encoding support,
- * I don't care about this (for now).
- */
- static int i18n_key_analyze(XKeyEvent * /*keyEvent*/, KeySym * key, /*FOLD00*/
- char *keyName, int nbytes) {
- KeySym t = (unsigned char) keyName[0];
- /*
- * ISO-8859-2 is using some characters from 8859-1 and
- * rest of them is located between 0x100 - 0x200 in 'X' so
- * with ISO-8859-2 font we'll remap them down bellow < 0x100
- * This is mostly true for all Latin-X alphas, just
- * special font to display them correctly is needed.
- * This jobs does Xserver - and keysymbol is returned
- * in the 1st. byte of keyName string.
- */
- if ((nbytes == 1) && *key < KEYBYTEMAX)
- *key = t;
- #ifdef USE_HACK_FOR_BAD_XSERVER
- /*
- * this is really hack - but some Xservers are somewhat
- * strange, so we remap character manually
- */
- else if (!nbytes && (*key > KEYMASK) && (*key < KEYBYTEMAX)) {
- *key &= KEYMASK;
- keyName[0] = *key & KEYMASK;
- nbytes = 1;
- }
- #endif
- return nbytes;
- }
- /*FOLD00*/
- #endif
- /*
- * Initialize I18N functions - took me hours to
- * figure out how this works even though it was
- * cut & pasted from 'xterm' sources, but as 'xterm'
- * is using Xt Toolkit some things have to be made
- * different
- */
- i18n_context_t* i18n_open(Display * display, Window win, unsigned long *mask) { /*FOLD00*/
- *mask = 0;
- #if XlibSpecificationRelease >= 6
- char *s, tmp[256];
- int found = False;
- i18n_context_t* ctx = (i18n_context_t*) malloc(sizeof(i18n_context_t));
- memset(ctx, 0, sizeof(i18n_context_t));
- /* Locale setting taken from XtSetLanguageProc */
- if (!(s = setlocale(LC_ALL, "")))
- fprintf(stderr, "I18N warning: Locale not supported by C library, "
- "locale unchanged!\n");
- if (!XSupportsLocale()) {
- fprintf(stderr, "I18N warning: Locale not supported by Xlib, "
- "locale set to C!\n");
- s = setlocale(LC_ALL, "C");
- }
- if (!XSetLocaleModifiers(""))
- fprintf(stderr, "I18N warning: X locale modifiers not supported, "
- "using default\n");
- ctx->xim = XOpenIM(display, NULL, NULL, NULL);
- if (ctx->xim == NULL) {
- // there are languages without Input Methods ????
- fprintf(stderr, "I18N warning: Input method not specified\n");
- i18n_destroy(&ctx);
- return NULL;
- }
- if (XGetIMValues(ctx->xim, XNQueryInputStyle, &ctx->xim_styles, NULL)
- || ctx->xim_styles == NULL) {
- fprintf(stderr, "I18N error: Input method doesn't support any style\n");
- i18n_destroy(&ctx);
- return NULL;
- }
- /*
- * This is some kind of debugging message to inform user
- * that something is wrong with his system
- */
- if (s != NULL && (strstr(s, XLocaleOfIM(ctx->xim)) == NULL))
- fprintf(stderr, "I18N warning: System locale: \"%s\" differs from "
- "IM locale: \"%s\"...\n", s, XLocaleOfIM(ctx->xim));
- /*
- * This part is cut&paste from other sources
- * There is no reason to do it this way, because
- * the only input style currently supported is Root
- * but for the future extension I'll leave it here
- */
- strcpy(tmp, XIM_INPUT_STYLE);
- for (s = tmp; s && !found;) {
- char *ns, *end;
- int i;
- while ((*s != 0) && isspace(*s))
- s++;
- if (*s == 0)
- break;
- if ((ns = end = strchr(s, ',')) != 0)
- ns++;
- else
- end = s + strlen(s);
- while (isspace(*end))
- end--;
- *end = '\0';
- if (!strcmp(s, "OverTheSpot"))
- ctx->input_style = (XIMPreeditPosition | XIMStatusArea);
- else if (!strcmp(s, "OffTheSpot"))
- ctx->input_style = (XIMPreeditArea | XIMStatusArea);
- else if (!strcmp(s, "Root"))
- ctx->input_style = (XIMPreeditNothing | XIMStatusNothing);
- for (i = 0; (unsigned short) i < ctx->xim_styles->count_styles; i++)
- if (ctx->input_style == ctx->xim_styles->supported_styles[i])
- //if (ctx->xim_styles->supported_styles[i] & (XIMPreeditNothing | XIMPreeditNone) &&
- // ctx->xim_styles->supported_styles[i] & (XIMStatusNothing | XIMStatusNone))
- {
- found = True;
- /* do not modify this!
- * unless consulted with kabi@users.sf.net
- */
- //ctx->input_style = ctx->xim_styles->supported_styles[i];
- break;
- }
- s = ns;
- }
- XFree(ctx->xim_styles);
- if (!found) {
- fprintf(stderr, "I18N error: Input method doesn't support my "
- "preedit type\n");
- i18n_destroy(&ctx);
- return NULL;
- }
- /* This program only understand the Root preedit_style yet */
- if (ctx->input_style != (XIMPreeditNothing | XIMStatusNothing)) {
- fprintf(stderr, "I18N error: This program only supports the "
- "'Root' preedit type\n");
- i18n_destroy(&ctx);
- return NULL;
- }
- ctx->xic = XCreateIC(ctx->xim, XNInputStyle, ctx->input_style,
- XNClientWindow, win,
- XNFocusWindow, win,
- NULL);
- if (ctx->xic == NULL) {
- fprintf(stderr, "I18N error: Failed to create input context\n");
- i18n_destroy(&ctx);
- } else if (XGetICValues(ctx->xic, XNFilterEvents, mask, NULL))
- fprintf(stderr, "I18N error: Can't get Event Mask\n");
- return ctx;
- #else
- return NULL;
- #endif
- }
- /*FOLD00*/
- void i18n_destroy(i18n_context_t** ctx) {
- if (ctx && *ctx) {
- if ((*ctx)->xic)
- XDestroyIC((*ctx)->xic);
- if ((*ctx)->xim)
- XCloseIM((*ctx)->xim);
- free(*ctx);
- *ctx = NULL;
- }
- }
- void i18n_focus_in(i18n_context_t* ctx) { /*FOLD00*/
- #if XlibSpecificationRelease >= 6
- if (ctx->xic != NULL)
- XSetICFocus(ctx->xic);
- #endif
- }
- /*FOLD00*/
- void i18n_focus_out(i18n_context_t* ctx) { /*FOLD00*/
- #if XlibSpecificationRelease >= 6
- if (ctx->xic != NULL)
- XUnsetICFocus(ctx->xic);
- #endif
- }
- /*FOLD00*/
- /*
- * Lookup correct keysymbol from keymap event
- */
- int i18n_lookup_sym(XKeyEvent * keyEvent, char *keyName, int keySize, /*FOLD00*/
- KeySym * key, XIC xic) {
- static int showKeys = 0;
- int nbytes = 0;
- #if XlibSpecificationRelease >= 6
- if (xic != NULL) {
- if (keyEvent->type == KeyPress) {
- Status status_return;
- /* No KeyRelease events here ! */
- #if 1
- nbytes = XmbLookupString(xic, keyEvent, keyName, keySize,
- key, &status_return);
- #else
- wchar_t wk;
- nbytes = XwcLookupString(xic, keyEvent, &wk, 1, key, &status_return);
- printf("code=%0X\n", wk);
- keySize = 1;
- keyName[0] = wk & 0xFF;
- #endif
- }
- } else
- #endif
- do {
- static XComposeStatus compose_status = { NULL, 0 };
- nbytes = XLookupString(keyEvent, keyName, keySize,
- key, &compose_status);
- } while (0);
- if (showKeys) {
- fprintf(stderr, "Key: 0x%04lx '%s'\tKeyEventState:0x%x\t",
- *key, XKeysymToString(*key), keyEvent->state);
- if (nbytes && isprint(keyName[0])) {
- keyName[nbytes] = 0;
- fprintf(stderr, "String:'%s' Size:%2d ", keyName, nbytes);
- }
- fputs("\n", stderr);
- }
- if (((*key == XK_F1) || (*key == XK_F11))
- && ((keyEvent->state & (ShiftMask | ControlMask))
- == (ShiftMask | ControlMask))
- && (keyEvent->type == KeyPress))
- showKeys = !showKeys;
- return i18n_key_analyze(keyEvent, key, keyName, nbytes);
- }
- /*FOLD00*/