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