XKBCvt.c revision b4ee4795
1/* 2 3Copyright 1988, 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29#ifdef HAVE_CONFIG_H 30#include <config.h> 31#endif 32#include <stdio.h> 33#include <sys/types.h> 34#include <sys/stat.h> 35 36#include <X11/X.h> 37#include <X11/Xlib.h> 38#define NEED_EVENTS 39#include "Xlibint.h" 40#include "Xlcint.h" 41#include "XlcPubI.h" 42#include "Ximint.h" 43#include <X11/Xutil.h> 44#include <X11/Xmd.h> 45#define XK_LATIN1 46#define XK_PUBLISHING 47#include <X11/keysym.h> 48#include <X11/extensions/XKBproto.h> 49#include "XKBlibint.h" 50#include <X11/Xlocale.h> 51#include <ctype.h> 52#include <X11/Xos.h> 53 54#ifdef __sgi_not_xconsortium 55#define XKB_EXTEND_LOOKUP_STRING 56#endif 57 58static int 59_XkbHandleSpecialSym(KeySym keysym, char *buffer, int nbytes, int *extra_rtrn) 60{ 61 62 /* try to convert to Latin-1, handling ctrl */ 63 if (!(((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) || 64 (keysym == XK_Return) || (keysym == XK_Escape) || 65 (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) || 66 (keysym == XK_KP_Enter) || 67 ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) || 68 (keysym == XK_KP_Equal) || 69 (keysym == XK_Delete))) 70 return 0; 71 72 if (nbytes<1) { 73 if (extra_rtrn) 74 *extra_rtrn= 1; 75 return 0; 76 } 77 /* if X keysym, convert to ascii by grabbing low 7 bits */ 78 if (keysym == XK_KP_Space) 79 buffer[0] = XK_space & 0x7F; /* patch encoding botch */ 80 else if (keysym == XK_hyphen) 81 buffer[0] = (char)(XK_minus & 0xFF); /* map to equiv character */ 82 else buffer[0] = (char)(keysym & 0x7F); 83 return 1; 84} 85 86/*ARGSUSED*/ 87static int 88_XkbKSToKnownSet ( XPointer priv, 89 KeySym keysym, 90 char * buffer, 91 int nbytes, 92 int * extra_rtrn) 93{ 94 char tbuf[8],*buf; 95 96 if (extra_rtrn) 97 *extra_rtrn= 0; 98 99 /* convert "dead" diacriticals for dumb applications */ 100 if ( (keysym&0xffffff00)== 0xfe00 ) { 101 switch ( keysym ) { 102 case XK_dead_grave: keysym = XK_grave; break; 103 case XK_dead_acute: keysym = XK_acute; break; 104 case XK_dead_circumflex: keysym = XK_asciicircum; break; 105 case XK_dead_tilde: keysym = XK_asciitilde; break; 106 case XK_dead_macron: keysym = XK_macron; break; 107 case XK_dead_breve: keysym = XK_breve; break; 108 case XK_dead_abovedot: keysym = XK_abovedot; break; 109 case XK_dead_diaeresis: keysym = XK_diaeresis; break; 110 case XK_dead_abovering: keysym = XK_degree; break; 111 case XK_dead_doubleacute: keysym = XK_doubleacute; break; 112 case XK_dead_caron: keysym = XK_caron; break; 113 case XK_dead_cedilla: keysym = XK_cedilla; break; 114 case XK_dead_ogonek : keysym = XK_ogonek; break; 115 case XK_dead_iota: keysym = XK_Greek_iota; break; 116#ifdef XK_KATAKANA 117 case XK_dead_voiced_sound: keysym = XK_voicedsound; break; 118 case XK_dead_semivoiced_sound:keysym = XK_semivoicedsound; break; 119#endif 120 } 121 } 122 123 if (nbytes<1) buf= tbuf; 124 else buf= buffer; 125 126 if ((keysym&0xffffff00)==0xff00) { 127 return _XkbHandleSpecialSym(keysym, buf, nbytes, extra_rtrn); 128 } 129 return _XimGetCharCode (priv, keysym, (unsigned char *)buf, nbytes); 130} 131 132typedef struct _XkbToKS { 133 unsigned prefix; 134 char *map; 135} XkbToKS; 136 137/*ARGSUSED*/ 138static KeySym 139_XkbKnownSetToKS(XPointer priv,char *buffer,int nbytes,Status *status) 140{ 141 if (nbytes!=1) 142 return NoSymbol; 143 if (((buffer[0]&0x80)==0)&&(buffer[0]>=32)) 144 return buffer[0]; 145 else if ((buffer[0]&0x7f)>=32) { 146 XkbToKS *map= (XkbToKS *)priv; 147 if ( map ) { 148 if ( map->map ) return map->prefix|map->map[buffer[0]&0x7f]; 149 else return map->prefix|buffer[0]; 150 } 151 return buffer[0]; 152 } 153 return NoSymbol; 154} 155 156static KeySym 157__XkbDefaultToUpper(KeySym sym) 158{ 159 KeySym lower,upper; 160 161 XConvertCase(sym, &lower, &upper); 162 return upper; 163} 164 165#ifdef XKB_EXTEND_LOOKUP_STRING 166static int 167Strcmp(char *str1, char *str2) 168{ 169 char str[256]; 170 char c, *s; 171 172 /* 173 * unchecked strings from the environment can end up here, so check 174 * the length before copying. 175 */ 176 if (strlen(str1) >= sizeof(str)) /* almost certain it's a mismatch */ 177 return 1; 178 179 for (s = str; (c = *str1++); ) { 180 if (isupper(c)) 181 c = tolower(c); 182 *s++ = c; 183 } 184 *s = '\0'; 185 return (strcmp(str, str2)); 186} 187#endif 188 189int 190_XkbGetConverters(const char *encoding_name, XkbConverters *cvt_rtrn) 191{ 192 if ( !cvt_rtrn ) return 0; 193 194 cvt_rtrn->KSToMB = _XkbKSToKnownSet; 195 cvt_rtrn->KSToMBPriv = _XimGetLocaleCode(encoding_name); 196 cvt_rtrn->MBToKS = _XkbKnownSetToKS; 197 cvt_rtrn->MBToKSPriv = NULL; 198 cvt_rtrn->KSToUpper = __XkbDefaultToUpper; 199 return 1; 200} 201 202/***====================================================================***/ 203 204/* 205 * The function _XkbGetCharset seems to be missnamed as what it seems to 206 * be used for is to determine the encoding-name for the locale. ??? 207 */ 208 209#ifdef XKB_EXTEND_LOOKUP_STRING 210 211/* 212 * XKB_EXTEND_LOOKUP_STRING is not used by the SI. It is used by various 213 * X Consortium/X Project Team members, so we leave it in the source as 214 * an simplify integration by these companies. 215 */ 216 217#define CHARSET_FILE "/usr/lib/X11/input/charsets" 218static 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"; 219 220char * 221_XkbGetCharset(void) 222{ 223 /* 224 * PAGE USAGE TUNING: explicitly initialize to move these to data 225 * instead of bss 226 */ 227 static char buf[100] = { 0 }; 228 char lang[256]; 229 char *start,*tmp,*end,*next,*set; 230 char *country,*charset; 231 char *locale; 232 233 tmp = getenv( "_XKB_CHARSET" ); 234 if ( tmp ) 235 return tmp; 236 locale = setlocale(LC_CTYPE,NULL); 237 238 if ( locale == NULL ) 239 return NULL; 240 241 if (strlen(locale) >= sizeof(lang)) 242 return NULL; 243 244 for (tmp = lang; *tmp = *locale++; tmp++) { 245 if (isupper(*tmp)) 246 *tmp = tolower(*tmp); 247 } 248 country = strchr( lang, '_'); 249 if ( country ) { 250 *country++ = '\0'; 251 charset = strchr( country, '.' ); 252 if ( charset ) *charset++ = '\0'; 253 if ( charset ) { 254 strncpy(buf,charset,99); 255 buf[99] = '\0'; 256 return buf; 257 } 258 } 259 else { 260 charset = NULL; 261 } 262 263 if ((tmp = getenv("_XKB_LOCALE_CHARSETS"))!=NULL) { 264 start = _XkbAlloc(strlen(tmp) + 1); 265 strcpy(start, tmp); 266 tmp = start; 267 } else { 268 struct stat sbuf; 269 FILE *file; 270#ifndef __UNIXOS2__ 271 char *cf = CHARSET_FILE; 272#else 273 char *cf = __XOS2RedirRoot(CHARSET_FILE); 274#endif 275 276#ifndef S_ISREG 277# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 278#endif 279 280 if ( (stat(cf,&sbuf)==0) && S_ISREG(sbuf.st_mode) && 281 (file = fopen(cf,"r")) ) { 282 tmp = _XkbAlloc(sbuf.st_size+1); 283 if (tmp!=NULL) { 284 sbuf.st_size = (long)fread(tmp,1,sbuf.st_size,file); 285 tmp[sbuf.st_size] = '\0'; 286 } 287 fclose(file); 288 } 289 } 290 291 if ( tmp == NULL ) { 292 tmp = _XkbAlloc(strlen(_XkbKnownLanguages) + 1); 293 if (!tmp) 294 return NULL; 295 strcpy(tmp, _XkbKnownLanguages); 296 } 297 start = tmp; 298 do { 299 if ( (set=strchr(tmp,'=')) == NULL ) 300 break; 301 *set++ = '\0'; 302 if ( (next=strchr(set,':')) != NULL ) 303 *next++ = '\0'; 304 while ( tmp && *tmp ) { 305 if ( (end=strchr(tmp,',')) != NULL ) 306 *end++ = '\0'; 307 if ( Strcmp( tmp, lang ) == 0 ) { 308 strncpy(buf,set,100); 309 buf[99] = '\0'; 310 Xfree(start); 311 return buf; 312 } 313 tmp = end; 314 } 315 tmp = next; 316 } while ( tmp && *tmp ); 317 Xfree(start); 318 return NULL; 319} 320#else 321char * 322_XkbGetCharset(void) 323{ 324 char *tmp; 325 XLCd lcd; 326 327 tmp = getenv( "_XKB_CHARSET" ); 328 if ( tmp ) 329 return tmp; 330 331 lcd = _XlcCurrentLC(); 332 if ( lcd ) 333 return XLC_PUBLIC(lcd,encoding_name); 334 335 return NULL; 336} 337#endif 338 339