a87224c5510b2c3d00c399562852574ac6e7b56c
[cascardo/linux.git] / drivers / staging / speakup / main.c
1 /* speakup.c
2  * review functions for the speakup screen review package.
3  * originally written by: Kirk Reiser and Andy Berdan.
4  *
5  * extensively modified by David Borowski.
6  *
7  ** Copyright (C) 1998  Kirk Reiser.
8  *  Copyright (C) 2003  David Borowski.
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
21 #include <linux/kernel.h>
22 #include <linux/vt.h>
23 #include <linux/tty.h>
24 #include <linux/mm.h>           /* __get_free_page() and friends */
25 #include <linux/vt_kern.h>
26 #include <linux/ctype.h>
27 #include <linux/selection.h>
28 #include <linux/unistd.h>
29 #include <linux/jiffies.h>
30 #include <linux/kthread.h>
31 #include <linux/keyboard.h>     /* for KT_SHIFT */
32 #include <linux/kbd_kern.h>     /* for vc_kbd_* and friends */
33 #include <linux/input.h>
34 #include <linux/kmod.h>
35
36 /* speakup_*_selection */
37 #include <linux/module.h>
38 #include <linux/sched.h>
39 #include <linux/slab.h>
40 #include <linux/types.h>
41 #include <linux/consolemap.h>
42
43 #include <linux/spinlock.h>
44 #include <linux/notifier.h>
45
46 #include <linux/uaccess.h>      /* copy_from|to|user() and others */
47
48 #include "spk_priv.h"
49 #include "speakup.h"
50
51 #define MAX_DELAY msecs_to_jiffies(500)
52 #define MINECHOCHAR SPACE
53
54 MODULE_AUTHOR("Kirk Reiser <kirk@braille.uwo.ca>");
55 MODULE_AUTHOR("Daniel Drake <dsd@gentoo.org>");
56 MODULE_DESCRIPTION("Speakup console speech");
57 MODULE_LICENSE("GPL");
58 MODULE_VERSION(SPEAKUP_VERSION);
59
60 char *synth_name;
61 module_param_named(synth, synth_name, charp, S_IRUGO);
62 module_param_named(quiet, spk_quiet_boot, bool, S_IRUGO);
63
64 MODULE_PARM_DESC(synth, "Synth to start if speakup is built in.");
65 MODULE_PARM_DESC(quiet, "Do not announce when the synthesizer is found.");
66
67 special_func spk_special_handler;
68
69 short spk_pitch_shift, synth_flags;
70 static char buf[256];
71 int spk_attrib_bleep, spk_bleeps, spk_bleep_time = 10;
72 int spk_no_intr, spk_spell_delay;
73 int spk_key_echo, spk_say_word_ctl;
74 int spk_say_ctrl, spk_bell_pos;
75 short spk_punc_mask;
76 int spk_punc_level, spk_reading_punc;
77 char spk_str_caps_start[MAXVARLEN + 1] = "\0";
78 char spk_str_caps_stop[MAXVARLEN + 1] = "\0";
79 const struct st_bits_data spk_punc_info[] = {
80         {"none", "", 0},
81         {"some", "/$%&@", SOME},
82         {"most", "$%&#()=+*/@^<>|\\", MOST},
83         {"all", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", PUNC},
84         {"delimiters", "", B_WDLM},
85         {"repeats", "()", CH_RPT},
86         {"extended numeric", "", B_EXNUM},
87         {"symbols", "", B_SYM},
88         {NULL, NULL}
89 };
90
91 static char mark_cut_flag;
92 #define MAX_KEY 160
93 static u_char *spk_shift_table;
94 u_char *spk_our_keys[MAX_KEY];
95 u_char spk_key_buf[600];
96 const u_char spk_key_defaults[] = {
97 #include "speakupmap.h"
98 };
99
100 /* Speakup Cursor Track Variables */
101 static int cursor_track = 1, prev_cursor_track = 1;
102
103 /* cursor track modes, must be ordered same as cursor_msgs */
104 enum {
105         CT_Off = 0,
106         CT_On,
107         CT_Highlight,
108         CT_Window,
109         CT_Max
110 };
111 #define read_all_mode CT_Max
112
113 static struct tty_struct *tty;
114
115 static void spkup_write(const char *in_buf, int count);
116
117 static char *phonetic[] = {
118         "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel",
119         "india", "juliett", "keelo", "leema", "mike", "november", "oscar",
120             "papa",
121         "keh beck", "romeo", "sierra", "tango", "uniform", "victer", "whiskey",
122         "x ray", "yankee", "zulu"
123 };
124
125 /* array of 256 char pointers (one for each character description)
126  * initialized to default_chars and user selectable via
127  * /proc/speakup/characters
128  */
129 char *spk_characters[256];
130
131 char *spk_default_chars[256] = {
132 /*000*/ "null", "^a", "^b", "^c", "^d", "^e", "^f", "^g",
133 /*008*/ "^h", "^i", "^j", "^k", "^l", "^m", "^n", "^o",
134 /*016*/ "^p", "^q", "^r", "^s", "^t", "^u", "^v", "^w",
135 /*024*/ "^x", "^y", "^z", "control", "control", "control", "control",
136             "control",
137 /*032*/ "space", "bang!", "quote", "number", "dollar", "percent", "and",
138             "tick",
139 /*040*/ "left paren", "right paren", "star", "plus", "comma", "dash",
140             "dot",
141         "slash",
142 /*048*/ "zero", "one", "two", "three", "four", "five", "six", "seven",
143         "eight", "nine",
144 /*058*/ "colon", "semmy", "less", "equals", "greater", "question", "at",
145 /*065*/ "EIGH", "B", "C", "D", "E", "F", "G",
146 /*072*/ "H", "I", "J", "K", "L", "M", "N", "O",
147 /*080*/ "P", "Q", "R", "S", "T", "U", "V", "W", "X",
148 /*089*/ "Y", "ZED", "left bracket", "backslash", "right bracket",
149             "caret",
150         "line",
151 /*096*/ "accent", "a", "b", "c", "d", "e", "f", "g",
152 /*104*/ "h", "i", "j", "k", "l", "m", "n", "o",
153 /*112*/ "p", "q", "r", "s", "t", "u", "v", "w",
154 /*120*/ "x", "y", "zed", "left brace", "bar", "right brace", "tihlduh",
155 /*127*/ "del", "control", "control", "control", "control", "control",
156             "control", "control", "control", "control", "control",
157 /*138*/ "control", "control", "control", "control", "control",
158             "control", "control", "control", "control", "control",
159             "control", "control",
160 /*150*/ "control", "control", "control", "control", "control",
161             "control", "control", "control", "control", "control",
162 /*160*/ "nbsp", "inverted bang",
163 /*162*/ "cents", "pounds", "currency", "yen", "broken bar", "section",
164 /*168*/ "diaeresis", "copyright", "female ordinal", "double left angle",
165 /*172*/ "not", "soft hyphen", "registered", "macron",
166 /*176*/ "degrees", "plus or minus", "super two", "super three",
167 /*180*/ "acute accent", "micro", "pilcrow", "middle dot",
168 /*184*/ "cedilla", "super one", "male ordinal", "double right angle",
169 /*188*/ "one quarter", "one half", "three quarters",
170             "inverted question",
171 /*192*/ "A GRAVE", "A ACUTE", "A CIRCUMFLEX", "A TILDE", "A OOMLAUT",
172             "A RING",
173 /*198*/ "AE", "C CIDELLA", "E GRAVE", "E ACUTE", "E CIRCUMFLEX",
174             "E OOMLAUT",
175 /*204*/ "I GRAVE", "I ACUTE", "I CIRCUMFLEX", "I OOMLAUT", "ETH",
176             "N TILDE",
177 /*210*/ "O GRAVE", "O ACUTE", "O CIRCUMFLEX", "O TILDE", "O OOMLAUT",
178 /*215*/ "multiplied by", "O STROKE", "U GRAVE", "U ACUTE",
179             "U CIRCUMFLEX",
180 /*220*/ "U OOMLAUT", "Y ACUTE", "THORN", "sharp s", "a grave",
181 /*225*/ "a acute", "a circumflex", "a tilde", "a oomlaut", "a ring",
182 /*230*/ "ae", "c cidella", "e grave", "e acute",
183 /*234*/ "e circumflex", "e oomlaut", "i grave", "i acute",
184             "i circumflex",
185 /*239*/ "i oomlaut", "eth", "n tilde", "o grave", "o acute",
186             "o circumflex",
187 /*245*/ "o tilde", "o oomlaut", "divided by", "o stroke", "u grave",
188             "u acute",
189 /* 251 */ "u circumflex", "u oomlaut", "y acute", "thorn", "y oomlaut"
190 };
191
192 /* array of 256 u_short (one for each character)
193  * initialized to default_chartab and user selectable via
194  * /sys/module/speakup/parameters/chartab
195  */
196 u_short spk_chartab[256];
197
198 static u_short default_chartab[256] = {
199         B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 0-7 */
200         B_CTL, B_CTL, A_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 8-15 */
201         B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /*16-23 */
202         B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 24-31 */
203         WDLM, A_PUNC, PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC,     /*  !"#$%&' */
204         PUNC, PUNC, PUNC, PUNC, A_PUNC, A_PUNC, A_PUNC, PUNC,   /* ()*+, -./ */
205         NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM, /* 01234567 */
206         NUM, NUM, A_PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC,       /* 89:;<=>? */
207         PUNC, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP,  /* @ABCDEFG */
208         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* HIJKLMNO */
209         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* PQRSTUVW */
210         A_CAP, A_CAP, A_CAP, PUNC, PUNC, PUNC, PUNC, PUNC,      /* XYZ[\]^_ */
211         PUNC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,  /* `abcdefg */
212         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* hijklmno */
213         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* pqrstuvw */
214         ALPHA, ALPHA, ALPHA, PUNC, PUNC, PUNC, PUNC, 0, /* xyz{|}~ */
215         B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 128-134 */
216         B_SYM,  /* 135 */
217         B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 136-142 */
218         B_CAPSYM,       /* 143 */
219         B_CAPSYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, /* 144-150 */
220         B_SYM,  /* 151 */
221         B_SYM, B_SYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, /*152-158 */
222         B_SYM,  /* 159 */
223         WDLM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, /* 160-166 */
224         B_SYM,  /* 167 */
225         B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 168-175 */
226         B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 176-183 */
227         B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 184-191 */
228         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* 192-199 */
229         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* 200-207 */
230         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, B_SYM, /* 208-215 */
231         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, ALPHA, /* 216-223 */
232         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* 224-231 */
233         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* 232-239 */
234         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, B_SYM, /* 240-247 */
235         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA  /* 248-255 */
236 };
237
238 struct task_struct *speakup_task;
239 struct bleep spk_unprocessed_sound;
240 static int spk_keydown;
241 static u_char spk_lastkey, spk_close_press, keymap_flags;
242 static u_char last_keycode, this_speakup_key;
243 static u_long last_spk_jiffy;
244
245 struct st_spk_t *speakup_console[MAX_NR_CONSOLES];
246
247 DEFINE_MUTEX(spk_mutex);
248
249 static int keyboard_notifier_call(struct notifier_block *,
250                                   unsigned long code, void *param);
251
252 static struct notifier_block keyboard_notifier_block = {
253         .notifier_call = keyboard_notifier_call,
254 };
255
256 static int vt_notifier_call(struct notifier_block *,
257                             unsigned long code, void *param);
258
259 static struct notifier_block vt_notifier_block = {
260         .notifier_call = vt_notifier_call,
261 };
262
263 static unsigned char get_attributes(struct vc_data *vc, u16 *pos)
264 {
265         pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, 1);
266         return (u_char) (scr_readw(pos) >> 8);
267 }
268
269 static void speakup_date(struct vc_data *vc)
270 {
271         spk_x = spk_cx = vc->vc_x;
272         spk_y = spk_cy = vc->vc_y;
273         spk_pos = spk_cp = vc->vc_pos;
274         spk_old_attr = spk_attr;
275         spk_attr = get_attributes(vc, (u_short *)spk_pos);
276 }
277
278 static void bleep(u_short val)
279 {
280         static const short vals[] = {
281                 350, 370, 392, 414, 440, 466, 491, 523, 554, 587, 619, 659
282         };
283         short freq;
284         int time = spk_bleep_time;
285
286         freq = vals[val % 12];
287         if (val > 11)
288                 freq *= (1 << (val / 12));
289         spk_unprocessed_sound.freq = freq;
290         spk_unprocessed_sound.jiffies = msecs_to_jiffies(time);
291         spk_unprocessed_sound.active = 1;
292         /* We can only have 1 active sound at a time. */
293 }
294
295 static void speakup_shut_up(struct vc_data *vc)
296 {
297         if (spk_killed)
298                 return;
299         spk_shut_up |= 0x01;
300         spk_parked &= 0xfe;
301         speakup_date(vc);
302         if (synth != NULL)
303                 spk_do_flush();
304 }
305
306 static void speech_kill(struct vc_data *vc)
307 {
308         char val = synth->is_alive(synth);
309
310         if (val == 0)
311                 return;
312
313         /* re-enables synth, if disabled */
314         if (val == 2 || spk_killed) {
315                 /* dead */
316                 spk_shut_up &= ~0x40;
317                 synth_printf("%s\n", spk_msg_get(MSG_IAM_ALIVE));
318         } else {
319                 synth_printf("%s\n", spk_msg_get(MSG_YOU_KILLED_SPEAKUP));
320                 spk_shut_up |= 0x40;
321         }
322 }
323
324 static void speakup_off(struct vc_data *vc)
325 {
326         if (spk_shut_up & 0x80) {
327                 spk_shut_up &= 0x7f;
328                 synth_printf("%s\n", spk_msg_get(MSG_HEY_THATS_BETTER));
329         } else {
330                 spk_shut_up |= 0x80;
331                 synth_printf("%s\n", spk_msg_get(MSG_YOU_TURNED_ME_OFF));
332         }
333         speakup_date(vc);
334 }
335
336 static void speakup_parked(struct vc_data *vc)
337 {
338         if (spk_parked & 0x80) {
339                 spk_parked = 0;
340                 synth_printf("%s\n", spk_msg_get(MSG_UNPARKED));
341         } else {
342                 spk_parked |= 0x80;
343                 synth_printf("%s\n", spk_msg_get(MSG_PARKED));
344         }
345 }
346
347 static void speakup_cut(struct vc_data *vc)
348 {
349         static const char err_buf[] = "set selection failed";
350         int ret;
351
352         if (!mark_cut_flag) {
353                 mark_cut_flag = 1;
354                 spk_xs = (u_short) spk_x;
355                 spk_ys = (u_short) spk_y;
356                 spk_sel_cons = vc;
357                 synth_printf("%s\n", spk_msg_get(MSG_MARK));
358                 return;
359         }
360         spk_xe = (u_short) spk_x;
361         spk_ye = (u_short) spk_y;
362         mark_cut_flag = 0;
363         synth_printf("%s\n", spk_msg_get(MSG_CUT));
364
365         speakup_clear_selection();
366         ret = speakup_set_selection(tty);
367
368         switch (ret) {
369         case 0:
370                 break;          /* no error */
371         case -EFAULT:
372                 pr_warn("%sEFAULT\n", err_buf);
373                 break;
374         case -EINVAL:
375                 pr_warn("%sEINVAL\n", err_buf);
376                 break;
377         case -ENOMEM:
378                 pr_warn("%sENOMEM\n", err_buf);
379                 break;
380         }
381 }
382
383 static void speakup_paste(struct vc_data *vc)
384 {
385         if (mark_cut_flag) {
386                 mark_cut_flag = 0;
387                 synth_printf("%s\n", spk_msg_get(MSG_MARK_CLEARED));
388         } else {
389                 synth_printf("%s\n", spk_msg_get(MSG_PASTE));
390                 speakup_paste_selection(tty);
391         }
392 }
393
394 static void say_attributes(struct vc_data *vc)
395 {
396         int fg = spk_attr & 0x0f;
397         int bg = spk_attr >> 4;
398
399         if (fg > 8) {
400                 synth_printf("%s ", spk_msg_get(MSG_BRIGHT));
401                 fg -= 8;
402         }
403         synth_printf("%s", spk_msg_get(MSG_COLORS_START + fg));
404         if (bg > 7) {
405                 synth_printf(" %s ", spk_msg_get(MSG_ON_BLINKING));
406                 bg -= 8;
407         } else
408                 synth_printf(" %s ", spk_msg_get(MSG_ON));
409         synth_printf("%s\n", spk_msg_get(MSG_COLORS_START + bg));
410 }
411
412 enum {
413         edge_top = 1,
414         edge_bottom,
415         edge_left,
416         edge_right,
417         edge_quiet
418 };
419
420 static void announce_edge(struct vc_data *vc, int msg_id)
421 {
422         if (spk_bleeps & 1)
423                 bleep(spk_y);
424         if ((spk_bleeps & 2) && (msg_id < edge_quiet))
425                 synth_printf("%s\n",
426                         spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
427 }
428
429 static void speak_char(u_char ch)
430 {
431         char *cp = spk_characters[ch];
432         struct var_t *direct = spk_get_var(DIRECT);
433
434         if (direct && direct->u.n.value) {
435                 if (IS_CHAR(ch, B_CAP)) {
436                         spk_pitch_shift++;
437                         synth_printf("%s", spk_str_caps_start);
438                 }
439                 synth_printf("%c", ch);
440                 if (IS_CHAR(ch, B_CAP))
441                         synth_printf("%s", spk_str_caps_stop);
442                 return;
443         }
444         if (cp == NULL) {
445                 pr_info("speak_char: cp == NULL!\n");
446                 return;
447         }
448         synth_buffer_add(SPACE);
449         if (IS_CHAR(ch, B_CAP)) {
450                 spk_pitch_shift++;
451                 synth_printf("%s", spk_str_caps_start);
452                 synth_printf("%s", cp);
453                 synth_printf("%s", spk_str_caps_stop);
454         } else {
455                 if (*cp == '^') {
456                         synth_printf("%s", spk_msg_get(MSG_CTRL));
457                         cp++;
458                 }
459                 synth_printf("%s", cp);
460         }
461         synth_buffer_add(SPACE);
462 }
463
464 static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs)
465 {
466         u16 ch = ' ';
467
468         if (vc && pos) {
469                 u16 w;
470                 u16 c;
471
472                 pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, 1);
473                 w = scr_readw(pos);
474                 c = w & 0xff;
475
476                 if (w & vc->vc_hi_font_mask)
477                         c |= 0x100;
478
479                 ch = inverse_translate(vc, c, 0);
480                 *attribs = (w & 0xff00) >> 8;
481         }
482         return ch;
483 }
484
485 static void say_char(struct vc_data *vc)
486 {
487         u_short ch;
488
489         spk_old_attr = spk_attr;
490         ch = get_char(vc, (u_short *) spk_pos, &spk_attr);
491         if (spk_attr != spk_old_attr) {
492                 if (spk_attrib_bleep & 1)
493                         bleep(spk_y);
494                 if (spk_attrib_bleep & 2)
495                         say_attributes(vc);
496         }
497         speak_char(ch & 0xff);
498 }
499
500 static void say_phonetic_char(struct vc_data *vc)
501 {
502         u_short ch;
503
504         spk_old_attr = spk_attr;
505         ch = get_char(vc, (u_short *) spk_pos, &spk_attr);
506         if (isascii(ch) && isalpha(ch)) {
507                 ch &= 0x1f;
508                 synth_printf("%s\n", phonetic[--ch]);
509         } else {
510                 if (IS_CHAR(ch, B_NUM))
511                         synth_printf("%s ", spk_msg_get(MSG_NUMBER));
512                 speak_char(ch);
513         }
514 }
515
516 static void say_prev_char(struct vc_data *vc)
517 {
518         spk_parked |= 0x01;
519         if (spk_x == 0) {
520                 announce_edge(vc, edge_left);
521                 return;
522         }
523         spk_x--;
524         spk_pos -= 2;
525         say_char(vc);
526 }
527
528 static void say_next_char(struct vc_data *vc)
529 {
530         spk_parked |= 0x01;
531         if (spk_x == vc->vc_cols - 1) {
532                 announce_edge(vc, edge_right);
533                 return;
534         }
535         spk_x++;
536         spk_pos += 2;
537         say_char(vc);
538 }
539
540 /* get_word - will first check to see if the character under the
541  * reading cursor is a space and if spk_say_word_ctl is true it will
542  * return the word space.  If spk_say_word_ctl is not set it will check to
543  * see if there is a word starting on the next position to the right
544  * and return that word if it exists.  If it does not exist it will
545  * move left to the beginning of any previous word on the line or the
546  * beginning off the line whichever comes first..
547  */
548
549 static u_long get_word(struct vc_data *vc)
550 {
551         u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
552         char ch;
553         u_short attr_ch;
554         u_char temp;
555
556         spk_old_attr = spk_attr;
557         ch = (char)get_char(vc, (u_short *) tmp_pos, &temp);
558
559 /* decided to take out the sayword if on a space (mis-information */
560         if (spk_say_word_ctl && ch == SPACE) {
561                 *buf = '\0';
562                 synth_printf("%s\n", spk_msg_get(MSG_SPACE));
563                 return 0;
564         } else if ((tmpx < vc->vc_cols - 2)
565                    && (ch == SPACE || ch == 0 || IS_WDLM(ch))
566                    && ((char)get_char(vc, (u_short *) &tmp_pos + 1, &temp) >
567                        SPACE)) {
568                 tmp_pos += 2;
569                 tmpx++;
570         } else
571                 while (tmpx > 0) {
572                         ch = (char)get_char(vc, (u_short *) tmp_pos - 1, &temp);
573                         if ((ch == SPACE || ch == 0 || IS_WDLM(ch))
574                             && ((char)get_char(vc, (u_short *) tmp_pos, &temp) >
575                                 SPACE))
576                                 break;
577                         tmp_pos -= 2;
578                         tmpx--;
579                 }
580         attr_ch = get_char(vc, (u_short *) tmp_pos, &spk_attr);
581         buf[cnt++] = attr_ch & 0xff;
582         while (tmpx < vc->vc_cols - 1) {
583                 tmp_pos += 2;
584                 tmpx++;
585                 ch = (char)get_char(vc, (u_short *) tmp_pos, &temp);
586                 if ((ch == SPACE) || ch == 0
587                     || (IS_WDLM(buf[cnt - 1]) && (ch > SPACE)))
588                         break;
589                 buf[cnt++] = ch;
590         }
591         buf[cnt] = '\0';
592         return cnt;
593 }
594
595 static void say_word(struct vc_data *vc)
596 {
597         u_long cnt = get_word(vc);
598         u_short saved_punc_mask = spk_punc_mask;
599
600         if (cnt == 0)
601                 return;
602         spk_punc_mask = PUNC;
603         buf[cnt++] = SPACE;
604         spkup_write(buf, cnt);
605         spk_punc_mask = saved_punc_mask;
606 }
607
608 static void say_prev_word(struct vc_data *vc)
609 {
610         u_char temp;
611         char ch;
612         u_short edge_said = 0, last_state = 0, state = 0;
613
614         spk_parked |= 0x01;
615
616         if (spk_x == 0) {
617                 if (spk_y == 0) {
618                         announce_edge(vc, edge_top);
619                         return;
620                 }
621                 spk_y--;
622                 spk_x = vc->vc_cols;
623                 edge_said = edge_quiet;
624         }
625         while (1) {
626                 if (spk_x == 0) {
627                         if (spk_y == 0) {
628                                 edge_said = edge_top;
629                                 break;
630                         }
631                         if (edge_said != edge_quiet)
632                                 edge_said = edge_left;
633                         if (state > 0)
634                                 break;
635                         spk_y--;
636                         spk_x = vc->vc_cols - 1;
637                 } else
638                         spk_x--;
639                 spk_pos -= 2;
640                 ch = (char)get_char(vc, (u_short *) spk_pos, &temp);
641                 if (ch == SPACE || ch == 0)
642                         state = 0;
643                 else if (IS_WDLM(ch))
644                         state = 1;
645                 else
646                         state = 2;
647                 if (state < last_state) {
648                         spk_pos += 2;
649                         spk_x++;
650                         break;
651                 }
652                 last_state = state;
653         }
654         if (spk_x == 0 && edge_said == edge_quiet)
655                 edge_said = edge_left;
656         if (edge_said > 0 && edge_said < edge_quiet)
657                 announce_edge(vc, edge_said);
658         say_word(vc);
659 }
660
661 static void say_next_word(struct vc_data *vc)
662 {
663         u_char temp;
664         char ch;
665         u_short edge_said = 0, last_state = 2, state = 0;
666
667         spk_parked |= 0x01;
668         if (spk_x == vc->vc_cols - 1 && spk_y == vc->vc_rows - 1) {
669                 announce_edge(vc, edge_bottom);
670                 return;
671         }
672         while (1) {
673                 ch = (char)get_char(vc, (u_short *) spk_pos, &temp);
674                 if (ch == SPACE || ch == 0)
675                         state = 0;
676                 else if (IS_WDLM(ch))
677                         state = 1;
678                 else
679                         state = 2;
680                 if (state > last_state)
681                         break;
682                 if (spk_x >= vc->vc_cols - 1) {
683                         if (spk_y == vc->vc_rows - 1) {
684                                 edge_said = edge_bottom;
685                                 break;
686                         }
687                         state = 0;
688                         spk_y++;
689                         spk_x = 0;
690                         edge_said = edge_right;
691                 } else
692                         spk_x++;
693                 spk_pos += 2;
694                 last_state = state;
695         }
696         if (edge_said > 0)
697                 announce_edge(vc, edge_said);
698         say_word(vc);
699 }
700
701 static void spell_word(struct vc_data *vc)
702 {
703         static char const *delay_str[] = { "", ",", ".", ". .", ". . ." };
704         char *cp = buf, *str_cap = spk_str_caps_stop;
705         char *cp1, *last_cap = spk_str_caps_stop;
706         u_char ch;
707
708         if (!get_word(vc))
709                 return;
710         while ((ch = (u_char) *cp)) {
711                 if (cp != buf)
712                         synth_printf(" %s ", delay_str[spk_spell_delay]);
713                 if (IS_CHAR(ch, B_CAP)) {
714                         str_cap = spk_str_caps_start;
715                         if (*spk_str_caps_stop)
716                                 spk_pitch_shift++;
717                         else    /* synth has no pitch */
718                                 last_cap = spk_str_caps_stop;
719                 } else
720                         str_cap = spk_str_caps_stop;
721                 if (str_cap != last_cap) {
722                         synth_printf("%s", str_cap);
723                         last_cap = str_cap;
724                 }
725                 if (this_speakup_key == SPELL_PHONETIC
726                     && (isascii(ch) && isalpha(ch))) {
727                         ch &= 31;
728                         cp1 = phonetic[--ch];
729                 } else {
730                         cp1 = spk_characters[ch];
731                         if (*cp1 == '^') {
732                                 synth_printf("%s", spk_msg_get(MSG_CTRL));
733                                 cp1++;
734                         }
735                 }
736                 synth_printf("%s", cp1);
737                 cp++;
738         }
739         if (str_cap != spk_str_caps_stop)
740                 synth_printf("%s", spk_str_caps_stop);
741 }
742
743 static int get_line(struct vc_data *vc)
744 {
745         u_long tmp = spk_pos - (spk_x * 2);
746         int i = 0;
747         u_char tmp2;
748
749         spk_old_attr = spk_attr;
750         spk_attr = get_attributes(vc, (u_short *)spk_pos);
751         for (i = 0; i < vc->vc_cols; i++) {
752                 buf[i] = (u_char) get_char(vc, (u_short *) tmp, &tmp2);
753                 tmp += 2;
754         }
755         for (--i; i >= 0; i--)
756                 if (buf[i] != SPACE)
757                         break;
758         return ++i;
759 }
760
761 static void say_line(struct vc_data *vc)
762 {
763         int i = get_line(vc);
764         char *cp;
765         u_short saved_punc_mask = spk_punc_mask;
766
767         if (i == 0) {
768                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
769                 return;
770         }
771         buf[i++] = '\n';
772         if (this_speakup_key == SAY_LINE_INDENT) {
773                 cp = buf;
774                 while (*cp == SPACE)
775                         cp++;
776                 synth_printf("%d, ", (cp - buf) + 1);
777         }
778         spk_punc_mask = spk_punc_masks[spk_reading_punc];
779         spkup_write(buf, i);
780         spk_punc_mask = saved_punc_mask;
781 }
782
783 static void say_prev_line(struct vc_data *vc)
784 {
785         spk_parked |= 0x01;
786         if (spk_y == 0) {
787                 announce_edge(vc, edge_top);
788                 return;
789         }
790         spk_y--;
791         spk_pos -= vc->vc_size_row;
792         say_line(vc);
793 }
794
795 static void say_next_line(struct vc_data *vc)
796 {
797         spk_parked |= 0x01;
798         if (spk_y == vc->vc_rows - 1) {
799                 announce_edge(vc, edge_bottom);
800                 return;
801         }
802         spk_y++;
803         spk_pos += vc->vc_size_row;
804         say_line(vc);
805 }
806
807 static int say_from_to(struct vc_data *vc, u_long from, u_long to,
808                        int read_punc)
809 {
810         int i = 0;
811         u_char tmp;
812         u_short saved_punc_mask = spk_punc_mask;
813
814         spk_old_attr = spk_attr;
815         spk_attr = get_attributes(vc, (u_short *)from);
816         while (from < to) {
817                 buf[i++] = (char)get_char(vc, (u_short *) from, &tmp);
818                 from += 2;
819                 if (i >= vc->vc_size_row)
820                         break;
821         }
822         for (--i; i >= 0; i--)
823                 if (buf[i] != SPACE)
824                         break;
825         buf[++i] = SPACE;
826         buf[++i] = '\0';
827         if (i < 1)
828                 return i;
829         if (read_punc)
830                 spk_punc_mask = spk_punc_info[spk_reading_punc].mask;
831         spkup_write(buf, i);
832         if (read_punc)
833                 spk_punc_mask = saved_punc_mask;
834         return i - 1;
835 }
836
837 static void say_line_from_to(struct vc_data *vc, u_long from, u_long to,
838                              int read_punc)
839 {
840         u_long start = vc->vc_origin + (spk_y * vc->vc_size_row);
841         u_long end = start + (to * 2);
842
843         start += from * 2;
844         if (say_from_to(vc, start, end, read_punc) <= 0)
845                 if (cursor_track != read_all_mode)
846                         synth_printf("%s\n", spk_msg_get(MSG_BLANK));
847 }
848
849 /* Sentence Reading Commands */
850
851 static int currsentence;
852 static int numsentences[2];
853 static char *sentbufend[2];
854 static char *sentmarks[2][10];
855 static int currbuf;
856 static int bn;
857 static char sentbuf[2][256];
858
859 static int say_sentence_num(int num, int prev)
860 {
861         bn = currbuf;
862         currsentence = num + 1;
863         if (prev && --bn == -1)
864                 bn = 1;
865
866         if (num > numsentences[bn])
867                 return 0;
868
869         spkup_write(sentmarks[bn][num], sentbufend[bn] - sentmarks[bn][num]);
870         return 1;
871 }
872
873 static int get_sentence_buf(struct vc_data *vc, int read_punc)
874 {
875         u_long start, end;
876         int i, bn;
877         u_char tmp;
878
879         currbuf++;
880         if (currbuf == 2)
881                 currbuf = 0;
882         bn = currbuf;
883         start = vc->vc_origin + ((spk_y) * vc->vc_size_row);
884         end = vc->vc_origin + ((spk_y) * vc->vc_size_row) + vc->vc_cols * 2;
885
886         numsentences[bn] = 0;
887         sentmarks[bn][0] = &sentbuf[bn][0];
888         i = 0;
889         spk_old_attr = spk_attr;
890         spk_attr = get_attributes(vc, (u_short *)start);
891
892         while (start < end) {
893                 sentbuf[bn][i] = (char)get_char(vc, (u_short *) start, &tmp);
894                 if (i > 0) {
895                         if (sentbuf[bn][i] == SPACE && sentbuf[bn][i - 1] == '.'
896                             && numsentences[bn] < 9) {
897                                 /* Sentence Marker */
898                                 numsentences[bn]++;
899                                 sentmarks[bn][numsentences[bn]] =
900                                     &sentbuf[bn][i];
901                         }
902                 }
903                 i++;
904                 start += 2;
905                 if (i >= vc->vc_size_row)
906                         break;
907         }
908
909         for (--i; i >= 0; i--)
910                 if (sentbuf[bn][i] != SPACE)
911                         break;
912
913         if (i < 1)
914                 return -1;
915
916         sentbuf[bn][++i] = SPACE;
917         sentbuf[bn][++i] = '\0';
918
919         sentbufend[bn] = &sentbuf[bn][i];
920         return numsentences[bn];
921 }
922
923 static void say_screen_from_to(struct vc_data *vc, u_long from, u_long to)
924 {
925         u_long start = vc->vc_origin, end;
926
927         if (from > 0)
928                 start += from * vc->vc_size_row;
929         if (to > vc->vc_rows)
930                 to = vc->vc_rows;
931         end = vc->vc_origin + (to * vc->vc_size_row);
932         for (from = start; from < end; from = to) {
933                 to = from + vc->vc_size_row;
934                 say_from_to(vc, from, to, 1);
935         }
936 }
937
938 static void say_screen(struct vc_data *vc)
939 {
940         say_screen_from_to(vc, 0, vc->vc_rows);
941 }
942
943 static void speakup_win_say(struct vc_data *vc)
944 {
945         u_long start, end, from, to;
946
947         if (win_start < 2) {
948                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
949                 return;
950         }
951         start = vc->vc_origin + (win_top * vc->vc_size_row);
952         end = vc->vc_origin + (win_bottom * vc->vc_size_row);
953         while (start <= end) {
954                 from = start + (win_left * 2);
955                 to = start + (win_right * 2);
956                 say_from_to(vc, from, to, 1);
957                 start += vc->vc_size_row;
958         }
959 }
960
961 static void top_edge(struct vc_data *vc)
962 {
963         spk_parked |= 0x01;
964         spk_pos = vc->vc_origin + 2 * spk_x;
965         spk_y = 0;
966         say_line(vc);
967 }
968
969 static void bottom_edge(struct vc_data *vc)
970 {
971         spk_parked |= 0x01;
972         spk_pos += (vc->vc_rows - spk_y - 1) * vc->vc_size_row;
973         spk_y = vc->vc_rows - 1;
974         say_line(vc);
975 }
976
977 static void left_edge(struct vc_data *vc)
978 {
979         spk_parked |= 0x01;
980         spk_pos -= spk_x * 2;
981         spk_x = 0;
982         say_char(vc);
983 }
984
985 static void right_edge(struct vc_data *vc)
986 {
987         spk_parked |= 0x01;
988         spk_pos += (vc->vc_cols - spk_x - 1) * 2;
989         spk_x = vc->vc_cols - 1;
990         say_char(vc);
991 }
992
993 static void say_first_char(struct vc_data *vc)
994 {
995         int i, len = get_line(vc);
996         u_char ch;
997
998         spk_parked |= 0x01;
999         if (len == 0) {
1000                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
1001                 return;
1002         }
1003         for (i = 0; i < len; i++)
1004                 if (buf[i] != SPACE)
1005                         break;
1006         ch = buf[i];
1007         spk_pos -= (spk_x - i) * 2;
1008         spk_x = i;
1009         synth_printf("%d, ", ++i);
1010         speak_char(ch);
1011 }
1012
1013 static void say_last_char(struct vc_data *vc)
1014 {
1015         int len = get_line(vc);
1016         u_char ch;
1017
1018         spk_parked |= 0x01;
1019         if (len == 0) {
1020                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
1021                 return;
1022         }
1023         ch = buf[--len];
1024         spk_pos -= (spk_x - len) * 2;
1025         spk_x = len;
1026         synth_printf("%d, ", ++len);
1027         speak_char(ch);
1028 }
1029
1030 static void say_position(struct vc_data *vc)
1031 {
1032         synth_printf(spk_msg_get(MSG_POS_INFO), spk_y + 1, spk_x + 1,
1033                      vc->vc_num + 1);
1034         synth_printf("\n");
1035 }
1036
1037 /* Added by brianb */
1038 static void say_char_num(struct vc_data *vc)
1039 {
1040         u_char tmp;
1041         u_short ch = get_char(vc, (u_short *) spk_pos, &tmp);
1042
1043         ch &= 0xff;
1044         synth_printf(spk_msg_get(MSG_CHAR_INFO), ch, ch);
1045 }
1046
1047 /* these are stub functions to keep keyboard.c happy. */
1048
1049 static void say_from_top(struct vc_data *vc)
1050 {
1051         say_screen_from_to(vc, 0, spk_y);
1052 }
1053
1054 static void say_to_bottom(struct vc_data *vc)
1055 {
1056         say_screen_from_to(vc, spk_y, vc->vc_rows);
1057 }
1058
1059 static void say_from_left(struct vc_data *vc)
1060 {
1061         say_line_from_to(vc, 0, spk_x, 1);
1062 }
1063
1064 static void say_to_right(struct vc_data *vc)
1065 {
1066         say_line_from_to(vc, spk_x, vc->vc_cols, 1);
1067 }
1068
1069 /* end of stub functions. */
1070
1071 static void spkup_write(const char *in_buf, int count)
1072 {
1073         static int rep_count;
1074         static u_char ch = '\0', old_ch = '\0';
1075         static u_short char_type, last_type;
1076         int in_count = count;
1077
1078         spk_keydown = 0;
1079         while (count--) {
1080                 if (cursor_track == read_all_mode) {
1081                         /* Insert Sentence Index */
1082                         if ((in_buf == sentmarks[bn][currsentence]) &&
1083                             (currsentence <= numsentences[bn]))
1084                                 synth_insert_next_index(currsentence++);
1085                 }
1086                 ch = (u_char) *in_buf++;
1087                 char_type = spk_chartab[ch];
1088                 if (ch == old_ch && !(char_type & B_NUM)) {
1089                         if (++rep_count > 2)
1090                                 continue;
1091                 } else {
1092                         if ((last_type & CH_RPT) && rep_count > 2) {
1093                                 synth_printf(" ");
1094                                 synth_printf(spk_msg_get(MSG_REPEAT_DESC),
1095                                              ++rep_count);
1096                                 synth_printf(" ");
1097                         }
1098                         rep_count = 0;
1099                 }
1100                 if (ch == spk_lastkey) {
1101                         rep_count = 0;
1102                         if (spk_key_echo == 1 && ch >= MINECHOCHAR)
1103                                 speak_char(ch);
1104                 } else if (char_type & B_ALPHA) {
1105                         if ((synth_flags & SF_DEC) && (last_type & PUNC))
1106                                 synth_buffer_add(SPACE);
1107                         synth_printf("%c", ch);
1108                 } else if (char_type & B_NUM) {
1109                         rep_count = 0;
1110                         synth_printf("%c", ch);
1111                 } else if (char_type & spk_punc_mask) {
1112                         speak_char(ch);
1113                         char_type &= ~PUNC;     /* for dec nospell processing */
1114                 } else if (char_type & SYNTH_OK) {
1115                         /* these are usually puncts like . and , which synth
1116                          * needs for expression.
1117                          * suppress multiple to get rid of long pauses and
1118                          * clear repeat count
1119                          * so if someone has
1120                          * repeats on you don't get nothing repeated count
1121                          */
1122                         if (ch != old_ch)
1123                                 synth_printf("%c", ch);
1124                         else
1125                                 rep_count = 0;
1126                 } else {
1127 /* send space and record position, if next is num overwrite space */
1128                         if (old_ch != ch)
1129                                 synth_buffer_add(SPACE);
1130                         else
1131                                 rep_count = 0;
1132                 }
1133                 old_ch = ch;
1134                 last_type = char_type;
1135         }
1136         spk_lastkey = 0;
1137         if (in_count > 2 && rep_count > 2) {
1138                 if (last_type & CH_RPT) {
1139                         synth_printf(" ");
1140                         synth_printf(spk_msg_get(MSG_REPEAT_DESC2),
1141                                         ++rep_count);
1142                         synth_printf(" ");
1143                 }
1144                 rep_count = 0;
1145         }
1146 }
1147
1148 static const int NUM_CTL_LABELS = (MSG_CTL_END - MSG_CTL_START + 1);
1149
1150 static void read_all_doc(struct vc_data *vc);
1151 static void cursor_done(u_long data);
1152 static DEFINE_TIMER(cursor_timer, cursor_done, 0, 0);
1153
1154 static void do_handle_shift(struct vc_data *vc, u_char value, char up_flag)
1155 {
1156         unsigned long flags;
1157
1158         if (synth == NULL || up_flag || spk_killed)
1159                 return;
1160         spin_lock_irqsave(&speakup_info.spinlock, flags);
1161         if (cursor_track == read_all_mode) {
1162                 switch (value) {
1163                 case KVAL(K_SHIFT):
1164                         del_timer(&cursor_timer);
1165                         spk_shut_up &= 0xfe;
1166                         spk_do_flush();
1167                         read_all_doc(vc);
1168                         break;
1169                 case KVAL(K_CTRL):
1170                         del_timer(&cursor_timer);
1171                         cursor_track = prev_cursor_track;
1172                         spk_shut_up &= 0xfe;
1173                         spk_do_flush();
1174                         break;
1175                 }
1176         } else {
1177                 spk_shut_up &= 0xfe;
1178                 spk_do_flush();
1179         }
1180         if (spk_say_ctrl && value < NUM_CTL_LABELS)
1181                 synth_printf("%s", spk_msg_get(MSG_CTL_START + value));
1182         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1183 }
1184
1185 static void do_handle_latin(struct vc_data *vc, u_char value, char up_flag)
1186 {
1187         unsigned long flags;
1188
1189         spin_lock_irqsave(&speakup_info.spinlock, flags);
1190         if (up_flag) {
1191                 spk_lastkey = 0;
1192                 spk_keydown = 0;
1193                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1194                 return;
1195         }
1196         if (synth == NULL || spk_killed) {
1197                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1198                 return;
1199         }
1200         spk_shut_up &= 0xfe;
1201         spk_lastkey = value;
1202         spk_keydown++;
1203         spk_parked &= 0xfe;
1204         if (spk_key_echo == 2 && value >= MINECHOCHAR)
1205                 speak_char(value);
1206         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1207 }
1208
1209 int spk_set_key_info(const u_char *key_info, u_char *k_buffer)
1210 {
1211         int i = 0, states, key_data_len;
1212         const u_char *cp = key_info;
1213         u_char *cp1 = k_buffer;
1214         u_char ch, version, num_keys;
1215
1216         version = *cp++;
1217         if (version != KEY_MAP_VER)
1218                 return -1;
1219         num_keys = *cp;
1220         states = (int)cp[1];
1221         key_data_len = (states + 1) * (num_keys + 1);
1222         if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(spk_key_buf))
1223                 return -2;
1224         memset(k_buffer, 0, SHIFT_TBL_SIZE);
1225         memset(spk_our_keys, 0, sizeof(spk_our_keys));
1226         spk_shift_table = k_buffer;
1227         spk_our_keys[0] = spk_shift_table;
1228         cp1 += SHIFT_TBL_SIZE;
1229         memcpy(cp1, cp, key_data_len + 3);
1230         /* get num_keys, states and data */
1231         cp1 += 2;               /* now pointing at shift states */
1232         for (i = 1; i <= states; i++) {
1233                 ch = *cp1++;
1234                 if (ch >= SHIFT_TBL_SIZE)
1235                         return -3;
1236                 spk_shift_table[ch] = i;
1237         }
1238         keymap_flags = *cp1++;
1239         while ((ch = *cp1)) {
1240                 if (ch >= MAX_KEY)
1241                         return -4;
1242                 spk_our_keys[ch] = cp1;
1243                 cp1 += states + 1;
1244         }
1245         return 0;
1246 }
1247
1248 static struct var_t spk_vars[] = {
1249         /* bell must be first to set high limit */
1250         {BELL_POS, .u.n = {NULL, 0, 0, 0, 0, 0, NULL} },
1251         {SPELL_DELAY, .u.n = {NULL, 0, 0, 4, 0, 0, NULL} },
1252         {ATTRIB_BLEEP, .u.n = {NULL, 1, 0, 3, 0, 0, NULL} },
1253         {BLEEPS, .u.n = {NULL, 3, 0, 3, 0, 0, NULL} },
1254         {BLEEP_TIME, .u.n = {NULL, 30, 1, 200, 0, 0, NULL} },
1255         {PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1256         {READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1257         {CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
1258         {SAY_CONTROL, TOGGLE_0},
1259         {SAY_WORD_CTL, TOGGLE_0},
1260         {NO_INTERRUPT, TOGGLE_0},
1261         {KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
1262         V_LAST_VAR
1263 };
1264
1265 static void toggle_cursoring(struct vc_data *vc)
1266 {
1267         if (cursor_track == read_all_mode)
1268                 cursor_track = prev_cursor_track;
1269         if (++cursor_track >= CT_Max)
1270                 cursor_track = 0;
1271         synth_printf("%s\n", spk_msg_get(MSG_CURSOR_MSGS_START + cursor_track));
1272 }
1273
1274 void spk_reset_default_chars(void)
1275 {
1276         int i;
1277
1278         /* First, free any non-default */
1279         for (i = 0; i < 256; i++) {
1280                 if ((spk_characters[i] != NULL)
1281                     && (spk_characters[i] != spk_default_chars[i]))
1282                         kfree(spk_characters[i]);
1283         }
1284
1285         memcpy(spk_characters, spk_default_chars, sizeof(spk_default_chars));
1286 }
1287
1288 void spk_reset_default_chartab(void)
1289 {
1290         memcpy(spk_chartab, default_chartab, sizeof(default_chartab));
1291 }
1292
1293 static const struct st_bits_data *pb_edit;
1294
1295 static int edit_bits(struct vc_data *vc, u_char type, u_char ch, u_short key)
1296 {
1297         short mask = pb_edit->mask, ch_type = spk_chartab[ch];
1298
1299         if (type != KT_LATIN || (ch_type & B_NUM) || ch < SPACE)
1300                 return -1;
1301         if (ch == SPACE) {
1302                 synth_printf("%s\n", spk_msg_get(MSG_EDIT_DONE));
1303                 spk_special_handler = NULL;
1304                 return 1;
1305         }
1306         if (mask < PUNC && !(ch_type & PUNC))
1307                 return -1;
1308         spk_chartab[ch] ^= mask;
1309         speak_char(ch);
1310         synth_printf(" %s\n",
1311                      (spk_chartab[ch] & mask) ? spk_msg_get(MSG_ON) :
1312                      spk_msg_get(MSG_OFF));
1313         return 1;
1314 }
1315
1316 /* Allocation concurrency is protected by the console semaphore */
1317 static int speakup_allocate(struct vc_data *vc)
1318 {
1319         int vc_num;
1320
1321         vc_num = vc->vc_num;
1322         if (speakup_console[vc_num] == NULL) {
1323                 speakup_console[vc_num] = kzalloc(sizeof(*speakup_console[0]),
1324                                                   GFP_ATOMIC);
1325                 if (speakup_console[vc_num] == NULL)
1326                         return -ENOMEM;
1327                 speakup_date(vc);
1328         } else if (!spk_parked)
1329                 speakup_date(vc);
1330
1331         return 0;
1332 }
1333
1334 static void speakup_deallocate(struct vc_data *vc)
1335 {
1336         int vc_num;
1337
1338         vc_num = vc->vc_num;
1339         kfree(speakup_console[vc_num]);
1340         speakup_console[vc_num] = NULL;
1341 }
1342
1343 static u_char is_cursor;
1344 static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
1345 static int cursor_con;
1346
1347 static void reset_highlight_buffers(struct vc_data *);
1348
1349 static int read_all_key;
1350
1351 static void start_read_all_timer(struct vc_data *vc, int command);
1352
1353 enum {
1354         RA_NOTHING,
1355         RA_NEXT_SENT,
1356         RA_PREV_LINE,
1357         RA_NEXT_LINE,
1358         RA_PREV_SENT,
1359         RA_DOWN_ARROW,
1360         RA_TIMER,
1361         RA_FIND_NEXT_SENT,
1362         RA_FIND_PREV_SENT,
1363 };
1364
1365 static void kbd_fakekey2(struct vc_data *vc, int command)
1366 {
1367         del_timer(&cursor_timer);
1368         speakup_fake_down_arrow();
1369         start_read_all_timer(vc, command);
1370 }
1371
1372 static void read_all_doc(struct vc_data *vc)
1373 {
1374         if ((vc->vc_num != fg_console) || synth == NULL || spk_shut_up)
1375                 return;
1376         if (!synth_supports_indexing())
1377                 return;
1378         if (cursor_track != read_all_mode)
1379                 prev_cursor_track = cursor_track;
1380         cursor_track = read_all_mode;
1381         spk_reset_index_count(0);
1382         if (get_sentence_buf(vc, 0) == -1)
1383                 kbd_fakekey2(vc, RA_DOWN_ARROW);
1384         else {
1385                 say_sentence_num(0, 0);
1386                 synth_insert_next_index(0);
1387                 start_read_all_timer(vc, RA_TIMER);
1388         }
1389 }
1390
1391 static void stop_read_all(struct vc_data *vc)
1392 {
1393         del_timer(&cursor_timer);
1394         cursor_track = prev_cursor_track;
1395         spk_shut_up &= 0xfe;
1396         spk_do_flush();
1397 }
1398
1399 static void start_read_all_timer(struct vc_data *vc, int command)
1400 {
1401         struct var_t *cursor_timeout;
1402
1403         cursor_con = vc->vc_num;
1404         read_all_key = command;
1405         cursor_timeout = spk_get_var(CURSOR_TIME);
1406         mod_timer(&cursor_timer,
1407                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1408 }
1409
1410 static void handle_cursor_read_all(struct vc_data *vc, int command)
1411 {
1412         int indcount, sentcount, rv, sn;
1413
1414         switch (command) {
1415         case RA_NEXT_SENT:
1416                 /* Get Current Sentence */
1417                 spk_get_index_count(&indcount, &sentcount);
1418                 /*printk("%d %d  ", indcount, sentcount); */
1419                 spk_reset_index_count(sentcount + 1);
1420                 if (indcount == 1) {
1421                         if (!say_sentence_num(sentcount + 1, 0)) {
1422                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1423                                 return;
1424                         }
1425                         synth_insert_next_index(0);
1426                 } else {
1427                         sn = 0;
1428                         if (!say_sentence_num(sentcount + 1, 1)) {
1429                                 sn = 1;
1430                                 spk_reset_index_count(sn);
1431                         } else
1432                                 synth_insert_next_index(0);
1433                         if (!say_sentence_num(sn, 0)) {
1434                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1435                                 return;
1436                         }
1437                         synth_insert_next_index(0);
1438                 }
1439                 start_read_all_timer(vc, RA_TIMER);
1440                 break;
1441         case RA_PREV_SENT:
1442                 break;
1443         case RA_NEXT_LINE:
1444                 read_all_doc(vc);
1445                 break;
1446         case RA_PREV_LINE:
1447                 break;
1448         case RA_DOWN_ARROW:
1449                 if (get_sentence_buf(vc, 0) == -1) {
1450                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1451                 } else {
1452                         say_sentence_num(0, 0);
1453                         synth_insert_next_index(0);
1454                         start_read_all_timer(vc, RA_TIMER);
1455                 }
1456                 break;
1457         case RA_FIND_NEXT_SENT:
1458                 rv = get_sentence_buf(vc, 0);
1459                 if (rv == -1)
1460                         read_all_doc(vc);
1461                 if (rv == 0)
1462                         kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1463                 else {
1464                         say_sentence_num(1, 0);
1465                         synth_insert_next_index(0);
1466                         start_read_all_timer(vc, RA_TIMER);
1467                 }
1468                 break;
1469         case RA_FIND_PREV_SENT:
1470                 break;
1471         case RA_TIMER:
1472                 spk_get_index_count(&indcount, &sentcount);
1473                 if (indcount < 2)
1474                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1475                 else
1476                         start_read_all_timer(vc, RA_TIMER);
1477                 break;
1478         }
1479 }
1480
1481 static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1482 {
1483         unsigned long flags;
1484
1485         spin_lock_irqsave(&speakup_info.spinlock, flags);
1486         if (cursor_track == read_all_mode) {
1487                 spk_parked &= 0xfe;
1488                 if (synth == NULL || up_flag || spk_shut_up) {
1489                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1490                         return NOTIFY_STOP;
1491                 }
1492                 del_timer(&cursor_timer);
1493                 spk_shut_up &= 0xfe;
1494                 spk_do_flush();
1495                 start_read_all_timer(vc, value + 1);
1496                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1497                 return NOTIFY_STOP;
1498         }
1499         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1500         return NOTIFY_OK;
1501 }
1502
1503 static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1504 {
1505         unsigned long flags;
1506         struct var_t *cursor_timeout;
1507
1508         spin_lock_irqsave(&speakup_info.spinlock, flags);
1509         spk_parked &= 0xfe;
1510         if (synth == NULL || up_flag || spk_shut_up || cursor_track == CT_Off) {
1511                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1512                 return;
1513         }
1514         spk_shut_up &= 0xfe;
1515         if (spk_no_intr)
1516                 spk_do_flush();
1517 /* the key press flushes if !no_inter but we want to flush on cursor
1518  * moves regardless of no_inter state
1519  */
1520         is_cursor = value + 1;
1521         old_cursor_pos = vc->vc_pos;
1522         old_cursor_x = vc->vc_x;
1523         old_cursor_y = vc->vc_y;
1524         speakup_console[vc->vc_num]->ht.cy = vc->vc_y;
1525         cursor_con = vc->vc_num;
1526         if (cursor_track == CT_Highlight)
1527                 reset_highlight_buffers(vc);
1528         cursor_timeout = spk_get_var(CURSOR_TIME);
1529         mod_timer(&cursor_timer,
1530                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1531         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1532 }
1533
1534 static void update_color_buffer(struct vc_data *vc, const char *ic, int len)
1535 {
1536         int i, bi, hi;
1537         int vc_num = vc->vc_num;
1538
1539         bi = (vc->vc_attr & 0x70) >> 4;
1540         hi = speakup_console[vc_num]->ht.highsize[bi];
1541
1542         i = 0;
1543         if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1544                 speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
1545                 speakup_console[vc_num]->ht.rx[bi] = vc->vc_x;
1546                 speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;
1547         }
1548         while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
1549                 if ((ic[i] > 32) && (ic[i] < 127)) {
1550                         speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
1551                         hi++;
1552                 } else if ((ic[i] == 32) && (hi != 0)) {
1553                         if (speakup_console[vc_num]->ht.highbuf[bi][hi - 1] !=
1554                             32) {
1555                                 speakup_console[vc_num]->ht.highbuf[bi][hi] =
1556                                     ic[i];
1557                                 hi++;
1558                         }
1559                 }
1560                 i++;
1561         }
1562         speakup_console[vc_num]->ht.highsize[bi] = hi;
1563 }
1564
1565 static void reset_highlight_buffers(struct vc_data *vc)
1566 {
1567         int i;
1568         int vc_num = vc->vc_num;
1569
1570         for (i = 0; i < 8; i++)
1571                 speakup_console[vc_num]->ht.highsize[i] = 0;
1572 }
1573
1574 static int count_highlight_color(struct vc_data *vc)
1575 {
1576         int i, bg;
1577         int cc;
1578         int vc_num = vc->vc_num;
1579         u16 ch;
1580         u16 *start = (u16 *) vc->vc_origin;
1581
1582         for (i = 0; i < 8; i++)
1583                 speakup_console[vc_num]->ht.bgcount[i] = 0;
1584
1585         for (i = 0; i < vc->vc_rows; i++) {
1586                 u16 *end = start + vc->vc_cols * 2;
1587                 u16 *ptr;
1588
1589                 for (ptr = start; ptr < end; ptr++) {
1590                         ch = get_attributes(vc, ptr);
1591                         bg = (ch & 0x70) >> 4;
1592                         speakup_console[vc_num]->ht.bgcount[bg]++;
1593                 }
1594                 start += vc->vc_size_row;
1595         }
1596
1597         cc = 0;
1598         for (i = 0; i < 8; i++)
1599                 if (speakup_console[vc_num]->ht.bgcount[i] > 0)
1600                         cc++;
1601         return cc;
1602 }
1603
1604 static int get_highlight_color(struct vc_data *vc)
1605 {
1606         int i, j;
1607         unsigned int cptr[8];
1608         int vc_num = vc->vc_num;
1609
1610         for (i = 0; i < 8; i++)
1611                 cptr[i] = i;
1612
1613         for (i = 0; i < 7; i++)
1614                 for (j = i + 1; j < 8; j++)
1615                         if (speakup_console[vc_num]->ht.bgcount[cptr[i]] >
1616                             speakup_console[vc_num]->ht.bgcount[cptr[j]])
1617                                 swap(cptr[i], cptr[j]);
1618
1619         for (i = 0; i < 8; i++)
1620                 if (speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
1621                         if (speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
1622                                 return cptr[i];
1623         return -1;
1624 }
1625
1626 static int speak_highlight(struct vc_data *vc)
1627 {
1628         int hc, d;
1629         int vc_num = vc->vc_num;
1630
1631         if (count_highlight_color(vc) == 1)
1632                 return 0;
1633         hc = get_highlight_color(vc);
1634         if (hc != -1) {
1635                 d = vc->vc_y - speakup_console[vc_num]->ht.cy;
1636                 if ((d == 1) || (d == -1))
1637                         if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y)
1638                                 return 0;
1639                 spk_parked |= 0x01;
1640                 spk_do_flush();
1641                 spkup_write(speakup_console[vc_num]->ht.highbuf[hc],
1642                             speakup_console[vc_num]->ht.highsize[hc]);
1643                 spk_pos = spk_cp = speakup_console[vc_num]->ht.rpos[hc];
1644                 spk_x = spk_cx = speakup_console[vc_num]->ht.rx[hc];
1645                 spk_y = spk_cy = speakup_console[vc_num]->ht.ry[hc];
1646                 return 1;
1647         }
1648         return 0;
1649 }
1650
1651 static void cursor_done(u_long data)
1652 {
1653         struct vc_data *vc = vc_cons[cursor_con].d;
1654         unsigned long flags;
1655
1656         del_timer(&cursor_timer);
1657         spin_lock_irqsave(&speakup_info.spinlock, flags);
1658         if (cursor_con != fg_console) {
1659                 is_cursor = 0;
1660                 goto out;
1661         }
1662         speakup_date(vc);
1663         if (win_enabled) {
1664                 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
1665                     vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
1666                         spk_keydown = 0;
1667                         is_cursor = 0;
1668                         goto out;
1669                 }
1670         }
1671         if (cursor_track == read_all_mode) {
1672                 handle_cursor_read_all(vc, read_all_key);
1673                 goto out;
1674         }
1675         if (cursor_track == CT_Highlight) {
1676                 if (speak_highlight(vc)) {
1677                         spk_keydown = 0;
1678                         is_cursor = 0;
1679                         goto out;
1680                 }
1681         }
1682         if (cursor_track == CT_Window)
1683                 speakup_win_say(vc);
1684         else if (is_cursor == 1 || is_cursor == 4)
1685                 say_line_from_to(vc, 0, vc->vc_cols, 0);
1686         else
1687                 say_char(vc);
1688         spk_keydown = 0;
1689         is_cursor = 0;
1690 out:
1691         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1692 }
1693
1694 /* called by: vt_notifier_call() */
1695 static void speakup_bs(struct vc_data *vc)
1696 {
1697         unsigned long flags;
1698
1699         if (!speakup_console[vc->vc_num])
1700                 return;
1701         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1702                 /* Speakup output, discard */
1703                 return;
1704         if (!spk_parked)
1705                 speakup_date(vc);
1706         if (spk_shut_up || synth == NULL) {
1707                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1708                 return;
1709         }
1710         if (vc->vc_num == fg_console && spk_keydown) {
1711                 spk_keydown = 0;
1712                 if (!is_cursor)
1713                         say_char(vc);
1714         }
1715         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1716 }
1717
1718 /* called by: vt_notifier_call() */
1719 static void speakup_con_write(struct vc_data *vc, const char *str, int len)
1720 {
1721         unsigned long flags;
1722
1723         if ((vc->vc_num != fg_console) || spk_shut_up || synth == NULL)
1724                 return;
1725         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1726                 /* Speakup output, discard */
1727                 return;
1728         if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1))
1729                 bleep(3);
1730         if ((is_cursor) || (cursor_track == read_all_mode)) {
1731                 if (cursor_track == CT_Highlight)
1732                         update_color_buffer(vc, str, len);
1733                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1734                 return;
1735         }
1736         if (win_enabled) {
1737                 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
1738                     vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
1739                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1740                         return;
1741                 }
1742         }
1743
1744         spkup_write(str, len);
1745         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1746 }
1747
1748 static void speakup_con_update(struct vc_data *vc)
1749 {
1750         unsigned long flags;
1751
1752         if (speakup_console[vc->vc_num] == NULL || spk_parked)
1753                 return;
1754         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1755                 /* Speakup output, discard */
1756                 return;
1757         speakup_date(vc);
1758         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1759 }
1760
1761 static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag)
1762 {
1763         unsigned long flags;
1764         int on_off = 2;
1765         char *label;
1766
1767         if (synth == NULL || up_flag || spk_killed)
1768                 return;
1769         spin_lock_irqsave(&speakup_info.spinlock, flags);
1770         spk_shut_up &= 0xfe;
1771         if (spk_no_intr)
1772                 spk_do_flush();
1773         switch (value) {
1774         case KVAL(K_CAPS):
1775                 label = spk_msg_get(MSG_KEYNAME_CAPSLOCK);
1776                 on_off = vt_get_leds(fg_console, VC_CAPSLOCK);
1777                 break;
1778         case KVAL(K_NUM):
1779                 label = spk_msg_get(MSG_KEYNAME_NUMLOCK);
1780                 on_off = vt_get_leds(fg_console, VC_NUMLOCK);
1781                 break;
1782         case KVAL(K_HOLD):
1783                 label = spk_msg_get(MSG_KEYNAME_SCROLLLOCK);
1784                 on_off = vt_get_leds(fg_console, VC_SCROLLOCK);
1785                 if (speakup_console[vc->vc_num])
1786                         speakup_console[vc->vc_num]->tty_stopped = on_off;
1787                 break;
1788         default:
1789                 spk_parked &= 0xfe;
1790                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1791                 return;
1792         }
1793         if (on_off < 2)
1794                 synth_printf("%s %s\n",
1795                              label, spk_msg_get(MSG_STATUS_START + on_off));
1796         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1797 }
1798
1799 static int inc_dec_var(u_char value)
1800 {
1801         struct st_var_header *p_header;
1802         struct var_t *var_data;
1803         char num_buf[32];
1804         char *cp = num_buf;
1805         char *pn;
1806         int var_id = (int)value - VAR_START;
1807         int how = (var_id & 1) ? E_INC : E_DEC;
1808
1809         var_id = var_id / 2 + FIRST_SET_VAR;
1810         p_header = spk_get_var_header(var_id);
1811         if (p_header == NULL)
1812                 return -1;
1813         if (p_header->var_type != VAR_NUM)
1814                 return -1;
1815         var_data = p_header->data;
1816         if (spk_set_num_var(1, p_header, how) != 0)
1817                 return -1;
1818         if (!spk_close_press) {
1819                 for (pn = p_header->name; *pn; pn++) {
1820                         if (*pn == '_')
1821                                 *cp = SPACE;
1822                         else
1823                                 *cp++ = *pn;
1824                 }
1825         }
1826         snprintf(cp, sizeof(num_buf) - (cp - num_buf), " %d ",
1827                  var_data->u.n.value);
1828         synth_printf("%s", num_buf);
1829         return 0;
1830 }
1831
1832 static void speakup_win_set(struct vc_data *vc)
1833 {
1834         char info[40];
1835
1836         if (win_start > 1) {
1837                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_ALREADY_SET));
1838                 return;
1839         }
1840         if (spk_x < win_left || spk_y < win_top) {
1841                 synth_printf("%s\n", spk_msg_get(MSG_END_BEFORE_START));
1842                 return;
1843         }
1844         if (win_start && spk_x == win_left && spk_y == win_top) {
1845                 win_left = 0;
1846                 win_right = vc->vc_cols - 1;
1847                 win_bottom = spk_y;
1848                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_LINE),
1849                          (int)win_top + 1);
1850         } else {
1851                 if (!win_start) {
1852                         win_top = spk_y;
1853                         win_left = spk_x;
1854                 } else {
1855                         win_bottom = spk_y;
1856                         win_right = spk_x;
1857                 }
1858                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_BOUNDARY),
1859                          (win_start) ?
1860                                 spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
1861                          (int)spk_y + 1, (int)spk_x + 1);
1862         }
1863         synth_printf("%s\n", info);
1864         win_start++;
1865 }
1866
1867 static void speakup_win_clear(struct vc_data *vc)
1868 {
1869         win_top = 0;
1870         win_bottom = 0;
1871         win_left = 0;
1872         win_right = 0;
1873         win_start = 0;
1874         synth_printf("%s\n", spk_msg_get(MSG_WINDOW_CLEARED));
1875 }
1876
1877 static void speakup_win_enable(struct vc_data *vc)
1878 {
1879         if (win_start < 2) {
1880                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
1881                 return;
1882         }
1883         win_enabled ^= 1;
1884         if (win_enabled)
1885                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCED));
1886         else
1887                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCE_DISABLED));
1888 }
1889
1890 static void speakup_bits(struct vc_data *vc)
1891 {
1892         int val = this_speakup_key - (FIRST_EDIT_BITS - 1);
1893
1894         if (spk_special_handler != NULL || val < 1 || val > 6) {
1895                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1896                 return;
1897         }
1898         pb_edit = &spk_punc_info[val];
1899         synth_printf(spk_msg_get(MSG_EDIT_PROMPT), pb_edit->name);
1900         spk_special_handler = edit_bits;
1901 }
1902
1903 static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
1904 {
1905         static u_char goto_buf[8];
1906         static int num;
1907         int maxlen;
1908         char *cp;
1909
1910         if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
1911                 goto do_goto;
1912         if (type == KT_LATIN && ch == '\n')
1913                 goto do_goto;
1914         if (type != 0)
1915                 goto oops;
1916         if (ch == 8) {
1917                 if (num == 0)
1918                         return -1;
1919                 ch = goto_buf[--num];
1920                 goto_buf[num] = '\0';
1921                 spkup_write(&ch, 1);
1922                 return 1;
1923         }
1924         if (ch < '+' || ch > 'y')
1925                 goto oops;
1926         goto_buf[num++] = ch;
1927         goto_buf[num] = '\0';
1928         spkup_write(&ch, 1);
1929         maxlen = (*goto_buf >= '0') ? 3 : 4;
1930         if ((ch == '+' || ch == '-') && num == 1)
1931                 return 1;
1932         if (ch >= '0' && ch <= '9' && num < maxlen)
1933                 return 1;
1934         if (num < maxlen - 1 || num > maxlen)
1935                 goto oops;
1936         if (ch < 'x' || ch > 'y') {
1937 oops:
1938                 if (!spk_killed)
1939                         synth_printf(" %s\n", spk_msg_get(MSG_GOTO_CANCELED));
1940                 goto_buf[num = 0] = '\0';
1941                 spk_special_handler = NULL;
1942                 return 1;
1943         }
1944
1945         goto_pos = simple_strtoul(goto_buf, &cp, 10);
1946
1947         if (*cp == 'x') {
1948                 if (*goto_buf < '0')
1949                         goto_pos += spk_x;
1950                 else if (goto_pos > 0)
1951                         goto_pos--;
1952
1953                 if (goto_pos >= vc->vc_cols)
1954                         goto_pos = vc->vc_cols - 1;
1955                 goto_x = 1;
1956         } else {
1957                 if (*goto_buf < '0')
1958                         goto_pos += spk_y;
1959                 else if (goto_pos > 0)
1960                         goto_pos--;
1961
1962                 if (goto_pos >= vc->vc_rows)
1963                         goto_pos = vc->vc_rows - 1;
1964                 goto_x = 0;
1965         }
1966         goto_buf[num = 0] = '\0';
1967 do_goto:
1968         spk_special_handler = NULL;
1969         spk_parked |= 0x01;
1970         if (goto_x) {
1971                 spk_pos -= spk_x * 2;
1972                 spk_x = goto_pos;
1973                 spk_pos += goto_pos * 2;
1974                 say_word(vc);
1975         } else {
1976                 spk_y = goto_pos;
1977                 spk_pos = vc->vc_origin + (goto_pos * vc->vc_size_row);
1978                 say_line(vc);
1979         }
1980         return 1;
1981 }
1982
1983 static void speakup_goto(struct vc_data *vc)
1984 {
1985         if (spk_special_handler != NULL) {
1986                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1987                 return;
1988         }
1989         synth_printf("%s\n", spk_msg_get(MSG_GOTO));
1990         spk_special_handler = handle_goto;
1991 }
1992
1993 static void speakup_help(struct vc_data *vc)
1994 {
1995         spk_handle_help(vc, KT_SPKUP, SPEAKUP_HELP, 0);
1996 }
1997
1998 static void do_nothing(struct vc_data *vc)
1999 {
2000         return;                 /* flush done in do_spkup */
2001 }
2002
2003 static u_char key_speakup, spk_key_locked;
2004
2005 static void speakup_lock(struct vc_data *vc)
2006 {
2007         if (!spk_key_locked) {
2008                 spk_key_locked = 16;
2009                 key_speakup = 16;
2010         } else {
2011                 spk_key_locked = 0;
2012                 key_speakup = 0;
2013         }
2014 }
2015
2016 typedef void (*spkup_hand) (struct vc_data *);
2017 static spkup_hand spkup_handler[] = {
2018         /* must be ordered same as defines in speakup.h */
2019         do_nothing, speakup_goto, speech_kill, speakup_shut_up,
2020         speakup_cut, speakup_paste, say_first_char, say_last_char,
2021         say_char, say_prev_char, say_next_char,
2022         say_word, say_prev_word, say_next_word,
2023         say_line, say_prev_line, say_next_line,
2024         top_edge, bottom_edge, left_edge, right_edge,
2025         spell_word, spell_word, say_screen,
2026         say_position, say_attributes,
2027         speakup_off, speakup_parked, say_line,  /* this is for indent */
2028         say_from_top, say_to_bottom,
2029         say_from_left, say_to_right,
2030         say_char_num, speakup_bits, speakup_bits, say_phonetic_char,
2031         speakup_bits, speakup_bits, speakup_bits,
2032         speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say,
2033         speakup_lock, speakup_help, toggle_cursoring, read_all_doc, NULL
2034 };
2035
2036 static void do_spkup(struct vc_data *vc, u_char value)
2037 {
2038         if (spk_killed && value != SPEECH_KILL)
2039                 return;
2040         spk_keydown = 0;
2041         spk_lastkey = 0;
2042         spk_shut_up &= 0xfe;
2043         this_speakup_key = value;
2044         if (value < SPKUP_MAX_FUNC && spkup_handler[value]) {
2045                 spk_do_flush();
2046                 (*spkup_handler[value]) (vc);
2047         } else {
2048                 if (inc_dec_var(value) < 0)
2049                         bleep(9);
2050         }
2051 }
2052
2053 static const char *pad_chars = "0123456789+-*/\015,.?()";
2054
2055 static int
2056 speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym,
2057             int up_flag)
2058 {
2059         unsigned long flags;
2060         int kh;
2061         u_char *key_info;
2062         u_char type = KTYP(keysym), value = KVAL(keysym), new_key = 0;
2063         u_char shift_info, offset;
2064         int ret = 0;
2065
2066         if (synth == NULL)
2067                 return 0;
2068
2069         spin_lock_irqsave(&speakup_info.spinlock, flags);
2070         tty = vc->port.tty;
2071         if (type >= 0xf0)
2072                 type -= 0xf0;
2073         if (type == KT_PAD
2074                 && (vt_get_leds(fg_console, VC_NUMLOCK))) {
2075                 if (up_flag) {
2076                         spk_keydown = 0;
2077                         goto out;
2078                 }
2079                 value = spk_lastkey = pad_chars[value];
2080                 spk_keydown++;
2081                 spk_parked &= 0xfe;
2082                 goto no_map;
2083         }
2084         if (keycode >= MAX_KEY)
2085                 goto no_map;
2086         key_info = spk_our_keys[keycode];
2087         if (!key_info)
2088                 goto no_map;
2089         /* Check valid read all mode keys */
2090         if ((cursor_track == read_all_mode) && (!up_flag)) {
2091                 switch (value) {
2092                 case KVAL(K_DOWN):
2093                 case KVAL(K_UP):
2094                 case KVAL(K_LEFT):
2095                 case KVAL(K_RIGHT):
2096                 case KVAL(K_PGUP):
2097                 case KVAL(K_PGDN):
2098                         break;
2099                 default:
2100                         stop_read_all(vc);
2101                         break;
2102                 }
2103         }
2104         shift_info = (shift_state & 0x0f) + key_speakup;
2105         offset = spk_shift_table[shift_info];
2106         if (offset) {
2107                 new_key = key_info[offset];
2108                 if (new_key) {
2109                         ret = 1;
2110                         if (new_key == SPK_KEY) {
2111                                 if (!spk_key_locked)
2112                                         key_speakup = (up_flag) ? 0 : 16;
2113                                 if (up_flag || spk_killed)
2114                                         goto out;
2115                                 spk_shut_up &= 0xfe;
2116                                 spk_do_flush();
2117                                 goto out;
2118                         }
2119                         if (up_flag)
2120                                 goto out;
2121                         if (last_keycode == keycode &&
2122                             time_after(last_spk_jiffy + MAX_DELAY, jiffies)) {
2123                                 spk_close_press = 1;
2124                                 offset = spk_shift_table[shift_info + 32];
2125                                 /* double press? */
2126                                 if (offset && key_info[offset])
2127                                         new_key = key_info[offset];
2128                         }
2129                         last_keycode = keycode;
2130                         last_spk_jiffy = jiffies;
2131                         type = KT_SPKUP;
2132                         value = new_key;
2133                 }
2134         }
2135 no_map:
2136         if (type == KT_SPKUP && spk_special_handler == NULL) {
2137                 do_spkup(vc, new_key);
2138                 spk_close_press = 0;
2139                 ret = 1;
2140                 goto out;
2141         }
2142         if (up_flag || spk_killed || type == KT_SHIFT)
2143                 goto out;
2144         spk_shut_up &= 0xfe;
2145         kh = (value == KVAL(K_DOWN))
2146             || (value == KVAL(K_UP))
2147             || (value == KVAL(K_LEFT))
2148             || (value == KVAL(K_RIGHT));
2149         if ((cursor_track != read_all_mode) || !kh)
2150                 if (!spk_no_intr)
2151                         spk_do_flush();
2152         if (spk_special_handler) {
2153                 if (type == KT_SPEC && value == 1) {
2154                         value = '\n';
2155                         type = KT_LATIN;
2156                 } else if (type == KT_LETTER)
2157                         type = KT_LATIN;
2158                 else if (value == 0x7f)
2159                         value = 8;      /* make del = backspace */
2160                 ret = (*spk_special_handler) (vc, type, value, keycode);
2161                 spk_close_press = 0;
2162                 if (ret < 0)
2163                         bleep(9);
2164                 goto out;
2165         }
2166         last_keycode = 0;
2167 out:
2168         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
2169         return ret;
2170 }
2171
2172 static int keyboard_notifier_call(struct notifier_block *nb,
2173                                   unsigned long code, void *_param)
2174 {
2175         struct keyboard_notifier_param *param = _param;
2176         struct vc_data *vc = param->vc;
2177         int up = !param->down;
2178         int ret = NOTIFY_OK;
2179         static int keycode;     /* to hold the current keycode */
2180
2181         if (vc->vc_mode == KD_GRAPHICS)
2182                 return ret;
2183
2184         /*
2185          * First, determine whether we are handling a fake keypress on
2186          * the current processor.  If we are, then return NOTIFY_OK,
2187          * to pass the keystroke up the chain.  This prevents us from
2188          * trying to take the Speakup lock while it is held by the
2189          * processor on which the simulated keystroke was generated.
2190          * Also, the simulated keystrokes should be ignored by Speakup.
2191          */
2192
2193         if (speakup_fake_key_pressed())
2194                 return ret;
2195
2196         switch (code) {
2197         case KBD_KEYCODE:
2198                 /* speakup requires keycode and keysym currently */
2199                 keycode = param->value;
2200                 break;
2201         case KBD_UNBOUND_KEYCODE:
2202                 /* not used yet */
2203                 break;
2204         case KBD_UNICODE:
2205                 /* not used yet */
2206                 break;
2207         case KBD_KEYSYM:
2208                 if (speakup_key(vc, param->shift, keycode, param->value, up))
2209                         ret = NOTIFY_STOP;
2210                 else if (KTYP(param->value) == KT_CUR)
2211                         ret = pre_handle_cursor(vc, KVAL(param->value), up);
2212                 break;
2213         case KBD_POST_KEYSYM:{
2214                         unsigned char type = KTYP(param->value) - 0xf0;
2215                         unsigned char val = KVAL(param->value);
2216
2217                         switch (type) {
2218                         case KT_SHIFT:
2219                                 do_handle_shift(vc, val, up);
2220                                 break;
2221                         case KT_LATIN:
2222                         case KT_LETTER:
2223                                 do_handle_latin(vc, val, up);
2224                                 break;
2225                         case KT_CUR:
2226                                 do_handle_cursor(vc, val, up);
2227                                 break;
2228                         case KT_SPEC:
2229                                 do_handle_spec(vc, val, up);
2230                                 break;
2231                         }
2232                         break;
2233                 }
2234         }
2235         return ret;
2236 }
2237
2238 static int vt_notifier_call(struct notifier_block *nb,
2239                             unsigned long code, void *_param)
2240 {
2241         struct vt_notifier_param *param = _param;
2242         struct vc_data *vc = param->vc;
2243
2244         switch (code) {
2245         case VT_ALLOCATE:
2246                 if (vc->vc_mode == KD_TEXT)
2247                         speakup_allocate(vc);
2248                 break;
2249         case VT_DEALLOCATE:
2250                 speakup_deallocate(vc);
2251                 break;
2252         case VT_WRITE:
2253                 if (param->c == '\b')
2254                         speakup_bs(vc);
2255                 else if (param->c < 0x100) {
2256                         char d = param->c;
2257
2258                         speakup_con_write(vc, &d, 1);
2259                 }
2260                 break;
2261         case VT_UPDATE:
2262                 speakup_con_update(vc);
2263                 break;
2264         }
2265         return NOTIFY_OK;
2266 }
2267
2268 /* called by: module_exit() */
2269 static void __exit speakup_exit(void)
2270 {
2271         int i;
2272
2273         unregister_keyboard_notifier(&keyboard_notifier_block);
2274         unregister_vt_notifier(&vt_notifier_block);
2275         speakup_unregister_devsynth();
2276         speakup_cancel_paste();
2277         del_timer(&cursor_timer);
2278         kthread_stop(speakup_task);
2279         speakup_task = NULL;
2280         mutex_lock(&spk_mutex);
2281         synth_release();
2282         mutex_unlock(&spk_mutex);
2283
2284         speakup_kobj_exit();
2285
2286         for (i = 0; i < MAX_NR_CONSOLES; i++)
2287                 kfree(speakup_console[i]);
2288
2289         speakup_remove_virtual_keyboard();
2290
2291         for (i = 0; i < MAXVARS; i++)
2292                 speakup_unregister_var(i);
2293
2294         for (i = 0; i < 256; i++) {
2295                 if (spk_characters[i] != spk_default_chars[i])
2296                         kfree(spk_characters[i]);
2297         }
2298
2299         spk_free_user_msgs();
2300 }
2301
2302 /* call by: module_init() */
2303 static int __init speakup_init(void)
2304 {
2305         int i;
2306         long err = 0;
2307         struct st_spk_t *first_console;
2308         struct vc_data *vc = vc_cons[fg_console].d;
2309         struct var_t *var;
2310
2311         /* These first few initializations cannot fail. */
2312         spk_initialize_msgs();  /* Initialize arrays for i18n. */
2313         spk_reset_default_chars();
2314         spk_reset_default_chartab();
2315         spk_strlwr(synth_name);
2316         spk_vars[0].u.n.high = vc->vc_cols;
2317         for (var = spk_vars; var->var_id != MAXVARS; var++)
2318                 speakup_register_var(var);
2319         for (var = synth_time_vars;
2320              (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
2321                 speakup_register_var(var);
2322         for (i = 1; spk_punc_info[i].mask != 0; i++)
2323                 spk_set_mask_bits(NULL, i, 2);
2324
2325         spk_set_key_info(spk_key_defaults, spk_key_buf);
2326
2327         /* From here on out, initializations can fail. */
2328         err = speakup_add_virtual_keyboard();
2329         if (err)
2330                 goto error_virtkeyboard;
2331
2332         first_console = kzalloc(sizeof(*first_console), GFP_KERNEL);
2333         if (!first_console) {
2334                 err = -ENOMEM;
2335                 goto error_alloc;
2336         }
2337
2338         speakup_console[vc->vc_num] = first_console;
2339         speakup_date(vc);
2340
2341         for (i = 0; i < MAX_NR_CONSOLES; i++)
2342                 if (vc_cons[i].d) {
2343                         err = speakup_allocate(vc_cons[i].d);
2344                         if (err)
2345                                 goto error_kobjects;
2346                 }
2347
2348         if (spk_quiet_boot)
2349                 spk_shut_up |= 0x01;
2350
2351         err = speakup_kobj_init();
2352         if (err)
2353                 goto error_kobjects;
2354
2355         synth_init(synth_name);
2356         speakup_register_devsynth();
2357         /*
2358          * register_devsynth might fail, but this error is not fatal.
2359          * /dev/synth is an extra feature; the rest of Speakup
2360          * will work fine without it.
2361          */
2362
2363         err = register_keyboard_notifier(&keyboard_notifier_block);
2364         if (err)
2365                 goto error_kbdnotifier;
2366         err = register_vt_notifier(&vt_notifier_block);
2367         if (err)
2368                 goto error_vtnotifier;
2369
2370         speakup_task = kthread_create(speakup_thread, NULL, "speakup");
2371
2372         if (IS_ERR(speakup_task)) {
2373                 err = PTR_ERR(speakup_task);
2374                 goto error_task;
2375         }
2376
2377         set_user_nice(speakup_task, 10);
2378         wake_up_process(speakup_task);
2379
2380         pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
2381         pr_info("synth name on entry is: %s\n", synth_name);
2382         goto out;
2383
2384 error_task:
2385         unregister_vt_notifier(&vt_notifier_block);
2386
2387 error_vtnotifier:
2388         unregister_keyboard_notifier(&keyboard_notifier_block);
2389         del_timer(&cursor_timer);
2390
2391 error_kbdnotifier:
2392         speakup_unregister_devsynth();
2393         mutex_lock(&spk_mutex);
2394         synth_release();
2395         mutex_unlock(&spk_mutex);
2396         speakup_kobj_exit();
2397
2398 error_kobjects:
2399         for (i = 0; i < MAX_NR_CONSOLES; i++)
2400                 kfree(speakup_console[i]);
2401
2402 error_alloc:
2403         speakup_remove_virtual_keyboard();
2404
2405 error_virtkeyboard:
2406         for (i = 0; i < MAXVARS; i++)
2407                 speakup_unregister_var(i);
2408
2409         for (i = 0; i < 256; i++) {
2410                 if (spk_characters[i] != spk_default_chars[i])
2411                         kfree(spk_characters[i]);
2412         }
2413
2414         spk_free_user_msgs();
2415
2416 out:
2417         return err;
2418 }
2419
2420 module_init(speakup_init);
2421 module_exit(speakup_exit);