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