… | |
… | |
82 | |
82 | |
83 | typedef unsigned char u_char; |
83 | typedef unsigned char u_char; |
84 | typedef unsigned int u_int; |
84 | typedef unsigned int u_int; |
85 | typedef unsigned long u_long; |
85 | typedef unsigned long u_long; |
86 | |
86 | |
87 | typedef struct s_xlat { |
87 | typedef struct s_xlat |
|
|
88 | { |
88 | u_int first, last; |
89 | u_int first, last; |
89 | u_int *pval; /* array of translated values */ |
90 | u_int *pval; /* array of translated values */ |
|
|
91 | } |
90 | } K_XLAT; |
92 | K_XLAT; |
91 | |
93 | |
92 | typedef struct s_switch { |
94 | typedef struct s_switch |
|
|
95 | { |
93 | u_char type; /* Ascii, Virtual, Scan */ |
96 | u_char type; /* Ascii, Virtual, Scan */ |
94 | u_int code; |
97 | u_int code; |
95 | u_char nextstate; |
98 | u_char nextstate; |
96 | u_char on; /* current state of key: 0 = off */ |
99 | u_char on; /* current state of key: 0 = off */ |
|
|
100 | } |
97 | } K_SWITCH; |
101 | K_SWITCH; |
98 | |
102 | |
99 | typedef struct s_state { |
103 | typedef struct s_state |
|
|
104 | { |
100 | u_int num_xlat; /* number of translations */ |
105 | u_int num_xlat; /* number of translations */ |
101 | K_XLAT *xlat; /* State translations ((dynamic - realloc'ed) */ |
106 | K_XLAT *xlat; /* State translations ((dynamic - realloc'ed) */ |
102 | u_int num_switcher; /* number of switcher keys */ |
107 | u_int num_switcher; /* number of switcher keys */ |
103 | K_SWITCH switcher[MAX_SWITCHER]; /* switcher keys to other states */ |
108 | K_SWITCH switcher[MAX_SWITCHER]; /* switcher keys to other states */ |
104 | u_char life; /* 0 = until switched by key */ |
109 | u_char life; /* 0 = until switched by key */ |
105 | u_char prev_state; /* filled when jumped to a new state */ |
110 | u_char prev_state; /* filled when jumped to a new state */ |
|
|
111 | } |
106 | } K_STATE; |
112 | K_STATE; |
107 | |
113 | |
108 | /* type for each one of the different greek standards (xlat types) */ |
114 | /* type for each one of the different greek standards (xlat types) */ |
109 | typedef struct s_xlat_type { |
115 | typedef struct s_xlat_type |
|
|
116 | { |
110 | char *plain; |
117 | char *plain; |
111 | char *accent; |
118 | char *accent; |
112 | char *accent_xtra; |
119 | char *accent_xtra; |
113 | char *umlaut; |
120 | char *umlaut; |
114 | char *acc_uml; |
121 | char *acc_uml; |
|
|
122 | } |
115 | } XLAT_TYPE; |
123 | XLAT_TYPE; |
116 | |
124 | |
117 | /* --- Local Data ------------ */ |
125 | /* --- Local Data ------------ */ |
118 | static K_STATE State[MAX_STATES]; |
126 | static K_STATE State[MAX_STATES]; |
119 | |
127 | |
120 | /* Current State */ |
128 | /* Current State */ |
… | |
… | |
146 | /* |
154 | /* |
147 | * currently ELOT928 and IBM437 are supported; easy to include others |
155 | * currently ELOT928 and IBM437 are supported; easy to include others |
148 | * (not recommended: stick to just these 2 if not only the ELOT one) |
156 | * (not recommended: stick to just these 2 if not only the ELOT one) |
149 | */ |
157 | */ |
150 | static XLAT_TYPE xlat_type[] = |
158 | static XLAT_TYPE xlat_type[] = |
151 | { |
159 | { |
152 | {elot_xlat_plain, elot_xlat_acc, elot_xlat_acc_xtra, elot_xlat_uml, elot_xlat_umacc}, |
160 | {elot_xlat_plain, elot_xlat_acc, elot_xlat_acc_xtra, elot_xlat_uml, elot_xlat_umacc}, |
153 | {i437_xlat_plain, i437_xlat_acc, i437_xlat_acc_xtra, i437_xlat_uml, i437_xlat_umacc}, |
161 | {i437_xlat_plain, i437_xlat_acc, i437_xlat_acc_xtra, i437_xlat_uml, i437_xlat_umacc}, |
154 | }; |
162 | }; |
155 | |
163 | |
156 | /* the current trasnaltion type */ |
164 | /* the current trasnaltion type */ |
157 | static XLAT_TYPE *xlat_now = &xlat_type[GREEK_ELOT928]; |
165 | static XLAT_TYPE *xlat_now = &xlat_type[GREEK_ELOT928]; |
158 | |
166 | |
159 | #define NUM_XLAT_TYPES (sizeof(xlat_type) / sizeof(xlat_type[0])) |
167 | #define NUM_XLAT_TYPES (sizeof(xlat_type) / sizeof(xlat_type[0])) |
… | |
… | |
164 | |
172 | |
165 | /* --- Functions ------------- */ |
173 | /* --- Functions ------------- */ |
166 | void |
174 | void |
167 | kstate_setcurr(int stateno) |
175 | kstate_setcurr(int stateno) |
168 | { |
176 | { |
169 | u_char prev_state; |
177 | u_char prev_state; |
170 | |
178 | |
171 | if ((u_int) stateno > (u_int) MAX_STATES) |
179 | if ((u_int) stateno > (u_int) MAX_STATES) |
172 | return; |
180 | return; |
173 | if (pStateNow->life == 1) |
181 | if (pStateNow->life == 1) |
174 | prev_state = pStateNow->prev_state; |
182 | prev_state = pStateNow->prev_state; |
175 | else |
183 | else |
176 | prev_state = nStateNow; |
184 | prev_state = nStateNow; |
177 | pStateNow = &State[nStateNow = stateno]; |
185 | pStateNow = &State[nStateNow = stateno]; |
178 | pStateNow->prev_state = prev_state; |
186 | pStateNow->prev_state = prev_state; |
179 | } |
187 | } |
180 | |
188 | |
181 | void |
189 | void |
182 | kstate_init(void) |
190 | kstate_init(void) |
183 | { |
191 | { |
184 | 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; |
185 | pStateNow->xlat = NULL; |
193 | pStateNow->xlat = NULL; |
186 | } |
194 | } |
187 | |
195 | |
188 | void |
196 | void |
189 | kstate_end(void) |
197 | kstate_end(void) |
190 | { |
198 | { |
191 | int i; |
199 | int i; |
192 | |
200 | |
193 | for (i = 0; i < pStateNow->num_xlat; i++) |
201 | for (i = 0; i < pStateNow->num_xlat; i++) |
194 | free(pStateNow->xlat[i].pval); |
202 | free(pStateNow->xlat[i].pval); |
195 | if (pStateNow->num_xlat > 0) |
203 | if (pStateNow->num_xlat > 0) |
196 | free(pStateNow->xlat); |
204 | free(pStateNow->xlat); |
197 | } |
205 | } |
198 | |
206 | |
199 | /* |
207 | /* |
200 | * 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 |
201 | * to support other remappers. |
209 | * to support other remappers. |
202 | */ |
210 | */ |
203 | void |
211 | void |
204 | kstate_init_all(int greek_mode) |
212 | kstate_init_all(int greek_mode) |
205 | { |
213 | { |
206 | /* 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 */ |
207 | int i; |
215 | int i; |
208 | |
216 | |
209 | for (i = 0; i < MAX_STATES; i++) { |
217 | for (i = 0; i < MAX_STATES; i++) |
|
|
218 | { |
210 | kstate_setcurr(i); |
219 | kstate_setcurr(i); |
211 | kstate_init(); |
220 | kstate_init(); |
212 | } |
221 | } |
213 | if (greek_mode < 0 || greek_mode >= NUM_XLAT_TYPES) /* avoid death */ |
222 | if (greek_mode < 0 || greek_mode >= NUM_XLAT_TYPES) /* avoid death */ |
214 | greek_mode = GREEK_ELOT928; |
223 | greek_mode = GREEK_ELOT928; |
215 | xlat_now = &xlat_type[greek_mode]; |
224 | xlat_now = &xlat_type[greek_mode]; |
216 | kstate_setcurr(0); |
225 | kstate_setcurr(0); |
217 | kstate_add_xlat(xlat_now->plain); |
226 | kstate_add_xlat(xlat_now->plain); |
218 | kstate_add_switcher("A;:1"); |
227 | kstate_add_switcher("A;:1"); |
219 | kstate_add_switcher("A::2"); |
228 | kstate_add_switcher("A::2"); |
220 | kstate_set_life("L0"); |
229 | kstate_set_life("L0"); |
221 | |
230 | |
222 | kstate_setcurr(1); |
231 | kstate_setcurr(1); |
223 | kstate_add_xlat(xlat_now->accent); |
232 | kstate_add_xlat(xlat_now->accent); |
224 | kstate_add_xlat(xlat_now->accent_xtra); |
233 | kstate_add_xlat(xlat_now->accent_xtra); |
225 | kstate_add_switcher("A::3"); |
234 | kstate_add_switcher("A::3"); |
226 | kstate_set_life("L1"); |
235 | kstate_set_life("L1"); |
227 | |
236 | |
228 | kstate_setcurr(2); |
237 | kstate_setcurr(2); |
229 | kstate_add_xlat(xlat_now->umlaut); |
238 | kstate_add_xlat(xlat_now->umlaut); |
230 | kstate_add_switcher("A;:3"); |
239 | kstate_add_switcher("A;:3"); |
231 | kstate_set_life("L1"); |
240 | kstate_set_life("L1"); |
232 | |
241 | |
233 | kstate_setcurr(3); |
242 | kstate_setcurr(3); |
234 | kstate_add_xlat(xlat_now->acc_uml); |
243 | kstate_add_xlat(xlat_now->acc_uml); |
235 | kstate_set_life("L1"); |
244 | kstate_set_life("L1"); |
236 | } |
245 | } |
237 | |
246 | |
238 | void |
247 | void |
239 | kstate_end_all(void) |
248 | kstate_end_all(void) |
240 | { |
249 | { |
241 | int i; |
250 | int i; |
242 | |
251 | |
243 | for (i = 0; i < MAX_STATES; i++) { |
252 | for (i = 0; i < MAX_STATES; i++) |
|
|
253 | { |
244 | kstate_setcurr(i); |
254 | kstate_setcurr(i); |
245 | kstate_end(); |
255 | kstate_end(); |
246 | } |
256 | } |
247 | kstate_setcurr(0); |
257 | kstate_setcurr(0); |
248 | } |
258 | } |
249 | |
259 | |
250 | /* |
260 | /* |
251 | * reset FSM |
261 | * reset FSM |
252 | */ |
262 | */ |
253 | void |
263 | void |
254 | kstate_reset(void) |
264 | kstate_reset(void) |
255 | { |
265 | { |
256 | kstate_setcurr(0); |
266 | kstate_setcurr(0); |
257 | } |
267 | } |
258 | |
268 | |
259 | void |
269 | void |
260 | kstate_add_xlat(char *str) |
270 | kstate_add_xlat(char *str) |
261 | { |
271 | { |
262 | K_XLAT *xlat; |
272 | K_XLAT *xlat; |
263 | u_int *pval_tmp; |
273 | u_int *pval_tmp; |
264 | char *sval; |
274 | char *sval; |
265 | int i; |
275 | int i; |
266 | |
276 | |
267 | if (str == NULL) |
277 | if (str == NULL) |
268 | return; |
278 | return; |
269 | /* add a new xlat table in state */ |
279 | /* add a new xlat table in state */ |
270 | if (pStateNow->num_xlat == 0) { |
280 | if (pStateNow->num_xlat == 0) |
|
|
281 | { |
271 | pStateNow->xlat = malloc(sizeof(K_XLAT)); |
282 | pStateNow->xlat = malloc(sizeof(K_XLAT)); |
|
|
283 | } |
272 | } else /* prefer contiguous data, realloc */ |
284 | else /* prefer contiguous data, realloc */ |
273 | 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)); |
274 | xlat = &pStateNow->xlat[pStateNow->num_xlat]; |
286 | xlat = &pStateNow->xlat[pStateNow->num_xlat]; |
275 | /* parse str and derive first, last, values */ |
287 | /* parse str and derive first, last, values */ |
276 | xlat->first = (u_int) atoi(strtok(str, "-")); |
288 | xlat->first = (u_int) atoi(strtok(str, "-")); |
277 | xlat->last = (u_int) atoi(strtok(NULL, ":")); |
289 | xlat->last = (u_int) atoi(strtok(NULL, ":")); |
278 | i = 0; |
290 | i = 0; |
279 | pval_tmp = calloc(MAX_VAL, sizeof(K_XLAT)); |
291 | pval_tmp = calloc(MAX_VAL, sizeof(K_XLAT)); |
280 | while ((sval = strtok(NULL, ",")) != NULL) |
292 | while ((sval = strtok(NULL, ",")) != NULL) |
281 | pval_tmp[i++] = (u_int) (atoi(sval)); |
293 | pval_tmp[i++] = (u_int) (atoi(sval)); |
282 | xlat->pval = calloc(i, sizeof(K_XLAT)); |
294 | xlat->pval = calloc(i, sizeof(K_XLAT)); |
283 | if (xlat->pval != NULL) |
295 | if (xlat->pval != NULL) |
284 | memcpy(xlat->pval, pval_tmp, i * sizeof(u_int)); |
296 | memcpy(xlat->pval, pval_tmp, i * sizeof(u_int)); |
285 | free(pval_tmp); |
297 | free(pval_tmp); |
286 | pStateNow->num_xlat++; |
298 | pStateNow->num_xlat++; |
287 | } |
299 | } |
288 | |
300 | |
289 | /* |
301 | /* |
290 | * Ascii only for this implementation |
302 | * Ascii only for this implementation |
291 | */ |
303 | */ |
292 | void |
304 | void |
293 | kstate_add_switcher(char *str) |
305 | kstate_add_switcher(char *str) |
294 | { |
306 | { |
295 | K_SWITCH *switcher; |
307 | K_SWITCH *switcher; |
296 | |
308 | |
297 | if (str == NULL) |
309 | if (str == NULL) |
298 | return; |
310 | return; |
299 | if (pStateNow->num_switcher >= MAX_SWITCHER) |
311 | if (pStateNow->num_switcher >= MAX_SWITCHER) |
300 | return; |
312 | return; |
301 | switcher = &pStateNow->switcher[pStateNow->num_switcher]; |
313 | switcher = &pStateNow->switcher[pStateNow->num_switcher]; |
302 | switch (switcher->type = str[0]) { |
314 | switch (switcher->type = str[0]) |
|
|
315 | { |
303 | case 'A': /* ascii eg: A;:2 */ |
316 | case 'A': /* ascii eg: A;:2 */ |
304 | switcher->code = str[1]; |
317 | switcher->code = str[1]; |
305 | switcher->nextstate = atoi(&str[3]); |
318 | switcher->nextstate = atoi(&str[3]); |
306 | break; |
319 | break; |
307 | } |
320 | } |
308 | switcher->on = 0; |
321 | switcher->on = 0; |
309 | pStateNow->num_switcher++; |
322 | pStateNow->num_switcher++; |
310 | } |
323 | } |
311 | |
324 | |
312 | /* L1 or L0 */ |
325 | /* L1 or L0 */ |
313 | void |
326 | void |
314 | kstate_set_life(char *str) |
327 | kstate_set_life(char *str) |
315 | { |
328 | { |
316 | pStateNow->life = atoi(&str[1]); |
329 | pStateNow->life = atoi(&str[1]); |
317 | } |
330 | } |
318 | |
331 | |
319 | unsigned int |
332 | unsigned int |
320 | kstate_cxlat(unsigned int c) |
333 | kstate_cxlat(unsigned int c) |
321 | { |
334 | { |
322 | int i; |
335 | int i; |
323 | |
336 | |
324 | /* check for ascii switcher */ |
337 | /* check for ascii switcher */ |
325 | for (i = 0; i < pStateNow->num_switcher; i++) |
338 | for (i = 0; i < pStateNow->num_switcher; i++) |
326 | if (pStateNow->switcher[i].type == 'A' && /* only ascii here */ |
339 | if (pStateNow->switcher[i].type == 'A' && /* only ascii here */ |
327 | c == pStateNow->switcher[i].code) { |
340 | c == pStateNow->switcher[i].code) |
|
|
341 | { |
328 | kstate_setcurr(pStateNow->switcher[i].nextstate); |
342 | kstate_setcurr(pStateNow->switcher[i].nextstate); |
329 | pStateNow->switcher[i].on = 1; |
343 | pStateNow->switcher[i].on = 1; |
330 | return ((unsigned int)-1); |
344 | return ((unsigned int)-1); |
331 | } |
345 | } |
332 | /* do translation */ |
346 | /* do translation */ |
333 | for (i = 0; i < pStateNow->num_xlat; i++) |
347 | for (i = 0; i < pStateNow->num_xlat; i++) |
334 | if (c >= pStateNow->xlat[i].first && c <= pStateNow->xlat[i].last) { |
348 | if (c >= pStateNow->xlat[i].first && c <= pStateNow->xlat[i].last) |
|
|
349 | { |
335 | c = pStateNow->xlat[i].pval[c - pStateNow->xlat[i].first]; |
350 | c = pStateNow->xlat[i].pval[c - pStateNow->xlat[i].first]; |
336 | break; |
351 | break; |
337 | } |
352 | } |
338 | /* switch back to previous state if life of current is 1 */ |
353 | /* switch back to previous state if life of current is 1 */ |
339 | if (pStateNow->life == 1) |
354 | if (pStateNow->life == 1) |
340 | kstate_setcurr(pStateNow->prev_state); |
355 | kstate_setcurr(pStateNow->prev_state); |
341 | return (c); |
356 | return (c); |
342 | } |
357 | } |
343 | |
358 | |
344 | #ifdef RXVT |
359 | #ifdef RXVT |
345 | void |
360 | void |
346 | greek_init(void) |
361 | greek_init(void) |
347 | { |
362 | { |
348 | kstate_init_all(GreekMode); |
363 | kstate_init_all(GreekMode); |
349 | } |
364 | } |
350 | |
365 | |
351 | void |
366 | void |
352 | greek_end(void) |
367 | greek_end(void) |
353 | { |
368 | { |
354 | kstate_end_all(); |
369 | kstate_end_all(); |
355 | } |
370 | } |
356 | |
371 | |
357 | void |
372 | void |
358 | greek_reset(void) |
373 | greek_reset(void) |
359 | { |
374 | { |
360 | kstate_reset(); |
375 | kstate_reset(); |
361 | } |
376 | } |
362 | |
377 | |
363 | void |
378 | void |
364 | greek_setmode(int greek_mode) |
379 | greek_setmode(int greek_mode) |
365 | { |
380 | { |
366 | GreekMode = greek_mode; |
381 | GreekMode = greek_mode; |
367 | } |
382 | } |
368 | |
383 | |
369 | int |
384 | int |
370 | greek_getmode(void) |
385 | greek_getmode(void) |
371 | { |
386 | { |
372 | return (GreekMode); |
387 | return (GreekMode); |
373 | } |
388 | } |
374 | |
389 | |
375 | /* |
390 | /* |
376 | * xlate a given string in-place - return new string length |
391 | * xlate a given string in-place - return new string length |
377 | */ |
392 | */ |
378 | int |
393 | int |
379 | greek_xlat(char *s, int num_chars) |
394 | greek_xlat(char *s, int num_chars) |
380 | { |
395 | { |
381 | int i, count; |
396 | int i, count; |
382 | unsigned int c; |
397 | unsigned int c; |
383 | |
398 | |
384 | for (i = 0, count = 0; i < num_chars; i++) { |
399 | for (i = 0, count = 0; i < num_chars; i++) |
|
|
400 | { |
385 | c = kstate_cxlat((unsigned int)s[i]); |
401 | c = kstate_cxlat((unsigned int)s[i]); |
386 | if (c != -1) |
402 | if (c != -1) |
387 | s[count++] = (char)c; |
403 | s[count++] = (char)c; |
388 | } |
404 | } |
389 | s[count] = '\0'; |
405 | s[count] = '\0'; |
390 | return (count); |
406 | return (count); |
391 | |
407 | |
392 | } |
408 | } |
393 | |
409 | |
394 | #ifdef TEST |
410 | #ifdef TEST |
395 | int |
411 | int |
396 | main(void) |
412 | main(void) |
397 | { |
413 | { |
398 | /*char text[] = "abcdef;aGDZXC"; */ |
414 | /*char text[] = "abcdef;aGDZXC"; */ |
399 | char text[] = "abcdef;a:ibgdezhuiklmnjoprstyfxcv"; |
415 | char text[] = "abcdef;a:ibgdezhuiklmnjoprstyfxcv"; |
400 | |
416 | |
401 | kstate_init_all(GREEK_ELOT928); |
417 | kstate_init_all(GREEK_ELOT928); |
402 | printf("text: %s\n", text); |
418 | printf("text: %s\n", text); |
403 | greek_xlat(text, strlen(text)); |
419 | greek_xlat(text, strlen(text)); |
404 | printf("xlat'ed text: %s\n", text); |
420 | printf("xlat'ed text: %s\n", text); |
405 | kstate_end_all(); |
421 | kstate_end_all(); |
406 | return 0; |
422 | return 0; |
407 | } |
423 | } |
408 | #endif |
424 | #endif |
409 | #endif /* RXVT */ |
425 | #endif /* RXVT */ |
410 | |
426 | |
411 | #endif /* GREEK_SUPPORT */ |
427 | #endif /* GREEK_SUPPORT */ |