imThaiFlt.c revision 61b2299d
11ab64890Smrg/* $Xorg: imThaiFlt.c,v 1.5 2001/02/09 02:03:39 xorgcvs Exp $ */ 21ab64890Smrg/*********************************************************** 31ab64890Smrg 41ab64890SmrgCopyright 1993, 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 in 131ab64890Smrgall copies or substantial portions of the Software. 141ab64890Smrg 151ab64890SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 161ab64890SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 171ab64890SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 181ab64890SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 191ab64890SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 201ab64890SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 211ab64890Smrg 221ab64890SmrgExcept as contained in this notice, the name of The Open Group shall not be 231ab64890Smrgused in advertising or otherwise to promote the sale, use or other dealings 241ab64890Smrgin this Software without prior written authorization from The Open Group. 251ab64890Smrg 261ab64890Smrg 271ab64890SmrgCopyright 1993 by Digital Equipment Corporation, Maynard, Massachusetts. 281ab64890Smrg 291ab64890Smrg All Rights Reserved 301ab64890Smrg 3161b2299dSmrgPermission to use, copy, modify, and distribute this software and its 3261b2299dSmrgdocumentation for any purpose and without fee is hereby granted, 331ab64890Smrgprovided that the above copyright notice appear in all copies and that 3461b2299dSmrgboth that copyright notice and this permission notice appear in 351ab64890Smrgsupporting documentation, and that the name of Digital not be 361ab64890Smrgused in advertising or publicity pertaining to distribution of the 3761b2299dSmrgsoftware without specific, written prior permission. 381ab64890Smrg 391ab64890SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 401ab64890SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 411ab64890SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 421ab64890SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 431ab64890SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 441ab64890SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 451ab64890SmrgSOFTWARE. 461ab64890Smrg 471ab64890Smrg******************************************************************/ 481ab64890Smrg/* $XFree86: xc/lib/X11/imThaiFlt.c,v 3.22tsi Exp $ */ 491ab64890Smrg 501ab64890Smrg/* 5161b2299dSmrg**++ 5261b2299dSmrg** FACILITY: 5361b2299dSmrg** 5461b2299dSmrg** Xlib 5561b2299dSmrg** 5661b2299dSmrg** ABSTRACT: 5761b2299dSmrg** 581ab64890Smrg** Thai specific functions. 591ab64890Smrg** Handles character classifications, composibility checking, 601ab64890Smrg** Input sequence check and other Thai specific requirements 611ab64890Smrg** according to WTT specification and DEC extensions. 6261b2299dSmrg** 6361b2299dSmrg** MODIFICATION HISTORY: 6461b2299dSmrg** 651ab64890Smrg**/ 661ab64890Smrg 671ab64890Smrg#ifdef HAVE_CONFIG_H 681ab64890Smrg#include <config.h> 691ab64890Smrg#endif 701ab64890Smrg#include <stdio.h> 711ab64890Smrg#include <X11/Xlib.h> 721ab64890Smrg#include <X11/Xmd.h> 731ab64890Smrg#include <X11/keysym.h> 741ab64890Smrg#include <X11/Xutil.h> 751ab64890Smrg#include "Xlibint.h" 761ab64890Smrg#include "Xlcint.h" 771ab64890Smrg#include "Ximint.h" 781ab64890Smrg#include "XimThai.h" 791ab64890Smrg#include "XlcPubI.h" 801ab64890Smrg 811ab64890Smrg 821ab64890Smrg#define SPACE 32 831ab64890Smrg 841ab64890Smrg/* character classification table */ 851ab64890Smrg#define TACTIS_CHARS 256 861ab64890SmrgPrivate 871ab64890Smrgchar const tactis_chtype[TACTIS_CHARS] = { 881ab64890Smrg CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, /* 0 - 7 */ 891ab64890Smrg CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, /* 8 - 15 */ 901ab64890Smrg CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, /* 16 - 23 */ 911ab64890Smrg CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, /* 24 - 31 */ 921ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 32 - 39 */ 931ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 40 - 47 */ 941ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 48 - 55 */ 951ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 56 - 63 */ 961ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 64 - 71 */ 971ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 72 - 79 */ 981ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 80 - 87 */ 991ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 88 - 95 */ 1001ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 96 - 103 */ 1011ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 104 - 111 */ 1021ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 112 - 119 */ 1031ab64890Smrg NON, NON, NON, NON, NON, NON, NON, CTRL, /* 120 - 127 */ 1041ab64890Smrg CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, /* 128 - 135 */ 1051ab64890Smrg CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, /* 136 - 143 */ 1061ab64890Smrg CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, /* 144 - 151 */ 1071ab64890Smrg CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, CTRL, /* 152 - 159 */ 1081ab64890Smrg NON, CONS, CONS, CONS, CONS, CONS, CONS, CONS, /* 160 - 167 */ 1091ab64890Smrg CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS, /* 168 - 175 */ 1101ab64890Smrg CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS, /* 176 - 183 */ 1111ab64890Smrg CONS, CONS, CONS, CONS, CONS, CONS, CONS, CONS, /* 184 - 191 */ 1121ab64890Smrg CONS, CONS, CONS, CONS, FV3, CONS, FV3, CONS, /* 192 - 199 */ 1131ab64890Smrg CONS, CONS, CONS, CONS, CONS, CONS, CONS, NON, /* 200 - 207 */ 1141ab64890Smrg FV1, AV2, FV1, FV1, AV1, AV3, AV2, AV3, /* 208 - 215 */ 1151ab64890Smrg BV1, BV2, BD, NON, NON, NON, NON, NON, /* 216 - 223 */ 1161ab64890Smrg LV, LV, LV, LV, LV, FV2, NON, AD2, /* 224 - 231 */ 1171ab64890Smrg TONE, TONE, TONE, TONE, AD1, AD1, AD3, NON, /* 232 - 239 */ 1181ab64890Smrg NON, NON, NON, NON, NON, NON, NON, NON, /* 240 - 247 */ 1191ab64890Smrg NON, NON, NON, NON, NON, NON, NON, CTRL /* 248 - 255 */ 1201ab64890Smrg}; 1211ab64890Smrg 1221ab64890Smrg/* Composibility checking tables */ 1231ab64890Smrg#define NC 0 /* NOT COMPOSIBLE - following char displays in next cell */ 1241ab64890Smrg#define CP 1 /* COMPOSIBLE - following char is displayed in the same cell 1251ab64890Smrg as leading char, also implies ACCEPT */ 1261ab64890Smrg#define XC 3 /* Non-display */ 1271ab64890Smrg#define AC 4 /* ACCEPT - display the following char in the next cell */ 1281ab64890Smrg#define RJ 5 /* REJECT - discard that following char, ignore it */ 1291ab64890Smrg 1301ab64890Smrg#define CH_CLASSES 17 /* 17 classes of chars */ 1311ab64890Smrg 1321ab64890SmrgPrivate 1331ab64890Smrgchar const write_rules_lookup[CH_CLASSES][CH_CLASSES] = { 1341ab64890Smrg /* Table 0: writing/outputing rules */ 1351ab64890Smrg /* row: leading char, column: following char */ 1361ab64890Smrg/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */ 1371ab64890Smrg {XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*CTRL*/ 1381ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*NON*/ 1391ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/ 1401ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*LV*/ 1411ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV1*/ 1421ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV2*/ 1431ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*FV3*/ 1441ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, CP, NC, NC, NC, NC, NC}/*BV1*/ 1451ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, NC, NC, NC, NC, NC}/*BV2*/ 1461ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*BD*/ 1471ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*TONE*/ 1481ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD1*/ 1491ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD2*/ 1501ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC}/*AD3*/ 1511ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, CP, NC, NC, NC, NC, NC}/*AV1*/ 1521ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, NC, NC, NC, NC, NC}/*AV2*/ 1531ab64890Smrg ,{XC, NC, NC, NC, NC, NC, NC, NC, NC, NC, CP, NC, CP, NC, NC, NC, NC}/*AV3*/ 1541ab64890Smrg}; 1551ab64890Smrg 1561ab64890SmrgPrivate 1571ab64890Smrgchar const wtt_isc1_lookup[CH_CLASSES][CH_CLASSES] = { 1581ab64890Smrg /* Table 1: WTT default input sequence check rules */ 1591ab64890Smrg /* row: leading char, column: following char */ 1601ab64890Smrg/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */ 1611ab64890Smrg {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/ 1621ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/ 1631ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/ 1641ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/ 1651ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/ 1661ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/ 1671ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV3*/ 1681ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/ 1691ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/ 1701ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/ 1711ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*TONE*/ 1721ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD1*/ 1731ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD2*/ 1741ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/ 1751ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/ 1761ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/ 1771ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/ 1781ab64890Smrg}; 1791ab64890Smrg 1801ab64890SmrgPrivate 1811ab64890Smrgchar const wtt_isc2_lookup[CH_CLASSES][CH_CLASSES] = { 1821ab64890Smrg /* Table 2: WTT strict input sequence check rules */ 1831ab64890Smrg /* row: leading char, column: following char */ 1841ab64890Smrg/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */ 1851ab64890Smrg {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/ 1861ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/ 1871ab64890Smrg ,{XC, AC, AC, AC, AC, RJ, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/ 1881ab64890Smrg ,{XC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/ 1891ab64890Smrg ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/ 1901ab64890Smrg ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/ 1911ab64890Smrg ,{XC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV3*/ 1921ab64890Smrg ,{XC, AC, AC, AC, AC, RJ, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/ 1931ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/ 1941ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/ 1951ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*TONE*/ 1961ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD1*/ 1971ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD2*/ 1981ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/ 1991ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/ 2001ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/ 2011ab64890Smrg ,{XC, AC, AC, AC, RJ, RJ, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/ 2021ab64890Smrg}; 2031ab64890Smrg 2041ab64890SmrgPrivate 2051ab64890Smrgchar const thaicat_isc_lookup[CH_CLASSES][CH_CLASSES] = { 2061ab64890Smrg /* Table 3: Thaicat input sequence check rules */ 2071ab64890Smrg /* row: leading char, column: following char */ 2081ab64890Smrg/* CTRL NON CONS LV FV1 FV2 FV3 BV1 BV2 BD TONE AD1 AD2 AD3 AV1 AV2 AV3 */ 2091ab64890Smrg {XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*CTRL*/ 2101ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*NON*/ 2111ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, CP, CP, CP, CP, CP, CP, CP, CP}/*CONS*/ 2121ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*LV*/ 2131ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV1*/ 2141ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*FV2*/ 2151ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ} /*FV3*/ 2161ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*BV1*/ 2171ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*BV2*/ 2181ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*BD*/ 2191ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, CP, CP, RJ, RJ, RJ, RJ, RJ, CP, CP, CP}/*TONE*/ 2201ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, CP, RJ, RJ, RJ, RJ, RJ, RJ, CP, RJ, RJ}/*AD1*/ 2211ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, CP}/*AD2*/ 2221ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ, RJ}/*AD3*/ 2231ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, CP, RJ, RJ, RJ, RJ, RJ}/*AV1*/ 2241ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, RJ, RJ, RJ, RJ, RJ}/*AV2*/ 2251ab64890Smrg ,{XC, AC, AC, AC, AC, AC, AC, RJ, RJ, RJ, CP, RJ, CP, RJ, RJ, RJ, RJ}/*AV3*/ 2261ab64890Smrg}; 2271ab64890Smrg 2281ab64890Smrg 2291ab64890Smrg/* returns classification of a char */ 2301ab64890SmrgPrivate int 2311ab64890SmrgTHAI_chtype (unsigned char ch) 2321ab64890Smrg{ 2331ab64890Smrg return tactis_chtype[ch]; 2341ab64890Smrg} 2351ab64890Smrg 2361ab64890Smrg#ifdef UNUSED 2371ab64890Smrg/* returns the display level */ 2381ab64890SmrgPrivate int 2391ab64890SmrgTHAI_chlevel (unsigned char ch) 2401ab64890Smrg{ 2411ab64890Smrg int chlevel; 2421ab64890Smrg 2431ab64890Smrg switch (tactis_chtype[ch]) 2441ab64890Smrg { 2451ab64890Smrg case CTRL: 2461ab64890Smrg chlevel = NON; 2471ab64890Smrg break; 2481ab64890Smrg case BV1: 2491ab64890Smrg case BV2: 2501ab64890Smrg case BD: 2511ab64890Smrg chlevel = BELOW; 2521ab64890Smrg break; 2531ab64890Smrg case TONE: 2541ab64890Smrg case AD1: 2551ab64890Smrg case AD2: 2561ab64890Smrg chlevel = TOP; 2571ab64890Smrg break; 2581ab64890Smrg case AV1: 2591ab64890Smrg case AV2: 2601ab64890Smrg case AV3: 2611ab64890Smrg case AD3: 2621ab64890Smrg chlevel = ABOVE; 2631ab64890Smrg break; 2641ab64890Smrg case NON: 2651ab64890Smrg case CONS: 2661ab64890Smrg case LV: 2671ab64890Smrg case FV1: 2681ab64890Smrg case FV2: 2691ab64890Smrg case FV3: 2701ab64890Smrg default: /* if tactis_chtype is invalid */ 2711ab64890Smrg chlevel = BASE; 2721ab64890Smrg break; 2731ab64890Smrg } 2741ab64890Smrg return chlevel; 2751ab64890Smrg} 2761ab64890Smrg 2771ab64890Smrg 2781ab64890Smrg/* return True if char is non-spacing */ 2791ab64890SmrgPrivate Bool 2801ab64890SmrgTHAI_isdead (unsigned char ch) 2811ab64890Smrg{ 2821ab64890Smrg return ((tactis_chtype[ch] == CTRL) || (tactis_chtype[ch] == BV1) || 2831ab64890Smrg (tactis_chtype[ch] == BV2) || (tactis_chtype[ch] == BD) || 2841ab64890Smrg (tactis_chtype[ch] == TONE) || (tactis_chtype[ch] == AD1) || 2851ab64890Smrg (tactis_chtype[ch] == AD2) || (tactis_chtype[ch] == AD3) || 2861ab64890Smrg (tactis_chtype[ch] == AV1) || (tactis_chtype[ch] == AV2) || 2871ab64890Smrg (tactis_chtype[ch] == AV3)); 2881ab64890Smrg} 2891ab64890Smrg 2901ab64890Smrg 2911ab64890Smrg/* return True if char is consonant */ 2921ab64890SmrgPrivate Bool 2931ab64890SmrgTHAI_iscons (unsigned char ch) 2941ab64890Smrg{ 2951ab64890Smrg return (tactis_chtype[ch] == CONS); 2961ab64890Smrg} 2971ab64890Smrg 2981ab64890Smrg 2991ab64890Smrg/* return True if char is vowel */ 3001ab64890SmrgPrivate Bool 3011ab64890SmrgTHAI_isvowel (unsigned char ch) 3021ab64890Smrg{ 3031ab64890Smrg return ((tactis_chtype[ch] == LV) || (tactis_chtype[ch] == FV1) || 3041ab64890Smrg (tactis_chtype[ch] == FV2) || (tactis_chtype[ch] == FV3) || 3051ab64890Smrg (tactis_chtype[ch] == BV1) || (tactis_chtype[ch] == BV2) || 3061ab64890Smrg (tactis_chtype[ch] == AV1) || (tactis_chtype[ch] == AV2) || 3071ab64890Smrg (tactis_chtype[ch] == AV3)); 3081ab64890Smrg} 3091ab64890Smrg 3101ab64890Smrg 3111ab64890Smrg/* return True if char is tonemark */ 3121ab64890SmrgPrivate Bool 3131ab64890SmrgTHAI_istone (unsigned char ch) 3141ab64890Smrg{ 3151ab64890Smrg return (tactis_chtype[ch] == TONE); 3161ab64890Smrg} 3171ab64890Smrg#endif 3181ab64890Smrg 3191ab64890SmrgPrivate Bool 3201ab64890SmrgTHAI_iscomposible ( 32161b2299dSmrg unsigned char follow_ch, 3221ab64890Smrg unsigned char lead_ch) 3231ab64890Smrg{/* "Can follow_ch be put in the same display cell as lead_ch?" */ 3241ab64890Smrg 32561b2299dSmrg return (write_rules_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] 3261ab64890Smrg == CP); 3271ab64890Smrg} 3281ab64890Smrg 3291ab64890SmrgPrivate Bool 3301ab64890SmrgTHAI_isaccepted ( 33161b2299dSmrg unsigned char follow_ch, 3321ab64890Smrg unsigned char lead_ch, 3331ab64890Smrg unsigned char mode) 3341ab64890Smrg{ 3351ab64890Smrg Bool iskeyvalid; /* means "Can follow_ch be keyed in after lead_ch?" */ 3361ab64890Smrg 3371ab64890Smrg switch (mode) 3381ab64890Smrg { 3391ab64890Smrg case WTT_ISC1: 34061b2299dSmrg iskeyvalid = 3411ab64890Smrg (wtt_isc1_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ); 3421ab64890Smrg break; 3431ab64890Smrg case WTT_ISC2: 34461b2299dSmrg iskeyvalid = 3451ab64890Smrg (wtt_isc2_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ); 3461ab64890Smrg break; 3471ab64890Smrg case THAICAT_ISC: 3481ab64890Smrg iskeyvalid = 3491ab64890Smrg (thaicat_isc_lookup[THAI_chtype(lead_ch)][THAI_chtype(follow_ch)] != RJ); 3501ab64890Smrg break; 3511ab64890Smrg default: 3521ab64890Smrg iskeyvalid = True; 3531ab64890Smrg break; 3541ab64890Smrg } 3551ab64890Smrg 3561ab64890Smrg return iskeyvalid; 3571ab64890Smrg} 3581ab64890Smrg 3591ab64890Smrg#ifdef UNUSED 36061b2299dSmrgPrivate void 3611ab64890SmrgTHAI_apply_write_rules( 36261b2299dSmrg unsigned char *instr, 36361b2299dSmrg unsigned char *outstr, 36461b2299dSmrg unsigned char insert_ch, 3651ab64890Smrg int *num_insert_ch) 3661ab64890Smrg{ 3671ab64890Smrg/* 36861b2299dSmrgInput parameters: 3691ab64890Smrg instr - input string 3701ab64890Smrg insert_ch specify what char to be added when invalid composition is found 3711ab64890SmrgOutput parameters: 3721ab64890Smrg outstr - output string after input string has been applied the rules 3731ab64890Smrg num_insert_ch - number of insert_ch added to outstr. 3741ab64890Smrg*/ 3751ab64890Smrg unsigned char *lead_ch = NULL, *follow_ch = NULL, *out_ch = NULL; 3761ab64890Smrg 3771ab64890Smrg *num_insert_ch = 0; 3781ab64890Smrg lead_ch = follow_ch = instr; 3791ab64890Smrg out_ch = outstr; 3801ab64890Smrg if ((*lead_ch == '\0') || !(THAI_find_chtype(instr,DEAD))) 3811ab64890Smrg { /* Empty string or can't find any non-spacing char*/ 3821ab64890Smrg strcpy((char *)outstr, (char *)instr); 3831ab64890Smrg } else { /* String of length >= 1, keep looking */ 3841ab64890Smrg follow_ch++; 3851ab64890Smrg if (THAI_isdead(*lead_ch)) { /* is first char non-spacing? */ 3861ab64890Smrg *out_ch++ = SPACE; 3871ab64890Smrg (*num_insert_ch)++; 3881ab64890Smrg } 3891ab64890Smrg *out_ch++ = *lead_ch; 3901ab64890Smrg while (*follow_ch != '\0') /* more char in string to check */ 3911ab64890Smrg { 39261b2299dSmrg if (THAI_isdead(*follow_ch) && 39361b2299dSmrg !THAI_iscomposible(*follow_ch,*lead_ch)) 3941ab64890Smrg { 3951ab64890Smrg *out_ch++ = SPACE; 3961ab64890Smrg (*num_insert_ch)++; 3971ab64890Smrg } 3981ab64890Smrg *out_ch++ = *follow_ch; 3991ab64890Smrg lead_ch = follow_ch; 4001ab64890Smrg follow_ch++; 4011ab64890Smrg } 4021ab64890Smrg *out_ch = '\0'; 4031ab64890Smrg } 4041ab64890Smrg} 4051ab64890Smrg 40661b2299dSmrgPrivate int 4071ab64890SmrgTHAI_find_chtype ( 40861b2299dSmrg unsigned char *instr, 4091ab64890Smrg int chtype) 4101ab64890Smrg{ 4111ab64890Smrg/* 4121ab64890SmrgInput parameters: 4131ab64890Smrg instr - input string 4141ab64890Smrg chtype - type of character to look for 4151ab64890SmrgOutput parameters: 4161ab64890Smrg function returns first position of character with matched chtype 4171ab64890Smrg function returns -1 if it does not find. 4181ab64890Smrg*/ 4191ab64890Smrg int i = 0, position = -1; 4201ab64890Smrg 4211ab64890Smrg switch (chtype) 4221ab64890Smrg { 4231ab64890Smrg case DEAD: 4241ab64890Smrg for (i = 0; *instr != '\0' && THAI_isdead(*instr); i++, instr++) 4251ab64890Smrg ; 42661b2299dSmrg if (*instr != '\0') position = i; 4271ab64890Smrg break; 4281ab64890Smrg default: 4291ab64890Smrg break; 4301ab64890Smrg } 4311ab64890Smrg return position; 4321ab64890Smrg} 4331ab64890Smrg 4341ab64890Smrg 43561b2299dSmrgPrivate int 4361ab64890SmrgTHAI_apply_scm( 43761b2299dSmrg unsigned char *instr, 43861b2299dSmrg unsigned char *outstr, 43961b2299dSmrg unsigned char spec_ch, 44061b2299dSmrg int num_sp, 4411ab64890Smrg unsigned char insert_ch) 4421ab64890Smrg{ 4431ab64890Smrg unsigned char *scan, *outch; 4441ab64890Smrg int i, dead_count, found_count; 4451ab64890Smrg Bool isconsecutive; 4461ab64890Smrg 4471ab64890Smrg scan = instr; 4481ab64890Smrg outch = outstr; 4491ab64890Smrg dead_count = found_count = 0; 4501ab64890Smrg isconsecutive = False; 4511ab64890Smrg while (*scan != '\0') { 4521ab64890Smrg if (THAI_isdead(*scan)) 4531ab64890Smrg dead_count++; /* count number of non-spacing char */ 4541ab64890Smrg if (*scan == spec_ch) 45561b2299dSmrg if (!isconsecutive) 4561ab64890Smrg found_count++; /* count number consecutive spec char found */ 4571ab64890Smrg *outch++ = *scan++; 4581ab64890Smrg if (found_count == num_sp) { 4591ab64890Smrg for (i = 0; i < dead_count; i++) 4601ab64890Smrg *outch++ = insert_ch; 4611ab64890Smrg dead_count = found_count = 0; 4621ab64890Smrg } 4631ab64890Smrg } 4641ab64890Smrg /* what to return? */ 4651ab64890Smrg return 0; /* probably not right but better than returning garbage */ 4661ab64890Smrg} 4671ab64890Smrg 4681ab64890Smrg 4691ab64890Smrg/* The following functions are copied from XKeyBind.c */ 4701ab64890Smrg 4711ab64890SmrgPrivate void ComputeMaskFromKeytrans(); 4721ab64890SmrgPrivate int IsCancelComposeKey(KeySym *symbol, XKeyEvent *event); 4731ab64890SmrgPrivate void SetLed(Display *dpy, int num, int state); 4741ab64890SmrgPrivate CARD8 FindKeyCode(); 4751ab64890Smrg 4761ab64890Smrg 47761b2299dSmrg/* The following functions are specific to this module */ 4781ab64890Smrg 4791ab64890SmrgPrivate int XThaiTranslateKey(); 4801ab64890SmrgPrivate int XThaiTranslateKeySym(); 4811ab64890Smrg 4821ab64890Smrg 4831ab64890SmrgPrivate KeySym HexIMNormalKey( 4841ab64890Smrg XicThaiPart *thai_part, 4851ab64890Smrg KeySym symbol, 4861ab64890Smrg XKeyEvent *event); 4871ab64890SmrgPrivate KeySym HexIMFirstComposeKey( 4881ab64890Smrg XicThaiPart *thai_part, 4891ab64890Smrg KeySym symbol, 4901ab64890Smrg XKeyEvent *event); 4911ab64890SmrgPrivate KeySym HexIMSecondComposeKey( 4921ab64890Smrg XicThaiPart *thai_part, 4931ab64890Smrg KeySym symbol 4941ab64890Smrg XKeyEvent *event); 4951ab64890SmrgPrivate KeySym HexIMComposeSequence(KeySym ks1, KeySym ks2); 4961ab64890SmrgPrivate void InitIscMode(Xic ic); 4971ab64890SmrgPrivate Bool ThaiComposeConvert( 4981ab64890Smrg Display *dpy, 4991ab64890Smrg KeySym insym, 5001ab64890Smrg KeySym *outsym, KeySym *lower, KeySym *upper); 5011ab64890Smrg#endif 5021ab64890Smrg 5031ab64890Smrg/* 5041ab64890Smrg * Definitions 5051ab64890Smrg */ 5061ab64890Smrg 5071ab64890Smrg#define BellVolume 0 5081ab64890Smrg 5091ab64890Smrg#define ucs2tis(wc) \ 5101ab64890Smrg (unsigned char) ( \ 5111ab64890Smrg (0<=(wc)&&(wc)<=0x7F) ? \ 5121ab64890Smrg (wc) : \ 5131ab64890Smrg ((0x0E01<=(wc)&&(wc)<=0x0E5F) ? ((wc)-0x0E00+0xA0) : 0)) 5141ab64890Smrg/* "c" is an unsigned char */ 5151ab64890Smrg#define tis2ucs(c) \ 5161ab64890Smrg ( \ 5171ab64890Smrg ((c)<=0x7F) ? \ 5181ab64890Smrg (wchar_t)(c) : \ 5191ab64890Smrg ((0x0A1<=(c)) ? ((wchar_t)(c)-0xA0+0x0E00) : 0)) 5201ab64890Smrg 5211ab64890Smrg/* 5221ab64890Smrg * Macros to save and recall last input character in XIC 5231ab64890Smrg */ 5241ab64890Smrg#define IC_SavePreviousChar(ic,ch) \ 5251ab64890Smrg ((ic)->private.local.base.mb[(ic)->private.local.base.tree[(ic)->private.local.context].mb] = (char) (ch)) 5261ab64890Smrg#define IC_ClearPreviousChar(ic) \ 5271ab64890Smrg ((ic)->private.local.base.mb[(ic)->private.local.base.tree[(ic)->private.local.context].mb] = 0) 5281ab64890Smrg#define IC_GetPreviousChar(ic) \ 5291ab64890Smrg (IC_RealGetPreviousChar(ic,1)) 5301ab64890Smrg#define IC_GetContextChar(ic) \ 5311ab64890Smrg (IC_RealGetPreviousChar(ic,2)) 5321ab64890Smrg#define IC_DeletePreviousChar(ic) \ 5331ab64890Smrg (IC_RealDeletePreviousChar(ic)) 5341ab64890Smrg 5351ab64890SmrgPrivate unsigned char 5361ab64890SmrgIC_RealGetPreviousChar(Xic ic, unsigned short pos) 5371ab64890Smrg{ 5381ab64890Smrg XICCallback* cb = &ic->core.string_conversion_callback; 5391ab64890Smrg DefTreeBase *b = &ic->private.local.base; 5401ab64890Smrg 5411ab64890Smrg if (cb && cb->callback) { 5421ab64890Smrg XIMStringConversionCallbackStruct screc; 5431ab64890Smrg unsigned char c; 5441ab64890Smrg 5451ab64890Smrg /* Use a safe value of position = 0 and stretch the range to desired 5461ab64890Smrg * place, as XIM protocol is unclear here whether it could be negative 5471ab64890Smrg */ 5481ab64890Smrg screc.position = 0; 5491ab64890Smrg screc.direction = XIMBackwardChar; 5501ab64890Smrg screc.operation = XIMStringConversionRetrieval; 5511ab64890Smrg screc.factor = pos; 5521ab64890Smrg screc.text = 0; 5531ab64890Smrg 5541ab64890Smrg (cb->callback)((XIC)ic, cb->client_data, (XPointer)&screc); 5551ab64890Smrg if (!screc.text) 5561ab64890Smrg return (unsigned char) b->mb[b->tree[(ic)->private.local.context].mb]; 5571ab64890Smrg if ((screc.text->feedback && 5581ab64890Smrg *screc.text->feedback == XIMStringConversionLeftEdge) || 5591ab64890Smrg screc.text->length < 1) 5601ab64890Smrg { 5611ab64890Smrg c = 0; 5621ab64890Smrg } else { 5631ab64890Smrg if (screc.text->encoding_is_wchar) { 5641ab64890Smrg c = ucs2tis(screc.text->string.wcs[0]); 5651ab64890Smrg XFree(screc.text->string.wcs); 5661ab64890Smrg } else { 5671ab64890Smrg c = screc.text->string.mbs[0]; 5681ab64890Smrg XFree(screc.text->string.mbs); 5691ab64890Smrg } 5701ab64890Smrg } 5711ab64890Smrg XFree(screc.text); 5721ab64890Smrg return c; 5731ab64890Smrg } else { 5741ab64890Smrg return (unsigned char) b->mb[b->tree[(ic)->private.local.context].mb]; 5751ab64890Smrg } 5761ab64890Smrg} 5771ab64890Smrg 5781ab64890SmrgPrivate unsigned char 5791ab64890SmrgIC_RealDeletePreviousChar(Xic ic) 5801ab64890Smrg{ 5811ab64890Smrg XICCallback* cb = &ic->core.string_conversion_callback; 5821ab64890Smrg 5831ab64890Smrg if (cb && cb->callback) { 5841ab64890Smrg XIMStringConversionCallbackStruct screc; 5851ab64890Smrg unsigned char c; 5861ab64890Smrg 5871ab64890Smrg screc.position = 0; 5881ab64890Smrg screc.direction = XIMBackwardChar; 5891ab64890Smrg screc.operation = XIMStringConversionSubstitution; 5901ab64890Smrg screc.factor = 1; 5911ab64890Smrg screc.text = 0; 5921ab64890Smrg 5931ab64890Smrg (cb->callback)((XIC)ic, cb->client_data, (XPointer)&screc); 5941ab64890Smrg if (!screc.text) { return 0; } 5951ab64890Smrg if ((screc.text->feedback && 5961ab64890Smrg *screc.text->feedback == XIMStringConversionLeftEdge) || 5971ab64890Smrg screc.text->length < 1) 5981ab64890Smrg { 5991ab64890Smrg c = 0; 6001ab64890Smrg } else { 6011ab64890Smrg if (screc.text->encoding_is_wchar) { 6021ab64890Smrg c = ucs2tis(screc.text->string.wcs[0]); 6031ab64890Smrg XFree(screc.text->string.wcs); 6041ab64890Smrg } else { 6051ab64890Smrg c = screc.text->string.mbs[0]; 6061ab64890Smrg XFree(screc.text->string.mbs); 6071ab64890Smrg } 6081ab64890Smrg } 6091ab64890Smrg XFree(screc.text); 6101ab64890Smrg return c; 6111ab64890Smrg } else { 6121ab64890Smrg return 0; 6131ab64890Smrg } 6141ab64890Smrg} 6151ab64890Smrg/* 6161ab64890Smrg * Input sequence check mode in XIC 6171ab64890Smrg */ 6181ab64890Smrg#define IC_IscMode(ic) ((ic)->private.local.thai.input_mode) 6191ab64890Smrg 6201ab64890Smrg/* 6211ab64890Smrg * Max. size of string handled by the two String Lookup functions. 6221ab64890Smrg */ 6231ab64890Smrg#define STR_LKUP_BUF_SIZE 256 6241ab64890Smrg 6251ab64890Smrg/* 6261ab64890Smrg * Size of buffer to contain previous locale name. 6271ab64890Smrg */ 6281ab64890Smrg#define SAV_LOCALE_NAME_SIZE 256 6291ab64890Smrg 6301ab64890Smrg/* 6311ab64890Smrg * Size of buffer to contain the IM modifier. 6321ab64890Smrg */ 6331ab64890Smrg#define MAXTHAIIMMODLEN 20 6341ab64890Smrg 6351ab64890Smrg#define AllMods (ShiftMask|LockMask|ControlMask| \ 6361ab64890Smrg Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask) 6371ab64890Smrg 6381ab64890Smrg 6391ab64890Smrg#define IsISOControlKey(ks) ((ks) >= XK_2 && (ks) <= XK_8) 6401ab64890Smrg 6411ab64890Smrg#define IsValidControlKey(ks) (((((ks)>=XK_A && (ks)<=XK_asciitilde) || \ 6421ab64890Smrg (ks)==XK_space || (ks)==XK_Delete) && \ 6431ab64890Smrg ((ks)!=0))) 6441ab64890Smrg 6451ab64890Smrg#define COMPOSE_LED 2 6461ab64890Smrg 6471ab64890Smrg#ifdef UNUSED 6481ab64890Smrgtypedef KeySym (*StateProc)( 6491ab64890Smrg XicThaiPart *thai_part, 6501ab64890Smrg KeySym symbol, 6511ab64890Smrg XKeyEvent *event); 6521ab64890Smrg 6531ab64890Smrg 6541ab64890Smrg/* 6551ab64890Smrg * macros to classify XKeyEvent state field 6561ab64890Smrg */ 6571ab64890Smrg 6581ab64890Smrg#define IsShift(state) (((state) & ShiftMask) != 0) 6591ab64890Smrg#define IsLock(state) (((state) & LockMask) != 0) 6601ab64890Smrg#define IsControl(state) (((state) & ControlMask) != 0) 6611ab64890Smrg#define IsMod1(state) (((state) & Mod1Mask) != 0) 6621ab64890Smrg#define IsMod2(state) (((state) & Mod2Mask) != 0) 6631ab64890Smrg#define IsMod3(state) (((state) & Mod3Mask) != 0) 6641ab64890Smrg#define IsMod4(state) (((state) & Mod4Mask) != 0) 6651ab64890Smrg#define IsMod5(state) (((state) & Mod5Mask) != 0) 6661ab64890Smrg 6671ab64890Smrg/* 6681ab64890Smrg * key starts Thai compose sequence (Hex input method) if : 6691ab64890Smrg */ 6701ab64890Smrg 6711ab64890Smrg#define IsComposeKey(ks, event) \ 6721ab64890Smrg (( ks==XK_Alt_L && \ 6731ab64890Smrg IsControl((event)->state) && \ 6741ab64890Smrg !IsShift((event)->state)) \ 6751ab64890Smrg ? True : False) 6761ab64890Smrg 6771ab64890Smrg 6781ab64890Smrg/* 6791ab64890Smrg * State handler to implement the Thai hex input method. 6801ab64890Smrg */ 6811ab64890Smrg 6821ab64890SmrgPrivate int const nstate_handlers = 3; 6831ab64890SmrgPrivate StateProc state_handler[] = { 6841ab64890Smrg HexIMNormalKey, 6851ab64890Smrg HexIMFirstComposeKey, 6861ab64890Smrg HexIMSecondComposeKey 6871ab64890Smrg}; 6881ab64890Smrg 6891ab64890Smrg 6901ab64890Smrg/* 6911ab64890Smrg * Table for 'Thai Compose' character input. 6921ab64890Smrg * The current implementation uses latin-1 keysyms. 6931ab64890Smrg */ 6941ab64890Smrgstruct _XMapThaiKey { 6951ab64890Smrg KeySym from; 6961ab64890Smrg KeySym to; 6971ab64890Smrg}; 6981ab64890Smrg 6991ab64890SmrgPrivate struct _XMapThaiKey const ThaiComposeTable[] = { 7001ab64890Smrg { /* 0xa4 */ XK_currency, /* 0xa5 */ XK_yen }, 7011ab64890Smrg { /* 0xa2 */ XK_cent, /* 0xa3 */ XK_sterling }, 7021ab64890Smrg { /* 0xe6 */ XK_ae, /* 0xef */ XK_idiaeresis }, 7031ab64890Smrg { /* 0xd3 */ XK_Oacute, /* 0xee */ XK_icircumflex }, 7041ab64890Smrg { /* 0xb9 */ XK_onesuperior, /* 0xfa */ XK_uacute }, 7051ab64890Smrg { /* 0xd2 */ XK_Ograve, /* 0xe5 */ XK_aring }, 7061ab64890Smrg { /* 0xbc */ XK_onequarter, /* 0xfb */ XK_ucircumflex }, 7071ab64890Smrg { XK_VoidSymbol, XK_VoidSymbol } 7081ab64890Smrg}; 7091ab64890Smrg 7101ab64890Smrgstruct _XKeytrans { 7111ab64890Smrg struct _XKeytrans *next;/* next on list */ 7121ab64890Smrg char *string; /* string to return when the time comes */ 7131ab64890Smrg int len; /* length of string (since NULL is legit)*/ 7141ab64890Smrg KeySym key; /* keysym rebound */ 7151ab64890Smrg unsigned int state; /* modifier state */ 7161ab64890Smrg KeySym *modifiers; /* modifier keysyms you want */ 7171ab64890Smrg int mlen; /* length of modifier list */ 7181ab64890Smrg}; 7191ab64890Smrg 7201ab64890Smrg 7211ab64890Smrg/* Convert keysym to 'Thai Compose' keysym */ 7221ab64890Smrg/* The current implementation use latin-1 keysyms */ 7231ab64890SmrgPrivate Bool 7241ab64890SmrgThaiComposeConvert( 7251ab64890Smrg Display *dpy, 7261ab64890Smrg KeySym insym, 7271ab64890Smrg KeySym *outsym, KeySym *lower, KeySym *upper) 7281ab64890Smrg{ 7291ab64890Smrg struct _XMapThaiKey const *table_entry = ThaiComposeTable; 7301ab64890Smrg 7311ab64890Smrg while (table_entry->from != XK_VoidSymbol) { 7321ab64890Smrg if (table_entry->from == insym) { 7331ab64890Smrg *outsym = table_entry->to; 7341ab64890Smrg *lower = *outsym; 7351ab64890Smrg *upper = *outsym; 7361ab64890Smrg return True; 7371ab64890Smrg } 7381ab64890Smrg table_entry++; 7391ab64890Smrg } 7401ab64890Smrg return False; 7411ab64890Smrg} 7421ab64890Smrg 7431ab64890SmrgPrivate int 7441ab64890SmrgXThaiTranslateKey( 7451ab64890Smrg register Display *dpy, 7461ab64890Smrg KeyCode keycode, 7471ab64890Smrg register unsigned int modifiers, 7481ab64890Smrg unsigned int *modifiers_return, 7491ab64890Smrg KeySym *keysym_return, 7501ab64890Smrg KeySym *lsym_return, 7511ab64890Smrg KeySym *usym_return) 7521ab64890Smrg{ 7531ab64890Smrg int per; 7541ab64890Smrg register KeySym *syms; 7551ab64890Smrg KeySym sym = 0, lsym = 0, usym = 0; 7561ab64890Smrg 7571ab64890Smrg if ((! dpy->keysyms) && (! _XKeyInitialize(dpy))) 7581ab64890Smrg return 0; 7591ab64890Smrg *modifiers_return = (ShiftMask|LockMask) | dpy->mode_switch; 7601ab64890Smrg if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode)) 7611ab64890Smrg { 7621ab64890Smrg *keysym_return = NoSymbol; 7631ab64890Smrg return 1; 7641ab64890Smrg } 7651ab64890Smrg per = dpy->keysyms_per_keycode; 7661ab64890Smrg syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per]; 7671ab64890Smrg while ((per > 2) && (syms[per - 1] == NoSymbol)) 7681ab64890Smrg per--; 7691ab64890Smrg if ((per > 2) && (modifiers & dpy->mode_switch)) { 7701ab64890Smrg syms += 2; 7711ab64890Smrg per -= 2; 7721ab64890Smrg } 7731ab64890Smrg if (!(modifiers & ShiftMask) && 7741ab64890Smrg (!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) { 7751ab64890Smrg if ((per == 1) || (syms[1] == NoSymbol)) 7761ab64890Smrg XConvertCase(syms[0], keysym_return, &usym); 7771ab64890Smrg else { 7781ab64890Smrg XConvertCase(syms[0], &lsym, &usym); 7791ab64890Smrg *keysym_return = syms[0]; 7801ab64890Smrg } 7811ab64890Smrg } else if (!(modifiers & LockMask) || 7821ab64890Smrg (dpy->lock_meaning != XK_Caps_Lock)) { 7831ab64890Smrg if ((per == 1) || ((usym = syms[1]) == NoSymbol)) 7841ab64890Smrg XConvertCase(syms[0], &lsym, &usym); 7851ab64890Smrg *keysym_return = usym; 7861ab64890Smrg } else { 7871ab64890Smrg if ((per == 1) || ((sym = syms[1]) == NoSymbol)) 7881ab64890Smrg sym = syms[0]; 7891ab64890Smrg XConvertCase(sym, &lsym, &usym); 7901ab64890Smrg if (!(modifiers & ShiftMask) && (sym != syms[0]) && 7911ab64890Smrg ((sym != usym) || (lsym == usym))) 7921ab64890Smrg XConvertCase(syms[0], &lsym, &usym); 7931ab64890Smrg *keysym_return = usym; 7941ab64890Smrg } 7951ab64890Smrg /* 7961ab64890Smrg * ThaiCat keyboard support : 79761b2299dSmrg * When the Shift and Thai keys are hold for some keys a 'Thai Compose' 7981ab64890Smrg * character code is generated which is different from column 3 and 79961b2299dSmrg * 4 of the keymap. 8001ab64890Smrg * Since we don't know whether ThaiCat keyboard or WTT keyboard is 8011ab64890Smrg * in use, the same mapping is done for all Thai input. 80261b2299dSmrg * We just arbitary choose to use column 3 keysyms as the indices of 8031ab64890Smrg * this mapping. 8041ab64890Smrg * When the control key is also hold, this mapping has no effect. 8051ab64890Smrg */ 8061ab64890Smrg if ((modifiers & Mod1Mask) && 8071ab64890Smrg (modifiers & ShiftMask) && 8081ab64890Smrg !(modifiers & ControlMask)) { 8091ab64890Smrg if (ThaiComposeConvert(dpy, syms[0], &sym, &lsym, &usym)) 8101ab64890Smrg *keysym_return = sym; 8111ab64890Smrg } 8121ab64890Smrg 8131ab64890Smrg if (*keysym_return == XK_VoidSymbol) 8141ab64890Smrg *keysym_return = NoSymbol; 8151ab64890Smrg *lsym_return = lsym; 8161ab64890Smrg *usym_return = usym; 8171ab64890Smrg return 1; 8181ab64890Smrg} 8191ab64890Smrg 82061b2299dSmrg/* 8211ab64890Smrg * XThaiTranslateKeySym 8221ab64890Smrg * 8231ab64890Smrg * Translate KeySym to TACTIS code output. 8241ab64890Smrg * The current implementation uses ISO latin-1 keysym. 8251ab64890Smrg * Should be changed to TACTIS keysyms when they are defined by the 8261ab64890Smrg * standard. 8271ab64890Smrg */ 8281ab64890SmrgPrivate int 8291ab64890SmrgXThaiTranslateKeySym( 8301ab64890Smrg Display *dpy, 8311ab64890Smrg register KeySym symbol, 8321ab64890Smrg register KeySym lsym, 8331ab64890Smrg register KeySym usym, 8341ab64890Smrg unsigned int modifiers, 8351ab64890Smrg unsigned char *buffer, 8361ab64890Smrg int nbytes) 8371ab64890Smrg{ 8381ab64890Smrg KeySym ckey = 0; 83961b2299dSmrg register struct _XKeytrans *p; 8401ab64890Smrg int length; 8411ab64890Smrg unsigned long hiBytes; 8421ab64890Smrg register unsigned char c; 8431ab64890Smrg 8441ab64890Smrg /* 8451ab64890Smrg * initialize length = 1 ; 8461ab64890Smrg */ 8471ab64890Smrg length = 1; 8481ab64890Smrg 8491ab64890Smrg if (!symbol) 8501ab64890Smrg return 0; 8511ab64890Smrg /* see if symbol rebound, if so, return that string. */ 8521ab64890Smrg for (p = dpy->key_bindings; p; p = p->next) { 8531ab64890Smrg if (((modifiers & AllMods) == p->state) && (symbol == p->key)) { 8541ab64890Smrg length = p->len; 8551ab64890Smrg if (length > nbytes) length = nbytes; 8561ab64890Smrg memcpy (buffer, p->string, length); 8571ab64890Smrg return length; 8581ab64890Smrg } 8591ab64890Smrg } 8601ab64890Smrg /* try to convert to TACTIS, handling control */ 8611ab64890Smrg hiBytes = symbol >> 8; 8621ab64890Smrg if (!(nbytes && 8631ab64890Smrg ((hiBytes == 0) || 8641ab64890Smrg ((hiBytes == 0xFF) && 8651ab64890Smrg (((symbol >= XK_BackSpace) && (symbol <= XK_Clear)) || 8661ab64890Smrg (symbol == XK_Return) || 8671ab64890Smrg (symbol == XK_Escape) || 8681ab64890Smrg (symbol == XK_KP_Space) || 8691ab64890Smrg (symbol == XK_KP_Tab) || 8701ab64890Smrg (symbol == XK_KP_Enter) || 8711ab64890Smrg ((symbol >= XK_KP_Multiply) && (symbol <= XK_KP_9)) || 8721ab64890Smrg (symbol == XK_KP_Equal) || 8731ab64890Smrg (symbol == XK_Scroll_Lock) || 8741ab64890Smrg#ifdef DXK_PRIVATE /* DEC private keysyms */ 8751ab64890Smrg (symbol == DXK_Remove) || 8761ab64890Smrg#endif 8771ab64890Smrg (symbol == NoSymbol) || 8781ab64890Smrg (symbol == XK_Delete)))))) 8791ab64890Smrg return 0; 8801ab64890Smrg 8811ab64890Smrg /* if X keysym, convert to ascii by grabbing low 7 bits */ 8821ab64890Smrg if (symbol == XK_KP_Space) 8831ab64890Smrg c = XK_space & 0x7F; /* patch encoding botch */ 8841ab64890Smrg/* not for Thai 8851ab64890Smrg else if (symbol == XK_hyphen) 8861ab64890Smrg c = XK_minus & 0xFF; */ /* map to equiv character */ 8871ab64890Smrg else if (hiBytes == 0xFF) 8881ab64890Smrg c = symbol & 0x7F; 8891ab64890Smrg else 8901ab64890Smrg c = symbol & 0xFF; 8911ab64890Smrg /* only apply Control key if it makes sense, else ignore it */ 8921ab64890Smrg if (modifiers & ControlMask) { 8931ab64890Smrg if (!(IsKeypadKey(lsym) || lsym==XK_Return || lsym==XK_Tab)) { 8941ab64890Smrg if (IsISOControlKey(lsym)) ckey = lsym; 8951ab64890Smrg else if (IsISOControlKey(usym)) ckey = usym; 8961ab64890Smrg else if (lsym == XK_question) ckey = lsym; 8971ab64890Smrg else if (usym == XK_question) ckey = usym; 8981ab64890Smrg else if (IsValidControlKey(lsym)) ckey = lsym; 8991ab64890Smrg else if (IsValidControlKey(usym)) ckey = usym; 9001ab64890Smrg else length = 0; 9011ab64890Smrg 9021ab64890Smrg if (length != 0) { 9031ab64890Smrg if (ckey == XK_2) c = '\000'; 9041ab64890Smrg else if (ckey >= XK_3 && ckey <= XK_7) 9051ab64890Smrg c = (char)(ckey-('3'-'\033')); 9061ab64890Smrg else if (ckey == XK_8) c = '\177'; 9071ab64890Smrg else if (ckey == XK_Delete) c = '\030'; 9081ab64890Smrg else if (ckey == XK_question) c = '\037'; 9091ab64890Smrg else if (ckey == XK_quoteleft) c = '\036'; /* KLee 1/24/91 */ 9101ab64890Smrg else c = (char)(ckey & 0x1f); 9111ab64890Smrg } 9121ab64890Smrg } 9131ab64890Smrg } 9141ab64890Smrg /* 9151ab64890Smrg * ThaiCat has a key that generates two TACTIS codes D1 & E9. 91661b2299dSmrg * It is represented by the latin-1 keysym XK_thorn (0xfe). 91761b2299dSmrg * If c is XK_thorn, this key is pressed and it is converted to 9181ab64890Smrg * 0xd1 0xe9. 9191ab64890Smrg */ 9201ab64890Smrg if (c == XK_thorn) { 9211ab64890Smrg buffer[0] = 0xd1; 9221ab64890Smrg buffer[1] = 0xe9; 9231ab64890Smrg buffer[2] = '\0'; 9241ab64890Smrg return 2; 9251ab64890Smrg } 9261ab64890Smrg else { 9271ab64890Smrg /* Normal case */ 9281ab64890Smrg buffer[0] = c; 9291ab64890Smrg buffer[1] = '\0'; 9301ab64890Smrg return 1; 9311ab64890Smrg } 9321ab64890Smrg} 9331ab64890Smrg 9341ab64890Smrg/* 9351ab64890Smrg * given a KeySym, returns the first keycode containing it, if any. 9361ab64890Smrg */ 9371ab64890SmrgPrivate CARD8 9381ab64890SmrgFindKeyCode( 9391ab64890Smrg register Display *dpy, 9401ab64890Smrg register KeySym code) 9411ab64890Smrg{ 9421ab64890Smrg 94361b2299dSmrg register KeySym *kmax = dpy->keysyms + 9441ab64890Smrg (dpy->max_keycode - dpy->min_keycode + 1) * dpy->keysyms_per_keycode; 9451ab64890Smrg register KeySym *k = dpy->keysyms; 9461ab64890Smrg while (k < kmax) { 9471ab64890Smrg if (*k == code) 9481ab64890Smrg return (((k - dpy->keysyms) / dpy->keysyms_per_keycode) + 9491ab64890Smrg dpy->min_keycode); 9501ab64890Smrg k += 1; 9511ab64890Smrg } 9521ab64890Smrg return 0; 9531ab64890Smrg} 9541ab64890Smrg 9551ab64890Smrg/* 9561ab64890Smrg * given a list of modifiers, computes the mask necessary for later matching. 9571ab64890Smrg * This routine must lookup the key in the Keymap and then search to see 9581ab64890Smrg * what modifier it is bound to, if any. Sets the AnyModifier bit if it 9591ab64890Smrg * can't map some keysym to a modifier. 9601ab64890Smrg */ 9611ab64890SmrgPrivate void 9621ab64890SmrgComputeMaskFromKeytrans( 9631ab64890Smrg Display *dpy, 9641ab64890Smrg register struct _XKeytrans *p) 9651ab64890Smrg{ 9661ab64890Smrg register int i; 9671ab64890Smrg register CARD8 code; 9681ab64890Smrg register XModifierKeymap *m = dpy->modifiermap; 9691ab64890Smrg 9701ab64890Smrg p->state = AnyModifier; 9711ab64890Smrg for (i = 0; i < p->mlen; i++) { 9721ab64890Smrg /* if not found, then not on current keyboard */ 9731ab64890Smrg if ((code = FindKeyCode(dpy, p->modifiers[i])) == 0) 9741ab64890Smrg return; 9751ab64890Smrg /* code is now the keycode for the modifier you want */ 9761ab64890Smrg { 9771ab64890Smrg register int j = m->max_keypermod<<3; 9781ab64890Smrg 9791ab64890Smrg while ((--j >= 0) && (code != m->modifiermap[j])) 9801ab64890Smrg ; 9811ab64890Smrg if (j < 0) 9821ab64890Smrg return; 9831ab64890Smrg p->state |= (1<<(j/m->max_keypermod)); 9841ab64890Smrg } 9851ab64890Smrg } 9861ab64890Smrg p->state &= AllMods; 9871ab64890Smrg} 9881ab64890Smrg 9891ab64890Smrg/************************************************************************ 9901ab64890Smrg * 9911ab64890Smrg * 9921ab64890Smrg * Compose handling routines - compose handlers 0,1,2 99361b2299dSmrg * 99461b2299dSmrg * 9951ab64890Smrg ************************************************************************/ 9961ab64890Smrg 9971ab64890Smrg#define NORMAL_KEY_STATE 0 9981ab64890Smrg#define FIRST_COMPOSE_KEY_STATE 1 9991ab64890Smrg#define SECOND_COMPOSE_KEY_STATE 2 10001ab64890Smrg 10011ab64890SmrgPrivate 10021ab64890SmrgKeySym HexIMNormalKey( 10031ab64890Smrg XicThaiPart *thai_part, 10041ab64890Smrg KeySym symbol, 10051ab64890Smrg XKeyEvent *event) 10061ab64890Smrg{ 10071ab64890Smrg if (IsComposeKey (symbol, event)) /* start compose sequence */ 10081ab64890Smrg { 10091ab64890Smrg SetLed (event->display,COMPOSE_LED, LedModeOn); 10101ab64890Smrg thai_part->comp_state = FIRST_COMPOSE_KEY_STATE; 10111ab64890Smrg return NoSymbol; 10121ab64890Smrg } 10131ab64890Smrg return symbol; 10141ab64890Smrg} 10151ab64890Smrg 10161ab64890Smrg 10171ab64890SmrgPrivate 10181ab64890SmrgKeySym HexIMFirstComposeKey( 10191ab64890Smrg XicThaiPart *thai_part, 10201ab64890Smrg KeySym symbol, 10211ab64890Smrg XKeyEvent *event) 10221ab64890Smrg{ 10231ab64890Smrg if (IsModifierKey (symbol)) return symbol; /* ignore shift etc. */ 10241ab64890Smrg if (IsCancelComposeKey (&symbol, event)) /* cancel sequence */ 10251ab64890Smrg { 10261ab64890Smrg SetLed (event->display,COMPOSE_LED, LedModeOff); 10271ab64890Smrg thai_part->comp_state = NORMAL_KEY_STATE; 10281ab64890Smrg return symbol; 10291ab64890Smrg } 10301ab64890Smrg if (IsComposeKey (symbol, event)) /* restart sequence ?? */ 10311ab64890Smrg { 10321ab64890Smrg return NoSymbol; /* no state change necessary */ 10331ab64890Smrg } 10341ab64890Smrg 10351ab64890Smrg thai_part->keysym = symbol; /* save key pressed */ 10361ab64890Smrg thai_part->comp_state = SECOND_COMPOSE_KEY_STATE; 10371ab64890Smrg return NoSymbol; 10381ab64890Smrg} 10391ab64890Smrg 10401ab64890SmrgPrivate 10411ab64890SmrgKeySym HexIMSecondComposeKey( 10421ab64890Smrg XicThaiPart *thai_part, 10431ab64890Smrg KeySym symbol, 10441ab64890Smrg XKeyEvent *event) 10451ab64890Smrg{ 10461ab64890Smrg if (IsModifierKey (symbol)) return symbol; /* ignore shift etc. */ 10471ab64890Smrg if (IsComposeKey (symbol, event)) /* restart sequence ? */ 10481ab64890Smrg { 10491ab64890Smrg thai_part->comp_state =FIRST_COMPOSE_KEY_STATE; 10501ab64890Smrg return NoSymbol; 10511ab64890Smrg } 10521ab64890Smrg SetLed (event->display,COMPOSE_LED, LedModeOff); 10531ab64890Smrg if (IsCancelComposeKey (&symbol, event)) /* cancel sequence ? */ 10541ab64890Smrg { 10551ab64890Smrg thai_part->comp_state = NORMAL_KEY_STATE; 10561ab64890Smrg return symbol; 10571ab64890Smrg } 10581ab64890Smrg 10591ab64890Smrg if ((symbol = HexIMComposeSequence (thai_part->keysym, symbol)) 10601ab64890Smrg ==NoSymbol) 10611ab64890Smrg { /* invalid compose sequence */ 10621ab64890Smrg XBell(event->display, BellVolume); 10631ab64890Smrg } 10641ab64890Smrg thai_part->comp_state = NORMAL_KEY_STATE; /* reset to normal state */ 10651ab64890Smrg return symbol; 10661ab64890Smrg} 10671ab64890Smrg 10681ab64890Smrg 10691ab64890Smrg/* 10701ab64890Smrg * Interprets two keysyms entered as hex digits and return the Thai keysym 10711ab64890Smrg * correspond to the TACTIS code formed. 10721ab64890Smrg * The current implementation of this routine returns ISO Latin Keysyms. 10731ab64890Smrg */ 10741ab64890Smrg 10751ab64890SmrgPrivate 10761ab64890SmrgKeySym HexIMComposeSequence(KeySym ks1, KeySym ks2) 10771ab64890Smrg{ 10781ab64890Smrgint hi_digit; 10791ab64890Smrgint lo_digit; 10801ab64890Smrgint tactis_code; 10811ab64890Smrg 10821ab64890Smrg if ((ks1 >= XK_0) && (ks1 <= XK_9)) 10831ab64890Smrg hi_digit = ks1 - XK_0; 10841ab64890Smrg else if ((ks1 >= XK_A) && (ks1 <= XK_F)) 10851ab64890Smrg hi_digit = ks1 - XK_A + 10; 10861ab64890Smrg else if ((ks1 >= XK_a) && (ks1 <= XK_f)) 10871ab64890Smrg hi_digit = ks1 - XK_a + 10; 10881ab64890Smrg else /* out of range */ 10891ab64890Smrg return NoSymbol; 109061b2299dSmrg 10911ab64890Smrg if ((ks2 >= XK_0) && (ks2 <= XK_9)) 10921ab64890Smrg lo_digit = ks2 - XK_0; 10931ab64890Smrg else if ((ks2 >= XK_A) && (ks2 <= XK_F)) 10941ab64890Smrg lo_digit = ks2 - XK_A + 10; 10951ab64890Smrg else if ((ks2 >= XK_a) && (ks2 <= XK_f)) 10961ab64890Smrg lo_digit = ks2 - XK_a + 10; 10971ab64890Smrg else /* out of range */ 10981ab64890Smrg return NoSymbol; 10991ab64890Smrg 11001ab64890Smrg tactis_code = hi_digit * 0x10 + lo_digit ; 11011ab64890Smrg 11021ab64890Smrg return (KeySym)tactis_code; 11031ab64890Smrg 11041ab64890Smrg} 11051ab64890Smrg 11061ab64890Smrg/* 11071ab64890Smrg * routine determines 11081ab64890Smrg * 1) whether key event should cancel a compose sequence 11091ab64890Smrg * 2) whether cancelling key event should be processed or ignored 11101ab64890Smrg */ 11111ab64890Smrg 11121ab64890SmrgPrivate 11131ab64890Smrgint IsCancelComposeKey( 11141ab64890Smrg KeySym *symbol, 11151ab64890Smrg XKeyEvent *event) 11161ab64890Smrg{ 11171ab64890Smrg if (*symbol==XK_Delete && !IsControl(event->state) && 11181ab64890Smrg !IsMod1(event->state)) { 11191ab64890Smrg *symbol=NoSymbol; /* cancel compose sequence, and ignore key */ 11201ab64890Smrg return True; 11211ab64890Smrg } 11221ab64890Smrg if (IsComposeKey(*symbol, event)) return False; 11231ab64890Smrg return ( 11241ab64890Smrg IsControl (event->state) || 11251ab64890Smrg IsMod1(event->state) || 11261ab64890Smrg IsKeypadKey (*symbol) || 11271ab64890Smrg IsFunctionKey (*symbol) || 11281ab64890Smrg IsMiscFunctionKey (*symbol) || 11291ab64890Smrg#ifdef DXK_PRIVATE /* DEC private keysyms */ 11301ab64890Smrg *symbol == DXK_Remove || 11311ab64890Smrg#endif 11321ab64890Smrg IsPFKey (*symbol) || 11331ab64890Smrg IsCursorKey (*symbol) || 11341ab64890Smrg (*symbol >= XK_Tab && *symbol < XK_Multi_key) 11351ab64890Smrg ? True : False); /* cancel compose sequence and pass */ 11361ab64890Smrg /* cancelling key through */ 11371ab64890Smrg} 11381ab64890Smrg 11391ab64890Smrg 11401ab64890Smrg/* 11411ab64890Smrg * set specified keyboard LED on or off 11421ab64890Smrg */ 11431ab64890Smrg 11441ab64890SmrgPrivate 11451ab64890Smrgvoid SetLed( 11461ab64890Smrg Display *dpy, 11471ab64890Smrg int num, 11481ab64890Smrg int state) 11491ab64890Smrg{ 11501ab64890Smrg XKeyboardControl led_control; 11511ab64890Smrg 11521ab64890Smrg led_control.led_mode = state; 11531ab64890Smrg led_control.led = num; 11541ab64890Smrg XChangeKeyboardControl (dpy, KBLed | KBLedMode, &led_control); 11551ab64890Smrg} 11561ab64890Smrg#endif 11571ab64890Smrg 11581ab64890Smrg/* 115961b2299dSmrg * Initialize ISC mode from im modifier 11601ab64890Smrg */ 11611ab64890SmrgPrivate void InitIscMode(Xic ic) 11621ab64890Smrg{ 11631ab64890Smrg Xim im; 11641ab64890Smrg char *im_modifier_name; 11651ab64890Smrg 11661ab64890Smrg /* If already defined, just return */ 11671ab64890Smrg 11681ab64890Smrg if (IC_IscMode(ic)) return; 11691ab64890Smrg 11701ab64890Smrg /* Get IM modifier */ 11711ab64890Smrg 11721ab64890Smrg im = (Xim) XIMOfIC((XIC)ic); 11731ab64890Smrg im_modifier_name = im->core.im_name; 11741ab64890Smrg 11751ab64890Smrg /* Match with predefined value, default is Basic Check */ 11761ab64890Smrg 11771ab64890Smrg if (!strncmp(im_modifier_name,"BasicCheck",MAXTHAIIMMODLEN+1)) 11781ab64890Smrg IC_IscMode(ic) = WTT_ISC1; 11791ab64890Smrg else if (!strncmp(im_modifier_name,"Strict",MAXTHAIIMMODLEN+1)) 11801ab64890Smrg IC_IscMode(ic) = WTT_ISC2; 11811ab64890Smrg else if (!strncmp(im_modifier_name,"Thaicat",MAXTHAIIMMODLEN+1)) 11821ab64890Smrg IC_IscMode(ic) = THAICAT_ISC; 11831ab64890Smrg else if (!strncmp(im_modifier_name,"Passthrough",MAXTHAIIMMODLEN+1)) 11841ab64890Smrg IC_IscMode(ic) = NOISC; 11851ab64890Smrg else 11861ab64890Smrg IC_IscMode(ic) = WTT_ISC1; 11871ab64890Smrg 11881ab64890Smrg return; 11891ab64890Smrg} 119061b2299dSmrg 11911ab64890Smrg/* 11921ab64890Smrg * Helper functions for _XimThaiFilter() 11931ab64890Smrg */ 11941ab64890SmrgPrivate Bool 11951ab64890SmrgThaiFltAcceptInput(Xic ic, unsigned char new_char, KeySym symbol) 11961ab64890Smrg{ 11971ab64890Smrg DefTreeBase *b = &ic->private.local.base; 11981ab64890Smrg b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char); 11991ab64890Smrg b->wc[b->tree[ic->private.local.composed].wc+1] = '\0'; 12001ab64890Smrg 12011ab64890Smrg if ((new_char <= 0x1f) || (new_char == 0x7f)) 12021ab64890Smrg b->tree[ic->private.local.composed].keysym = symbol; 12031ab64890Smrg else 12041ab64890Smrg b->tree[ic->private.local.composed].keysym = NoSymbol; 12051ab64890Smrg 12061ab64890Smrg return True; 12071ab64890Smrg} 12081ab64890Smrg 12091ab64890SmrgPrivate Bool 12101ab64890SmrgThaiFltReorderInput(Xic ic, unsigned char previous_char, unsigned char new_char) 12111ab64890Smrg{ 12121ab64890Smrg DefTreeBase *b = &ic->private.local.base; 12131ab64890Smrg if (!IC_DeletePreviousChar(ic)) return False; 12141ab64890Smrg b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char); 12151ab64890Smrg b->wc[b->tree[ic->private.local.composed].wc+1] = tis2ucs(previous_char); 12161ab64890Smrg b->wc[b->tree[ic->private.local.composed].wc+2] = '\0'; 12171ab64890Smrg 12181ab64890Smrg b->tree[ic->private.local.composed].keysym = NoSymbol; 12191ab64890Smrg 12201ab64890Smrg return True; 12211ab64890Smrg} 12221ab64890Smrg 12231ab64890SmrgPrivate Bool 12241ab64890SmrgThaiFltReplaceInput(Xic ic, unsigned char new_char, KeySym symbol) 12251ab64890Smrg{ 12261ab64890Smrg DefTreeBase *b = &ic->private.local.base; 12271ab64890Smrg if (!IC_DeletePreviousChar(ic)) return False; 12281ab64890Smrg b->wc[b->tree[ic->private.local.composed].wc+0] = tis2ucs(new_char); 12291ab64890Smrg b->wc[b->tree[ic->private.local.composed].wc+1] = '\0'; 12301ab64890Smrg 12311ab64890Smrg if ((new_char <= 0x1f) || (new_char == 0x7f)) 12321ab64890Smrg b->tree[ic->private.local.composed].keysym = symbol; 12331ab64890Smrg else 12341ab64890Smrg b->tree[ic->private.local.composed].keysym = NoSymbol; 12351ab64890Smrg 12361ab64890Smrg return True; 12371ab64890Smrg} 12381ab64890Smrg 12391ab64890Smrg/* 12401ab64890Smrg * Filter function for TACTIS 12411ab64890Smrg */ 12421ab64890SmrgBool 124361b2299dSmrg_XimThaiFilter(Display *d, Window w, XEvent *ev, XPointer client_data) 12441ab64890Smrg{ 12451ab64890Smrg Xic ic = (Xic)client_data; 12461ab64890Smrg KeySym symbol; 12471ab64890Smrg int isc_mode; /* Thai Input Sequence Check mode */ 12481ab64890Smrg unsigned char previous_char; /* Last inputted Thai char */ 12491ab64890Smrg unsigned char new_char; 12501ab64890Smrg#ifdef UNUSED 12511ab64890Smrg unsigned int modifiers; 12521ab64890Smrg KeySym lsym,usym; 12531ab64890Smrg int state; 12541ab64890Smrg XicThaiPart *thai_part; 12551ab64890Smrg char buf[10]; 12561ab64890Smrg#endif 12571ab64890Smrg wchar_t wbuf[10]; 12581ab64890Smrg Bool isReject; 12591ab64890Smrg DefTreeBase *b = &ic->private.local.base; 12601ab64890Smrg 12611ab64890Smrg if ((ev->type != KeyPress) 12621ab64890Smrg || (ev->xkey.keycode == 0)) 12631ab64890Smrg return False; 12641ab64890Smrg 12651ab64890Smrg if (!IC_IscMode(ic)) InitIscMode(ic); 12661ab64890Smrg 12671ab64890Smrg XwcLookupString((XIC)ic, &ev->xkey, wbuf, sizeof(wbuf) / sizeof(wbuf[0]), 12681ab64890Smrg &symbol, NULL); 12691ab64890Smrg 12701ab64890Smrg if ((ev->xkey.state & (AllMods & ~ShiftMask)) || 12711ab64890Smrg ((symbol >> 8 == 0xFF) && 12721ab64890Smrg ((XK_BackSpace <= symbol && symbol <= XK_Clear) || 12731ab64890Smrg (symbol == XK_Return) || 12741ab64890Smrg (symbol == XK_Pause) || 12751ab64890Smrg (symbol == XK_Scroll_Lock) || 12761ab64890Smrg (symbol == XK_Sys_Req) || 12771ab64890Smrg (symbol == XK_Escape) || 12781ab64890Smrg (symbol == XK_Delete) || 12791ab64890Smrg IsCursorKey(symbol) || 12801ab64890Smrg IsKeypadKey(symbol) || 12811ab64890Smrg IsMiscFunctionKey(symbol) || 12821ab64890Smrg IsFunctionKey(symbol)))) 12831ab64890Smrg { 128461b2299dSmrg IC_ClearPreviousChar(ic); 12851ab64890Smrg return False; 12861ab64890Smrg } 12871ab64890Smrg if (((symbol >> 8 == 0xFF) && 12881ab64890Smrg IsModifierKey(symbol)) || 12891ab64890Smrg#ifdef XK_XKB_KEYS 12901ab64890Smrg ((symbol >> 8 == 0xFE) && 12911ab64890Smrg (XK_ISO_Lock <= symbol && symbol <= XK_ISO_Last_Group_Lock)) || 12921ab64890Smrg#endif 12931ab64890Smrg (symbol == NoSymbol)) 12941ab64890Smrg { 12951ab64890Smrg return False; 12961ab64890Smrg } 12971ab64890Smrg#ifdef UNUSED 12981ab64890Smrg if (! XThaiTranslateKey(ev->xkey.display, ev->xkey.keycode, ev->xkey.state, 12991ab64890Smrg &modifiers, &symbol, &lsym, &usym)) 13001ab64890Smrg return False; 13011ab64890Smrg 13021ab64890Smrg /* 130361b2299dSmrg * Hex input method processing 13041ab64890Smrg */ 13051ab64890Smrg 13061ab64890Smrg thai_part = &ic->private.local.thai; 13071ab64890Smrg state = thai_part->comp_state; 13081ab64890Smrg if (state >= 0 && state < nstate_handlers) /* call handler for state */ 13091ab64890Smrg { 13101ab64890Smrg symbol = (* state_handler[state])(thai_part, symbol, (XKeyEvent *)ev); 13111ab64890Smrg } 13121ab64890Smrg 13131ab64890Smrg /* 13141ab64890Smrg * Translate KeySym into mb. 13151ab64890Smrg */ 13161ab64890Smrg count = XThaiTranslateKeySym(ev->xkey.display, symbol, lsym, 13171ab64890Smrg usym, ev->xkey.state, buf, 10); 13181ab64890Smrg 13191ab64890Smrg if (!symbol && !count) 13201ab64890Smrg return True; 13211ab64890Smrg 13221ab64890Smrg /* Return symbol if cannot convert to character */ 13231ab64890Smrg if (!count) 13241ab64890Smrg return False; 13251ab64890Smrg#endif 13261ab64890Smrg 13271ab64890Smrg /* 13281ab64890Smrg * Thai Input sequence check 13291ab64890Smrg */ 13301ab64890Smrg isc_mode = IC_IscMode(ic); 13311ab64890Smrg if (!(previous_char = IC_GetPreviousChar(ic))) previous_char = ' '; 13321ab64890Smrg new_char = ucs2tis(wbuf[0]); 13331ab64890Smrg isReject = True; 13341ab64890Smrg if (THAI_isaccepted(new_char, previous_char, isc_mode)) { 13351ab64890Smrg ThaiFltAcceptInput(ic, new_char, symbol); 13361ab64890Smrg isReject = False; 13371ab64890Smrg } else { 13381ab64890Smrg unsigned char context_char; 13391ab64890Smrg 13401ab64890Smrg context_char = IC_GetContextChar(ic); 13411ab64890Smrg if (context_char) { 13421ab64890Smrg if (THAI_iscomposible(new_char, context_char)) { 13431ab64890Smrg if (THAI_iscomposible(previous_char, new_char)) { 13441ab64890Smrg isReject = !ThaiFltReorderInput(ic, previous_char, new_char); 13451ab64890Smrg } else if (THAI_iscomposible(previous_char, context_char)) { 13461ab64890Smrg isReject = !ThaiFltReplaceInput(ic, new_char, symbol); 13471ab64890Smrg } else if (THAI_chtype(previous_char) == FV1 13481ab64890Smrg && THAI_chtype(new_char) == TONE) { 13491ab64890Smrg isReject = !ThaiFltReorderInput(ic, previous_char, new_char); 13501ab64890Smrg } 13511ab64890Smrg } else if (THAI_isaccepted(new_char, context_char, isc_mode)) { 13521ab64890Smrg isReject = !ThaiFltReplaceInput(ic, new_char, symbol); 13531ab64890Smrg } 13541ab64890Smrg } 13551ab64890Smrg } 13561ab64890Smrg if (isReject) { 13571ab64890Smrg /* reject character */ 13581ab64890Smrg XBell(ev->xkey.display, BellVolume); 13591ab64890Smrg return True; 13601ab64890Smrg } 13611ab64890Smrg 13621ab64890Smrg _Xlcwcstombs(ic->core.im->core.lcd, &b->mb[b->tree[ic->private.local.composed].mb], 13631ab64890Smrg &b->wc[b->tree[ic->private.local.composed].wc], 10); 13641ab64890Smrg 13651ab64890Smrg _Xlcmbstoutf8(ic->core.im->core.lcd, &b->utf8[b->tree[ic->private.local.composed].utf8], 13661ab64890Smrg &b->mb[b->tree[ic->private.local.composed].mb], 10); 13671ab64890Smrg 13681ab64890Smrg /* Remember the last character inputted 13691ab64890Smrg * (as fallback in case StringConversionCallback is not provided) 13701ab64890Smrg */ 13711ab64890Smrg IC_SavePreviousChar(ic, new_char); 13721ab64890Smrg 13731ab64890Smrg ev->xkey.keycode = 0; 13741ab64890Smrg XPutBackEvent(d, ev); 13751ab64890Smrg return True; 13761ab64890Smrg} 1377