diff options
Diffstat (limited to 'src/xlibi18n/lcRM.c')
-rw-r--r-- | src/xlibi18n/lcRM.c | 219 |
1 files changed, 160 insertions, 59 deletions
diff --git a/src/xlibi18n/lcRM.c b/src/xlibi18n/lcRM.c index 0824a6f7..2e0f15cc 100644 --- a/src/xlibi18n/lcRM.c +++ b/src/xlibi18n/lcRM.c @@ -22,101 +22,202 @@ * * Author: Katsuhisa Yano TOSHIBA Corp. * mopi@osa.ilab.toshiba.co.jp + * Bug fixes: Bruno Haible XFree86 Inc. */ +/* $XFree86: xc/lib/X11/lcRM.c,v 1.5 2001/01/17 19:41:55 dawes Exp $ */ #include "Xlibint.h" #include "XlcPubI.h" #include <stdio.h> -typedef struct _StateRec { - XLCd lcd; - XlcConv conv; -} StateRec, *State; +/* + * Default implementation of methods for Xrm parsing. + */ + +/* ======================= Unibyte implementation ======================= */ + +/* Only for efficiency, to speed up things. */ + +/* This implementation must keep the locale, for lcname. */ +typedef struct _UbStateRec { + XLCd lcd; +} UbStateRec, *UbState; + +/* Sets the state to the initial state. + Initiates a sequence of calls to mbchar. */ +static void +ub_mbinit( + XPointer state) +{ +} + +/* Transforms one multibyte character, and return a 'char' in the same + parsing class. Returns the number of consumed bytes in *lenp. */ +static char +ub_mbchar( + XPointer state, + const char *str, + int *lenp) +{ + *lenp = 1; + return *str; +} + +/* Terminates a sequence of calls to mbchar. */ +static void +ub_mbfinish( + XPointer state) +{ +} +/* Returns the name of the state's locale, as a static string. */ +static const char * +ub_lcname( + XPointer state) +{ + return ((UbState) state)->lcd->core->name; +} + +/* Frees the state, which was allocated by _XrmDefaultInitParseInfo. */ static void -mbinit(state) - XPointer state; +ub_destroy( + XPointer state) { - _XlcResetConverter(((State) state)->conv); + _XCloseLC(((UbState) state)->lcd); + Xfree((char *) state); } +static const XrmMethodsRec ub_methods = { + ub_mbinit, + ub_mbchar, + ub_mbfinish, + ub_lcname, + ub_destroy +}; + +/* ======================= Multibyte implementation ======================= */ + +/* This implementation uses an XlcConv from XlcNMultiByte to XlcNWideChar. */ +typedef struct _MbStateRec { + XLCd lcd; + XlcConv conv; +} MbStateRec, *MbState; + +/* Sets the state to the initial state. + Initiates a sequence of calls to mbchar. */ +static void +mb_mbinit( + XPointer state) +{ + _XlcResetConverter(((MbState) state)->conv); +} + +/* Transforms one multibyte character, and return a 'char' in the same + parsing class. Returns the number of consumed bytes in *lenp. */ static char -mbchar(state, str, lenp) - XPointer state; - char *str; - int *lenp; +mb_mbchar( + XPointer state, + const char *str, + int *lenp) { - XlcConv conv = ((State) state)->conv; - XlcCharSet charset; - char *from, *to, buf[BUFSIZ]; - int from_left, to_left; - XPointer args[1]; + XlcConv conv = ((MbState) state)->conv; + const char *from; + wchar_t *to, wc; + int cur_max, i, from_left, to_left, ret; + + cur_max = XLC_PUBLIC(((MbState) state)->lcd, mb_cur_max); from = str; - *lenp = from_left = XLC_PUBLIC(((State) state)->lcd, mb_cur_max); - to = buf; - to_left = BUFSIZ; - args[0] = (XPointer) &charset; - - _XlcConvert(conv, (XPointer *) &from, &from_left, (XPointer *) &to, - &to_left, args, 1); - + /* Determine from_left. Avoid overrun error which could occur if + from_left > strlen(str). */ + from_left = cur_max; + for (i = 0; i < cur_max; i++) + if (str[i] == '\0') { + from_left = i; + break; + } + *lenp = from_left; + + to = &wc; + to_left = 1; + + ret = _XlcConvert(conv, (XPointer *) &from, &from_left, + (XPointer *) &to, &to_left, NULL, 0); *lenp -= from_left; - /* XXX */ - return buf[0]; + if (ret < 0 || to_left > 0) { + /* Invalid or incomplete multibyte character seen. */ + *lenp = 1; + return 0x7f; + } + /* Return a 'char' equivalent to wc. */ + return (wc >= 0 && wc <= 0x7f ? wc : 0x7f); } +/* Terminates a sequence of calls to mbchar. */ static void -mbfinish(state) - XPointer state; +mb_mbfinish( + XPointer state) { } -static char * -lcname(state) - XPointer state; +/* Returns the name of the state's locale, as a static string. */ +static const char * +mb_lcname( + XPointer state) { - return ((State) state)->lcd->core->name; + return ((MbState) state)->lcd->core->name; } +/* Frees the state, which was allocated by _XrmDefaultInitParseInfo. */ static void -destroy(state) - XPointer state; +mb_destroy( + XPointer state) { - _XlcCloseConverter(((State) state)->conv); - _XCloseLC(((State) state)->lcd); + _XlcCloseConverter(((MbState) state)->conv); + _XCloseLC(((MbState) state)->lcd); Xfree((char *) state); } -static XrmMethodsRec rm_methods = { - mbinit, - mbchar, - mbfinish, - lcname, - destroy -} ; +static const XrmMethodsRec mb_methods = { + mb_mbinit, + mb_mbchar, + mb_mbfinish, + mb_lcname, + mb_destroy +}; + +/* ======================= Exported function ======================= */ XrmMethods -_XrmDefaultInitParseInfo(lcd, rm_state) - XLCd lcd; - XPointer *rm_state; +_XrmDefaultInitParseInfo( + XLCd lcd, + XPointer *rm_state) { - State state; + if (XLC_PUBLIC(lcd, mb_cur_max) == 1) { + /* Unibyte case. */ + UbState state = (UbState) Xmalloc(sizeof(UbStateRec)); + if (state == NULL) + return (XrmMethods) NULL; + + state->lcd = lcd; - state = (State) Xmalloc(sizeof(StateRec)); - if (state == NULL) - return (XrmMethods) NULL; + *rm_state = (XPointer) state; + return &ub_methods; + } else { + /* Multibyte case. */ + MbState state = (MbState) Xmalloc(sizeof(MbStateRec)); + if (state == NULL) + return (XrmMethods) NULL; - state->lcd = lcd; - state->conv = _XlcOpenConverter(lcd, XlcNMultiByte, lcd, XlcNChar); - if (state->conv == NULL) { - Xfree((char *) state); + state->lcd = lcd; + state->conv = _XlcOpenConverter(lcd, XlcNMultiByte, lcd, XlcNWideChar); + if (state->conv == NULL) { + Xfree((char *) state); + return (XrmMethods) NULL; + } - return (XrmMethods) NULL; + *rm_state = (XPointer) state; + return &mb_methods; } - - *rm_state = (XPointer) state; - - return &rm_methods; } |