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