11ab64890Smrg/* 21ab64890Smrg 31ab64890SmrgCopyright 1988, 1989, 1998 The Open Group 41ab64890Smrg 51ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its 61ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that 71ab64890Smrgthe above copyright notice appear in all copies and that both that 81ab64890Smrgcopyright notice and this permission notice appear in supporting 91ab64890Smrgdocumentation. 101ab64890Smrg 111ab64890SmrgThe above copyright notice and this permission notice shall be included 121ab64890Smrgin all copies or substantial portions of the Software. 131ab64890Smrg 141ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 171ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 181ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 191ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 201ab64890SmrgOTHER DEALINGS IN THE SOFTWARE. 211ab64890Smrg 221ab64890SmrgExcept as contained in this notice, the name of The Open Group shall 231ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or 241ab64890Smrgother dealings in this Software without prior written authorization 251ab64890Smrgfrom The Open Group. 261ab64890Smrg 271ab64890Smrg*/ 281ab64890Smrg 291ab64890Smrg#ifdef HAVE_CONFIG_H 301ab64890Smrg#include <config.h> 311ab64890Smrg#endif 321ab64890Smrg#include <stdio.h> 331ab64890Smrg#include <sys/types.h> 341ab64890Smrg#include <sys/stat.h> 351ab64890Smrg 361ab64890Smrg#include <X11/X.h> 371ab64890Smrg#include <X11/Xlib.h> 381ab64890Smrg#include "Xlibint.h" 391ab64890Smrg#include "Xlcint.h" 401ab64890Smrg#include "XlcPubI.h" 411ab64890Smrg#include "Ximint.h" 421ab64890Smrg#include <X11/Xutil.h> 431ab64890Smrg#include <X11/Xmd.h> 441ab64890Smrg#define XK_LATIN1 451ab64890Smrg#define XK_PUBLISHING 461ab64890Smrg#include <X11/keysym.h> 471ab64890Smrg#include <X11/extensions/XKBproto.h> 481ab64890Smrg#include "XKBlibint.h" 491ab64890Smrg#include <X11/Xlocale.h> 501ab64890Smrg#include <ctype.h> 511ab64890Smrg#include <X11/Xos.h> 521ab64890Smrg 5361b2299dSmrgstatic int 541ab64890Smrg_XkbHandleSpecialSym(KeySym keysym, char *buffer, int nbytes, int *extra_rtrn) 551ab64890Smrg{ 561ab64890Smrg /* try to convert to Latin-1, handling ctrl */ 571ab64890Smrg if (!(((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) || 58818534a1Smrg (keysym == XK_Return) || (keysym == XK_Escape) || 59818534a1Smrg (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) || 60818534a1Smrg (keysym == XK_KP_Enter) || 61818534a1Smrg ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) || 62818534a1Smrg (keysym == XK_KP_Equal) || (keysym == XK_Delete))) 63818534a1Smrg return 0; 64818534a1Smrg 65818534a1Smrg if (nbytes < 1) { 66818534a1Smrg if (extra_rtrn) 67818534a1Smrg *extra_rtrn = 1; 68818534a1Smrg return 0; 691ab64890Smrg } 701ab64890Smrg /* if X keysym, convert to ascii by grabbing low 7 bits */ 711ab64890Smrg if (keysym == XK_KP_Space) 72818534a1Smrg buffer[0] = XK_space & 0x7F; /* patch encoding botch */ 73818534a1Smrg else 74818534a1Smrg buffer[0] = (char) (keysym & 0x7F); 751ab64890Smrg return 1; 761ab64890Smrg} 771ab64890Smrg 781ab64890Smrg/*ARGSUSED*/ 7961b2299dSmrgstatic int 80818534a1Smrg_XkbKSToKnownSet(XPointer priv, 81818534a1Smrg KeySym keysym, 82818534a1Smrg char *buffer, 83818534a1Smrg int nbytes, 84818534a1Smrg int *extra_rtrn) 851ab64890Smrg{ 86818534a1Smrg char tbuf[8], *buf; 871ab64890Smrg 881ab64890Smrg if (extra_rtrn) 89818534a1Smrg *extra_rtrn = 0; 901ab64890Smrg 911ab64890Smrg /* convert "dead" diacriticals for dumb applications */ 92818534a1Smrg if ((keysym & 0xffffff00) == 0xfe00) { 93818534a1Smrg switch (keysym) { 94818534a1Smrg case XK_dead_grave: keysym = XK_grave; break; 95818534a1Smrg case XK_dead_acute: keysym = XK_acute; break; 96818534a1Smrg case XK_dead_circumflex: keysym = XK_asciicircum; break; 97818534a1Smrg case XK_dead_tilde: keysym = XK_asciitilde; break; 98818534a1Smrg case XK_dead_macron: keysym = XK_macron; break; 99818534a1Smrg case XK_dead_breve: keysym = XK_breve; break; 100818534a1Smrg case XK_dead_abovedot: keysym = XK_abovedot; break; 101818534a1Smrg case XK_dead_diaeresis: keysym = XK_diaeresis; break; 102818534a1Smrg case XK_dead_abovering: keysym = XK_degree; break; 103818534a1Smrg case XK_dead_doubleacute: keysym = XK_doubleacute; break; 104818534a1Smrg case XK_dead_caron: keysym = XK_caron; break; 105818534a1Smrg case XK_dead_cedilla: keysym = XK_cedilla; break; 106818534a1Smrg case XK_dead_ogonek: keysym = XK_ogonek; break; 107818534a1Smrg case XK_dead_iota: keysym = XK_Greek_iota; break; 1081ab64890Smrg#ifdef XK_KATAKANA 109818534a1Smrg case XK_dead_voiced_sound: keysym = XK_voicedsound; break; 110818534a1Smrg case XK_dead_semivoiced_sound: keysym = XK_semivoicedsound; break; 1111ab64890Smrg#endif 112818534a1Smrg } 1131ab64890Smrg } 1141ab64890Smrg 115818534a1Smrg if (nbytes < 1) 116818534a1Smrg buf = tbuf; 117818534a1Smrg else 118818534a1Smrg buf = buffer; 1191ab64890Smrg 120818534a1Smrg if ((keysym & 0xffffff00) == 0xff00) { 121818534a1Smrg return _XkbHandleSpecialSym(keysym, buf, nbytes, extra_rtrn); 1221ab64890Smrg } 123818534a1Smrg return _XimGetCharCode(priv, keysym, (unsigned char *) buf, nbytes); 1241ab64890Smrg} 1251ab64890Smrg 1261ab64890Smrgtypedef struct _XkbToKS { 127818534a1Smrg unsigned prefix; 128818534a1Smrg char *map; 1291ab64890Smrg} XkbToKS; 1301ab64890Smrg 1311ab64890Smrg/*ARGSUSED*/ 1321ab64890Smrgstatic KeySym 133818534a1Smrg_XkbKnownSetToKS(XPointer priv, char *buffer, int nbytes, Status *status) 1341ab64890Smrg{ 135818534a1Smrg if (nbytes != 1) 136818534a1Smrg return NoSymbol; 137818534a1Smrg if (((buffer[0] & 0x80) == 0) && (buffer[0] >= 32)) 138818534a1Smrg return buffer[0]; 139818534a1Smrg else if ((buffer[0] & 0x7f) >= 32) { 140818534a1Smrg XkbToKS *map = (XkbToKS *) priv; 141818534a1Smrg 142818534a1Smrg if (map) { 143818534a1Smrg if (map->map) 144818534a1Smrg return map->prefix | map->map[buffer[0] & 0x7f]; 145818534a1Smrg else 146818534a1Smrg return map->prefix | buffer[0]; 147818534a1Smrg } 148818534a1Smrg return buffer[0]; 1491ab64890Smrg } 1501ab64890Smrg return NoSymbol; 1511ab64890Smrg} 1521ab64890Smrg 1531ab64890Smrgstatic KeySym 1541ab64890Smrg__XkbDefaultToUpper(KeySym sym) 1551ab64890Smrg{ 156818534a1Smrg KeySym lower, upper; 1571ab64890Smrg 1581ab64890Smrg XConvertCase(sym, &lower, &upper); 1591ab64890Smrg return upper; 1601ab64890Smrg} 1611ab64890Smrg 1621ab64890Smrg#ifdef XKB_EXTEND_LOOKUP_STRING 1631ab64890Smrgstatic int 1641ab64890SmrgStrcmp(char *str1, char *str2) 1651ab64890Smrg{ 1661ab64890Smrg char str[256]; 1671ab64890Smrg char c, *s; 1681ab64890Smrg 1691ab64890Smrg /* 1701ab64890Smrg * unchecked strings from the environment can end up here, so check 1711ab64890Smrg * the length before copying. 1721ab64890Smrg */ 173818534a1Smrg if (strlen(str1) >= sizeof(str)) /* almost certain it's a mismatch */ 174818534a1Smrg return 1; 1751ab64890Smrg 176818534a1Smrg for (s = str; (c = *str1++);) { 177818534a1Smrg if (isupper(c)) 178818534a1Smrg c = tolower(c); 179818534a1Smrg *s++ = c; 1801ab64890Smrg } 1811ab64890Smrg *s = '\0'; 1821ab64890Smrg return (strcmp(str, str2)); 1831ab64890Smrg} 1841ab64890Smrg#endif 1851ab64890Smrg 18661b2299dSmrgint 187818534a1Smrg_XkbGetConverters(const char *encoding_name, XkbConverters * cvt_rtrn) 1881ab64890Smrg{ 189818534a1Smrg if (!cvt_rtrn) 190818534a1Smrg return 0; 1911ab64890Smrg 1921ab64890Smrg cvt_rtrn->KSToMB = _XkbKSToKnownSet; 1931ab64890Smrg cvt_rtrn->KSToMBPriv = _XimGetLocaleCode(encoding_name); 1941ab64890Smrg cvt_rtrn->MBToKS = _XkbKnownSetToKS; 1951ab64890Smrg cvt_rtrn->MBToKSPriv = NULL; 1961ab64890Smrg cvt_rtrn->KSToUpper = __XkbDefaultToUpper; 1971ab64890Smrg return 1; 1981ab64890Smrg} 1991ab64890Smrg 2001ab64890Smrg/***====================================================================***/ 2011ab64890Smrg 20261b2299dSmrg/* 2031ab64890Smrg * The function _XkbGetCharset seems to be missnamed as what it seems to 2041ab64890Smrg * be used for is to determine the encoding-name for the locale. ??? 2051ab64890Smrg */ 2061ab64890Smrg 2071ab64890Smrg#ifdef XKB_EXTEND_LOOKUP_STRING 2081ab64890Smrg 20961b2299dSmrg/* 2101ab64890Smrg * XKB_EXTEND_LOOKUP_STRING is not used by the SI. It is used by various 2111ab64890Smrg * X Consortium/X Project Team members, so we leave it in the source as 2121ab64890Smrg * an simplify integration by these companies. 2131ab64890Smrg */ 2141ab64890Smrg 2151ab64890Smrg#define CHARSET_FILE "/usr/lib/X11/input/charsets" 216818534a1Smrgstatic char *_XkbKnownLanguages = 217818534a1Smrg "c=ascii:da,de,en,es,fr,is,it,nl,no,pt,sv=iso8859-1:hu,pl,cs=iso8859-2:" 218818534a1Smrg "eo=iso8859-3:sp=iso8859-5:ar,ara=iso8859-6:el=iso8859-7:he=iso8859-8:" 219818534a1Smrg "tr=iso8859-9:lt,lv=iso8859-13:et,fi=iso8859-15:ru=koi8-r:uk=koi8-u:" 220818534a1Smrg "th,th_TH,th_TH.iso8859-11=iso8859-11:th_TH.TIS620=tis620:hy=armscii-8:" 221818534a1Smrg "vi=tcvn-5712:ka=georgian-academy:be,bg=microsoft-cp1251"; 222818534a1Smrg 223818534a1Smrgchar * 2241ab64890Smrg_XkbGetCharset(void) 2251ab64890Smrg{ 2261ab64890Smrg /* 2271ab64890Smrg * PAGE USAGE TUNING: explicitly initialize to move these to data 2281ab64890Smrg * instead of bss 2291ab64890Smrg */ 2301ab64890Smrg static char buf[100] = { 0 }; 2311ab64890Smrg char lang[256]; 232818534a1Smrg char *start, *tmp, *end, *next, *set; 233818534a1Smrg char *country, *charset; 2341ab64890Smrg char *locale; 2351ab64890Smrg 236818534a1Smrg tmp = getenv("_XKB_CHARSET"); 237818534a1Smrg if (tmp) 238818534a1Smrg return tmp; 239818534a1Smrg locale = setlocale(LC_CTYPE, NULL); 2401ab64890Smrg 241818534a1Smrg if (locale == NULL) 242818534a1Smrg return NULL; 2431ab64890Smrg 2441ab64890Smrg if (strlen(locale) >= sizeof(lang)) 245818534a1Smrg return NULL; 2461ab64890Smrg 2471ab64890Smrg for (tmp = lang; *tmp = *locale++; tmp++) { 248818534a1Smrg if (isupper(*tmp)) 249818534a1Smrg *tmp = tolower(*tmp); 2501ab64890Smrg } 251818534a1Smrg country = strchr(lang, '_'); 252818534a1Smrg if (country) { 253818534a1Smrg *country++ = '\0'; 254818534a1Smrg charset = strchr(country, '.'); 255818534a1Smrg if (charset) 256818534a1Smrg *charset++ = '\0'; 257818534a1Smrg if (charset) { 258818534a1Smrg strncpy(buf, charset, 99); 259818534a1Smrg buf[99] = '\0'; 260818534a1Smrg return buf; 261818534a1Smrg } 2621ab64890Smrg } 26361b2299dSmrg else { 264818534a1Smrg charset = NULL; 2651ab64890Smrg } 2661ab64890Smrg 267818534a1Smrg if ((tmp = getenv("_XKB_LOCALE_CHARSETS")) != NULL) { 268818534a1Smrg start = _XkbAlloc(strlen(tmp) + 1); 269818534a1Smrg strcpy(start, tmp); 270818534a1Smrg tmp = start; 271818534a1Smrg } 272818534a1Smrg else { 273818534a1Smrg struct stat sbuf; 274818534a1Smrg FILE *file; 275818534a1Smrg char *cf = CHARSET_FILE; 2761ab64890Smrg 2771ab64890Smrg#ifndef S_ISREG 2781ab64890Smrg# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 2791ab64890Smrg#endif 28061b2299dSmrg 281818534a1Smrg if ((stat(cf, &sbuf) == 0) && S_ISREG(sbuf.st_mode) && 282818534a1Smrg (file = fopen(cf, "r"))) { 283818534a1Smrg tmp = _XkbAlloc(sbuf.st_size + 1); 284818534a1Smrg if (tmp != NULL) { 285818534a1Smrg sbuf.st_size = (long) fread(tmp, 1, sbuf.st_size, file); 286818534a1Smrg tmp[sbuf.st_size] = '\0'; 287818534a1Smrg } 288818534a1Smrg fclose(file); 289818534a1Smrg } 2901ab64890Smrg } 2911ab64890Smrg 292818534a1Smrg if (tmp == NULL) { 293818534a1Smrg tmp = _XkbAlloc(strlen(_XkbKnownLanguages) + 1); 294818534a1Smrg if (!tmp) 295818534a1Smrg return NULL; 296818534a1Smrg strcpy(tmp, _XkbKnownLanguages); 2971ab64890Smrg } 2981ab64890Smrg start = tmp; 2991ab64890Smrg do { 300818534a1Smrg if ((set = strchr(tmp, '=')) == NULL) 301818534a1Smrg break; 302818534a1Smrg *set++ = '\0'; 303818534a1Smrg if ((next = strchr(set, ':')) != NULL) 304818534a1Smrg *next++ = '\0'; 305818534a1Smrg while (tmp && *tmp) { 306818534a1Smrg if ((end = strchr(tmp, ',')) != NULL) 307818534a1Smrg *end++ = '\0'; 308818534a1Smrg if (Strcmp(tmp, lang) == 0) { 309818534a1Smrg strncpy(buf, set, 100); 310818534a1Smrg buf[99] = '\0'; 311818534a1Smrg Xfree(start); 312818534a1Smrg return buf; 313818534a1Smrg } 314818534a1Smrg tmp = end; 315818534a1Smrg } 316818534a1Smrg tmp = next; 317818534a1Smrg } while (tmp && *tmp); 3181ab64890Smrg Xfree(start); 3191ab64890Smrg return NULL; 3201ab64890Smrg} 3211ab64890Smrg#else 322818534a1Smrgchar * 3231ab64890Smrg_XkbGetCharset(void) 3241ab64890Smrg{ 3251ab64890Smrg char *tmp; 3261ab64890Smrg XLCd lcd; 3271ab64890Smrg 328818534a1Smrg tmp = getenv("_XKB_CHARSET"); 329818534a1Smrg if (tmp) 330818534a1Smrg return tmp; 3311ab64890Smrg 3321ab64890Smrg lcd = _XlcCurrentLC(); 333818534a1Smrg if (lcd) 334818534a1Smrg return XLC_PUBLIC(lcd, encoding_name); 3351ab64890Smrg 3361ab64890Smrg return NULL; 3371ab64890Smrg} 3381ab64890Smrg#endif 339