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