XKBCvt.c revision 61b2299d
11ab64890Smrg/* $Xorg: XKBCvt.c,v 1.5 2001/02/09 02:03:38 xorgcvs Exp $ */
21ab64890Smrg/*
31ab64890Smrg
41ab64890SmrgCopyright 1988, 1989, 1998  The Open Group
51ab64890Smrg
61ab64890SmrgPermission to use, copy, modify, distribute, and sell this software and its
71ab64890Smrgdocumentation for any purpose is hereby granted without fee, provided that
81ab64890Smrgthe above copyright notice appear in all copies and that both that
91ab64890Smrgcopyright notice and this permission notice appear in supporting
101ab64890Smrgdocumentation.
111ab64890Smrg
121ab64890SmrgThe above copyright notice and this permission notice shall be included
131ab64890Smrgin all copies or substantial portions of the Software.
141ab64890Smrg
151ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
161ab64890SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
171ab64890SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
181ab64890SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
191ab64890SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
201ab64890SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
211ab64890SmrgOTHER DEALINGS IN THE SOFTWARE.
221ab64890Smrg
231ab64890SmrgExcept as contained in this notice, the name of The Open Group shall
241ab64890Smrgnot be used in advertising or otherwise to promote the sale, use or
251ab64890Smrgother dealings in this Software without prior written authorization
261ab64890Smrgfrom The Open Group.
271ab64890Smrg
281ab64890Smrg*/
291ab64890Smrg/* $XFree86: xc/lib/X11/XKBCvt.c,v 3.34 2002/10/08 23:31:35 dawes Exp $ */
301ab64890Smrg
311ab64890Smrg#ifdef HAVE_CONFIG_H
321ab64890Smrg#include <config.h>
331ab64890Smrg#endif
341ab64890Smrg#include <stdio.h>
351ab64890Smrg#include <sys/types.h>
361ab64890Smrg#include <sys/stat.h>
371ab64890Smrg
381ab64890Smrg#include <X11/X.h>
391ab64890Smrg#include <X11/Xlib.h>
401ab64890Smrg#define NEED_EVENTS
411ab64890Smrg#include "Xlibint.h"
421ab64890Smrg#include "Xlcint.h"
431ab64890Smrg#include "XlcPubI.h"
441ab64890Smrg#include "Ximint.h"
451ab64890Smrg#include <X11/Xutil.h>
461ab64890Smrg#include <X11/Xmd.h>
471ab64890Smrg#define XK_LATIN1
481ab64890Smrg#define XK_PUBLISHING
491ab64890Smrg#include <X11/keysym.h>
501ab64890Smrg#include <X11/extensions/XKBproto.h>
511ab64890Smrg#include "XKBlibint.h"
521ab64890Smrg#include <X11/Xlocale.h>
531ab64890Smrg#include <ctype.h>
541ab64890Smrg#include <X11/Xos.h>
551ab64890Smrg
561ab64890Smrg#ifdef __sgi_not_xconsortium
571ab64890Smrg#define	XKB_EXTEND_LOOKUP_STRING
581ab64890Smrg#endif
591ab64890Smrg
6061b2299dSmrgstatic int
611ab64890Smrg_XkbHandleSpecialSym(KeySym keysym, char *buffer, int nbytes, int *extra_rtrn)
621ab64890Smrg{
631ab64890Smrg
641ab64890Smrg    /* try to convert to Latin-1, handling ctrl */
651ab64890Smrg    if (!(((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) ||
661ab64890Smrg	   (keysym == XK_Return) || (keysym == XK_Escape) ||
671ab64890Smrg	   (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) ||
6861b2299dSmrg	   (keysym == XK_KP_Enter) ||
691ab64890Smrg	   ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) ||
701ab64890Smrg	   (keysym == XK_KP_Equal) ||
711ab64890Smrg	   (keysym == XK_Delete)))
721ab64890Smrg	return 0;
731ab64890Smrg
741ab64890Smrg    if (nbytes<1) {
7561b2299dSmrg	if (extra_rtrn)
761ab64890Smrg	    *extra_rtrn= 1;
771ab64890Smrg	return 0;
781ab64890Smrg    }
791ab64890Smrg    /* if X keysym, convert to ascii by grabbing low 7 bits */
801ab64890Smrg    if (keysym == XK_KP_Space)
811ab64890Smrg	 buffer[0] = XK_space & 0x7F; /* patch encoding botch */
821ab64890Smrg    else if (keysym == XK_hyphen)
831ab64890Smrg	 buffer[0] = (char)(XK_minus & 0xFF); /* map to equiv character */
841ab64890Smrg    else buffer[0] = (char)(keysym & 0x7F);
851ab64890Smrg    return 1;
861ab64890Smrg}
871ab64890Smrg
881ab64890Smrg/*ARGSUSED*/
8961b2299dSmrgstatic int
901ab64890Smrg_XkbKSToKnownSet (	XPointer 	priv,
911ab64890Smrg			KeySym 		keysym,
921ab64890Smrg			char *		buffer,
931ab64890Smrg			int 		nbytes,
941ab64890Smrg			int *		extra_rtrn)
951ab64890Smrg{
961ab64890Smrg    char tbuf[8],*buf;
971ab64890Smrg
981ab64890Smrg    if (extra_rtrn)
991ab64890Smrg	*extra_rtrn= 0;
1001ab64890Smrg
1011ab64890Smrg    /* convert "dead" diacriticals for dumb applications */
1021ab64890Smrg    if ( (keysym&0xffffff00)== 0xfe00 ) {
1031ab64890Smrg	switch ( keysym ) {
1041ab64890Smrg	    case XK_dead_grave:		keysym = XK_grave; break;
1051ab64890Smrg	    case XK_dead_acute:		keysym = XK_acute; break;
1061ab64890Smrg	    case XK_dead_circumflex:	keysym = XK_asciicircum; break;
1071ab64890Smrg	    case XK_dead_tilde:		keysym = XK_asciitilde; break;
1081ab64890Smrg	    case XK_dead_macron:	keysym = XK_macron; break;
1091ab64890Smrg	    case XK_dead_breve:		keysym = XK_breve; break;
1101ab64890Smrg	    case XK_dead_abovedot:	keysym = XK_abovedot; break;
1111ab64890Smrg	    case XK_dead_diaeresis:	keysym = XK_diaeresis; break;
1121ab64890Smrg	    case XK_dead_abovering:	keysym = XK_degree; break;
1131ab64890Smrg	    case XK_dead_doubleacute:	keysym = XK_doubleacute; break;
1141ab64890Smrg	    case XK_dead_caron:		keysym = XK_caron; break;
1151ab64890Smrg	    case XK_dead_cedilla:	keysym = XK_cedilla; break;
1161ab64890Smrg	    case XK_dead_ogonek	:	keysym = XK_ogonek; break;
1171ab64890Smrg	    case XK_dead_iota:		keysym = XK_Greek_iota; break;
1181ab64890Smrg#ifdef XK_KATAKANA
1191ab64890Smrg	    case XK_dead_voiced_sound:	keysym = XK_voicedsound; break;
1201ab64890Smrg	    case XK_dead_semivoiced_sound:keysym = XK_semivoicedsound; break;
1211ab64890Smrg#endif
1221ab64890Smrg	}
1231ab64890Smrg    }
1241ab64890Smrg
1251ab64890Smrg    if (nbytes<1)	buf= tbuf;
1261ab64890Smrg    else		buf= buffer;
1271ab64890Smrg
1281ab64890Smrg    if ((keysym&0xffffff00)==0xff00) {
1291ab64890Smrg	return _XkbHandleSpecialSym(keysym, buf, nbytes, extra_rtrn);
1301ab64890Smrg    }
1311ab64890Smrg    return _XimGetCharCode (priv, keysym, (unsigned char *)buf, nbytes);
1321ab64890Smrg}
1331ab64890Smrg
1341ab64890Smrgtypedef struct _XkbToKS {
1351ab64890Smrg	unsigned	 prefix;
1361ab64890Smrg	char		*map;
1371ab64890Smrg} XkbToKS;
1381ab64890Smrg
1391ab64890Smrg/*ARGSUSED*/
1401ab64890Smrgstatic KeySym
1411ab64890Smrg_XkbKnownSetToKS(XPointer priv,char *buffer,int nbytes,Status *status)
1421ab64890Smrg{
1431ab64890Smrg    if (nbytes!=1)
1441ab64890Smrg	return NoSymbol;
1451ab64890Smrg    if (((buffer[0]&0x80)==0)&&(buffer[0]>=32))
1461ab64890Smrg	return buffer[0];
14761b2299dSmrg    else if ((buffer[0]&0x7f)>=32) {
1481ab64890Smrg	XkbToKS *map= (XkbToKS *)priv;
1491ab64890Smrg	if ( map ) {
1501ab64890Smrg	    if ( map->map )	return map->prefix|map->map[buffer[0]&0x7f];
1511ab64890Smrg	    else		return map->prefix|buffer[0];
1521ab64890Smrg	}
1531ab64890Smrg	return buffer[0];
1541ab64890Smrg    }
1551ab64890Smrg    return NoSymbol;
1561ab64890Smrg}
1571ab64890Smrg
1581ab64890Smrgstatic KeySym
1591ab64890Smrg__XkbDefaultToUpper(KeySym sym)
1601ab64890Smrg{
1611ab64890Smrg    KeySym	lower,upper;
1621ab64890Smrg
1631ab64890Smrg    XConvertCase(sym, &lower, &upper);
1641ab64890Smrg    return upper;
1651ab64890Smrg}
1661ab64890Smrg
1671ab64890Smrg#ifdef XKB_EXTEND_LOOKUP_STRING
1681ab64890Smrgstatic int
1691ab64890SmrgStrcmp(char *str1, char *str2)
1701ab64890Smrg{
1711ab64890Smrg    char str[256];
1721ab64890Smrg    char c, *s;
1731ab64890Smrg
1741ab64890Smrg    /*
1751ab64890Smrg     * unchecked strings from the environment can end up here, so check
1761ab64890Smrg     * the length before copying.
1771ab64890Smrg     */
1781ab64890Smrg    if (strlen(str1) >= sizeof(str)) /* almost certain it's a mismatch */
1791ab64890Smrg	return 1;
1801ab64890Smrg
1811ab64890Smrg    for (s = str; (c = *str1++); ) {
1821ab64890Smrg	if (isupper(c))
1831ab64890Smrg	    c = tolower(c);
1841ab64890Smrg	*s++ = c;
1851ab64890Smrg    }
1861ab64890Smrg    *s = '\0';
1871ab64890Smrg    return (strcmp(str, str2));
1881ab64890Smrg}
1891ab64890Smrg#endif
1901ab64890Smrg
19161b2299dSmrgint
1921ab64890Smrg_XkbGetConverters(const char *encoding_name, XkbConverters *cvt_rtrn)
1931ab64890Smrg{
1941ab64890Smrg    if ( !cvt_rtrn ) return 0;
1951ab64890Smrg
1961ab64890Smrg    cvt_rtrn->KSToMB = _XkbKSToKnownSet;
1971ab64890Smrg    cvt_rtrn->KSToMBPriv = _XimGetLocaleCode(encoding_name);
1981ab64890Smrg    cvt_rtrn->MBToKS = _XkbKnownSetToKS;
1991ab64890Smrg    cvt_rtrn->MBToKSPriv = NULL;
2001ab64890Smrg    cvt_rtrn->KSToUpper = __XkbDefaultToUpper;
2011ab64890Smrg    return 1;
2021ab64890Smrg}
2031ab64890Smrg
2041ab64890Smrg/***====================================================================***/
2051ab64890Smrg
20661b2299dSmrg/*
2071ab64890Smrg * The function _XkbGetCharset seems to be missnamed as what it seems to
2081ab64890Smrg * be used for is to determine the encoding-name for the locale. ???
2091ab64890Smrg */
2101ab64890Smrg
2111ab64890Smrg#ifdef XKB_EXTEND_LOOKUP_STRING
2121ab64890Smrg
21361b2299dSmrg/*
2141ab64890Smrg * XKB_EXTEND_LOOKUP_STRING is not used by the SI. It is used by various
2151ab64890Smrg * X Consortium/X Project Team members, so we leave it in the source as
2161ab64890Smrg * an simplify integration by these companies.
2171ab64890Smrg */
2181ab64890Smrg
2191ab64890Smrg#define	CHARSET_FILE	"/usr/lib/X11/input/charsets"
2201ab64890Smrgstatic 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";
2211ab64890Smrg
2221ab64890Smrgchar	*
2231ab64890Smrg_XkbGetCharset(void)
2241ab64890Smrg{
2251ab64890Smrg    /*
2261ab64890Smrg     * PAGE USAGE TUNING: explicitly initialize to move these to data
2271ab64890Smrg     * instead of bss
2281ab64890Smrg     */
2291ab64890Smrg    static char buf[100] = { 0 };
2301ab64890Smrg    char lang[256];
2311ab64890Smrg    char *start,*tmp,*end,*next,*set;
2321ab64890Smrg    char *country,*charset;
2331ab64890Smrg    char *locale;
2341ab64890Smrg
2351ab64890Smrg    tmp = getenv( "_XKB_CHARSET" );
2361ab64890Smrg    if ( tmp )
2371ab64890Smrg	return tmp;
2381ab64890Smrg    locale = setlocale(LC_CTYPE,NULL);
2391ab64890Smrg
2401ab64890Smrg    if ( locale == NULL )
2411ab64890Smrg	return NULL;
2421ab64890Smrg
2431ab64890Smrg    if (strlen(locale) >= sizeof(lang))
2441ab64890Smrg	return NULL;
2451ab64890Smrg
2461ab64890Smrg    for (tmp = lang; *tmp = *locale++; tmp++) {
2471ab64890Smrg	if (isupper(*tmp))
2481ab64890Smrg	    *tmp = tolower(*tmp);
2491ab64890Smrg    }
2501ab64890Smrg    country = strchr( lang, '_');
2511ab64890Smrg    if ( country ) {
2521ab64890Smrg	*country++ = '\0';
2531ab64890Smrg	charset = strchr( country, '.' );
2541ab64890Smrg	if ( charset )	*charset++ = '\0';
2551ab64890Smrg	if ( charset ) {
2561ab64890Smrg	    strncpy(buf,charset,99);
2571ab64890Smrg	    buf[99] = '\0';
2581ab64890Smrg	    return buf;
2591ab64890Smrg	}
2601ab64890Smrg    }
26161b2299dSmrg    else {
2621ab64890Smrg	charset = NULL;
2631ab64890Smrg    }
2641ab64890Smrg
2651ab64890Smrg    if ((tmp = getenv("_XKB_LOCALE_CHARSETS"))!=NULL) {
2661ab64890Smrg	start = _XkbAlloc(strlen(tmp) + 1);
2671ab64890Smrg	strcpy(start, tmp);
2681ab64890Smrg	tmp = start;
2691ab64890Smrg    } else {
2701ab64890Smrg	struct stat sbuf;
2711ab64890Smrg	FILE *file;
2721ab64890Smrg#ifndef __UNIXOS2__
2731ab64890Smrg	char *cf = CHARSET_FILE;
2741ab64890Smrg#else
2751ab64890Smrg        char *cf = __XOS2RedirRoot(CHARSET_FILE);
2761ab64890Smrg#endif
2771ab64890Smrg
2781ab64890Smrg#ifndef S_ISREG
2791ab64890Smrg# define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
2801ab64890Smrg#endif
28161b2299dSmrg
2821ab64890Smrg	if ( (stat(cf,&sbuf)==0) && S_ISREG(sbuf.st_mode) &&
2831ab64890Smrg	    (file = fopen(cf,"r")) ) {
2841ab64890Smrg	    tmp = _XkbAlloc(sbuf.st_size+1);
2851ab64890Smrg	    if (tmp!=NULL) {
2861ab64890Smrg		sbuf.st_size = (long)fread(tmp,1,sbuf.st_size,file);
2871ab64890Smrg		tmp[sbuf.st_size] = '\0';
2881ab64890Smrg	    }
2891ab64890Smrg	    fclose(file);
2901ab64890Smrg	}
2911ab64890Smrg    }
2921ab64890Smrg
2931ab64890Smrg    if ( tmp == NULL ) {
2941ab64890Smrg	tmp = _XkbAlloc(strlen(_XkbKnownLanguages) + 1);
2951ab64890Smrg	if (!tmp)
2961ab64890Smrg	    return NULL;
2971ab64890Smrg	strcpy(tmp, _XkbKnownLanguages);
2981ab64890Smrg    }
2991ab64890Smrg    start = tmp;
3001ab64890Smrg    do {
3011ab64890Smrg	if ( (set=strchr(tmp,'=')) == NULL )
3021ab64890Smrg	    break;
3031ab64890Smrg	*set++ = '\0';
30461b2299dSmrg	if ( (next=strchr(set,':')) != NULL )
3051ab64890Smrg	    *next++ = '\0';
3061ab64890Smrg	while ( tmp && *tmp ) {
3071ab64890Smrg	    if ( (end=strchr(tmp,',')) != NULL )
3081ab64890Smrg		*end++ = '\0';
3091ab64890Smrg	    if ( Strcmp( tmp, lang ) == 0 ) {
3101ab64890Smrg		strncpy(buf,set,100);
3111ab64890Smrg		buf[99] = '\0';
3121ab64890Smrg		Xfree(start);
3131ab64890Smrg		return buf;
3141ab64890Smrg	    }
3151ab64890Smrg	    tmp = end;
3161ab64890Smrg	}
3171ab64890Smrg	tmp = next;
3181ab64890Smrg    } while ( tmp && *tmp );
3191ab64890Smrg    Xfree(start);
3201ab64890Smrg    return NULL;
3211ab64890Smrg}
3221ab64890Smrg#else
3231ab64890Smrgchar	*
3241ab64890Smrg_XkbGetCharset(void)
3251ab64890Smrg{
3261ab64890Smrg    char *tmp;
3271ab64890Smrg    XLCd lcd;
3281ab64890Smrg
3291ab64890Smrg    tmp = getenv( "_XKB_CHARSET" );
3301ab64890Smrg    if ( tmp )
3311ab64890Smrg	return tmp;
3321ab64890Smrg
3331ab64890Smrg    lcd = _XlcCurrentLC();
3341ab64890Smrg    if ( lcd )
3351ab64890Smrg	return XLC_PUBLIC(lcd,encoding_name);
3361ab64890Smrg
3371ab64890Smrg    return NULL;
3381ab64890Smrg}
3391ab64890Smrg#endif
3401ab64890Smrg
341