aboutsummaryrefslogtreecommitdiff
path: root/libX11/modules/im/ximcp/imLcPrs.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-05-19 10:32:31 +0000
committermarha <marha@users.sourceforge.net>2010-05-19 10:32:31 +0000
commitb16c0295c9f95426980d567e93ae00c52545b3fa (patch)
treed25e3271be998e47e0ff07048d8297001409ea5f /libX11/modules/im/ximcp/imLcPrs.c
parentc1b8f2475ebdeb148f4a27b78ed3cb24c68a92c4 (diff)
parent153f5cafa19da4e4c0cf21e9c909958359ed8ebd (diff)
downloadvcxsrv-b16c0295c9f95426980d567e93ae00c52545b3fa.tar.gz
vcxsrv-b16c0295c9f95426980d567e93ae00c52545b3fa.tar.bz2
vcxsrv-b16c0295c9f95426980d567e93ae00c52545b3fa.zip
svn merge "^/branches/released" .
Diffstat (limited to 'libX11/modules/im/ximcp/imLcPrs.c')
-rw-r--r--libX11/modules/im/ximcp/imLcPrs.c1373
1 files changed, 684 insertions, 689 deletions
diff --git a/libX11/modules/im/ximcp/imLcPrs.c b/libX11/modules/im/ximcp/imLcPrs.c
index c0801722a..f6c42daa8 100644
--- a/libX11/modules/im/ximcp/imLcPrs.c
+++ b/libX11/modules/im/ximcp/imLcPrs.c
@@ -1,689 +1,684 @@
-/******************************************************************
-
- Copyright 1992 by Oki Technosystems Laboratory, Inc.
- Copyright 1992 by Fuji Xerox Co., Ltd.
-
-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, and that the name of Oki Technosystems
-Laboratory and Fuji Xerox not be used in advertising or publicity
-pertaining to distribution of the software without specific, written
-prior permission.
-Oki Technosystems Laboratory and Fuji Xerox make no representations
-about the suitability of this software for any purpose. It is provided
-"as is" without express or implied warranty.
-
-OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX DISCLAIM ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OKI TECHNOSYSTEMS
-LABORATORY AND FUJI XEROX BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
-OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
-OR PERFORMANCE OF THIS SOFTWARE.
-
- Author: Yasuhiro Kawai Oki Technosystems Laboratory
- Author: Kazunori Nishihara Fuji Xerox
-
-******************************************************************/
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <X11/Xlib.h>
-#include <X11/Xmd.h>
-#include <X11/Xos.h>
-#include "Xlibint.h"
-#include "Xlcint.h"
-#include "Ximint.h"
-#include <sys/stat.h>
-#include <stdio.h>
-
-#define XLC_BUFSIZE 256
-
-extern void xlocaledir(
- char *buf,
- int buf_len
-);
-
-extern int _Xmbstowcs(
- wchar_t *wstr,
- char *str,
- int len
-);
-
-extern int _Xmbstoutf8(
- char *ustr,
- const char *str,
- int len
-);
-
-/*
- * Parsing File Format:
- *
- * FILE ::= { [PRODUCTION] [COMMENT] "\n"}
- * PRODUCTION ::= LHS ":" RHS [ COMMENT ]
- * COMMENT ::= "#" {<any character except null or newline>}
- * LHS ::= EVENT { EVENT }
- * EVENT ::= [MODIFIER_LIST] "<" keysym ">"
- * MODIFIER_LIST ::= ("!" {MODIFIER} ) | "None"
- * MODIFIER ::= ["~"] modifier_name
- * RHS ::= ( STRING | keysym | STRING keysym )
- * STRING ::= '"' { CHAR } '"'
- * CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR
- * GRAPHIC_CHAR ::= locale (codeset) dependent code
- * ESCAPED_CHAR ::= ('\\' | '\"' | OCTAL | HEX )
- * OCTAL ::= '\' OCTAL_CHAR [OCTAL_CHAR [OCTAL_CHAR]]
- * OCTAL_CHAR ::= (0|1|2|3|4|5|6|7)
- * HEX ::= '\' (x|X) HEX_CHAR [HEX_CHAR]]
- * HEX_CHAR ::= (0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|a|b|c|d|e|f)
- *
- */
-
-static int
-nextch(
- FILE *fp,
- int *lastch)
-{
- int c;
-
- if (*lastch != 0) {
- c = *lastch;
- *lastch = 0;
- } else {
- c = getc(fp);
- if (c == '\\') {
- c = getc(fp);
- if (c == '\n') {
- c = getc(fp);
- } else {
- ungetc(c, fp);
- c = '\\';
- }
- }
- }
- return(c);
-}
-
-static void
-putbackch(
- int c,
- int *lastch)
-{
- *lastch = c;
-}
-
-#define ENDOFFILE 0
-#define ENDOFLINE 1
-#define COLON 2
-#define LESS 3
-#define GREATER 4
-#define EXCLAM 5
-#define TILDE 6
-#define STRING 7
-#define KEY 8
-#define ERROR 9
-
-#ifndef isalnum
-#define isalnum(c) \
- (('0' <= (c) && (c) <= '9') || \
- ('A' <= (c) && (c) <= 'Z') || \
- ('a' <= (c) && (c) <= 'z'))
-#endif
-
-static int
-nexttoken(
- FILE *fp,
- char *tokenbuf,
- int *lastch)
-{
- int c;
- int token;
- char *p;
- int i, j;
-
- while ((c = nextch(fp, lastch)) == ' ' || c == '\t') {
- }
- switch (c) {
- case EOF:
- token = ENDOFFILE;
- break;
- case '\n':
- token = ENDOFLINE;
- break;
- case '<':
- token = LESS;
- break;
- case '>':
- token = GREATER;
- break;
- case ':':
- token = COLON;
- break;
- case '!':
- token = EXCLAM;
- break;
- case '~':
- token = TILDE;
- break;
- case '"':
- p = tokenbuf;
- while ((c = nextch(fp, lastch)) != '"') {
- if (c == '\n' || c == EOF) {
- putbackch(c, lastch);
- token = ERROR;
- goto string_error;
- } else if (c == '\\') {
- c = nextch(fp, lastch);
- switch (c) {
- case '\\':
- case '"':
- *p++ = c;
- break;
- case 'n':
- *p++ = '\n';
- break;
- case 'r':
- *p++ = '\r';
- break;
- case 't':
- *p++ = '\t';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- i = c - '0';
- c = nextch(fp, lastch);
- for (j = 0; j < 2 && c >= '0' && c <= '7'; j++) {
- i <<= 3;
- i += c - '0';
- c = nextch(fp, lastch);
- }
- putbackch(c, lastch);
- *p++ = (char)i;
- break;
- case 'X':
- case 'x':
- i = 0;
- for (j = 0; j < 2; j++) {
- c = nextch(fp, lastch);
- i <<= 4;
- if (c >= '0' && c <= '9') {
- i += c - '0';
- } else if (c >= 'A' && c <= 'F') {
- i += c - 'A' + 10;
- } else if (c >= 'a' && c <= 'f') {
- i += c - 'a' + 10;
- } else {
- putbackch(c, lastch);
- i >>= 4;
- break;
- }
- }
- if (j == 0) {
- token = ERROR;
- goto string_error;
- }
- *p++ = (char)i;
- break;
- case EOF:
- putbackch(c, lastch);
- token = ERROR;
- goto string_error;
- default:
- *p++ = c;
- break;
- }
- } else {
- *p++ = c;
- }
- }
- *p = '\0';
- token = STRING;
- break;
- case '#':
- while ((c = nextch(fp, lastch)) != '\n' && c != EOF) {
- }
- if (c == '\n') {
- token = ENDOFLINE;
- } else {
- token = ENDOFFILE;
- }
- break;
- default:
- if (isalnum(c) || c == '_' || c == '-') {
- p = tokenbuf;
- *p++ = c;
- c = nextch(fp, lastch);
- while (isalnum(c) || c == '_' || c == '-') {
- *p++ = c;
- c = nextch(fp, lastch);
- }
- *p = '\0';
- putbackch(c, lastch);
- token = KEY;
- } else {
- token = ERROR;
- }
- break;
- }
-string_error:
- return(token);
-}
-
-static long
-modmask(
- char *name)
-{
- struct _modtbl {
- const char name[6];
- long mask;
- };
-
- static const struct _modtbl tbl[] = {
- { "Ctrl", ControlMask },
- { "Lock", LockMask },
- { "Caps", LockMask },
- { "Shift", ShiftMask },
- { "Alt", Mod1Mask },
- { "Meta", Mod1Mask }};
-
- int i, num_entries = sizeof (tbl) / sizeof (tbl[0]);
-
- for (i = 0; i < num_entries; i++)
- if (!strcmp (name, tbl[i].name))
- return tbl[i].mask;
-
- return 0;
-}
-
-static char*
-TransFileName(Xim im, char *name)
-{
- char *home = NULL, *lcCompose = NULL;
- char dir[XLC_BUFSIZE];
- char *i = name, *ret, *j;
- int l = 0;
-
- while (*i) {
- if (*i == '%') {
- i++;
- switch (*i) {
- case '%':
- l++;
- break;
- case 'H':
- home = getenv("HOME");
- if (home)
- l += strlen(home);
- break;
- case 'L':
- lcCompose = _XlcFileName(im->core.lcd, COMPOSE_FILE);
- if (lcCompose)
- l += strlen(lcCompose);
- break;
- case 'S':
- xlocaledir(dir, XLC_BUFSIZE);
- l += strlen(dir);
- break;
- }
- } else {
- l++;
- }
- i++;
- }
-
- j = ret = Xmalloc(l+1);
- if (ret == NULL)
- return ret;
- i = name;
- while (*i) {
- if (*i == '%') {
- i++;
- switch (*i) {
- case '%':
- *j++ = '%';
- break;
- case 'H':
- if (home) {
- strcpy(j, home);
- j += strlen(home);
- }
- break;
- case 'L':
- if (lcCompose) {
- strcpy(j, lcCompose);
- j += strlen(lcCompose);
- Xfree(lcCompose);
- }
- break;
- case 'S':
- strcpy(j, dir);
- j += strlen(dir);
- break;
- }
- i++;
- } else {
- *j++ = *i++;
- }
- }
- *j = '\0';
- return ret;
-}
-
-#ifndef MB_LEN_MAX
-#define MB_LEN_MAX 6
-#endif
-
-static int
-get_mb_string (Xim im, char *buf, KeySym ks)
-{
- XPointer from, to;
- int from_len, to_len, len;
- XPointer args[1];
- XlcCharSet charset;
- char local_buf[MB_LEN_MAX];
- unsigned int ucs;
- ucs = KeySymToUcs4(ks);
-
- from = (XPointer) &ucs;
- to = (XPointer) local_buf;
- from_len = 1;
- to_len = MB_LEN_MAX;
- args[0] = (XPointer) &charset;
- if (_XlcConvert(im->private.local.ucstoc_conv,
- &from, &from_len, &to, &to_len, args, 1 ) != 0) {
- return 0;
- }
-
- from = (XPointer) local_buf;
- to = (XPointer) buf;
- from_len = MB_LEN_MAX - to_len;
- to_len = MB_LEN_MAX + 1;
- args[0] = (XPointer) charset;
- if (_XlcConvert(im->private.local.cstomb_conv,
- &from, &from_len, &to, &to_len, args, 1 ) != 0) {
- return 0;
- }
- len = MB_LEN_MAX + 1 - to_len;
- buf[len] = '\0';
- return len;
-}
-
-#define AllMask (ShiftMask | LockMask | ControlMask | Mod1Mask)
-#define LOCAL_WC_BUFSIZE 128
-#define LOCAL_UTF8_BUFSIZE 256
-#define SEQUENCE_MAX 10
-
-static int
-parseline(
- FILE *fp,
- Xim im,
- char* tokenbuf)
-{
- int token;
- DTModifier modifier_mask;
- DTModifier modifier;
- DTModifier tmp;
- KeySym keysym = NoSymbol;
- DTIndex *top = &im->private.local.top;
- DefTreeBase *b = &im->private.local.base;
- DTIndex t;
- DefTree *p = NULL;
- Bool exclam, tilde;
- KeySym rhs_keysym = 0;
- char *rhs_string_mb;
- int l;
- int lastch = 0;
- char local_mb_buf[MB_LEN_MAX+1];
- wchar_t local_wc_buf[LOCAL_WC_BUFSIZE], *rhs_string_wc;
- char local_utf8_buf[LOCAL_UTF8_BUFSIZE], *rhs_string_utf8;
-
- struct DefBuffer {
- DTModifier modifier_mask;
- DTModifier modifier;
- KeySym keysym;
- };
-
- struct DefBuffer buf[SEQUENCE_MAX];
- int i, n;
-
- do {
- token = nexttoken(fp, tokenbuf, &lastch);
- } while (token == ENDOFLINE);
-
- if (token == ENDOFFILE) {
- return(-1);
- }
-
- n = 0;
- do {
- if ((token == KEY) && (strcmp("include", tokenbuf) == 0)) {
- char *filename;
- FILE *infp;
- token = nexttoken(fp, tokenbuf, &lastch);
- if (token != KEY && token != STRING)
- goto error;
- if ((filename = TransFileName(im, tokenbuf)) == NULL)
- goto error;
- infp = _XFopenFile(filename, "r");
- Xfree(filename);
- if (infp == NULL)
- goto error;
- _XimParseStringFile(infp, im);
- fclose(infp);
- return (0);
- } else if ((token == KEY) && (strcmp("None", tokenbuf) == 0)) {
- modifier = 0;
- modifier_mask = AllMask;
- token = nexttoken(fp, tokenbuf, &lastch);
- } else {
- modifier_mask = modifier = 0;
- exclam = False;
- if (token == EXCLAM) {
- exclam = True;
- token = nexttoken(fp, tokenbuf, &lastch);
- }
- while (token == TILDE || token == KEY) {
- tilde = False;
- if (token == TILDE) {
- tilde = True;
- token = nexttoken(fp, tokenbuf, &lastch);
- if (token != KEY)
- goto error;
- }
- tmp = modmask(tokenbuf);
- if (!tmp) {
- goto error;
- }
- modifier_mask |= tmp;
- if (tilde) {
- modifier &= ~tmp;
- } else {
- modifier |= tmp;
- }
- token = nexttoken(fp, tokenbuf, &lastch);
- }
- if (exclam) {
- modifier_mask = AllMask;
- }
- }
-
- if (token != LESS) {
- goto error;
- }
-
- token = nexttoken(fp, tokenbuf, &lastch);
- if (token != KEY) {
- goto error;
- }
-
- token = nexttoken(fp, tokenbuf, &lastch);
- if (token != GREATER) {
- goto error;
- }
-
- keysym = XStringToKeysym(tokenbuf);
- if (keysym == NoSymbol) {
- goto error;
- }
-
- buf[n].keysym = keysym;
- buf[n].modifier = modifier;
- buf[n].modifier_mask = modifier_mask;
- n++;
- if( n >= SEQUENCE_MAX )
- goto error;
- token = nexttoken(fp, tokenbuf, &lastch);
- } while (token != COLON);
-
- token = nexttoken(fp, tokenbuf, &lastch);
- if (token == STRING) {
- l = strlen(tokenbuf) + 1;
- while (b->mbused + l > b->mbsize) {
- b->mbsize = b->mbsize ? b->mbsize * 1.5 : 1024;
- if (! (b->mb = Xrealloc (b->mb, b->mbsize)) )
- goto error;
- }
- rhs_string_mb = &b->mb[b->mbused];
- b->mbused += l;
- strcpy(rhs_string_mb, tokenbuf);
- token = nexttoken(fp, tokenbuf, &lastch);
- if (token == KEY) {
- rhs_keysym = XStringToKeysym(tokenbuf);
- if (rhs_keysym == NoSymbol) {
- goto error;
- }
- token = nexttoken(fp, tokenbuf, &lastch);
- }
- if (token != ENDOFLINE && token != ENDOFFILE) {
- goto error;
- }
- } else if (token == KEY) {
- rhs_keysym = XStringToKeysym(tokenbuf);
- if (rhs_keysym == NoSymbol) {
- goto error;
- }
- token = nexttoken(fp, tokenbuf, &lastch);
- if (token != ENDOFLINE && token != ENDOFFILE) {
- goto error;
- }
-
- l = get_mb_string(im, local_mb_buf, rhs_keysym);
- while (b->mbused + l + 1 > b->mbsize) {
- b->mbsize = b->mbsize ? b->mbsize * 1.5 : 1024;
- if (! (b->mb = Xrealloc (b->mb, b->mbsize)) )
- goto error;
- }
- rhs_string_mb = &b->mb[b->mbused];
- b->mbused += l + 1;
- memcpy(rhs_string_mb, local_mb_buf, l);
- rhs_string_mb[l] = '\0';
- } else {
- goto error;
- }
-
- l = _Xmbstowcs(local_wc_buf, rhs_string_mb, LOCAL_WC_BUFSIZE - 1);
- if (l == LOCAL_WC_BUFSIZE - 1) {
- local_wc_buf[l] = (wchar_t)'\0';
- }
- while (b->wcused + l + 1 > b->wcsize) {
- b->wcsize = b->wcsize ? b->wcsize * 1.5 : 512;
- if (! (b->wc = Xrealloc (b->wc, sizeof(wchar_t) * b->wcsize)) )
- goto error;
- }
- rhs_string_wc = &b->wc[b->wcused];
- b->wcused += l + 1;
- memcpy((char *)rhs_string_wc, (char *)local_wc_buf, (l + 1) * sizeof(wchar_t) );
-
- l = _Xmbstoutf8(local_utf8_buf, rhs_string_mb, LOCAL_UTF8_BUFSIZE - 1);
- if (l == LOCAL_UTF8_BUFSIZE - 1) {
- local_utf8_buf[l] = '\0';
- }
- while (b->utf8used + l + 1 > b->utf8size) {
- b->utf8size = b->utf8size ? b->utf8size * 1.5 : 1024;
- if (! (b->utf8 = Xrealloc (b->utf8, b->utf8size)) )
- goto error;
- }
- rhs_string_utf8 = &b->utf8[b->utf8used];
- b->utf8used += l + 1;
- memcpy(rhs_string_utf8, local_utf8_buf, l + 1);
-
- for (i = 0; i < n; i++) {
- for (t = *top; t; t = b->tree[t].next) {
- if (buf[i].keysym == b->tree[t].keysym &&
- buf[i].modifier == b->tree[t].modifier &&
- buf[i].modifier_mask == b->tree[t].modifier_mask) {
- break;
- }
- }
- if (t) {
- p = &b->tree[t];
- top = &p->succession;
- } else {
- while (b->treeused >= b->treesize) {
- DefTree *old = b->tree;
- int oldsize = b->treesize;
- b->treesize = b->treesize ? b->treesize * 1.5 : 256;
- if (! (b->tree = Xrealloc (b->tree, sizeof(DefTree) * b->treesize)) )
- goto error;
- if (top >= (DTIndex *) old && top < (DTIndex *) &old[oldsize])
- top = (DTIndex *) (((char *) top) + (((char *)b->tree)-(char *)old));
- }
- p = &b->tree[b->treeused];
- p->keysym = buf[i].keysym;
- p->modifier = buf[i].modifier;
- p->modifier_mask = buf[i].modifier_mask;
- p->succession = 0;
- p->next = *top;
- p->mb = 0;
- p->wc = 0;
- p->utf8 = 0;
- p->ks = NoSymbol;
- *top = b->treeused;
- top = &p->succession;
- b->treeused++;
- }
- }
-
- /* old entries no longer freed... */
- p->mb = rhs_string_mb - b->mb;
- p->wc = rhs_string_wc - b->wc;
- p->utf8 = rhs_string_utf8 - b->utf8;
- p->ks = rhs_keysym;
- return(n);
-error:
- while (token != ENDOFLINE && token != ENDOFFILE) {
- token = nexttoken(fp, tokenbuf, &lastch);
- }
- return(0);
-}
-
-void
-_XimParseStringFile(
- FILE *fp,
- Xim im)
-{
- char tb[8192];
- char* tbp;
- struct stat st;
-
- if (fstat (fileno (fp), &st) != -1) {
- unsigned long size = (unsigned long) st.st_size;
- if (size <= sizeof tb) tbp = tb;
- else tbp = malloc (size);
-
- if (tbp != NULL) {
- while (parseline(fp, im, tbp) >= 0) {}
- if (tbp != tb) free (tbp);
- }
- }
-}
+/******************************************************************
+
+ Copyright 1992 by Oki Technosystems Laboratory, Inc.
+ Copyright 1992 by Fuji Xerox Co., Ltd.
+
+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, and that the name of Oki Technosystems
+Laboratory and Fuji Xerox not be used in advertising or publicity
+pertaining to distribution of the software without specific, written
+prior permission.
+Oki Technosystems Laboratory and Fuji Xerox make no representations
+about the suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX DISCLAIM ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OKI TECHNOSYSTEMS
+LABORATORY AND FUJI XEROX BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+OR PERFORMANCE OF THIS SOFTWARE.
+
+ Author: Yasuhiro Kawai Oki Technosystems Laboratory
+ Author: Kazunori Nishihara Fuji Xerox
+
+******************************************************************/
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/Xlib.h>
+#include <X11/Xmd.h>
+#include <X11/Xos.h>
+#include "Xlibint.h"
+#include "Xlcint.h"
+#include "Ximint.h"
+#include <sys/stat.h>
+#include <stdio.h>
+
+#define XLC_BUFSIZE 256
+
+extern int _Xmbstowcs(
+ wchar_t *wstr,
+ char *str,
+ int len
+);
+
+extern int _Xmbstoutf8(
+ char *ustr,
+ const char *str,
+ int len
+);
+
+/*
+ * Parsing File Format:
+ *
+ * FILE ::= { [PRODUCTION] [COMMENT] "\n"}
+ * PRODUCTION ::= LHS ":" RHS [ COMMENT ]
+ * COMMENT ::= "#" {<any character except null or newline>}
+ * LHS ::= EVENT { EVENT }
+ * EVENT ::= [MODIFIER_LIST] "<" keysym ">"
+ * MODIFIER_LIST ::= ("!" {MODIFIER} ) | "None"
+ * MODIFIER ::= ["~"] modifier_name
+ * RHS ::= ( STRING | keysym | STRING keysym )
+ * STRING ::= '"' { CHAR } '"'
+ * CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR
+ * GRAPHIC_CHAR ::= locale (codeset) dependent code
+ * ESCAPED_CHAR ::= ('\\' | '\"' | OCTAL | HEX )
+ * OCTAL ::= '\' OCTAL_CHAR [OCTAL_CHAR [OCTAL_CHAR]]
+ * OCTAL_CHAR ::= (0|1|2|3|4|5|6|7)
+ * HEX ::= '\' (x|X) HEX_CHAR [HEX_CHAR]]
+ * HEX_CHAR ::= (0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|a|b|c|d|e|f)
+ *
+ */
+
+static int
+nextch(
+ FILE *fp,
+ int *lastch)
+{
+ int c;
+
+ if (*lastch != 0) {
+ c = *lastch;
+ *lastch = 0;
+ } else {
+ c = getc(fp);
+ if (c == '\\') {
+ c = getc(fp);
+ if (c == '\n') {
+ c = getc(fp);
+ } else {
+ ungetc(c, fp);
+ c = '\\';
+ }
+ }
+ }
+ return(c);
+}
+
+static void
+putbackch(
+ int c,
+ int *lastch)
+{
+ *lastch = c;
+}
+
+#define ENDOFFILE 0
+#define ENDOFLINE 1
+#define COLON 2
+#define LESS 3
+#define GREATER 4
+#define EXCLAM 5
+#define TILDE 6
+#define STRING 7
+#define KEY 8
+#define ERROR 9
+
+#ifndef isalnum
+#define isalnum(c) \
+ (('0' <= (c) && (c) <= '9') || \
+ ('A' <= (c) && (c) <= 'Z') || \
+ ('a' <= (c) && (c) <= 'z'))
+#endif
+
+static int
+nexttoken(
+ FILE *fp,
+ char *tokenbuf,
+ int *lastch)
+{
+ int c;
+ int token;
+ char *p;
+ int i, j;
+
+ while ((c = nextch(fp, lastch)) == ' ' || c == '\t') {
+ }
+ switch (c) {
+ case EOF:
+ token = ENDOFFILE;
+ break;
+ case '\n':
+ token = ENDOFLINE;
+ break;
+ case '<':
+ token = LESS;
+ break;
+ case '>':
+ token = GREATER;
+ break;
+ case ':':
+ token = COLON;
+ break;
+ case '!':
+ token = EXCLAM;
+ break;
+ case '~':
+ token = TILDE;
+ break;
+ case '"':
+ p = tokenbuf;
+ while ((c = nextch(fp, lastch)) != '"') {
+ if (c == '\n' || c == EOF) {
+ putbackch(c, lastch);
+ token = ERROR;
+ goto string_error;
+ } else if (c == '\\') {
+ c = nextch(fp, lastch);
+ switch (c) {
+ case '\\':
+ case '"':
+ *p++ = c;
+ break;
+ case 'n':
+ *p++ = '\n';
+ break;
+ case 'r':
+ *p++ = '\r';
+ break;
+ case 't':
+ *p++ = '\t';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ i = c - '0';
+ c = nextch(fp, lastch);
+ for (j = 0; j < 2 && c >= '0' && c <= '7'; j++) {
+ i <<= 3;
+ i += c - '0';
+ c = nextch(fp, lastch);
+ }
+ putbackch(c, lastch);
+ *p++ = (char)i;
+ break;
+ case 'X':
+ case 'x':
+ i = 0;
+ for (j = 0; j < 2; j++) {
+ c = nextch(fp, lastch);
+ i <<= 4;
+ if (c >= '0' && c <= '9') {
+ i += c - '0';
+ } else if (c >= 'A' && c <= 'F') {
+ i += c - 'A' + 10;
+ } else if (c >= 'a' && c <= 'f') {
+ i += c - 'a' + 10;
+ } else {
+ putbackch(c, lastch);
+ i >>= 4;
+ break;
+ }
+ }
+ if (j == 0) {
+ token = ERROR;
+ goto string_error;
+ }
+ *p++ = (char)i;
+ break;
+ case EOF:
+ putbackch(c, lastch);
+ token = ERROR;
+ goto string_error;
+ default:
+ *p++ = c;
+ break;
+ }
+ } else {
+ *p++ = c;
+ }
+ }
+ *p = '\0';
+ token = STRING;
+ break;
+ case '#':
+ while ((c = nextch(fp, lastch)) != '\n' && c != EOF) {
+ }
+ if (c == '\n') {
+ token = ENDOFLINE;
+ } else {
+ token = ENDOFFILE;
+ }
+ break;
+ default:
+ if (isalnum(c) || c == '_' || c == '-') {
+ p = tokenbuf;
+ *p++ = c;
+ c = nextch(fp, lastch);
+ while (isalnum(c) || c == '_' || c == '-') {
+ *p++ = c;
+ c = nextch(fp, lastch);
+ }
+ *p = '\0';
+ putbackch(c, lastch);
+ token = KEY;
+ } else {
+ token = ERROR;
+ }
+ break;
+ }
+string_error:
+ return(token);
+}
+
+static long
+modmask(
+ char *name)
+{
+ struct _modtbl {
+ const char name[6];
+ long mask;
+ };
+
+ static const struct _modtbl tbl[] = {
+ { "Ctrl", ControlMask },
+ { "Lock", LockMask },
+ { "Caps", LockMask },
+ { "Shift", ShiftMask },
+ { "Alt", Mod1Mask },
+ { "Meta", Mod1Mask }};
+
+ int i, num_entries = sizeof (tbl) / sizeof (tbl[0]);
+
+ for (i = 0; i < num_entries; i++)
+ if (!strcmp (name, tbl[i].name))
+ return tbl[i].mask;
+
+ return 0;
+}
+
+static char*
+TransFileName(Xim im, char *name)
+{
+ char *home = NULL, *lcCompose = NULL;
+ char dir[XLC_BUFSIZE];
+ char *i = name, *ret, *j;
+ int l = 0;
+
+ while (*i) {
+ if (*i == '%') {
+ i++;
+ switch (*i) {
+ case '%':
+ l++;
+ break;
+ case 'H':
+ home = getenv("HOME");
+ if (home)
+ l += strlen(home);
+ break;
+ case 'L':
+ lcCompose = _XlcFileName(im->core.lcd, COMPOSE_FILE);
+ if (lcCompose)
+ l += strlen(lcCompose);
+ break;
+ case 'S':
+ xlocaledir(dir, XLC_BUFSIZE);
+ l += strlen(dir);
+ break;
+ }
+ } else {
+ l++;
+ }
+ i++;
+ }
+
+ j = ret = Xmalloc(l+1);
+ if (ret == NULL)
+ return ret;
+ i = name;
+ while (*i) {
+ if (*i == '%') {
+ i++;
+ switch (*i) {
+ case '%':
+ *j++ = '%';
+ break;
+ case 'H':
+ if (home) {
+ strcpy(j, home);
+ j += strlen(home);
+ }
+ break;
+ case 'L':
+ if (lcCompose) {
+ strcpy(j, lcCompose);
+ j += strlen(lcCompose);
+ Xfree(lcCompose);
+ }
+ break;
+ case 'S':
+ strcpy(j, dir);
+ j += strlen(dir);
+ break;
+ }
+ i++;
+ } else {
+ *j++ = *i++;
+ }
+ }
+ *j = '\0';
+ return ret;
+}
+
+#ifndef MB_LEN_MAX
+#define MB_LEN_MAX 6
+#endif
+
+static int
+get_mb_string (Xim im, char *buf, KeySym ks)
+{
+ XPointer from, to;
+ int from_len, to_len, len;
+ XPointer args[1];
+ XlcCharSet charset;
+ char local_buf[MB_LEN_MAX];
+ unsigned int ucs;
+ ucs = KeySymToUcs4(ks);
+
+ from = (XPointer) &ucs;
+ to = (XPointer) local_buf;
+ from_len = 1;
+ to_len = MB_LEN_MAX;
+ args[0] = (XPointer) &charset;
+ if (_XlcConvert(im->private.local.ucstoc_conv,
+ &from, &from_len, &to, &to_len, args, 1 ) != 0) {
+ return 0;
+ }
+
+ from = (XPointer) local_buf;
+ to = (XPointer) buf;
+ from_len = MB_LEN_MAX - to_len;
+ to_len = MB_LEN_MAX + 1;
+ args[0] = (XPointer) charset;
+ if (_XlcConvert(im->private.local.cstomb_conv,
+ &from, &from_len, &to, &to_len, args, 1 ) != 0) {
+ return 0;
+ }
+ len = MB_LEN_MAX + 1 - to_len;
+ buf[len] = '\0';
+ return len;
+}
+
+#define AllMask (ShiftMask | LockMask | ControlMask | Mod1Mask)
+#define LOCAL_WC_BUFSIZE 128
+#define LOCAL_UTF8_BUFSIZE 256
+#define SEQUENCE_MAX 10
+
+static int
+parseline(
+ FILE *fp,
+ Xim im,
+ char* tokenbuf)
+{
+ int token;
+ DTModifier modifier_mask;
+ DTModifier modifier;
+ DTModifier tmp;
+ KeySym keysym = NoSymbol;
+ DTIndex *top = &im->private.local.top;
+ DefTreeBase *b = &im->private.local.base;
+ DTIndex t;
+ DefTree *p = NULL;
+ Bool exclam, tilde;
+ KeySym rhs_keysym = 0;
+ char *rhs_string_mb;
+ int l;
+ int lastch = 0;
+ char local_mb_buf[MB_LEN_MAX+1];
+ wchar_t local_wc_buf[LOCAL_WC_BUFSIZE], *rhs_string_wc;
+ char local_utf8_buf[LOCAL_UTF8_BUFSIZE], *rhs_string_utf8;
+
+ struct DefBuffer {
+ DTModifier modifier_mask;
+ DTModifier modifier;
+ KeySym keysym;
+ };
+
+ struct DefBuffer buf[SEQUENCE_MAX];
+ int i, n;
+
+ do {
+ token = nexttoken(fp, tokenbuf, &lastch);
+ } while (token == ENDOFLINE);
+
+ if (token == ENDOFFILE) {
+ return(-1);
+ }
+
+ n = 0;
+ do {
+ if ((token == KEY) && (strcmp("include", tokenbuf) == 0)) {
+ char *filename;
+ FILE *infp;
+ token = nexttoken(fp, tokenbuf, &lastch);
+ if (token != KEY && token != STRING)
+ goto error;
+ if ((filename = TransFileName(im, tokenbuf)) == NULL)
+ goto error;
+ infp = _XFopenFile(filename, "r");
+ Xfree(filename);
+ if (infp == NULL)
+ goto error;
+ _XimParseStringFile(infp, im);
+ fclose(infp);
+ return (0);
+ } else if ((token == KEY) && (strcmp("None", tokenbuf) == 0)) {
+ modifier = 0;
+ modifier_mask = AllMask;
+ token = nexttoken(fp, tokenbuf, &lastch);
+ } else {
+ modifier_mask = modifier = 0;
+ exclam = False;
+ if (token == EXCLAM) {
+ exclam = True;
+ token = nexttoken(fp, tokenbuf, &lastch);
+ }
+ while (token == TILDE || token == KEY) {
+ tilde = False;
+ if (token == TILDE) {
+ tilde = True;
+ token = nexttoken(fp, tokenbuf, &lastch);
+ if (token != KEY)
+ goto error;
+ }
+ tmp = modmask(tokenbuf);
+ if (!tmp) {
+ goto error;
+ }
+ modifier_mask |= tmp;
+ if (tilde) {
+ modifier &= ~tmp;
+ } else {
+ modifier |= tmp;
+ }
+ token = nexttoken(fp, tokenbuf, &lastch);
+ }
+ if (exclam) {
+ modifier_mask = AllMask;
+ }
+ }
+
+ if (token != LESS) {
+ goto error;
+ }
+
+ token = nexttoken(fp, tokenbuf, &lastch);
+ if (token != KEY) {
+ goto error;
+ }
+
+ token = nexttoken(fp, tokenbuf, &lastch);
+ if (token != GREATER) {
+ goto error;
+ }
+
+ keysym = XStringToKeysym(tokenbuf);
+ if (keysym == NoSymbol) {
+ goto error;
+ }
+
+ buf[n].keysym = keysym;
+ buf[n].modifier = modifier;
+ buf[n].modifier_mask = modifier_mask;
+ n++;
+ if( n >= SEQUENCE_MAX )
+ goto error;
+ token = nexttoken(fp, tokenbuf, &lastch);
+ } while (token != COLON);
+
+ token = nexttoken(fp, tokenbuf, &lastch);
+ if (token == STRING) {
+ l = strlen(tokenbuf) + 1;
+ while (b->mbused + l > b->mbsize) {
+ b->mbsize = b->mbsize ? b->mbsize * 1.5 : 1024;
+ if (! (b->mb = Xrealloc (b->mb, b->mbsize)) )
+ goto error;
+ }
+ rhs_string_mb = &b->mb[b->mbused];
+ b->mbused += l;
+ strcpy(rhs_string_mb, tokenbuf);
+ token = nexttoken(fp, tokenbuf, &lastch);
+ if (token == KEY) {
+ rhs_keysym = XStringToKeysym(tokenbuf);
+ if (rhs_keysym == NoSymbol) {
+ goto error;
+ }
+ token = nexttoken(fp, tokenbuf, &lastch);
+ }
+ if (token != ENDOFLINE && token != ENDOFFILE) {
+ goto error;
+ }
+ } else if (token == KEY) {
+ rhs_keysym = XStringToKeysym(tokenbuf);
+ if (rhs_keysym == NoSymbol) {
+ goto error;
+ }
+ token = nexttoken(fp, tokenbuf, &lastch);
+ if (token != ENDOFLINE && token != ENDOFFILE) {
+ goto error;
+ }
+
+ l = get_mb_string(im, local_mb_buf, rhs_keysym);
+ while (b->mbused + l + 1 > b->mbsize) {
+ b->mbsize = b->mbsize ? b->mbsize * 1.5 : 1024;
+ if (! (b->mb = Xrealloc (b->mb, b->mbsize)) )
+ goto error;
+ }
+ rhs_string_mb = &b->mb[b->mbused];
+ b->mbused += l + 1;
+ memcpy(rhs_string_mb, local_mb_buf, l);
+ rhs_string_mb[l] = '\0';
+ } else {
+ goto error;
+ }
+
+ l = _Xmbstowcs(local_wc_buf, rhs_string_mb, LOCAL_WC_BUFSIZE - 1);
+ if (l == LOCAL_WC_BUFSIZE - 1) {
+ local_wc_buf[l] = (wchar_t)'\0';
+ }
+ while (b->wcused + l + 1 > b->wcsize) {
+ b->wcsize = b->wcsize ? b->wcsize * 1.5 : 512;
+ if (! (b->wc = Xrealloc (b->wc, sizeof(wchar_t) * b->wcsize)) )
+ goto error;
+ }
+ rhs_string_wc = &b->wc[b->wcused];
+ b->wcused += l + 1;
+ memcpy((char *)rhs_string_wc, (char *)local_wc_buf, (l + 1) * sizeof(wchar_t) );
+
+ l = _Xmbstoutf8(local_utf8_buf, rhs_string_mb, LOCAL_UTF8_BUFSIZE - 1);
+ if (l == LOCAL_UTF8_BUFSIZE - 1) {
+ local_utf8_buf[l] = '\0';
+ }
+ while (b->utf8used + l + 1 > b->utf8size) {
+ b->utf8size = b->utf8size ? b->utf8size * 1.5 : 1024;
+ if (! (b->utf8 = Xrealloc (b->utf8, b->utf8size)) )
+ goto error;
+ }
+ rhs_string_utf8 = &b->utf8[b->utf8used];
+ b->utf8used += l + 1;
+ memcpy(rhs_string_utf8, local_utf8_buf, l + 1);
+
+ for (i = 0; i < n; i++) {
+ for (t = *top; t; t = b->tree[t].next) {
+ if (buf[i].keysym == b->tree[t].keysym &&
+ buf[i].modifier == b->tree[t].modifier &&
+ buf[i].modifier_mask == b->tree[t].modifier_mask) {
+ break;
+ }
+ }
+ if (t) {
+ p = &b->tree[t];
+ top = &p->succession;
+ } else {
+ while (b->treeused >= b->treesize) {
+ DefTree *old = b->tree;
+ int oldsize = b->treesize;
+ b->treesize = b->treesize ? b->treesize * 1.5 : 256;
+ if (! (b->tree = Xrealloc (b->tree, sizeof(DefTree) * b->treesize)) )
+ goto error;
+ if (top >= (DTIndex *) old && top < (DTIndex *) &old[oldsize])
+ top = (DTIndex *) (((char *) top) + (((char *)b->tree)-(char *)old));
+ }
+ p = &b->tree[b->treeused];
+ p->keysym = buf[i].keysym;
+ p->modifier = buf[i].modifier;
+ p->modifier_mask = buf[i].modifier_mask;
+ p->succession = 0;
+ p->next = *top;
+ p->mb = 0;
+ p->wc = 0;
+ p->utf8 = 0;
+ p->ks = NoSymbol;
+ *top = b->treeused;
+ top = &p->succession;
+ b->treeused++;
+ }
+ }
+
+ /* old entries no longer freed... */
+ p->mb = rhs_string_mb - b->mb;
+ p->wc = rhs_string_wc - b->wc;
+ p->utf8 = rhs_string_utf8 - b->utf8;
+ p->ks = rhs_keysym;
+ return(n);
+error:
+ while (token != ENDOFLINE && token != ENDOFFILE) {
+ token = nexttoken(fp, tokenbuf, &lastch);
+ }
+ return(0);
+}
+
+void
+_XimParseStringFile(
+ FILE *fp,
+ Xim im)
+{
+ char tb[8192];
+ char* tbp;
+ struct stat st;
+
+ if (fstat (fileno (fp), &st) != -1) {
+ unsigned long size = (unsigned long) st.st_size;
+ if (size <= sizeof tb) tbp = tb;
+ else tbp = malloc (size);
+
+ if (tbp != NULL) {
+ while (parseline(fp, im, tbp) >= 0) {}
+ if (tbp != tb) free (tbp);
+ }
+ }
+}