… | |
… | |
31 | * for greek kbd bindings. An extension to other languages is easy |
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). |
32 | * (well don't know how the FSM lends itself to Far East languages). |
33 | * |
33 | * |
34 | * The FSM can have MAX_STATES states (change it for more). |
34 | * The FSM can have MAX_STATES states (change it for more). |
35 | * Each state contains: |
35 | * Each state contains: |
36 | * 1. many tranlsation tables (registered via kstate_add_xlat()) |
36 | * 1. many tranlsation tables (registered via kstate_add_xlat ()) |
37 | * 2. many switch codes for transition to other states (registered via |
37 | * 2. many switch codes for transition to other states (registered via |
38 | * kstate_add_switcher()) : limit is static now: MAX_SWITCHER |
38 | * kstate_add_switcher ()) : limit is static now: MAX_SWITCHER |
39 | * 3. life: the number of xlations allowed in a state (0 = unlimited) |
39 | * 3. life: the number of xlations allowed in a state (0 = unlimited) |
40 | * |
40 | * |
41 | * Format of tranlation strings: |
41 | * Format of tranlation strings: |
42 | * <first>-<last>:n1,n2,n3,... |
42 | * <first>-<last>:n1,n2,n3,... |
43 | * Format of switcher string: |
43 | * Format of switcher string: |
… | |
… | |
164 | /* the current trasnaltion type */ |
164 | /* the current trasnaltion type */ |
165 | static XLAT_TYPE *xlat_now = &xlat_type[GREEK_ELOT928]; |
165 | static XLAT_TYPE *xlat_now = &xlat_type[GREEK_ELOT928]; |
166 | |
166 | |
167 | #define NUM_XLAT_TYPES (sizeof(xlat_type) / sizeof(xlat_type[0])) |
167 | #define NUM_XLAT_TYPES (sizeof(xlat_type) / sizeof(xlat_type[0])) |
168 | |
168 | |
169 | static void kstate_add_xlat(char *str); |
169 | static void kstate_add_xlat (char *str); |
170 | static void kstate_add_switcher(char *str); |
170 | static void kstate_add_switcher (char *str); |
171 | static void kstate_set_life(char *str); |
171 | static void kstate_set_life (char *str); |
172 | |
172 | |
173 | /* --- Functions ------------- */ |
173 | /* --- Functions ------------- */ |
174 | void |
174 | void |
175 | kstate_setcurr(int stateno) |
175 | kstate_setcurr (int stateno) |
176 | { |
176 | { |
177 | u_char prev_state; |
177 | u_char prev_state; |
178 | |
178 | |
179 | if ((u_int) stateno > (u_int) MAX_STATES) |
179 | if ((u_int) stateno > (u_int) MAX_STATES) |
180 | return; |
180 | return; |
… | |
… | |
185 | pStateNow = &State[nStateNow = stateno]; |
185 | pStateNow = &State[nStateNow = stateno]; |
186 | pStateNow->prev_state = prev_state; |
186 | pStateNow->prev_state = prev_state; |
187 | } |
187 | } |
188 | |
188 | |
189 | void |
189 | void |
190 | kstate_init(void) |
190 | kstate_init (void) |
191 | { |
191 | { |
192 | pStateNow->num_xlat = pStateNow->num_switcher = pStateNow->life = pStateNow->prev_state = 0; |
192 | pStateNow->num_xlat = pStateNow->num_switcher = pStateNow->life = pStateNow->prev_state = 0; |
193 | pStateNow->xlat = NULL; |
193 | pStateNow->xlat = NULL; |
194 | } |
194 | } |
195 | |
195 | |
196 | void |
196 | void |
197 | kstate_end(void) |
197 | kstate_end (void) |
198 | { |
198 | { |
199 | int i; |
199 | int i; |
200 | |
200 | |
201 | for (i = 0; i < pStateNow->num_xlat; i++) |
201 | for (i = 0; i < pStateNow->num_xlat; i++) |
202 | free(pStateNow->xlat[i].pval); |
202 | free (pStateNow->xlat[i].pval); |
203 | if (pStateNow->num_xlat > 0) |
203 | if (pStateNow->num_xlat > 0) |
204 | free(pStateNow->xlat); |
204 | free (pStateNow->xlat); |
205 | } |
205 | } |
206 | |
206 | |
207 | /* |
207 | /* |
208 | * Hard coded ELOT-928 translations. Could read these from an rc-type file |
208 | * Hard coded ELOT-928 translations. Could read these from an rc-type file |
209 | * to support other remappers. |
209 | * to support other remappers. |
210 | */ |
210 | */ |
211 | void |
211 | void |
212 | kstate_init_all(int greek_mode) |
212 | kstate_init_all (int greek_mode) |
213 | { |
213 | { |
214 | /* the translation tables for the 4 FSM states for ELOT-928 mappings */ |
214 | /* the translation tables for the 4 FSM states for ELOT-928 mappings */ |
215 | int i; |
215 | int i; |
216 | |
216 | |
217 | for (i = 0; i < MAX_STATES; i++) |
217 | for (i = 0; i < MAX_STATES; i++) |
218 | { |
218 | { |
219 | kstate_setcurr(i); |
219 | kstate_setcurr (i); |
220 | kstate_init(); |
220 | kstate_init (); |
221 | } |
221 | } |
222 | if (greek_mode < 0 || greek_mode >= NUM_XLAT_TYPES) /* avoid death */ |
222 | if (greek_mode < 0 || greek_mode >= NUM_XLAT_TYPES) /* avoid death */ |
223 | greek_mode = GREEK_ELOT928; |
223 | greek_mode = GREEK_ELOT928; |
224 | xlat_now = &xlat_type[greek_mode]; |
224 | xlat_now = &xlat_type[greek_mode]; |
225 | kstate_setcurr(0); |
225 | kstate_setcurr (0); |
226 | kstate_add_xlat(xlat_now->plain); |
226 | kstate_add_xlat (xlat_now->plain); |
227 | kstate_add_switcher("A;:1"); |
227 | kstate_add_switcher ("A;:1"); |
228 | kstate_add_switcher("A::2"); |
228 | kstate_add_switcher ("A::2"); |
229 | kstate_set_life("L0"); |
229 | kstate_set_life ("L0"); |
230 | |
230 | |
231 | kstate_setcurr(1); |
231 | kstate_setcurr (1); |
232 | kstate_add_xlat(xlat_now->accent); |
232 | kstate_add_xlat (xlat_now->accent); |
233 | kstate_add_xlat(xlat_now->accent_xtra); |
233 | kstate_add_xlat (xlat_now->accent_xtra); |
234 | kstate_add_switcher("A::3"); |
234 | kstate_add_switcher ("A::3"); |
235 | kstate_set_life("L1"); |
235 | kstate_set_life ("L1"); |
236 | |
236 | |
237 | kstate_setcurr(2); |
237 | kstate_setcurr (2); |
238 | kstate_add_xlat(xlat_now->umlaut); |
238 | kstate_add_xlat (xlat_now->umlaut); |
239 | kstate_add_switcher("A;:3"); |
239 | kstate_add_switcher ("A;:3"); |
240 | kstate_set_life("L1"); |
240 | kstate_set_life ("L1"); |
241 | |
241 | |
242 | kstate_setcurr(3); |
242 | kstate_setcurr (3); |
243 | kstate_add_xlat(xlat_now->acc_uml); |
243 | kstate_add_xlat (xlat_now->acc_uml); |
244 | kstate_set_life("L1"); |
244 | kstate_set_life ("L1"); |
245 | } |
245 | } |
246 | |
246 | |
247 | void |
247 | void |
248 | kstate_end_all(void) |
248 | kstate_end_all (void) |
249 | { |
249 | { |
250 | int i; |
250 | int i; |
251 | |
251 | |
252 | for (i = 0; i < MAX_STATES; i++) |
252 | for (i = 0; i < MAX_STATES; i++) |
253 | { |
253 | { |
254 | kstate_setcurr(i); |
254 | kstate_setcurr (i); |
255 | kstate_end(); |
255 | kstate_end (); |
256 | } |
256 | } |
257 | kstate_setcurr(0); |
257 | kstate_setcurr (0); |
258 | } |
258 | } |
259 | |
259 | |
260 | /* |
260 | /* |
261 | * reset FSM |
261 | * reset FSM |
262 | */ |
262 | */ |
263 | void |
263 | void |
264 | kstate_reset(void) |
264 | kstate_reset (void) |
265 | { |
265 | { |
266 | kstate_setcurr(0); |
266 | kstate_setcurr (0); |
267 | } |
267 | } |
268 | |
268 | |
269 | void |
269 | void |
270 | kstate_add_xlat(char *str) |
270 | kstate_add_xlat (char *str) |
271 | { |
271 | { |
272 | K_XLAT *xlat; |
272 | K_XLAT *xlat; |
273 | u_int *pval_tmp; |
273 | u_int *pval_tmp; |
274 | char *sval; |
274 | char *sval; |
275 | int i; |
275 | int i; |
… | |
… | |
277 | if (str == NULL) |
277 | if (str == NULL) |
278 | return; |
278 | return; |
279 | /* add a new xlat table in state */ |
279 | /* add a new xlat table in state */ |
280 | if (pStateNow->num_xlat == 0) |
280 | if (pStateNow->num_xlat == 0) |
281 | { |
281 | { |
282 | pStateNow->xlat = malloc(sizeof(K_XLAT)); |
282 | pStateNow->xlat = malloc (sizeof (K_XLAT)); |
283 | } |
283 | } |
284 | else /* prefer contiguous data, realloc */ |
284 | else /* prefer contiguous data, realloc */ |
285 | pStateNow->xlat = realloc(pStateNow->xlat, (pStateNow->num_xlat + 1) * sizeof(K_XLAT)); |
285 | pStateNow->xlat = realloc (pStateNow->xlat, (pStateNow->num_xlat + 1) * sizeof (K_XLAT)); |
286 | xlat = &pStateNow->xlat[pStateNow->num_xlat]; |
286 | xlat = &pStateNow->xlat[pStateNow->num_xlat]; |
287 | /* parse str and derive first, last, values */ |
287 | /* parse str and derive first, last, values */ |
288 | xlat->first = (u_int) atoi(strtok(str, "-")); |
288 | xlat->first = (u_int) atoi (strtok (str, "-")); |
289 | xlat->last = (u_int) atoi(strtok(NULL, ":")); |
289 | xlat->last = (u_int) atoi (strtok (NULL, ":")); |
290 | i = 0; |
290 | i = 0; |
291 | pval_tmp = calloc(MAX_VAL, sizeof(K_XLAT)); |
291 | pval_tmp = calloc (MAX_VAL, sizeof (K_XLAT)); |
292 | while ((sval = strtok(NULL, ",")) != NULL) |
292 | while ((sval = strtok (NULL, ",")) != NULL) |
293 | pval_tmp[i++] = (u_int) (atoi(sval)); |
293 | pval_tmp[i++] = (u_int) (atoi (sval)); |
294 | xlat->pval = calloc(i, sizeof(K_XLAT)); |
294 | xlat->pval = calloc (i, sizeof (K_XLAT)); |
295 | if (xlat->pval != NULL) |
295 | if (xlat->pval != NULL) |
296 | memcpy(xlat->pval, pval_tmp, i * sizeof(u_int)); |
296 | memcpy (xlat->pval, pval_tmp, i * sizeof (u_int)); |
297 | free(pval_tmp); |
297 | free (pval_tmp); |
298 | pStateNow->num_xlat++; |
298 | pStateNow->num_xlat++; |
299 | } |
299 | } |
300 | |
300 | |
301 | /* |
301 | /* |
302 | * Ascii only for this implementation |
302 | * Ascii only for this implementation |
303 | */ |
303 | */ |
304 | void |
304 | void |
305 | kstate_add_switcher(char *str) |
305 | kstate_add_switcher (char *str) |
306 | { |
306 | { |
307 | K_SWITCH *switcher; |
307 | K_SWITCH *switcher; |
308 | |
308 | |
309 | if (str == NULL) |
309 | if (str == NULL) |
310 | return; |
310 | return; |
… | |
… | |
313 | switcher = &pStateNow->switcher[pStateNow->num_switcher]; |
313 | switcher = &pStateNow->switcher[pStateNow->num_switcher]; |
314 | switch (switcher->type = str[0]) |
314 | switch (switcher->type = str[0]) |
315 | { |
315 | { |
316 | case 'A': /* ascii eg: A;:2 */ |
316 | case 'A': /* ascii eg: A;:2 */ |
317 | switcher->code = str[1]; |
317 | switcher->code = str[1]; |
318 | switcher->nextstate = atoi(&str[3]); |
318 | switcher->nextstate = atoi (&str[3]); |
319 | break; |
319 | break; |
320 | } |
320 | } |
321 | switcher->on = 0; |
321 | switcher->on = 0; |
322 | pStateNow->num_switcher++; |
322 | pStateNow->num_switcher++; |
323 | } |
323 | } |
324 | |
324 | |
325 | /* L1 or L0 */ |
325 | /* L1 or L0 */ |
326 | void |
326 | void |
327 | kstate_set_life(char *str) |
327 | kstate_set_life (char *str) |
328 | { |
328 | { |
329 | pStateNow->life = atoi(&str[1]); |
329 | pStateNow->life = atoi (&str[1]); |
330 | } |
330 | } |
331 | |
331 | |
332 | unsigned int |
332 | unsigned int |
333 | kstate_cxlat(unsigned int c) |
333 | kstate_cxlat (unsigned int c) |
334 | { |
334 | { |
335 | int i; |
335 | int i; |
336 | |
336 | |
337 | /* check for ascii switcher */ |
337 | /* check for ascii switcher */ |
338 | for (i = 0; i < pStateNow->num_switcher; i++) |
338 | for (i = 0; i < pStateNow->num_switcher; i++) |
339 | if (pStateNow->switcher[i].type == 'A' && /* only ascii here */ |
339 | if (pStateNow->switcher[i].type == 'A' && /* only ascii here */ |
340 | c == pStateNow->switcher[i].code) |
340 | c == pStateNow->switcher[i].code) |
341 | { |
341 | { |
342 | kstate_setcurr(pStateNow->switcher[i].nextstate); |
342 | kstate_setcurr (pStateNow->switcher[i].nextstate); |
343 | pStateNow->switcher[i].on = 1; |
343 | pStateNow->switcher[i].on = 1; |
344 | return ((unsigned int)-1); |
344 | return ((unsigned int)-1); |
345 | } |
345 | } |
346 | /* do translation */ |
346 | /* do translation */ |
347 | for (i = 0; i < pStateNow->num_xlat; i++) |
347 | for (i = 0; i < pStateNow->num_xlat; i++) |
… | |
… | |
350 | c = pStateNow->xlat[i].pval[c - pStateNow->xlat[i].first]; |
350 | c = pStateNow->xlat[i].pval[c - pStateNow->xlat[i].first]; |
351 | break; |
351 | break; |
352 | } |
352 | } |
353 | /* switch back to previous state if life of current is 1 */ |
353 | /* switch back to previous state if life of current is 1 */ |
354 | if (pStateNow->life == 1) |
354 | if (pStateNow->life == 1) |
355 | kstate_setcurr(pStateNow->prev_state); |
355 | kstate_setcurr (pStateNow->prev_state); |
356 | return (c); |
356 | return (c); |
357 | } |
357 | } |
358 | |
358 | |
359 | #ifdef RXVT |
359 | #ifdef RXVT |
360 | void |
360 | void |
361 | greek_init(void) |
361 | greek_init (void) |
362 | { |
362 | { |
363 | kstate_init_all(GreekMode); |
363 | kstate_init_all (GreekMode); |
364 | } |
364 | } |
365 | |
365 | |
366 | void |
366 | void |
367 | greek_end(void) |
367 | greek_end (void) |
368 | { |
368 | { |
369 | kstate_end_all(); |
369 | kstate_end_all (); |
370 | } |
370 | } |
371 | |
371 | |
372 | void |
372 | void |
373 | greek_reset(void) |
373 | greek_reset (void) |
374 | { |
374 | { |
375 | kstate_reset(); |
375 | kstate_reset (); |
376 | } |
376 | } |
377 | |
377 | |
378 | void |
378 | void |
379 | greek_setmode(int greek_mode) |
379 | greek_setmode (int greek_mode) |
380 | { |
380 | { |
381 | GreekMode = greek_mode; |
381 | GreekMode = greek_mode; |
382 | } |
382 | } |
383 | |
383 | |
384 | int |
384 | int |
385 | greek_getmode(void) |
385 | greek_getmode (void) |
386 | { |
386 | { |
387 | return (GreekMode); |
387 | return (GreekMode); |
388 | } |
388 | } |
389 | |
389 | |
390 | /* |
390 | /* |
391 | * xlate a given string in-place - return new string length |
391 | * xlate a given string in-place - return new string length |
392 | */ |
392 | */ |
393 | int |
393 | int |
394 | greek_xlat(char *s, int num_chars) |
394 | greek_xlat (char *s, int num_chars) |
395 | { |
395 | { |
396 | int i, count; |
396 | int i, count; |
397 | unsigned int c; |
397 | unsigned int c; |
398 | |
398 | |
399 | for (i = 0, count = 0; i < num_chars; i++) |
399 | for (i = 0, count = 0; i < num_chars; i++) |
400 | { |
400 | { |
401 | c = kstate_cxlat((unsigned int)s[i]); |
401 | c = kstate_cxlat ((unsigned int)s[i]); |
402 | if (c != -1) |
402 | if (c != -1) |
403 | s[count++] = (char)c; |
403 | s[count++] = (char)c; |
404 | } |
404 | } |
405 | s[count] = '\0'; |
405 | s[count] = '\0'; |
406 | return (count); |
406 | return (count); |
407 | |
407 | |
408 | } |
408 | } |
409 | |
409 | |
410 | #ifdef TEST |
410 | #ifdef TEST |
411 | int |
411 | int |
412 | main(void) |
412 | main (void) |
413 | { |
413 | { |
414 | /*char text[] = "abcdef;aGDZXC"; */ |
414 | /*char text[] = "abcdef;aGDZXC"; */ |
415 | char text[] = "abcdef;a:ibgdezhuiklmnjoprstyfxcv"; |
415 | char text[] = "abcdef;a:ibgdezhuiklmnjoprstyfxcv"; |
416 | |
416 | |
417 | kstate_init_all(GREEK_ELOT928); |
417 | kstate_init_all (GREEK_ELOT928); |
418 | printf("text: %s\n", text); |
418 | printf ("text: %s\n", text); |
419 | greek_xlat(text, strlen(text)); |
419 | greek_xlat (text, strlen (text)); |
420 | printf("xlat'ed text: %s\n", text); |
420 | printf ("xlat'ed text: %s\n", text); |
421 | kstate_end_all(); |
421 | kstate_end_all (); |
422 | return 0; |
422 | return 0; |
423 | } |
423 | } |
424 | #endif |
424 | #endif |
425 | #endif /* RXVT */ |
425 | #endif /* RXVT */ |
426 | |
426 | |