home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / evbl0627.zip / everblue_20010627.zip / x11 / XKBCvt.c < prev    next >
C/C++ Source or Header  |  1999-11-02  |  17KB  |  659 lines

  1. /* $TOG: XKBCvt.c /main/35 1998/05/30 20:29:41 kaleb $ */
  2. /*
  3.  
  4. Copyright 1988, 1989, 1998  The Open Group
  5.  
  6. All Rights Reserved.
  7.  
  8. The above copyright notice and this permission notice shall be included
  9. in all copies or substantial portions of the Software.
  10.  
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  12. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  13. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  14. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
  15. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  16. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  17. OTHER DEALINGS IN THE SOFTWARE.
  18.  
  19. Except as contained in this notice, the name of The Open Group shall
  20. not be used in advertising or otherwise to promote the sale, use or
  21. other dealings in this Software without prior written authorization
  22. from The Open Group.
  23.  
  24. */
  25. /* $XFree86: xc/lib/X11/XKBCvt.c,v 3.13.2.4 1998/10/21 06:40:37 dawes Exp $ */
  26.  
  27. #include <stdio.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30.  
  31. #include <X11/X.h>
  32. #include <X11/Xlib.h>
  33. #define NEED_EVENTS
  34. #include "Xlib_private.h"
  35. #include "Xlcint.h"
  36. #include "XlcPubI.h"
  37. #include <X11/Xutil.h>
  38. #include <X11/Xmd.h>
  39. #define XK_LATIN1
  40. #define XK_PUBLISHING
  41. #include <X11/keysym.h>
  42. #include <X11/extensions/XKBproto.h>
  43. #include "XKBlibint.h"
  44. #include <X11/Xlocale.h>
  45. #include <ctype.h>
  46. #include <X11/Xos.h>
  47.  
  48. #ifdef __sgi_not_xconsortium
  49. #define    XKB_EXTEND_LOOKUP_STRING
  50. #endif
  51.  
  52. #ifdef X_NOT_STDC_ENV
  53. extern char *getenv();
  54. #endif
  55.  
  56. #ifdef __STDC__
  57. #define Const const
  58. #else
  59. #define Const /**/
  60. #endif
  61. #if defined(__STDC__) && !defined(NORCONST)
  62. #define RConst const
  63. #else
  64. #define RConst /**/
  65. #endif
  66.  
  67. /* bit (1<<i) means character is in codeset i at the same codepoint */
  68. extern unsigned int _Xlatin1[];
  69.  
  70. /* bit (1<<i) means character is in codeset i at the same codepoint */
  71. extern unsigned int _Xlatin2[];
  72.  
  73. /* maps Cyrillic keysyms to KOI8-R */
  74. extern unsigned char _Xkoi8[];
  75.  
  76. extern unsigned short _Xkoi8_size;
  77.  
  78. #define sLatin1         0
  79. #define sLatin2         1
  80. #define sLatin3         2
  81. #define sLatin4         3
  82. #define sKana           4
  83. #define sX0201          0x01000004
  84. #define sArabic         5
  85. #define sCyrillic       6
  86. #define sGreek          7
  87. #define sAPL            11
  88. #define sHebrew         12
  89. #define sThai        13
  90. #define sKorean        14
  91. #define sLatin5        15
  92. #define sLatin6        16
  93. #define sLatin7        17
  94. #define sLatin8        18
  95. #define sLatin9        19
  96. #define sCurrency    32
  97.  
  98.  
  99. static unsigned long    WantLatin1 = sLatin1;
  100. static unsigned long    WantLatin2 = sLatin2;
  101. static unsigned long    WantLatin3 = sLatin3;
  102. static unsigned long    WantLatin4 = sLatin4;
  103. static unsigned long    WantLatin5 = sLatin5;
  104. static unsigned long    WantLatin6 = sLatin6;
  105. static unsigned long    WantKana = sKana;
  106. static unsigned long    WantX0201 = sX0201;
  107. static unsigned long    WantArabic = sArabic;
  108. static unsigned long    WantCyrillic = sCyrillic;
  109. static unsigned long    WantGreek = sGreek;
  110. static unsigned long    WantAPL = sAPL;
  111. static unsigned long    WantHebrew = sHebrew;
  112.  
  113. static int 
  114. #if NeedFunctionPrototypes
  115. _XkbHandleSpecialSym(KeySym keysym, char *buffer, int nbytes, int *extra_rtrn)
  116. #else
  117. _XkbHandleSpecialSym(keysym, buffer, nbytes, extra_rtrn)
  118.     KeySym     keysym;
  119.     char    *buffer;
  120.     int         nbytes;
  121.     int *     extra_rtrn;
  122. #endif
  123. {
  124.     DBUG_ENTER("_XkbHandleSpecialSym")
  125.  
  126.     /* try to convert to Latin-1, handling ctrl */
  127.     if (!(((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) ||
  128.        (keysym == XK_Return) || (keysym == XK_Escape) ||
  129.        (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) ||
  130.        (keysym == XK_KP_Enter) || 
  131.        ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) ||
  132.        (keysym == XK_KP_Equal) ||
  133.        (keysym == XK_Delete)))
  134.     DBUG_RETURN(0);
  135.  
  136.     if (nbytes<1) {
  137.     if (extra_rtrn) 
  138.         *extra_rtrn= 1;
  139.     DBUG_RETURN(0);
  140.     }
  141.     /* if X keysym, convert to ascii by grabbing low 7 bits */
  142.     if (keysym == XK_KP_Space)
  143.      buffer[0] = XK_space & 0x7F; /* patch encoding botch */
  144.     else if (keysym == XK_hyphen)
  145.      buffer[0] = (char)(XK_minus & 0xFF); /* map to equiv character */
  146.     else buffer[0] = (char)(keysym & 0x7F);
  147.     DBUG_RETURN(1);
  148. }
  149.  
  150. extern int
  151. _XGetCharCode (
  152. #if NeedFunctionPrototypes
  153.     unsigned long, KeySym, char*, int
  154. #endif
  155. );
  156.  
  157. /*ARGSUSED*/
  158. int 
  159. #if NeedFunctionPrototypes
  160. _XkbKSToKnownSet (    XPointer     priv,
  161.             KeySym         keysym,
  162.             char *        buffer,
  163.             int         nbytes,
  164.             int *        extra_rtrn)
  165. #else
  166. _XkbKSToKnownSet (priv, keysym, buffer, nbytes, extra_rtrn)
  167.     XPointer priv;
  168.     KeySym keysym;
  169.     char *buffer;
  170.     int nbytes;
  171.     int *extra_rtrn;
  172. #endif
  173. {
  174.     DBUG_ENTER("_XkbKSToKnownSet")
  175.     unsigned long kset,keysymSet;
  176.     int    count,isLatin1,result;
  177.     char tbuf[8],*buf;
  178.  
  179.     if (extra_rtrn)
  180.     *extra_rtrn= 0;
  181.  
  182.     keysymSet = *((unsigned long *)priv);
  183.     kset = keysymSet&0xffffff;
  184.  
  185.     /* convert "dead" diacriticals for dumb applications */
  186.     if ( (keysym&0xffffff00)== 0xfe00 ) {
  187.     switch ( keysym ) {
  188.         case XK_dead_grave:        keysym = XK_grave; break;
  189.         case XK_dead_acute:        keysym = XK_acute; break;
  190.         case XK_dead_circumflex:    keysym = XK_asciicircum; break;
  191.         case XK_dead_tilde:        keysym = XK_asciitilde; break;
  192.         case XK_dead_macron:    keysym = XK_macron; break;
  193.         case XK_dead_breve:        keysym = XK_breve; break;
  194.         case XK_dead_abovedot:    keysym = XK_abovedot; break;
  195.         case XK_dead_diaeresis:    keysym = XK_diaeresis; break;
  196.         case XK_dead_abovering:    keysym = XK_degree; break;
  197.         case XK_dead_doubleacute:    keysym = XK_doubleacute; break;
  198.         case XK_dead_caron:        keysym = XK_caron; break;
  199.         case XK_dead_cedilla:    keysym = XK_cedilla; break;
  200.         case XK_dead_ogonek    :    keysym = XK_ogonek; break;
  201.         case XK_dead_iota:        keysym = XK_Greek_iota; break;
  202. #ifdef XK_KATAKANA
  203.         case XK_dead_voiced_sound:    keysym = XK_voicedsound; break;
  204.         case XK_dead_semivoiced_sound:keysym = XK_semivoicedsound; break;
  205. #endif
  206.     }
  207.     }
  208.  
  209.     isLatin1 = ((keysym&0xffffff00)==0);
  210.     count = 0;
  211.  
  212.     if (nbytes<1)    buf= tbuf;
  213.     else        buf= buffer;
  214.  
  215.     if ((keysym&0xffffff00)==0xff00) {
  216.     result = _XkbHandleSpecialSym(keysym, buf, nbytes, extra_rtrn);
  217.     } else {
  218.         result = _XGetCharCode (keysymSet, keysym, buf, nbytes);
  219.     }
  220.     DBUG_RETURN(result);
  221. }
  222.  
  223. typedef struct _XkbToKS {
  224.     unsigned     prefix;
  225.     char        *map;
  226. } XkbToKS;
  227.  
  228. /*ARGSUSED*/
  229. static KeySym
  230. #if NeedFunctionPrototypes
  231. _XkbKnownSetToKS(XPointer priv,char *buffer,int nbytes,Status *status)
  232. #else
  233. _XkbKnownSetToKS(priv,buffer,nbytes,status)
  234.     XPointer priv;
  235.     char *buffer;
  236.     int nbytes;
  237.     Status *status;
  238. #endif
  239. {
  240.     DBUG_ENTER("_XkbKnownSetToKS")
  241.     if (nbytes!=1)
  242.     DBUG_RETURN(NoSymbol);
  243.     if (((buffer[0]&0x80)==0)&&(buffer[0]>=32)) {
  244.     DBUG_RETURN(buffer[0]);
  245.     } else if ((buffer[0]&0x7f)>=32) { 
  246.     XkbToKS *map= (XkbToKS *)priv;
  247.     if ( map ) {
  248.         if ( map->map ) {    DBUG_RETURN(map->prefix|map->map[buffer[0]&0x7f]);
  249.         } else        DBUG_RETURN(map->prefix|buffer[0]);
  250.     }
  251.     DBUG_RETURN(buffer[0]);
  252.     }
  253.     DBUG_RETURN(NoSymbol);
  254. }
  255.  
  256. /*ARGSUSED*/
  257. int 
  258. #if NeedFunctionPrototypes
  259. _XkbKSToThai (    XPointer     priv,
  260.         KeySym         keysym,
  261.         char *        buffer,
  262.         int         nbytes,
  263.         int *        extra_rtrn)
  264. #else
  265. _XkbKSToThai (priv, keysym, buffer, nbytes, extra_rtrn)
  266.     XPointer priv;
  267.     KeySym keysym;
  268.     char *buffer;
  269.     int nbytes;
  270.     int *extra_rtrn;
  271. #endif
  272. {
  273.     DBUG_ENTER("_XkbKSToThai")
  274.  
  275.     if ((keysym&0xffffff00)==0xff00) {
  276.         int result = _XkbHandleSpecialSym(keysym, buffer, nbytes, extra_rtrn);
  277.     DBUG_RETURN(result);
  278.     }
  279.     else if (((keysym&0xffffff80)==0xd80)||((keysym&0xffffff80)==0)) {
  280.         if (nbytes>0) {
  281.             buffer[0]= (char)(keysym&0xff);
  282.             if (nbytes>1)
  283.                 buffer[1]= '\0';
  284.             DBUG_RETURN(1);
  285.         }
  286.     if (extra_rtrn)
  287.         *extra_rtrn= 1;
  288.     }
  289.     DBUG_RETURN(0);
  290. }
  291.  
  292. /*ARGSUSED*/
  293. static KeySym
  294. #if NeedFunctionPrototypes
  295. _XkbThaiToKS(XPointer priv,char *buffer,int nbytes,Status *status)
  296. #else
  297. _XkbThaiToKS(priv,buffer,nbytes,status)
  298.     XPointer priv;
  299.     char *buffer;
  300.     int nbytes;
  301.     Status *status;
  302. #endif
  303. {
  304.     if (nbytes!=1)
  305.         return NoSymbol;
  306.     if (((buffer[0]&0x80)==0)&&(buffer[0]>=32))
  307.         return buffer[0];
  308.     else if ((buffer[0]&0x7f)>=32) {
  309.         return 0xd00|buffer[0];
  310.     }
  311.     return NoSymbol;
  312. }
  313.  
  314. static KeySym
  315. #if NeedFunctionPrototypes
  316. __XkbDefaultToUpper(KeySym sym)
  317. #else
  318. __XkbDefaultToUpper(sym)
  319.     KeySym    sym;
  320. #endif
  321. {
  322.     KeySym    lower,upper;
  323.  
  324.     XConvertCase(sym, &lower, &upper);
  325.     return upper;
  326. }
  327.  
  328. static int _XkbKSToKoi8 (priv, keysym, buffer, nbytes, status)
  329.     XPointer priv;
  330.     KeySym keysym;
  331.     char *buffer;
  332.     int nbytes;
  333.     Status *status;
  334. {
  335.     if ((keysym&0xffffff00)==0xff00) {
  336.         return _XkbHandleSpecialSym(keysym, buffer, nbytes, status);
  337.     }
  338.     else if (((keysym&0xffffff80)==0x680)||((keysym&0xffffff80)==0)) {
  339.     if (nbytes>0) {
  340.         if ( (keysym&0x80)==0 )
  341.          buffer[0] = keysym&0x7f;
  342.         else buffer[0] = _Xkoi8[keysym & 0x7f];
  343.         if (nbytes>1)
  344.         buffer[1]= '\0';
  345.         return 1;
  346.     }
  347.     }
  348.     return 0;
  349. }
  350.  
  351. static KeySym
  352. _XkbKoi8ToKS(priv,buffer,nbytes,status)
  353.     XPointer priv;
  354.     char *buffer;
  355.     int nbytes;
  356.     Status *status;
  357. {
  358.     if (nbytes!=1)
  359.         return NoSymbol;
  360.     if (((buffer[0]&0x80)==0)&&(buffer[0]>=32))
  361.         return buffer[0];
  362.     else if ((buffer[0]&0x7f)>=32) {
  363.     register int i;
  364.     for (i=0;i<_Xkoi8_size;i++) {
  365.         if (_Xkoi8[i]==buffer[0])
  366.         return 0x680|i;
  367.     }
  368.     }
  369.     return NoSymbol;
  370. }
  371.  
  372. /***====================================================================***/
  373.  
  374.  
  375. static XkbConverters RConst cvt_ascii = {
  376.     _XkbKSToKnownSet,(XPointer)&WantLatin1,_XkbKnownSetToKS,NULL,__XkbDefaultToUpper
  377. };
  378.  
  379. static XkbConverters RConst cvt_latin1 = {
  380.     _XkbKSToKnownSet,(XPointer)&WantLatin1,_XkbKnownSetToKS,NULL,NULL
  381. };
  382.  
  383. static XkbConverters RConst cvt_latin2 = {
  384.     _XkbKSToKnownSet,(XPointer)&WantLatin2,_XkbKnownSetToKS,NULL,NULL
  385. };
  386.  
  387. static XkbConverters RConst cvt_latin3 = {
  388.     _XkbKSToKnownSet,(XPointer)&WantLatin3,_XkbKnownSetToKS,NULL,NULL
  389. };
  390.  
  391. static XkbConverters RConst cvt_latin4 = {
  392.     _XkbKSToKnownSet,(XPointer)&WantLatin4,_XkbKnownSetToKS,NULL,NULL
  393. };
  394.  
  395. static XkbConverters RConst cvt_latin5 = {
  396.     _XkbKSToKnownSet,(XPointer)&WantLatin5,_XkbKnownSetToKS,NULL,NULL
  397. };
  398.  
  399. static XkbConverters RConst cvt_latin6 = {
  400.     _XkbKSToKnownSet,(XPointer)&WantLatin6,_XkbKnownSetToKS,NULL,NULL
  401. };
  402.  
  403. static XkbConverters RConst cvt_kana = {
  404.     _XkbKSToKnownSet,(XPointer)&WantKana,_XkbKnownSetToKS,NULL,NULL
  405. };
  406.  
  407. static XkbConverters RConst cvt_X0201 = {
  408.     _XkbKSToKnownSet,(XPointer)&WantX0201,_XkbKnownSetToKS,NULL,NULL
  409. };
  410.  
  411. static XkbConverters RConst cvt_Arabic = {
  412.     _XkbKSToKnownSet,(XPointer)&WantArabic,_XkbKnownSetToKS,NULL,NULL
  413. };
  414.  
  415. static XkbConverters RConst cvt_Cyrillic = {
  416.     _XkbKSToKnownSet,(XPointer)&WantCyrillic,_XkbKnownSetToKS,NULL,NULL
  417. };
  418.  
  419. static XkbConverters RConst cvt_Greek = {
  420.     _XkbKSToKnownSet,(XPointer)&WantGreek,_XkbKnownSetToKS,NULL,NULL
  421. };
  422.  
  423. static XkbConverters RConst cvt_APL = {
  424.     _XkbKSToKnownSet,(XPointer)&WantAPL,_XkbKnownSetToKS,NULL,NULL
  425. };
  426.  
  427. static XkbConverters RConst cvt_Hebrew = {
  428.     _XkbKSToKnownSet,(XPointer)&WantHebrew,_XkbKnownSetToKS,NULL,NULL
  429. };
  430.  
  431. static XkbConverters    cvt_Thai = {
  432.         _XkbKSToThai, NULL, _XkbThaiToKS, NULL, NULL
  433. };
  434.  
  435. static XkbConverters    cvt_Koi8 = {
  436.         _XkbKSToKoi8, NULL, _XkbKoi8ToKS, NULL, NULL
  437. };
  438.  
  439. static int
  440. #if NeedFunctionPrototypes
  441. Strcmp(char *str1, char *str2)
  442. #else
  443. Strcmp(str1, str2)
  444.     char *str1, *str2;
  445. #endif
  446. {
  447.     char str[256];
  448.     char c, *s;
  449.  
  450.     /*
  451.      * unchecked strings from the environment can end up here, so check
  452.      * the length before copying.
  453.      */
  454.     if (strlen(str1) >= sizeof(str)) /* almost certain it's a mismatch */
  455.     return 1;
  456.  
  457.     for (s = str; c = *str1++; ) {
  458.     if (isupper(c))
  459.         c = tolower(c);
  460.     *s++ = c;
  461.     }
  462.     *s = '\0';
  463.     return (strcmp(str, str2));
  464. }
  465.  
  466. int 
  467. #if NeedFunctionPrototypes
  468. _XkbGetConverters(char *encoding_name, XkbConverters *cvt_rtrn)
  469. #else
  470. _XkbGetConverters(encoding_name, cvt_rtrn)
  471.     char *encoding_name;
  472.     XkbConverters *cvt_rtrn;
  473. #endif
  474. {
  475.     if ( cvt_rtrn ) {
  476.     if ( (encoding_name==NULL) || 
  477.          (Strcmp(encoding_name,"ascii")==0) ||
  478.          (Strcmp(encoding_name,"string")==0) )
  479.          *cvt_rtrn = cvt_ascii;
  480.     else if (Strcmp(encoding_name,"iso8859-1")==0)
  481.          *cvt_rtrn = cvt_latin1;
  482.     else if (Strcmp(encoding_name, "iso8859-2")==0)
  483.          *cvt_rtrn = cvt_latin2;
  484.     else if (Strcmp(encoding_name, "iso8859-3")==0)
  485.          *cvt_rtrn = cvt_latin3;
  486.     else if (Strcmp(encoding_name, "iso8859-4")==0)
  487.          *cvt_rtrn = cvt_latin4;
  488.     else if (Strcmp(encoding_name, "iso8859-5")==0)
  489.          *cvt_rtrn = cvt_Cyrillic;
  490.     else if (Strcmp(encoding_name, "iso8859-6")==0)
  491.          *cvt_rtrn = cvt_Arabic;
  492.     else if (Strcmp(encoding_name, "iso8859-7")==0)
  493.          *cvt_rtrn = cvt_Greek;
  494.     else if (Strcmp(encoding_name, "iso8859-8")==0)
  495.          *cvt_rtrn = cvt_Hebrew;
  496.     else if (Strcmp(encoding_name, "iso8859-9")==0)
  497.          *cvt_rtrn = cvt_latin5;
  498.     else if (Strcmp(encoding_name, "iso8859-10")==0)
  499.          *cvt_rtrn = cvt_latin6;
  500.     else if (Strcmp(encoding_name, "apl")==0)
  501.          *cvt_rtrn = cvt_APL;
  502. #if 0
  503.     else if (Strcmp(encoding_name, "ja.euc")==0)
  504.          *cvt_rtrn = ???;
  505.     else if (Strcmp(encoding_name, "ja.jis")==0)
  506.          *cvt_rtrn = ???;
  507.     else if (Strcmp(encoding_name, "ja.sjis")==0)
  508.          *cvt_rtrn = ???;
  509. #endif 
  510.     else if (Strcmp(encoding_name, "jisx0201")==0) /* ??? */
  511.          *cvt_rtrn = cvt_X0201;
  512.     else if (Strcmp(encoding_name, "kana")==0) /* ??? */
  513.          *cvt_rtrn = cvt_kana;
  514.     else if ((Strcmp(encoding_name, "tactis")==0) ||
  515.          (Strcmp(encoding_name, "tis620.2533-1")==0))
  516.          *cvt_rtrn = cvt_Thai;
  517.     else if (Strcmp(encoding_name, "koi8-r")==0)
  518.          *cvt_rtrn = cvt_Koi8;
  519.     /* other codesets go here */
  520.     else *cvt_rtrn = cvt_latin1;
  521.     return 1;
  522.     }
  523.     *cvt_rtrn= cvt_latin1;
  524.     return 1;
  525. }
  526.  
  527. /***====================================================================***/
  528.  
  529. /* 
  530.  * The function _XkbGetCharset seems to be missnamed as what it seems to
  531.  * be used for is to determine the encoding-name for the locale. ???
  532.  */
  533.  
  534. #ifdef XKB_EXTEND_LOOKUP_STRING
  535.  
  536. /* 
  537.  * XKB_EXTEND_LOOKUP_STRING is not used by the SI. It is used by various
  538.  * X Consortium/X Project Team members, so we leave it in the source as
  539.  * an simplify integration by these companies.
  540.  */
  541.  
  542. #define    CHARSET_FILE    "/usr/lib/X11/input/charsets"
  543. static char *_XkbKnownLanguages = "c=ascii:da,de,en,es,fi,fr,is,it,nl,no,pt,sv=iso8859-1:hu,pl,cs=iso8859-2:bg,ru=iso8859-5:ar,ara=iso8859-6:el=iso8859-7:th,th_TH,th_TH.TACTIS=tactis";
  544.  
  545. char    *
  546. _XkbGetCharset()
  547. {
  548.     /*
  549.      * PAGE USAGE TUNING: explicitly initialize to move these to data
  550.      * instead of bss
  551.      */
  552.     static char buf[100] = { 0 };
  553.     char lang[256];
  554.     char *start,*tmp,*end,*next,*set;
  555.     char *country,*charset;
  556.     char *locale;
  557.  
  558.     tmp = getenv( "_XKB_CHARSET" );
  559.     if ( tmp )
  560.     return tmp;
  561.     locale = setlocale(LC_CTYPE,NULL);
  562.  
  563.     if ( locale == NULL )
  564.     return NULL;
  565.  
  566.     if (strlen(locale) >= sizeof(lang))
  567.     return NULL;
  568.  
  569.     for (tmp = lang; *tmp = *locale++; tmp++) {
  570.     if (isupper(*tmp))
  571.         *tmp = tolower(*tmp);
  572.     }
  573.     country = strchr( lang, '_');
  574.     if ( country ) {
  575.     *country++ = '\0';
  576.     charset = strchr( country, '.' );
  577.     if ( charset )    *charset++ = '\0';
  578.     if ( charset ) {
  579.         strncpy(buf,charset,99);
  580.         buf[99] = '\0';
  581.         return buf;
  582.     }
  583.     }
  584.     else { 
  585.     charset = NULL;
  586.     }
  587.  
  588.     if ((tmp = getenv("_XKB_LOCALE_CHARSETS"))!=NULL) {
  589.     start = _XkbAlloc(strlen(tmp) + 1);
  590.     strcpy(start, tmp);
  591.     tmp = start;
  592.     } else {
  593.     struct stat sbuf;
  594.     FILE *file;
  595. #ifndef __EMX__
  596.     char *cf = CHARSET_FILE;
  597. #else
  598.         char *cf = __XOS2RedirRoot(CHARSET_FILE);
  599. #endif
  600.     if ( (stat(cf,&sbuf)==0) && (sbuf.st_mode&S_IFREG) &&
  601.         (file = fopen(cf,"r")) ) {
  602.         tmp = _XkbAlloc(sbuf.st_size+1);
  603.         if (tmp!=NULL) {
  604.         sbuf.st_size = (long)fread(tmp,1,sbuf.st_size,file);
  605.         tmp[sbuf.st_size] = '\0';
  606.         }
  607.         fclose(file);
  608.     }
  609.     }
  610.  
  611.     if ( tmp == NULL ) {
  612.     tmp = _XkbAlloc(strlen(_XkbKnownLanguages) + 1);
  613.     if (!tmp)
  614.         return NULL;
  615.     strcpy(tmp, _XkbKnownLanguages);
  616.     }
  617.     start = tmp;
  618.     do {
  619.     if ( (set=strchr(tmp,'=')) == NULL )
  620.         break;
  621.     *set++ = '\0';
  622.     if ( (next=strchr(set,':')) != NULL ) 
  623.         *next++ = '\0';
  624.     while ( tmp && *tmp ) {
  625.         if ( (end=strchr(tmp,',')) != NULL )
  626.         *end++ = '\0';
  627.         if ( Strcmp( tmp, lang ) == 0 ) {
  628.         strncpy(buf,set,100);
  629.         buf[99] = '\0';
  630.         Xfree(start);
  631.         return buf;
  632.         }
  633.         tmp = end;
  634.     }
  635.     tmp = next;
  636.     } while ( tmp && *tmp );
  637.     Xfree(start);
  638.     return NULL;
  639. }
  640. #else
  641. char    *
  642. _XkbGetCharset()
  643. {
  644.     char *tmp;
  645.     XLCd lcd;
  646.  
  647.     tmp = getenv( "_XKB_CHARSET" );
  648.     if ( tmp )
  649.     return tmp;
  650.  
  651.     lcd = _XlcCurrentLC();
  652.     if ( lcd )
  653.     return XLC_PUBLIC(lcd,encoding_name);
  654.  
  655.     return NULL;
  656. }
  657. #endif
  658.  
  659.