ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/grkelot.C
Revision: 1.7
Committed: Sun Feb 22 08:09:37 2004 UTC (20 years, 3 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.6: +0 -0 lines
State: FILE REMOVED
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*---------------------------------*C*--------------------------------------*
2     * File: grkelot.c
3     *--------------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1994,1995 Angelo Haritsis. All rights reserved.
7     * - original version
8     * Copyright (c) 1997,1998 Oezger Kesim <kesim@math.fu-berlin.de>
9     *
10     * This program is free software; you can redistribute it and/or modify
11     * it under the terms of the GNU General Public License as published by
12     * the Free Software Foundation; either version 2 of the License, or
13     * (at your option) any later version.
14     *
15     * This program is distributed in the hope that it will be useful,
16     * but WITHOUT ANY WARRANTY; without even the implied warranty of
17     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     * GNU General Public License for more details.
19     *
20     * You should have received a copy of the GNU General Public License
21     * along with this program; if not, write to the Free Software
22     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23     *--------------------------------------------------------------------------*
24     * Synopsis: string -> greek ELOT928 or IBM437 string;
25     * 4-state FSM implementation.
26     *
27     * System: Any (ANSI C)
28     *
29     * This is code derived from a more generic key remapper written by the same
30     * author and used in other environments. It was not written only
31     * for greek kbd bindings. An extension to other languages is easy
32     * (well don't know how the FSM lends itself to Far East languages).
33     *
34     * The FSM can have MAX_STATES states (change it for more).
35     * Each state contains:
36 pcg 1.6 * 1. many tranlsation tables (registered via kstate_add_xlat ())
37 pcg 1.1 * 2. many switch codes for transition to other states (registered via
38 pcg 1.6 * kstate_add_switcher ()) : limit is static now: MAX_SWITCHER
39 pcg 1.1 * 3. life: the number of xlations allowed in a state (0 = unlimited)
40     *
41     * Format of tranlation strings:
42     * <first>-<last>:n1,n2,n3,...
43     * Format of switcher string:
44     * A<char>:<state_no>
45     * (other switchers apart from A=ascii can be supported; not in this context)
46     * Format of life string:
47     * L<N> (N=0,1,...)
48     *-------------------------------------------------------------------------*
49     * Written by Angelo Haritis.
50     *
51     * Redistribution and use in source and binary forms are permitted provided
52     * that the above copyright notice and this paragraph are duplicated in all
53     * such forms and that any documentation, advertising materials, and other
54     * materials related to such distribution and use acknowledge that the
55     * software was developed by Angelo Haritsis.
56     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
57     * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
58     * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
59     *
60     * NB: DO NOT ALTER! THIS CODE IS USED IN MANY PLATFORMS!!!
61     *
62     * TODO: make it more dynamic (linked lists is an idea but slower)
63     */
64    
65     #define RXVT /* define for use by rxvt */
66    
67     #ifdef RXVT
68     #include "../config.h" /* NECESSARY */
69     #include "rxvt.h" /* NECESSARY */
70     #include "grkelot.intpro" /* PROTOS for internal routines */
71     #endif /* RXVT */
72    
73     #ifdef GREEK_SUPPORT
74     #include "grkelot.h"
75     #include <stdlib.h>
76     #include <string.h>
77    
78     /* --- Macros, Types --------- */
79     #define MAX_STATES 4 /* max # states for the FSM */
80     #define MAX_SWITCHER 2U /* per state */
81     #define MAX_VAL 256 /* for temp allocation */
82    
83     typedef unsigned char u_char;
84     typedef unsigned int u_int;
85     typedef unsigned long u_long;
86    
87 pcg 1.5 typedef struct s_xlat
88     {
89 pcg 1.1 u_int first, last;
90     u_int *pval; /* array of translated values */
91 pcg 1.5 }
92     K_XLAT;
93 pcg 1.1
94 pcg 1.5 typedef struct s_switch
95     {
96 pcg 1.1 u_char type; /* Ascii, Virtual, Scan */
97     u_int code;
98     u_char nextstate;
99     u_char on; /* current state of key: 0 = off */
100 pcg 1.5 }
101     K_SWITCH;
102 pcg 1.1
103 pcg 1.5 typedef struct s_state
104     {
105 pcg 1.1 u_int num_xlat; /* number of translations */
106     K_XLAT *xlat; /* State translations ((dynamic - realloc'ed) */
107     u_int num_switcher; /* number of switcher keys */
108     K_SWITCH switcher[MAX_SWITCHER]; /* switcher keys to other states */
109     u_char life; /* 0 = until switched by key */
110     u_char prev_state; /* filled when jumped to a new state */
111 pcg 1.5 }
112     K_STATE;
113 pcg 1.1
114     /* type for each one of the different greek standards (xlat types) */
115 pcg 1.5 typedef struct s_xlat_type
116     {
117 pcg 1.1 char *plain;
118     char *accent;
119     char *accent_xtra;
120     char *umlaut;
121     char *acc_uml;
122 pcg 1.5 }
123     XLAT_TYPE;
124 pcg 1.1
125     /* --- Local Data ------------ */
126     static K_STATE State[MAX_STATES];
127    
128     /* Current State */
129     static u_char nStateNow = 0;
130     static K_STATE *pStateNow = &State[0];
131     static int GreekMode = GREEK_ELOT928;
132    
133     /*
134     * The following are hard-coded for now. The idea is that such strings would
135     * be read from a config file making it possible to change language/encodings
136     * more flexibly.
137     */
138     /* elot 928 xlations */
139     static char elot_xlat_plain[] = "65-122:193,194,216,196,197,214,195,199,201,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,213,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,233,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,245,230";
140    
141     /* c and s give copyright and section sign */
142     static char elot_xlat_acc[] = "65-122:182,194,216,196,184,214,195,185,186,206,202,203,204,205,188,208,81,209,211,212,200,191,87,215,190,198,91,92,93,94,95,96,220,226," /*248 */ "169,228,221,246,227,222,223,238,234,235,236,237,252,240,113,241," /*243 */ "167,244,232,254,242,247,253,230";
143     static char elot_xlat_acc_xtra[] = "46-62:183,47,48,49,50,51,52,53,54,55,56,57,58,59,171,61,187"; /* anw teleia, quotes */
144     static char elot_xlat_uml[] = "65-122:193,194,216,196,197,214,195,199,218,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,219,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,250,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,251,230";
145     static char elot_xlat_umacc[] = "65-122:193,194,216,196,197,214,195,199,201,206,202,203,204,205,207,208,81,209,211,212,200,217,87,215,213,198,91,92,93,94,95,96,225,226,248,228,229,246,227,231,192,238,234,235,236,237,239,240,113,241,243,244,232,249,242,247,224,230";
146    
147     /* ibm 437 xlations */
148     static char i437_xlat_plain[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,160,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,172,157";
149     static char i437_xlat_acc[] = "65-122:234,129,150,131,235,148,130,236,237,141,137,138,139,140,238,143,81,144,145,146,135,240,87,149,239,133,91,92,93,94,95,96,225,153,175,155,226,173,154,227,229,165,161,162,163,164,230,167,113,168,169,171,159,233,170,174,231,157";
150     static char i437_xlat_acc_xtra[] = "46-46:250"; /* anw teleia */
151     static char i437_xlat_uml[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,228,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,232,157";
152     static char i437_xlat_umacc[] = "65-122:128,129,150,131,132,148,130,134,136,141,137,138,139,140,142,143,81,144,145,146,135,151,87,149,147,133,91,92,93,94,95,96,152,153,175,155,156,173,154,158,42,165,161,162,163,164,166,167,113,168,169,171,159,224,170,174,42,157";
153    
154     /*
155     * currently ELOT928 and IBM437 are supported; easy to include others
156     * (not recommended: stick to just these 2 if not only the ELOT one)
157     */
158     static XLAT_TYPE xlat_type[] =
159 pcg 1.5 {
160 pcg 1.1 {elot_xlat_plain, elot_xlat_acc, elot_xlat_acc_xtra, elot_xlat_uml, elot_xlat_umacc},
161     {i437_xlat_plain, i437_xlat_acc, i437_xlat_acc_xtra, i437_xlat_uml, i437_xlat_umacc},
162 pcg 1.5 };
163 pcg 1.1
164     /* the current trasnaltion type */
165     static XLAT_TYPE *xlat_now = &xlat_type[GREEK_ELOT928];
166    
167     #define NUM_XLAT_TYPES (sizeof(xlat_type) / sizeof(xlat_type[0]))
168    
169 pcg 1.6 static void kstate_add_xlat (char *str);
170     static void kstate_add_switcher (char *str);
171     static void kstate_set_life (char *str);
172 pcg 1.1
173     /* --- Functions ------------- */
174     void
175 pcg 1.6 kstate_setcurr (int stateno)
176 pcg 1.1 {
177 pcg 1.5 u_char prev_state;
178 pcg 1.1
179 pcg 1.5 if ((u_int) stateno > (u_int) MAX_STATES)
180     return;
181     if (pStateNow->life == 1)
182     prev_state = pStateNow->prev_state;
183     else
184     prev_state = nStateNow;
185     pStateNow = &State[nStateNow = stateno];
186     pStateNow->prev_state = prev_state;
187 pcg 1.1 }
188    
189     void
190 pcg 1.6 kstate_init (void)
191 pcg 1.1 {
192 pcg 1.5 pStateNow->num_xlat = pStateNow->num_switcher = pStateNow->life = pStateNow->prev_state = 0;
193     pStateNow->xlat = NULL;
194 pcg 1.1 }
195    
196     void
197 pcg 1.6 kstate_end (void)
198 pcg 1.1 {
199 pcg 1.5 int i;
200 pcg 1.1
201 pcg 1.5 for (i = 0; i < pStateNow->num_xlat; i++)
202 pcg 1.6 free (pStateNow->xlat[i].pval);
203 pcg 1.5 if (pStateNow->num_xlat > 0)
204 pcg 1.6 free (pStateNow->xlat);
205 pcg 1.1 }
206    
207     /*
208     * Hard coded ELOT-928 translations. Could read these from an rc-type file
209     * to support other remappers.
210     */
211     void
212 pcg 1.6 kstate_init_all (int greek_mode)
213 pcg 1.1 {
214 pcg 1.5 /* the translation tables for the 4 FSM states for ELOT-928 mappings */
215     int i;
216 pcg 1.1
217 pcg 1.5 for (i = 0; i < MAX_STATES; i++)
218     {
219 pcg 1.6 kstate_setcurr (i);
220     kstate_init ();
221 pcg 1.1 }
222 pcg 1.5 if (greek_mode < 0 || greek_mode >= NUM_XLAT_TYPES) /* avoid death */
223     greek_mode = GREEK_ELOT928;
224     xlat_now = &xlat_type[greek_mode];
225 pcg 1.6 kstate_setcurr (0);
226     kstate_add_xlat (xlat_now->plain);
227     kstate_add_switcher ("A;:1");
228     kstate_add_switcher ("A::2");
229     kstate_set_life ("L0");
230    
231     kstate_setcurr (1);
232     kstate_add_xlat (xlat_now->accent);
233     kstate_add_xlat (xlat_now->accent_xtra);
234     kstate_add_switcher ("A::3");
235     kstate_set_life ("L1");
236    
237     kstate_setcurr (2);
238     kstate_add_xlat (xlat_now->umlaut);
239     kstate_add_switcher ("A;:3");
240     kstate_set_life ("L1");
241    
242     kstate_setcurr (3);
243     kstate_add_xlat (xlat_now->acc_uml);
244     kstate_set_life ("L1");
245 pcg 1.1 }
246    
247     void
248 pcg 1.6 kstate_end_all (void)
249 pcg 1.1 {
250 pcg 1.5 int i;
251 pcg 1.1
252 pcg 1.5 for (i = 0; i < MAX_STATES; i++)
253     {
254 pcg 1.6 kstate_setcurr (i);
255     kstate_end ();
256 pcg 1.1 }
257 pcg 1.6 kstate_setcurr (0);
258 pcg 1.1 }
259    
260     /*
261     * reset FSM
262     */
263     void
264 pcg 1.6 kstate_reset (void)
265 pcg 1.1 {
266 pcg 1.6 kstate_setcurr (0);
267 pcg 1.1 }
268    
269     void
270 pcg 1.6 kstate_add_xlat (char *str)
271 pcg 1.1 {
272 pcg 1.5 K_XLAT *xlat;
273     u_int *pval_tmp;
274     char *sval;
275     int i;
276    
277     if (str == NULL)
278     return;
279     /* add a new xlat table in state */
280     if (pStateNow->num_xlat == 0)
281     {
282 pcg 1.6 pStateNow->xlat = malloc (sizeof (K_XLAT));
283 pcg 1.5 }
284     else /* prefer contiguous data, realloc */
285 pcg 1.6 pStateNow->xlat = realloc (pStateNow->xlat, (pStateNow->num_xlat + 1) * sizeof (K_XLAT));
286 pcg 1.5 xlat = &pStateNow->xlat[pStateNow->num_xlat];
287     /* parse str and derive first, last, values */
288 pcg 1.6 xlat->first = (u_int) atoi (strtok (str, "-"));
289     xlat->last = (u_int) atoi (strtok (NULL, ":"));
290 pcg 1.5 i = 0;
291 pcg 1.6 pval_tmp = calloc (MAX_VAL, sizeof (K_XLAT));
292     while ((sval = strtok (NULL, ",")) != NULL)
293     pval_tmp[i++] = (u_int) (atoi (sval));
294     xlat->pval = calloc (i, sizeof (K_XLAT));
295 pcg 1.5 if (xlat->pval != NULL)
296 pcg 1.6 memcpy (xlat->pval, pval_tmp, i * sizeof (u_int));
297     free (pval_tmp);
298 pcg 1.5 pStateNow->num_xlat++;
299 pcg 1.1 }
300    
301     /*
302     * Ascii only for this implementation
303     */
304     void
305 pcg 1.6 kstate_add_switcher (char *str)
306 pcg 1.1 {
307 pcg 1.5 K_SWITCH *switcher;
308 pcg 1.1
309 pcg 1.5 if (str == NULL)
310     return;
311     if (pStateNow->num_switcher >= MAX_SWITCHER)
312     return;
313     switcher = &pStateNow->switcher[pStateNow->num_switcher];
314     switch (switcher->type = str[0])
315     {
316     case 'A': /* ascii eg: A;:2 */
317     switcher->code = str[1];
318 pcg 1.6 switcher->nextstate = atoi (&str[3]);
319 pcg 1.5 break;
320 pcg 1.1 }
321 pcg 1.5 switcher->on = 0;
322     pStateNow->num_switcher++;
323 pcg 1.1 }
324    
325     /* L1 or L0 */
326     void
327 pcg 1.6 kstate_set_life (char *str)
328 pcg 1.1 {
329 pcg 1.6 pStateNow->life = atoi (&str[1]);
330 pcg 1.1 }
331    
332     unsigned int
333 pcg 1.6 kstate_cxlat (unsigned int c)
334 pcg 1.1 {
335 pcg 1.5 int i;
336 pcg 1.1
337 pcg 1.5 /* check for ascii switcher */
338     for (i = 0; i < pStateNow->num_switcher; i++)
339     if (pStateNow->switcher[i].type == 'A' && /* only ascii here */
340     c == pStateNow->switcher[i].code)
341     {
342 pcg 1.6 kstate_setcurr (pStateNow->switcher[i].nextstate);
343 pcg 1.5 pStateNow->switcher[i].on = 1;
344     return ((unsigned int)-1);
345     }
346     /* do translation */
347     for (i = 0; i < pStateNow->num_xlat; i++)
348     if (c >= pStateNow->xlat[i].first && c <= pStateNow->xlat[i].last)
349     {
350     c = pStateNow->xlat[i].pval[c - pStateNow->xlat[i].first];
351     break;
352     }
353     /* switch back to previous state if life of current is 1 */
354     if (pStateNow->life == 1)
355 pcg 1.6 kstate_setcurr (pStateNow->prev_state);
356 pcg 1.5 return (c);
357 pcg 1.1 }
358    
359     #ifdef RXVT
360     void
361 pcg 1.6 greek_init (void)
362 pcg 1.1 {
363 pcg 1.6 kstate_init_all (GreekMode);
364 pcg 1.1 }
365    
366     void
367 pcg 1.6 greek_end (void)
368 pcg 1.1 {
369 pcg 1.6 kstate_end_all ();
370 pcg 1.1 }
371    
372     void
373 pcg 1.6 greek_reset (void)
374 pcg 1.1 {
375 pcg 1.6 kstate_reset ();
376 pcg 1.1 }
377    
378     void
379 pcg 1.6 greek_setmode (int greek_mode)
380 pcg 1.1 {
381 pcg 1.5 GreekMode = greek_mode;
382 pcg 1.1 }
383    
384     int
385 pcg 1.6 greek_getmode (void)
386 pcg 1.1 {
387 pcg 1.5 return (GreekMode);
388 pcg 1.1 }
389    
390     /*
391     * xlate a given string in-place - return new string length
392     */
393     int
394 pcg 1.6 greek_xlat (char *s, int num_chars)
395 pcg 1.1 {
396 pcg 1.5 int i, count;
397     unsigned int c;
398 pcg 1.1
399 pcg 1.5 for (i = 0, count = 0; i < num_chars; i++)
400     {
401 pcg 1.6 c = kstate_cxlat ((unsigned int)s[i]);
402 pcg 1.5 if (c != -1)
403     s[count++] = (char)c;
404 pcg 1.1 }
405 pcg 1.5 s[count] = '\0';
406     return (count);
407 pcg 1.1
408     }
409    
410     #ifdef TEST
411     int
412 pcg 1.6 main (void)
413 pcg 1.1 {
414 pcg 1.5 /*char text[] = "abcdef;aGDZXC"; */
415     char text[] = "abcdef;a:ibgdezhuiklmnjoprstyfxcv";
416 pcg 1.1
417 pcg 1.6 kstate_init_all (GREEK_ELOT928);
418     printf ("text: %s\n", text);
419     greek_xlat (text, strlen (text));
420     printf ("xlat'ed text: %s\n", text);
421     kstate_end_all ();
422 pcg 1.5 return 0;
423 pcg 1.1 }
424     #endif
425     #endif /* RXVT */
426    
427     #endif /* GREEK_SUPPORT */