XKBCvt.c revision 61b2299d
11ab64890Smrg/* $Xorg: XKBCvt.c,v 1.5 2001/02/09 02:03:38 xorgcvs Exp $ */ 21ab64890Smrg/* 31ab64890Smrg 41ab64890SmrgCopyright 1988, 1989, 1998 The Open Group 51ab64890Smrg 61ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its 71ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that 81ab64890Smrgthe above copyright notice appear in all copies and that both that 91ab64890Smrgcopyright notice and this permission notice appear in supporting 101ab64890Smrgdocumentation. 111ab64890Smrg 121ab64890SmrgThe above copyright notice and this permission notice shall be included 131ab64890Smrgin all copies or substantial portions of the Software. 141ab64890Smrg 151ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 161ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 171ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 181ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 191ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 201ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 211ab64890SmrgOTHER DEALINGS IN THE SOFTWARE. 221ab64890Smrg 231ab64890SmrgExcept as contained in this notice, the name of The Open Group shall 241ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or 251ab64890Smrgother dealings in this Software without prior written authorization 261ab64890Smrgfrom The Open Group. 271ab64890Smrg 281ab64890Smrg*/ 291ab64890Smrg/* $XFree86: xc/lib/X11/XKBCvt.c,v 3.34 2002/10/08 23:31:35 dawes Exp $ */ 301ab64890Smrg 311ab64890Smrg#ifdef HAVE_CONFIG_H 321ab64890Smrg#include <config.h> 331ab64890Smrg#endif 341ab64890Smrg#include <stdio.h> 351ab64890Smrg#include <sys/types.h> 361ab64890Smrg#include <sys/stat.h> 371ab64890Smrg 381ab64890Smrg#include <X11/X.h> 391ab64890Smrg#include <X11/Xlib.h> 401ab64890Smrg#define NEED_EVENTS 411ab64890Smrg#include "Xlibint.h" 421ab64890Smrg#include "Xlcint.h" 431ab64890Smrg#include "XlcPubI.h" 441ab64890Smrg#include "Ximint.h" 451ab64890Smrg#include <X11/Xutil.h> 461ab64890Smrg#include <X11/Xmd.h> 471ab64890Smrg#define XK_LATIN1 481ab64890Smrg#define XK_PUBLISHING 491ab64890Smrg#include <X11/keysym.h> 501ab64890Smrg#include <X11/extensions/XKBproto.h> 511ab64890Smrg#include "XKBlibint.h" 521ab64890Smrg#include <X11/Xlocale.h> 531ab64890Smrg#include <ctype.h> 541ab64890Smrg#include <X11/Xos.h> 551ab64890Smrg 561ab64890Smrg#ifdef __sgi_not_xconsortium 571ab64890Smrg#define XKB_EXTEND_LOOKUP_STRING 581ab64890Smrg#endif 591ab64890Smrg 6061b2299dSmrgstatic int 611ab64890Smrg_XkbHandleSpecialSym(KeySym keysym, char *buffer, int nbytes, int *extra_rtrn) 621ab64890Smrg{ 631ab64890Smrg 641ab64890Smrg /* try to convert to Latin-1, handling ctrl */ 651ab64890Smrg if (!(((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) || 661ab64890Smrg (keysym == XK_Return) || (keysym == XK_Escape) || 671ab64890Smrg (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) || 6861b2299dSmrg (keysym == XK_KP_Enter) || 691ab64890Smrg ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) || 701ab64890Smrg (keysym == XK_KP_Equal) || 711ab64890Smrg (keysym == XK_Delete))) 721ab64890Smrg return 0; 731ab64890Smrg 741ab64890Smrg if (nbytes<1) { 7561b2299dSmrg if (extra_rtrn) 761ab64890Smrg *extra_rtrn= 1; 771ab64890Smrg return 0; 781ab64890Smrg } 791ab64890Smrg /* if X keysym, convert to ascii by grabbing low 7 bits */ 801ab64890Smrg if (keysym == XK_KP_Space) 811ab64890Smrg buffer[0] = XK_space & 0x7F; /* patch encoding botch */ 821ab64890Smrg else if (keysym == XK_hyphen) 831ab64890Smrg buffer[0] = (char)(XK_minus & 0xFF); /* map to equiv character */ 841ab64890Smrg else buffer[0] = (char)(keysym & 0x7F); 851ab64890Smrg return 1; 861ab64890Smrg} 871ab64890Smrg 881ab64890Smrg/*ARGSUSED*/ 8961b2299dSmrgstatic int 901ab64890Smrg_XkbKSToKnownSet ( XPointer priv, 911ab64890Smrg KeySym keysym, 921ab64890Smrg char * buffer, 931ab64890Smrg int nbytes, 941ab64890Smrg int * extra_rtrn) 951ab64890Smrg{ 961ab64890Smrg char tbuf[8],*buf; 971ab64890Smrg 981ab64890Smrg if (extra_rtrn) 991ab64890Smrg *extra_rtrn= 0; 1001ab64890Smrg 1011ab64890Smrg /* convert "dead" diacriticals for dumb applications */ 1021ab64890Smrg if ( (keysym&0xffffff00)== 0xfe00 ) { 1031ab64890Smrg switch ( keysym ) { 1041ab64890Smrg case XK_dead_grave: keysym = XK_grave; break; 1051ab64890Smrg case XK_dead_acute: keysym = XK_acute; break; 1061ab64890Smrg case XK_dead_circumflex: keysym = XK_asciicircum; break; 1071ab64890Smrg case XK_dead_tilde: keysym = XK_asciitilde; break; 1081ab64890Smrg case XK_dead_macron: keysym = XK_macron; break; 1091ab64890Smrg case XK_dead_breve: keysym = XK_breve; break; 1101ab64890Smrg case XK_dead_abovedot: keysym = XK_abovedot; break; 1111ab64890Smrg case XK_dead_diaeresis: keysym = XK_diaeresis; break; 1121ab64890Smrg case XK_dead_abovering: keysym = XK_degree; break; 1131ab64890Smrg case XK_dead_doubleacute: keysym = XK_doubleacute; break; 1141ab64890Smrg case XK_dead_caron: keysym = XK_caron; break; 1151ab64890Smrg case XK_dead_cedilla: keysym = XK_cedilla; break; 1161ab64890Smrg case XK_dead_ogonek : keysym = XK_ogonek; break; 1171ab64890Smrg case XK_dead_iota: keysym = XK_Greek_iota; break; 1181ab64890Smrg#ifdef XK_KATAKANA 1191ab64890Smrg case XK_dead_voiced_sound: keysym = XK_voicedsound; break; 1201ab64890Smrg case XK_dead_semivoiced_sound:keysym = XK_semivoicedsound; break; 1211ab64890Smrg#endif 1221ab64890Smrg } 1231ab64890Smrg } 1241ab64890Smrg 1251ab64890Smrg if (nbytes<1) buf= tbuf; 1261ab64890Smrg else buf= buffer; 1271ab64890Smrg 1281ab64890Smrg if ((keysym&0xffffff00)==0xff00) { 1291ab64890Smrg return _XkbHandleSpecialSym(keysym, buf, nbytes, extra_rtrn); 1301ab64890Smrg } 1311ab64890Smrg return _XimGetCharCode (priv, keysym, (unsigned char *)buf, nbytes); 1321ab64890Smrg} 1331ab64890Smrg 1341ab64890Smrgtypedef struct _XkbToKS { 1351ab64890Smrg unsigned prefix; 1361ab64890Smrg char *map; 1371ab64890Smrg} XkbToKS; 1381ab64890Smrg 1391ab64890Smrg/*ARGSUSED*/ 1401ab64890Smrgstatic KeySym 1411ab64890Smrg_XkbKnownSetToKS(XPointer priv,char *buffer,int nbytes,Status *status) 1421ab64890Smrg{ 1431ab64890Smrg if (nbytes!=1) 1441ab64890Smrg return NoSymbol; 1451ab64890Smrg if (((buffer[0]&0x80)==0)&&(buffer[0]>=32)) 1461ab64890Smrg return buffer[0]; 14761b2299dSmrg else if ((buffer[0]&0x7f)>=32) { 1481ab64890Smrg XkbToKS *map= (XkbToKS *)priv; 1491ab64890Smrg if ( map ) { 1501ab64890Smrg if ( map->map ) return map->prefix|map->map[buffer[0]&0x7f]; 1511ab64890Smrg else return map->prefix|buffer[0]; 1521ab64890Smrg } 1531ab64890Smrg return buffer[0]; 1541ab64890Smrg } 1551ab64890Smrg return NoSymbol; 1561ab64890Smrg} 1571ab64890Smrg 1581ab64890Smrgstatic KeySym 1591ab64890Smrg__XkbDefaultToUpper(KeySym sym) 1601ab64890Smrg{ 1611ab64890Smrg KeySym lower,upper; 1621ab64890Smrg 1631ab64890Smrg XConvertCase(sym, &lower, &upper); 1641ab64890Smrg return upper; 1651ab64890Smrg} 1661ab64890Smrg 1671ab64890Smrg#ifdef XKB_EXTEND_LOOKUP_STRING 1681ab64890Smrgstatic int 1691ab64890SmrgStrcmp(char *str1, char *str2) 1701ab64890Smrg{ 1711ab64890Smrg char str[256]; 1721ab64890Smrg char c, *s; 1731ab64890Smrg 1741ab64890Smrg /* 1751ab64890Smrg * unchecked strings from the environment can end up here, so check 1761ab64890Smrg * the length before copying. 1771ab64890Smrg */ 1781ab64890Smrg if (strlen(str1) >= sizeof(str)) /* almost certain it's a mismatch */ 1791ab64890Smrg return 1; 1801ab64890Smrg 1811ab64890Smrg for (s = str; (c = *str1++); ) { 1821ab64890Smrg if (isupper(c)) 1831ab64890Smrg c = tolower(c); 1841ab64890Smrg *s++ = c; 1851ab64890Smrg } 1861ab64890Smrg *s = '\0'; 1871ab64890Smrg return (strcmp(str, str2)); 1881ab64890Smrg} 1891ab64890Smrg#endif 1901ab64890Smrg 19161b2299dSmrgint 1921ab64890Smrg_XkbGetConverters(const char *encoding_name, XkbConverters *cvt_rtrn) 1931ab64890Smrg{ 1941ab64890Smrg if ( !cvt_rtrn ) return 0; 1951ab64890Smrg 1961ab64890Smrg cvt_rtrn->KSToMB = _XkbKSToKnownSet; 1971ab64890Smrg cvt_rtrn->KSToMBPriv = _XimGetLocaleCode(encoding_name); 1981ab64890Smrg cvt_rtrn->MBToKS = _XkbKnownSetToKS; 1991ab64890Smrg cvt_rtrn->MBToKSPriv = NULL; 2001ab64890Smrg cvt_rtrn->KSToUpper = __XkbDefaultToUpper; 2011ab64890Smrg return 1; 2021ab64890Smrg} 2031ab64890Smrg 2041ab64890Smrg/***====================================================================***/ 2051ab64890Smrg 20661b2299dSmrg/* 2071ab64890Smrg * The function _XkbGetCharset seems to be missnamed as what it seems to 2081ab64890Smrg * be used for is to determine the encoding-name for the locale. ??? 2091ab64890Smrg */ 2101ab64890Smrg 2111ab64890Smrg#ifdef XKB_EXTEND_LOOKUP_STRING 2121ab64890Smrg 21361b2299dSmrg/* 2141ab64890Smrg * XKB_EXTEND_LOOKUP_STRING is not used by the SI. It is used by various 2151ab64890Smrg * X Consortium/X Project Team members, so we leave it in the source as 2161ab64890Smrg * an simplify integration by these companies. 2171ab64890Smrg */ 2181ab64890Smrg 2191ab64890Smrg#define CHARSET_FILE "/usr/lib/X11/input/charsets" 2201ab64890Smrgstatic char *_XkbKnownLanguages = "c=ascii:da,de,en,es,fr,is,it,nl,no,pt,sv=iso8859-1:hu,pl,cs=iso8859-2:eo=iso8859-3:sp=iso8859-5:ar,ara=iso8859-6:el=iso8859-7:he=iso8859-8:tr=iso8859-9:lt,lv=iso8859-13:et,fi=iso8859-15:ru=koi8-r:uk=koi8-u:th,th_TH,th_TH.iso8859-11=iso8859-11:th_TH.TIS620=tis620:hy=armscii-8:vi=tcvn-5712:ka=georgian-academy:be,bg=microsoft-cp1251"; 2211ab64890Smrg 2221ab64890Smrgchar * 2231ab64890Smrg_XkbGetCharset(void) 2241ab64890Smrg{ 2251ab64890Smrg /* 2261ab64890Smrg * PAGE USAGE TUNING: explicitly initialize to move these to data 2271ab64890Smrg * instead of bss 2281ab64890Smrg */ 2291ab64890Smrg static char buf[100] = { 0 }; 2301ab64890Smrg char lang[256]; 2311ab64890Smrg char *start,*tmp,*end,*next,*set; 2321ab64890Smrg char *country,*charset; 2331ab64890Smrg char *locale; 2341ab64890Smrg 2351ab64890Smrg tmp = getenv( "_XKB_CHARSET" ); 2361ab64890Smrg if ( tmp ) 2371ab64890Smrg return tmp; 2381ab64890Smrg locale = setlocale(LC_CTYPE,NULL); 2391ab64890Smrg 2401ab64890Smrg if ( locale == NULL ) 2411ab64890Smrg return NULL; 2421ab64890Smrg 2431ab64890Smrg if (strlen(locale) >= sizeof(lang)) 2441ab64890Smrg return NULL; 2451ab64890Smrg 2461ab64890Smrg for (tmp = lang; *tmp = *locale++; tmp++) { 2471ab64890Smrg if (isupper(*tmp)) 2481ab64890Smrg *tmp = tolower(*tmp); 2491ab64890Smrg } 2501ab64890Smrg country = strchr( lang, '_'); 2511ab64890Smrg if ( country ) { 2521ab64890Smrg *country++ = '\0'; 2531ab64890Smrg charset = strchr( country, '.' ); 2541ab64890Smrg if ( charset ) *charset++ = '\0'; 2551ab64890Smrg if ( charset ) { 2561ab64890Smrg strncpy(buf,charset,99); 2571ab64890Smrg buf[99] = '\0'; 2581ab64890Smrg return buf; 2591ab64890Smrg } 2601ab64890Smrg } 26161b2299dSmrg else { 2621ab64890Smrg charset = NULL; 2631ab64890Smrg } 2641ab64890Smrg 2651ab64890Smrg if ((tmp = getenv("_XKB_LOCALE_CHARSETS"))!=NULL) { 2661ab64890Smrg start = _XkbAlloc(strlen(tmp) + 1); 2671ab64890Smrg strcpy(start, tmp); 2681ab64890Smrg tmp = start; 2691ab64890Smrg } else { 2701ab64890Smrg struct stat sbuf; 2711ab64890Smrg FILE *file; 2721ab64890Smrg#ifndef __UNIXOS2__ 2731ab64890Smrg char *cf = CHARSET_FILE; 2741ab64890Smrg#else 2751ab64890Smrg char *cf = __XOS2RedirRoot(CHARSET_FILE); 2761ab64890Smrg#endif 2771ab64890Smrg 2781ab64890Smrg#ifndef S_ISREG 2791ab64890Smrg# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 2801ab64890Smrg#endif 28161b2299dSmrg 2821ab64890Smrg if ( (stat(cf,&sbuf)==0) && S_ISREG(sbuf.st_mode) && 2831ab64890Smrg (file = fopen(cf,"r")) ) { 2841ab64890Smrg tmp = _XkbAlloc(sbuf.st_size+1); 2851ab64890Smrg if (tmp!=NULL) { 2861ab64890Smrg sbuf.st_size = (long)fread(tmp,1,sbuf.st_size,file); 2871ab64890Smrg tmp[sbuf.st_size] = '\0'; 2881ab64890Smrg } 2891ab64890Smrg fclose(file); 2901ab64890Smrg } 2911ab64890Smrg } 2921ab64890Smrg 2931ab64890Smrg if ( tmp == NULL ) { 2941ab64890Smrg tmp = _XkbAlloc(strlen(_XkbKnownLanguages) + 1); 2951ab64890Smrg if (!tmp) 2961ab64890Smrg return NULL; 2971ab64890Smrg strcpy(tmp, _XkbKnownLanguages); 2981ab64890Smrg } 2991ab64890Smrg start = tmp; 3001ab64890Smrg do { 3011ab64890Smrg if ( (set=strchr(tmp,'=')) == NULL ) 3021ab64890Smrg break; 3031ab64890Smrg *set++ = '\0'; 30461b2299dSmrg if ( (next=strchr(set,':')) != NULL ) 3051ab64890Smrg *next++ = '\0'; 3061ab64890Smrg while ( tmp && *tmp ) { 3071ab64890Smrg if ( (end=strchr(tmp,',')) != NULL ) 3081ab64890Smrg *end++ = '\0'; 3091ab64890Smrg if ( Strcmp( tmp, lang ) == 0 ) { 3101ab64890Smrg strncpy(buf,set,100); 3111ab64890Smrg buf[99] = '\0'; 3121ab64890Smrg Xfree(start); 3131ab64890Smrg return buf; 3141ab64890Smrg } 3151ab64890Smrg tmp = end; 3161ab64890Smrg } 3171ab64890Smrg tmp = next; 3181ab64890Smrg } while ( tmp && *tmp ); 3191ab64890Smrg Xfree(start); 3201ab64890Smrg return NULL; 3211ab64890Smrg} 3221ab64890Smrg#else 3231ab64890Smrgchar * 3241ab64890Smrg_XkbGetCharset(void) 3251ab64890Smrg{ 3261ab64890Smrg char *tmp; 3271ab64890Smrg XLCd lcd; 3281ab64890Smrg 3291ab64890Smrg tmp = getenv( "_XKB_CHARSET" ); 3301ab64890Smrg if ( tmp ) 3311ab64890Smrg return tmp; 3321ab64890Smrg 3331ab64890Smrg lcd = _XlcCurrentLC(); 3341ab64890Smrg if ( lcd ) 3351ab64890Smrg return XLC_PUBLIC(lcd,encoding_name); 3361ab64890Smrg 3371ab64890Smrg return NULL; 3381ab64890Smrg} 3391ab64890Smrg#endif 3401ab64890Smrg 341