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