Merge branch 'stacking-fixes' (vfs stacking fixes from Jann)
[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 (scr_readw(pos) & ~vc->vc_hi_font_mask) >> 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                         w &= ~vc->vc_hi_font_mask;
478                         c |= 0x100;
479                 }
480
481                 ch = inverse_translate(vc, c, 0);
482                 *attribs = (w & 0xff00) >> 8;
483         }
484         return ch;
485 }
486
487 static void say_char(struct vc_data *vc)
488 {
489         u_short ch;
490
491         spk_old_attr = spk_attr;
492         ch = get_char(vc, (u_short *) spk_pos, &spk_attr);
493         if (spk_attr != spk_old_attr) {
494                 if (spk_attrib_bleep & 1)
495                         bleep(spk_y);
496                 if (spk_attrib_bleep & 2)
497                         say_attributes(vc);
498         }
499         speak_char(ch & 0xff);
500 }
501
502 static void say_phonetic_char(struct vc_data *vc)
503 {
504         u_short ch;
505
506         spk_old_attr = spk_attr;
507         ch = get_char(vc, (u_short *) spk_pos, &spk_attr);
508         if (isascii(ch) && isalpha(ch)) {
509                 ch &= 0x1f;
510                 synth_printf("%s\n", phonetic[--ch]);
511         } else {
512                 if (IS_CHAR(ch, B_NUM))
513                         synth_printf("%s ", spk_msg_get(MSG_NUMBER));
514                 speak_char(ch);
515         }
516 }
517
518 static void say_prev_char(struct vc_data *vc)
519 {
520         spk_parked |= 0x01;
521         if (spk_x == 0) {
522                 announce_edge(vc, edge_left);
523                 return;
524         }
525         spk_x--;
526         spk_pos -= 2;
527         say_char(vc);
528 }
529
530 static void say_next_char(struct vc_data *vc)
531 {
532         spk_parked |= 0x01;
533         if (spk_x == vc->vc_cols - 1) {
534                 announce_edge(vc, edge_right);
535                 return;
536         }
537         spk_x++;
538         spk_pos += 2;
539         say_char(vc);
540 }
541
542 /* get_word - will first check to see if the character under the
543  * reading cursor is a space and if spk_say_word_ctl is true it will
544  * return the word space.  If spk_say_word_ctl is not set it will check to
545  * see if there is a word starting on the next position to the right
546  * and return that word if it exists.  If it does not exist it will
547  * move left to the beginning of any previous word on the line or the
548  * beginning off the line whichever comes first..
549  */
550
551 static u_long get_word(struct vc_data *vc)
552 {
553         u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
554         char ch;
555         u_short attr_ch;
556         u_char temp;
557
558         spk_old_attr = spk_attr;
559         ch = (char)get_char(vc, (u_short *) tmp_pos, &temp);
560
561 /* decided to take out the sayword if on a space (mis-information */
562         if (spk_say_word_ctl && ch == SPACE) {
563                 *buf = '\0';
564                 synth_printf("%s\n", spk_msg_get(MSG_SPACE));
565                 return 0;
566         } else if ((tmpx < vc->vc_cols - 2)
567                    && (ch == SPACE || ch == 0 || IS_WDLM(ch))
568                    && ((char)get_char(vc, (u_short *) &tmp_pos + 1, &temp) >
569                        SPACE)) {
570                 tmp_pos += 2;
571                 tmpx++;
572         } else
573                 while (tmpx > 0) {
574                         ch = (char)get_char(vc, (u_short *) tmp_pos - 1, &temp);
575                         if ((ch == SPACE || ch == 0 || IS_WDLM(ch))
576                             && ((char)get_char(vc, (u_short *) tmp_pos, &temp) >
577                                 SPACE))
578                                 break;
579                         tmp_pos -= 2;
580                         tmpx--;
581                 }
582         attr_ch = get_char(vc, (u_short *) tmp_pos, &spk_attr);
583         buf[cnt++] = attr_ch & 0xff;
584         while (tmpx < vc->vc_cols - 1) {
585                 tmp_pos += 2;
586                 tmpx++;
587                 ch = (char)get_char(vc, (u_short *) tmp_pos, &temp);
588                 if ((ch == SPACE) || ch == 0
589                     || (IS_WDLM(buf[cnt - 1]) && (ch > SPACE)))
590                         break;
591                 buf[cnt++] = ch;
592         }
593         buf[cnt] = '\0';
594         return cnt;
595 }
596
597 static void say_word(struct vc_data *vc)
598 {
599         u_long cnt = get_word(vc);
600         u_short saved_punc_mask = spk_punc_mask;
601
602         if (cnt == 0)
603                 return;
604         spk_punc_mask = PUNC;
605         buf[cnt++] = SPACE;
606         spkup_write(buf, cnt);
607         spk_punc_mask = saved_punc_mask;
608 }
609
610 static void say_prev_word(struct vc_data *vc)
611 {
612         u_char temp;
613         char ch;
614         u_short edge_said = 0, last_state = 0, state = 0;
615
616         spk_parked |= 0x01;
617
618         if (spk_x == 0) {
619                 if (spk_y == 0) {
620                         announce_edge(vc, edge_top);
621                         return;
622                 }
623                 spk_y--;
624                 spk_x = vc->vc_cols;
625                 edge_said = edge_quiet;
626         }
627         while (1) {
628                 if (spk_x == 0) {
629                         if (spk_y == 0) {
630                                 edge_said = edge_top;
631                                 break;
632                         }
633                         if (edge_said != edge_quiet)
634                                 edge_said = edge_left;
635                         if (state > 0)
636                                 break;
637                         spk_y--;
638                         spk_x = vc->vc_cols - 1;
639                 } else
640                         spk_x--;
641                 spk_pos -= 2;
642                 ch = (char)get_char(vc, (u_short *) spk_pos, &temp);
643                 if (ch == SPACE || ch == 0)
644                         state = 0;
645                 else if (IS_WDLM(ch))
646                         state = 1;
647                 else
648                         state = 2;
649                 if (state < last_state) {
650                         spk_pos += 2;
651                         spk_x++;
652                         break;
653                 }
654                 last_state = state;
655         }
656         if (spk_x == 0 && edge_said == edge_quiet)
657                 edge_said = edge_left;
658         if (edge_said > 0 && edge_said < edge_quiet)
659                 announce_edge(vc, edge_said);
660         say_word(vc);
661 }
662
663 static void say_next_word(struct vc_data *vc)
664 {
665         u_char temp;
666         char ch;
667         u_short edge_said = 0, last_state = 2, state = 0;
668
669         spk_parked |= 0x01;
670         if (spk_x == vc->vc_cols - 1 && spk_y == vc->vc_rows - 1) {
671                 announce_edge(vc, edge_bottom);
672                 return;
673         }
674         while (1) {
675                 ch = (char)get_char(vc, (u_short *) spk_pos, &temp);
676                 if (ch == SPACE || ch == 0)
677                         state = 0;
678                 else if (IS_WDLM(ch))
679                         state = 1;
680                 else
681                         state = 2;
682                 if (state > last_state)
683                         break;
684                 if (spk_x >= vc->vc_cols - 1) {
685                         if (spk_y == vc->vc_rows - 1) {
686                                 edge_said = edge_bottom;
687                                 break;
688                         }
689                         state = 0;
690                         spk_y++;
691                         spk_x = 0;
692                         edge_said = edge_right;
693                 } else
694                         spk_x++;
695                 spk_pos += 2;
696                 last_state = state;
697         }
698         if (edge_said > 0)
699                 announce_edge(vc, edge_said);
700         say_word(vc);
701 }
702
703 static void spell_word(struct vc_data *vc)
704 {
705         static char const *delay_str[] = { "", ",", ".", ". .", ". . ." };
706         char *cp = buf, *str_cap = spk_str_caps_stop;
707         char *cp1, *last_cap = spk_str_caps_stop;
708         u_char ch;
709
710         if (!get_word(vc))
711                 return;
712         while ((ch = (u_char) *cp)) {
713                 if (cp != buf)
714                         synth_printf(" %s ", delay_str[spk_spell_delay]);
715                 if (IS_CHAR(ch, B_CAP)) {
716                         str_cap = spk_str_caps_start;
717                         if (*spk_str_caps_stop)
718                                 spk_pitch_shift++;
719                         else    /* synth has no pitch */
720                                 last_cap = spk_str_caps_stop;
721                 } else
722                         str_cap = spk_str_caps_stop;
723                 if (str_cap != last_cap) {
724                         synth_printf("%s", str_cap);
725                         last_cap = str_cap;
726                 }
727                 if (this_speakup_key == SPELL_PHONETIC
728                     && (isascii(ch) && isalpha(ch))) {
729                         ch &= 31;
730                         cp1 = phonetic[--ch];
731                 } else {
732                         cp1 = spk_characters[ch];
733                         if (*cp1 == '^') {
734                                 synth_printf("%s", spk_msg_get(MSG_CTRL));
735                                 cp1++;
736                         }
737                 }
738                 synth_printf("%s", cp1);
739                 cp++;
740         }
741         if (str_cap != spk_str_caps_stop)
742                 synth_printf("%s", spk_str_caps_stop);
743 }
744
745 static int get_line(struct vc_data *vc)
746 {
747         u_long tmp = spk_pos - (spk_x * 2);
748         int i = 0;
749         u_char tmp2;
750
751         spk_old_attr = spk_attr;
752         spk_attr = get_attributes(vc, (u_short *)spk_pos);
753         for (i = 0; i < vc->vc_cols; i++) {
754                 buf[i] = (u_char) get_char(vc, (u_short *) tmp, &tmp2);
755                 tmp += 2;
756         }
757         for (--i; i >= 0; i--)
758                 if (buf[i] != SPACE)
759                         break;
760         return ++i;
761 }
762
763 static void say_line(struct vc_data *vc)
764 {
765         int i = get_line(vc);
766         char *cp;
767         u_short saved_punc_mask = spk_punc_mask;
768
769         if (i == 0) {
770                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
771                 return;
772         }
773         buf[i++] = '\n';
774         if (this_speakup_key == SAY_LINE_INDENT) {
775                 cp = buf;
776                 while (*cp == SPACE)
777                         cp++;
778                 synth_printf("%d, ", (cp - buf) + 1);
779         }
780         spk_punc_mask = spk_punc_masks[spk_reading_punc];
781         spkup_write(buf, i);
782         spk_punc_mask = saved_punc_mask;
783 }
784
785 static void say_prev_line(struct vc_data *vc)
786 {
787         spk_parked |= 0x01;
788         if (spk_y == 0) {
789                 announce_edge(vc, edge_top);
790                 return;
791         }
792         spk_y--;
793         spk_pos -= vc->vc_size_row;
794         say_line(vc);
795 }
796
797 static void say_next_line(struct vc_data *vc)
798 {
799         spk_parked |= 0x01;
800         if (spk_y == vc->vc_rows - 1) {
801                 announce_edge(vc, edge_bottom);
802                 return;
803         }
804         spk_y++;
805         spk_pos += vc->vc_size_row;
806         say_line(vc);
807 }
808
809 static int say_from_to(struct vc_data *vc, u_long from, u_long to,
810                        int read_punc)
811 {
812         int i = 0;
813         u_char tmp;
814         u_short saved_punc_mask = spk_punc_mask;
815
816         spk_old_attr = spk_attr;
817         spk_attr = get_attributes(vc, (u_short *)from);
818         while (from < to) {
819                 buf[i++] = (char)get_char(vc, (u_short *) from, &tmp);
820                 from += 2;
821                 if (i >= vc->vc_size_row)
822                         break;
823         }
824         for (--i; i >= 0; i--)
825                 if (buf[i] != SPACE)
826                         break;
827         buf[++i] = SPACE;
828         buf[++i] = '\0';
829         if (i < 1)
830                 return i;
831         if (read_punc)
832                 spk_punc_mask = spk_punc_info[spk_reading_punc].mask;
833         spkup_write(buf, i);
834         if (read_punc)
835                 spk_punc_mask = saved_punc_mask;
836         return i - 1;
837 }
838
839 static void say_line_from_to(struct vc_data *vc, u_long from, u_long to,
840                              int read_punc)
841 {
842         u_long start = vc->vc_origin + (spk_y * vc->vc_size_row);
843         u_long end = start + (to * 2);
844
845         start += from * 2;
846         if (say_from_to(vc, start, end, read_punc) <= 0)
847                 if (cursor_track != read_all_mode)
848                         synth_printf("%s\n", spk_msg_get(MSG_BLANK));
849 }
850
851 /* Sentence Reading Commands */
852
853 static int currsentence;
854 static int numsentences[2];
855 static char *sentbufend[2];
856 static char *sentmarks[2][10];
857 static int currbuf;
858 static int bn;
859 static char sentbuf[2][256];
860
861 static int say_sentence_num(int num, int prev)
862 {
863         bn = currbuf;
864         currsentence = num + 1;
865         if (prev && --bn == -1)
866                 bn = 1;
867
868         if (num > numsentences[bn])
869                 return 0;
870
871         spkup_write(sentmarks[bn][num], sentbufend[bn] - sentmarks[bn][num]);
872         return 1;
873 }
874
875 static int get_sentence_buf(struct vc_data *vc, int read_punc)
876 {
877         u_long start, end;
878         int i, bn;
879         u_char tmp;
880
881         currbuf++;
882         if (currbuf == 2)
883                 currbuf = 0;
884         bn = currbuf;
885         start = vc->vc_origin + ((spk_y) * vc->vc_size_row);
886         end = vc->vc_origin + ((spk_y) * vc->vc_size_row) + vc->vc_cols * 2;
887
888         numsentences[bn] = 0;
889         sentmarks[bn][0] = &sentbuf[bn][0];
890         i = 0;
891         spk_old_attr = spk_attr;
892         spk_attr = get_attributes(vc, (u_short *)start);
893
894         while (start < end) {
895                 sentbuf[bn][i] = (char)get_char(vc, (u_short *) start, &tmp);
896                 if (i > 0) {
897                         if (sentbuf[bn][i] == SPACE && sentbuf[bn][i - 1] == '.'
898                             && numsentences[bn] < 9) {
899                                 /* Sentence Marker */
900                                 numsentences[bn]++;
901                                 sentmarks[bn][numsentences[bn]] =
902                                     &sentbuf[bn][i];
903                         }
904                 }
905                 i++;
906                 start += 2;
907                 if (i >= vc->vc_size_row)
908                         break;
909         }
910
911         for (--i; i >= 0; i--)
912                 if (sentbuf[bn][i] != SPACE)
913                         break;
914
915         if (i < 1)
916                 return -1;
917
918         sentbuf[bn][++i] = SPACE;
919         sentbuf[bn][++i] = '\0';
920
921         sentbufend[bn] = &sentbuf[bn][i];
922         return numsentences[bn];
923 }
924
925 static void say_screen_from_to(struct vc_data *vc, u_long from, u_long to)
926 {
927         u_long start = vc->vc_origin, end;
928
929         if (from > 0)
930                 start += from * vc->vc_size_row;
931         if (to > vc->vc_rows)
932                 to = vc->vc_rows;
933         end = vc->vc_origin + (to * vc->vc_size_row);
934         for (from = start; from < end; from = to) {
935                 to = from + vc->vc_size_row;
936                 say_from_to(vc, from, to, 1);
937         }
938 }
939
940 static void say_screen(struct vc_data *vc)
941 {
942         say_screen_from_to(vc, 0, vc->vc_rows);
943 }
944
945 static void speakup_win_say(struct vc_data *vc)
946 {
947         u_long start, end, from, to;
948
949         if (win_start < 2) {
950                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
951                 return;
952         }
953         start = vc->vc_origin + (win_top * vc->vc_size_row);
954         end = vc->vc_origin + (win_bottom * vc->vc_size_row);
955         while (start <= end) {
956                 from = start + (win_left * 2);
957                 to = start + (win_right * 2);
958                 say_from_to(vc, from, to, 1);
959                 start += vc->vc_size_row;
960         }
961 }
962
963 static void top_edge(struct vc_data *vc)
964 {
965         spk_parked |= 0x01;
966         spk_pos = vc->vc_origin + 2 * spk_x;
967         spk_y = 0;
968         say_line(vc);
969 }
970
971 static void bottom_edge(struct vc_data *vc)
972 {
973         spk_parked |= 0x01;
974         spk_pos += (vc->vc_rows - spk_y - 1) * vc->vc_size_row;
975         spk_y = vc->vc_rows - 1;
976         say_line(vc);
977 }
978
979 static void left_edge(struct vc_data *vc)
980 {
981         spk_parked |= 0x01;
982         spk_pos -= spk_x * 2;
983         spk_x = 0;
984         say_char(vc);
985 }
986
987 static void right_edge(struct vc_data *vc)
988 {
989         spk_parked |= 0x01;
990         spk_pos += (vc->vc_cols - spk_x - 1) * 2;
991         spk_x = vc->vc_cols - 1;
992         say_char(vc);
993 }
994
995 static void say_first_char(struct vc_data *vc)
996 {
997         int i, len = get_line(vc);
998         u_char ch;
999
1000         spk_parked |= 0x01;
1001         if (len == 0) {
1002                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
1003                 return;
1004         }
1005         for (i = 0; i < len; i++)
1006                 if (buf[i] != SPACE)
1007                         break;
1008         ch = buf[i];
1009         spk_pos -= (spk_x - i) * 2;
1010         spk_x = i;
1011         synth_printf("%d, ", ++i);
1012         speak_char(ch);
1013 }
1014
1015 static void say_last_char(struct vc_data *vc)
1016 {
1017         int len = get_line(vc);
1018         u_char ch;
1019
1020         spk_parked |= 0x01;
1021         if (len == 0) {
1022                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
1023                 return;
1024         }
1025         ch = buf[--len];
1026         spk_pos -= (spk_x - len) * 2;
1027         spk_x = len;
1028         synth_printf("%d, ", ++len);
1029         speak_char(ch);
1030 }
1031
1032 static void say_position(struct vc_data *vc)
1033 {
1034         synth_printf(spk_msg_get(MSG_POS_INFO), spk_y + 1, spk_x + 1,
1035                      vc->vc_num + 1);
1036         synth_printf("\n");
1037 }
1038
1039 /* Added by brianb */
1040 static void say_char_num(struct vc_data *vc)
1041 {
1042         u_char tmp;
1043         u_short ch = get_char(vc, (u_short *) spk_pos, &tmp);
1044
1045         ch &= 0xff;
1046         synth_printf(spk_msg_get(MSG_CHAR_INFO), ch, ch);
1047 }
1048
1049 /* these are stub functions to keep keyboard.c happy. */
1050
1051 static void say_from_top(struct vc_data *vc)
1052 {
1053         say_screen_from_to(vc, 0, spk_y);
1054 }
1055
1056 static void say_to_bottom(struct vc_data *vc)
1057 {
1058         say_screen_from_to(vc, spk_y, vc->vc_rows);
1059 }
1060
1061 static void say_from_left(struct vc_data *vc)
1062 {
1063         say_line_from_to(vc, 0, spk_x, 1);
1064 }
1065
1066 static void say_to_right(struct vc_data *vc)
1067 {
1068         say_line_from_to(vc, spk_x, vc->vc_cols, 1);
1069 }
1070
1071 /* end of stub functions. */
1072
1073 static void spkup_write(const char *in_buf, int count)
1074 {
1075         static int rep_count;
1076         static u_char ch = '\0', old_ch = '\0';
1077         static u_short char_type, last_type;
1078         int in_count = count;
1079
1080         spk_keydown = 0;
1081         while (count--) {
1082                 if (cursor_track == read_all_mode) {
1083                         /* Insert Sentence Index */
1084                         if ((in_buf == sentmarks[bn][currsentence]) &&
1085                             (currsentence <= numsentences[bn]))
1086                                 synth_insert_next_index(currsentence++);
1087                 }
1088                 ch = (u_char) *in_buf++;
1089                 char_type = spk_chartab[ch];
1090                 if (ch == old_ch && !(char_type & B_NUM)) {
1091                         if (++rep_count > 2)
1092                                 continue;
1093                 } else {
1094                         if ((last_type & CH_RPT) && rep_count > 2) {
1095                                 synth_printf(" ");
1096                                 synth_printf(spk_msg_get(MSG_REPEAT_DESC),
1097                                              ++rep_count);
1098                                 synth_printf(" ");
1099                         }
1100                         rep_count = 0;
1101                 }
1102                 if (ch == spk_lastkey) {
1103                         rep_count = 0;
1104                         if (spk_key_echo == 1 && ch >= MINECHOCHAR)
1105                                 speak_char(ch);
1106                 } else if (char_type & B_ALPHA) {
1107                         if ((synth_flags & SF_DEC) && (last_type & PUNC))
1108                                 synth_buffer_add(SPACE);
1109                         synth_printf("%c", ch);
1110                 } else if (char_type & B_NUM) {
1111                         rep_count = 0;
1112                         synth_printf("%c", ch);
1113                 } else if (char_type & spk_punc_mask) {
1114                         speak_char(ch);
1115                         char_type &= ~PUNC;     /* for dec nospell processing */
1116                 } else if (char_type & SYNTH_OK) {
1117                         /* these are usually puncts like . and , which synth
1118                          * needs for expression.
1119                          * suppress multiple to get rid of long pauses and
1120                          * clear repeat count
1121                          * so if someone has
1122                          * repeats on you don't get nothing repeated count
1123                          */
1124                         if (ch != old_ch)
1125                                 synth_printf("%c", ch);
1126                         else
1127                                 rep_count = 0;
1128                 } else {
1129 /* send space and record position, if next is num overwrite space */
1130                         if (old_ch != ch)
1131                                 synth_buffer_add(SPACE);
1132                         else
1133                                 rep_count = 0;
1134                 }
1135                 old_ch = ch;
1136                 last_type = char_type;
1137         }
1138         spk_lastkey = 0;
1139         if (in_count > 2 && rep_count > 2) {
1140                 if (last_type & CH_RPT) {
1141                         synth_printf(" ");
1142                         synth_printf(spk_msg_get(MSG_REPEAT_DESC2),
1143                                         ++rep_count);
1144                         synth_printf(" ");
1145                 }
1146                 rep_count = 0;
1147         }
1148 }
1149
1150 static const int NUM_CTL_LABELS = (MSG_CTL_END - MSG_CTL_START + 1);
1151
1152 static void read_all_doc(struct vc_data *vc);
1153 static void cursor_done(u_long data);
1154 static DEFINE_TIMER(cursor_timer, cursor_done, 0, 0);
1155
1156 static void do_handle_shift(struct vc_data *vc, u_char value, char up_flag)
1157 {
1158         unsigned long flags;
1159
1160         if (synth == NULL || up_flag || spk_killed)
1161                 return;
1162         spin_lock_irqsave(&speakup_info.spinlock, flags);
1163         if (cursor_track == read_all_mode) {
1164                 switch (value) {
1165                 case KVAL(K_SHIFT):
1166                         del_timer(&cursor_timer);
1167                         spk_shut_up &= 0xfe;
1168                         spk_do_flush();
1169                         read_all_doc(vc);
1170                         break;
1171                 case KVAL(K_CTRL):
1172                         del_timer(&cursor_timer);
1173                         cursor_track = prev_cursor_track;
1174                         spk_shut_up &= 0xfe;
1175                         spk_do_flush();
1176                         break;
1177                 }
1178         } else {
1179                 spk_shut_up &= 0xfe;
1180                 spk_do_flush();
1181         }
1182         if (spk_say_ctrl && value < NUM_CTL_LABELS)
1183                 synth_printf("%s", spk_msg_get(MSG_CTL_START + value));
1184         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1185 }
1186
1187 static void do_handle_latin(struct vc_data *vc, u_char value, char up_flag)
1188 {
1189         unsigned long flags;
1190
1191         spin_lock_irqsave(&speakup_info.spinlock, flags);
1192         if (up_flag) {
1193                 spk_lastkey = 0;
1194                 spk_keydown = 0;
1195                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1196                 return;
1197         }
1198         if (synth == NULL || spk_killed) {
1199                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1200                 return;
1201         }
1202         spk_shut_up &= 0xfe;
1203         spk_lastkey = value;
1204         spk_keydown++;
1205         spk_parked &= 0xfe;
1206         if (spk_key_echo == 2 && value >= MINECHOCHAR)
1207                 speak_char(value);
1208         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1209 }
1210
1211 int spk_set_key_info(const u_char *key_info, u_char *k_buffer)
1212 {
1213         int i = 0, states, key_data_len;
1214         const u_char *cp = key_info;
1215         u_char *cp1 = k_buffer;
1216         u_char ch, version, num_keys;
1217
1218         version = *cp++;
1219         if (version != KEY_MAP_VER)
1220                 return -1;
1221         num_keys = *cp;
1222         states = (int)cp[1];
1223         key_data_len = (states + 1) * (num_keys + 1);
1224         if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(spk_key_buf))
1225                 return -2;
1226         memset(k_buffer, 0, SHIFT_TBL_SIZE);
1227         memset(spk_our_keys, 0, sizeof(spk_our_keys));
1228         spk_shift_table = k_buffer;
1229         spk_our_keys[0] = spk_shift_table;
1230         cp1 += SHIFT_TBL_SIZE;
1231         memcpy(cp1, cp, key_data_len + 3);
1232         /* get num_keys, states and data */
1233         cp1 += 2;               /* now pointing at shift states */
1234         for (i = 1; i <= states; i++) {
1235                 ch = *cp1++;
1236                 if (ch >= SHIFT_TBL_SIZE)
1237                         return -3;
1238                 spk_shift_table[ch] = i;
1239         }
1240         keymap_flags = *cp1++;
1241         while ((ch = *cp1)) {
1242                 if (ch >= MAX_KEY)
1243                         return -4;
1244                 spk_our_keys[ch] = cp1;
1245                 cp1 += states + 1;
1246         }
1247         return 0;
1248 }
1249
1250 static struct var_t spk_vars[] = {
1251         /* bell must be first to set high limit */
1252         {BELL_POS, .u.n = {NULL, 0, 0, 0, 0, 0, NULL} },
1253         {SPELL_DELAY, .u.n = {NULL, 0, 0, 4, 0, 0, NULL} },
1254         {ATTRIB_BLEEP, .u.n = {NULL, 1, 0, 3, 0, 0, NULL} },
1255         {BLEEPS, .u.n = {NULL, 3, 0, 3, 0, 0, NULL} },
1256         {BLEEP_TIME, .u.n = {NULL, 30, 1, 200, 0, 0, NULL} },
1257         {PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1258         {READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1259         {CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
1260         {SAY_CONTROL, TOGGLE_0},
1261         {SAY_WORD_CTL, TOGGLE_0},
1262         {NO_INTERRUPT, TOGGLE_0},
1263         {KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
1264         V_LAST_VAR
1265 };
1266
1267 static void toggle_cursoring(struct vc_data *vc)
1268 {
1269         if (cursor_track == read_all_mode)
1270                 cursor_track = prev_cursor_track;
1271         if (++cursor_track >= CT_Max)
1272                 cursor_track = 0;
1273         synth_printf("%s\n", spk_msg_get(MSG_CURSOR_MSGS_START + cursor_track));
1274 }
1275
1276 void spk_reset_default_chars(void)
1277 {
1278         int i;
1279
1280         /* First, free any non-default */
1281         for (i = 0; i < 256; i++) {
1282                 if ((spk_characters[i] != NULL)
1283                     && (spk_characters[i] != spk_default_chars[i]))
1284                         kfree(spk_characters[i]);
1285         }
1286
1287         memcpy(spk_characters, spk_default_chars, sizeof(spk_default_chars));
1288 }
1289
1290 void spk_reset_default_chartab(void)
1291 {
1292         memcpy(spk_chartab, default_chartab, sizeof(default_chartab));
1293 }
1294
1295 static const struct st_bits_data *pb_edit;
1296
1297 static int edit_bits(struct vc_data *vc, u_char type, u_char ch, u_short key)
1298 {
1299         short mask = pb_edit->mask, ch_type = spk_chartab[ch];
1300
1301         if (type != KT_LATIN || (ch_type & B_NUM) || ch < SPACE)
1302                 return -1;
1303         if (ch == SPACE) {
1304                 synth_printf("%s\n", spk_msg_get(MSG_EDIT_DONE));
1305                 spk_special_handler = NULL;
1306                 return 1;
1307         }
1308         if (mask < PUNC && !(ch_type & PUNC))
1309                 return -1;
1310         spk_chartab[ch] ^= mask;
1311         speak_char(ch);
1312         synth_printf(" %s\n",
1313                      (spk_chartab[ch] & mask) ? spk_msg_get(MSG_ON) :
1314                      spk_msg_get(MSG_OFF));
1315         return 1;
1316 }
1317
1318 /* Allocation concurrency is protected by the console semaphore */
1319 static int speakup_allocate(struct vc_data *vc)
1320 {
1321         int vc_num;
1322
1323         vc_num = vc->vc_num;
1324         if (speakup_console[vc_num] == NULL) {
1325                 speakup_console[vc_num] = kzalloc(sizeof(*speakup_console[0]),
1326                                                   GFP_ATOMIC);
1327                 if (speakup_console[vc_num] == NULL)
1328                         return -ENOMEM;
1329                 speakup_date(vc);
1330         } else if (!spk_parked)
1331                 speakup_date(vc);
1332
1333         return 0;
1334 }
1335
1336 static void speakup_deallocate(struct vc_data *vc)
1337 {
1338         int vc_num;
1339
1340         vc_num = vc->vc_num;
1341         kfree(speakup_console[vc_num]);
1342         speakup_console[vc_num] = NULL;
1343 }
1344
1345 static u_char is_cursor;
1346 static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
1347 static int cursor_con;
1348
1349 static void reset_highlight_buffers(struct vc_data *);
1350
1351 static int read_all_key;
1352
1353 static void start_read_all_timer(struct vc_data *vc, int command);
1354
1355 enum {
1356         RA_NOTHING,
1357         RA_NEXT_SENT,
1358         RA_PREV_LINE,
1359         RA_NEXT_LINE,
1360         RA_PREV_SENT,
1361         RA_DOWN_ARROW,
1362         RA_TIMER,
1363         RA_FIND_NEXT_SENT,
1364         RA_FIND_PREV_SENT,
1365 };
1366
1367 static void kbd_fakekey2(struct vc_data *vc, int command)
1368 {
1369         del_timer(&cursor_timer);
1370         speakup_fake_down_arrow();
1371         start_read_all_timer(vc, command);
1372 }
1373
1374 static void read_all_doc(struct vc_data *vc)
1375 {
1376         if ((vc->vc_num != fg_console) || synth == NULL || spk_shut_up)
1377                 return;
1378         if (!synth_supports_indexing())
1379                 return;
1380         if (cursor_track != read_all_mode)
1381                 prev_cursor_track = cursor_track;
1382         cursor_track = read_all_mode;
1383         spk_reset_index_count(0);
1384         if (get_sentence_buf(vc, 0) == -1)
1385                 kbd_fakekey2(vc, RA_DOWN_ARROW);
1386         else {
1387                 say_sentence_num(0, 0);
1388                 synth_insert_next_index(0);
1389                 start_read_all_timer(vc, RA_TIMER);
1390         }
1391 }
1392
1393 static void stop_read_all(struct vc_data *vc)
1394 {
1395         del_timer(&cursor_timer);
1396         cursor_track = prev_cursor_track;
1397         spk_shut_up &= 0xfe;
1398         spk_do_flush();
1399 }
1400
1401 static void start_read_all_timer(struct vc_data *vc, int command)
1402 {
1403         struct var_t *cursor_timeout;
1404
1405         cursor_con = vc->vc_num;
1406         read_all_key = command;
1407         cursor_timeout = spk_get_var(CURSOR_TIME);
1408         mod_timer(&cursor_timer,
1409                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1410 }
1411
1412 static void handle_cursor_read_all(struct vc_data *vc, int command)
1413 {
1414         int indcount, sentcount, rv, sn;
1415
1416         switch (command) {
1417         case RA_NEXT_SENT:
1418                 /* Get Current Sentence */
1419                 spk_get_index_count(&indcount, &sentcount);
1420                 /*printk("%d %d  ", indcount, sentcount); */
1421                 spk_reset_index_count(sentcount + 1);
1422                 if (indcount == 1) {
1423                         if (!say_sentence_num(sentcount + 1, 0)) {
1424                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1425                                 return;
1426                         }
1427                         synth_insert_next_index(0);
1428                 } else {
1429                         sn = 0;
1430                         if (!say_sentence_num(sentcount + 1, 1)) {
1431                                 sn = 1;
1432                                 spk_reset_index_count(sn);
1433                         } else
1434                                 synth_insert_next_index(0);
1435                         if (!say_sentence_num(sn, 0)) {
1436                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1437                                 return;
1438                         }
1439                         synth_insert_next_index(0);
1440                 }
1441                 start_read_all_timer(vc, RA_TIMER);
1442                 break;
1443         case RA_PREV_SENT:
1444                 break;
1445         case RA_NEXT_LINE:
1446                 read_all_doc(vc);
1447                 break;
1448         case RA_PREV_LINE:
1449                 break;
1450         case RA_DOWN_ARROW:
1451                 if (get_sentence_buf(vc, 0) == -1) {
1452                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1453                 } else {
1454                         say_sentence_num(0, 0);
1455                         synth_insert_next_index(0);
1456                         start_read_all_timer(vc, RA_TIMER);
1457                 }
1458                 break;
1459         case RA_FIND_NEXT_SENT:
1460                 rv = get_sentence_buf(vc, 0);
1461                 if (rv == -1)
1462                         read_all_doc(vc);
1463                 if (rv == 0)
1464                         kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1465                 else {
1466                         say_sentence_num(1, 0);
1467                         synth_insert_next_index(0);
1468                         start_read_all_timer(vc, RA_TIMER);
1469                 }
1470                 break;
1471         case RA_FIND_PREV_SENT:
1472                 break;
1473         case RA_TIMER:
1474                 spk_get_index_count(&indcount, &sentcount);
1475                 if (indcount < 2)
1476                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1477                 else
1478                         start_read_all_timer(vc, RA_TIMER);
1479                 break;
1480         }
1481 }
1482
1483 static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1484 {
1485         unsigned long flags;
1486
1487         spin_lock_irqsave(&speakup_info.spinlock, flags);
1488         if (cursor_track == read_all_mode) {
1489                 spk_parked &= 0xfe;
1490                 if (synth == NULL || up_flag || spk_shut_up) {
1491                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1492                         return NOTIFY_STOP;
1493                 }
1494                 del_timer(&cursor_timer);
1495                 spk_shut_up &= 0xfe;
1496                 spk_do_flush();
1497                 start_read_all_timer(vc, value + 1);
1498                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1499                 return NOTIFY_STOP;
1500         }
1501         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1502         return NOTIFY_OK;
1503 }
1504
1505 static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1506 {
1507         unsigned long flags;
1508         struct var_t *cursor_timeout;
1509
1510         spin_lock_irqsave(&speakup_info.spinlock, flags);
1511         spk_parked &= 0xfe;
1512         if (synth == NULL || up_flag || spk_shut_up || cursor_track == CT_Off) {
1513                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1514                 return;
1515         }
1516         spk_shut_up &= 0xfe;
1517         if (spk_no_intr)
1518                 spk_do_flush();
1519 /* the key press flushes if !no_inter but we want to flush on cursor
1520  * moves regardless of no_inter state
1521  */
1522         is_cursor = value + 1;
1523         old_cursor_pos = vc->vc_pos;
1524         old_cursor_x = vc->vc_x;
1525         old_cursor_y = vc->vc_y;
1526         speakup_console[vc->vc_num]->ht.cy = vc->vc_y;
1527         cursor_con = vc->vc_num;
1528         if (cursor_track == CT_Highlight)
1529                 reset_highlight_buffers(vc);
1530         cursor_timeout = spk_get_var(CURSOR_TIME);
1531         mod_timer(&cursor_timer,
1532                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1533         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1534 }
1535
1536 static void update_color_buffer(struct vc_data *vc, const char *ic, int len)
1537 {
1538         int i, bi, hi;
1539         int vc_num = vc->vc_num;
1540
1541         bi = (vc->vc_attr & 0x70) >> 4;
1542         hi = speakup_console[vc_num]->ht.highsize[bi];
1543
1544         i = 0;
1545         if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1546                 speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
1547                 speakup_console[vc_num]->ht.rx[bi] = vc->vc_x;
1548                 speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;
1549         }
1550         while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
1551                 if ((ic[i] > 32) && (ic[i] < 127)) {
1552                         speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
1553                         hi++;
1554                 } else if ((ic[i] == 32) && (hi != 0)) {
1555                         if (speakup_console[vc_num]->ht.highbuf[bi][hi - 1] !=
1556                             32) {
1557                                 speakup_console[vc_num]->ht.highbuf[bi][hi] =
1558                                     ic[i];
1559                                 hi++;
1560                         }
1561                 }
1562                 i++;
1563         }
1564         speakup_console[vc_num]->ht.highsize[bi] = hi;
1565 }
1566
1567 static void reset_highlight_buffers(struct vc_data *vc)
1568 {
1569         int i;
1570         int vc_num = vc->vc_num;
1571
1572         for (i = 0; i < 8; i++)
1573                 speakup_console[vc_num]->ht.highsize[i] = 0;
1574 }
1575
1576 static int count_highlight_color(struct vc_data *vc)
1577 {
1578         int i, bg;
1579         int cc;
1580         int vc_num = vc->vc_num;
1581         u16 ch;
1582         u16 *start = (u16 *) vc->vc_origin;
1583
1584         for (i = 0; i < 8; i++)
1585                 speakup_console[vc_num]->ht.bgcount[i] = 0;
1586
1587         for (i = 0; i < vc->vc_rows; i++) {
1588                 u16 *end = start + vc->vc_cols * 2;
1589                 u16 *ptr;
1590
1591                 for (ptr = start; ptr < end; ptr++) {
1592                         ch = get_attributes(vc, ptr);
1593                         bg = (ch & 0x70) >> 4;
1594                         speakup_console[vc_num]->ht.bgcount[bg]++;
1595                 }
1596                 start += vc->vc_size_row;
1597         }
1598
1599         cc = 0;
1600         for (i = 0; i < 8; i++)
1601                 if (speakup_console[vc_num]->ht.bgcount[i] > 0)
1602                         cc++;
1603         return cc;
1604 }
1605
1606 static int get_highlight_color(struct vc_data *vc)
1607 {
1608         int i, j;
1609         unsigned int cptr[8];
1610         int vc_num = vc->vc_num;
1611
1612         for (i = 0; i < 8; i++)
1613                 cptr[i] = i;
1614
1615         for (i = 0; i < 7; i++)
1616                 for (j = i + 1; j < 8; j++)
1617                         if (speakup_console[vc_num]->ht.bgcount[cptr[i]] >
1618                             speakup_console[vc_num]->ht.bgcount[cptr[j]])
1619                                 swap(cptr[i], cptr[j]);
1620
1621         for (i = 0; i < 8; i++)
1622                 if (speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
1623                         if (speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
1624                                 return cptr[i];
1625         return -1;
1626 }
1627
1628 static int speak_highlight(struct vc_data *vc)
1629 {
1630         int hc, d;
1631         int vc_num = vc->vc_num;
1632
1633         if (count_highlight_color(vc) == 1)
1634                 return 0;
1635         hc = get_highlight_color(vc);
1636         if (hc != -1) {
1637                 d = vc->vc_y - speakup_console[vc_num]->ht.cy;
1638                 if ((d == 1) || (d == -1))
1639                         if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y)
1640                                 return 0;
1641                 spk_parked |= 0x01;
1642                 spk_do_flush();
1643                 spkup_write(speakup_console[vc_num]->ht.highbuf[hc],
1644                             speakup_console[vc_num]->ht.highsize[hc]);
1645                 spk_pos = spk_cp = speakup_console[vc_num]->ht.rpos[hc];
1646                 spk_x = spk_cx = speakup_console[vc_num]->ht.rx[hc];
1647                 spk_y = spk_cy = speakup_console[vc_num]->ht.ry[hc];
1648                 return 1;
1649         }
1650         return 0;
1651 }
1652
1653 static void cursor_done(u_long data)
1654 {
1655         struct vc_data *vc = vc_cons[cursor_con].d;
1656         unsigned long flags;
1657
1658         del_timer(&cursor_timer);
1659         spin_lock_irqsave(&speakup_info.spinlock, flags);
1660         if (cursor_con != fg_console) {
1661                 is_cursor = 0;
1662                 goto out;
1663         }
1664         speakup_date(vc);
1665         if (win_enabled) {
1666                 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
1667                     vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
1668                         spk_keydown = 0;
1669                         is_cursor = 0;
1670                         goto out;
1671                 }
1672         }
1673         if (cursor_track == read_all_mode) {
1674                 handle_cursor_read_all(vc, read_all_key);
1675                 goto out;
1676         }
1677         if (cursor_track == CT_Highlight) {
1678                 if (speak_highlight(vc)) {
1679                         spk_keydown = 0;
1680                         is_cursor = 0;
1681                         goto out;
1682                 }
1683         }
1684         if (cursor_track == CT_Window)
1685                 speakup_win_say(vc);
1686         else if (is_cursor == 1 || is_cursor == 4)
1687                 say_line_from_to(vc, 0, vc->vc_cols, 0);
1688         else
1689                 say_char(vc);
1690         spk_keydown = 0;
1691         is_cursor = 0;
1692 out:
1693         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1694 }
1695
1696 /* called by: vt_notifier_call() */
1697 static void speakup_bs(struct vc_data *vc)
1698 {
1699         unsigned long flags;
1700
1701         if (!speakup_console[vc->vc_num])
1702                 return;
1703         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1704                 /* Speakup output, discard */
1705                 return;
1706         if (!spk_parked)
1707                 speakup_date(vc);
1708         if (spk_shut_up || synth == NULL) {
1709                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1710                 return;
1711         }
1712         if (vc->vc_num == fg_console && spk_keydown) {
1713                 spk_keydown = 0;
1714                 if (!is_cursor)
1715                         say_char(vc);
1716         }
1717         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1718 }
1719
1720 /* called by: vt_notifier_call() */
1721 static void speakup_con_write(struct vc_data *vc, const char *str, int len)
1722 {
1723         unsigned long flags;
1724
1725         if ((vc->vc_num != fg_console) || spk_shut_up || synth == NULL)
1726                 return;
1727         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1728                 /* Speakup output, discard */
1729                 return;
1730         if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1))
1731                 bleep(3);
1732         if ((is_cursor) || (cursor_track == read_all_mode)) {
1733                 if (cursor_track == CT_Highlight)
1734                         update_color_buffer(vc, str, len);
1735                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1736                 return;
1737         }
1738         if (win_enabled) {
1739                 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
1740                     vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
1741                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1742                         return;
1743                 }
1744         }
1745
1746         spkup_write(str, len);
1747         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1748 }
1749
1750 static void speakup_con_update(struct vc_data *vc)
1751 {
1752         unsigned long flags;
1753
1754         if (speakup_console[vc->vc_num] == NULL || spk_parked)
1755                 return;
1756         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1757                 /* Speakup output, discard */
1758                 return;
1759         speakup_date(vc);
1760         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1761 }
1762
1763 static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag)
1764 {
1765         unsigned long flags;
1766         int on_off = 2;
1767         char *label;
1768
1769         if (synth == NULL || up_flag || spk_killed)
1770                 return;
1771         spin_lock_irqsave(&speakup_info.spinlock, flags);
1772         spk_shut_up &= 0xfe;
1773         if (spk_no_intr)
1774                 spk_do_flush();
1775         switch (value) {
1776         case KVAL(K_CAPS):
1777                 label = spk_msg_get(MSG_KEYNAME_CAPSLOCK);
1778                 on_off = vt_get_leds(fg_console, VC_CAPSLOCK);
1779                 break;
1780         case KVAL(K_NUM):
1781                 label = spk_msg_get(MSG_KEYNAME_NUMLOCK);
1782                 on_off = vt_get_leds(fg_console, VC_NUMLOCK);
1783                 break;
1784         case KVAL(K_HOLD):
1785                 label = spk_msg_get(MSG_KEYNAME_SCROLLLOCK);
1786                 on_off = vt_get_leds(fg_console, VC_SCROLLOCK);
1787                 if (speakup_console[vc->vc_num])
1788                         speakup_console[vc->vc_num]->tty_stopped = on_off;
1789                 break;
1790         default:
1791                 spk_parked &= 0xfe;
1792                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1793                 return;
1794         }
1795         if (on_off < 2)
1796                 synth_printf("%s %s\n",
1797                              label, spk_msg_get(MSG_STATUS_START + on_off));
1798         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1799 }
1800
1801 static int inc_dec_var(u_char value)
1802 {
1803         struct st_var_header *p_header;
1804         struct var_t *var_data;
1805         char num_buf[32];
1806         char *cp = num_buf;
1807         char *pn;
1808         int var_id = (int)value - VAR_START;
1809         int how = (var_id & 1) ? E_INC : E_DEC;
1810
1811         var_id = var_id / 2 + FIRST_SET_VAR;
1812         p_header = spk_get_var_header(var_id);
1813         if (p_header == NULL)
1814                 return -1;
1815         if (p_header->var_type != VAR_NUM)
1816                 return -1;
1817         var_data = p_header->data;
1818         if (spk_set_num_var(1, p_header, how) != 0)
1819                 return -1;
1820         if (!spk_close_press) {
1821                 for (pn = p_header->name; *pn; pn++) {
1822                         if (*pn == '_')
1823                                 *cp = SPACE;
1824                         else
1825                                 *cp++ = *pn;
1826                 }
1827         }
1828         snprintf(cp, sizeof(num_buf) - (cp - num_buf), " %d ",
1829                  var_data->u.n.value);
1830         synth_printf("%s", num_buf);
1831         return 0;
1832 }
1833
1834 static void speakup_win_set(struct vc_data *vc)
1835 {
1836         char info[40];
1837
1838         if (win_start > 1) {
1839                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_ALREADY_SET));
1840                 return;
1841         }
1842         if (spk_x < win_left || spk_y < win_top) {
1843                 synth_printf("%s\n", spk_msg_get(MSG_END_BEFORE_START));
1844                 return;
1845         }
1846         if (win_start && spk_x == win_left && spk_y == win_top) {
1847                 win_left = 0;
1848                 win_right = vc->vc_cols - 1;
1849                 win_bottom = spk_y;
1850                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_LINE),
1851                          (int)win_top + 1);
1852         } else {
1853                 if (!win_start) {
1854                         win_top = spk_y;
1855                         win_left = spk_x;
1856                 } else {
1857                         win_bottom = spk_y;
1858                         win_right = spk_x;
1859                 }
1860                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_BOUNDARY),
1861                          (win_start) ?
1862                                 spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
1863                          (int)spk_y + 1, (int)spk_x + 1);
1864         }
1865         synth_printf("%s\n", info);
1866         win_start++;
1867 }
1868
1869 static void speakup_win_clear(struct vc_data *vc)
1870 {
1871         win_top = 0;
1872         win_bottom = 0;
1873         win_left = 0;
1874         win_right = 0;
1875         win_start = 0;
1876         synth_printf("%s\n", spk_msg_get(MSG_WINDOW_CLEARED));
1877 }
1878
1879 static void speakup_win_enable(struct vc_data *vc)
1880 {
1881         if (win_start < 2) {
1882                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
1883                 return;
1884         }
1885         win_enabled ^= 1;
1886         if (win_enabled)
1887                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCED));
1888         else
1889                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCE_DISABLED));
1890 }
1891
1892 static void speakup_bits(struct vc_data *vc)
1893 {
1894         int val = this_speakup_key - (FIRST_EDIT_BITS - 1);
1895
1896         if (spk_special_handler != NULL || val < 1 || val > 6) {
1897                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1898                 return;
1899         }
1900         pb_edit = &spk_punc_info[val];
1901         synth_printf(spk_msg_get(MSG_EDIT_PROMPT), pb_edit->name);
1902         spk_special_handler = edit_bits;
1903 }
1904
1905 static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
1906 {
1907         static u_char goto_buf[8];
1908         static int num;
1909         int maxlen;
1910         char *cp;
1911
1912         if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
1913                 goto do_goto;
1914         if (type == KT_LATIN && ch == '\n')
1915                 goto do_goto;
1916         if (type != 0)
1917                 goto oops;
1918         if (ch == 8) {
1919                 if (num == 0)
1920                         return -1;
1921                 ch = goto_buf[--num];
1922                 goto_buf[num] = '\0';
1923                 spkup_write(&ch, 1);
1924                 return 1;
1925         }
1926         if (ch < '+' || ch > 'y')
1927                 goto oops;
1928         goto_buf[num++] = ch;
1929         goto_buf[num] = '\0';
1930         spkup_write(&ch, 1);
1931         maxlen = (*goto_buf >= '0') ? 3 : 4;
1932         if ((ch == '+' || ch == '-') && num == 1)
1933                 return 1;
1934         if (ch >= '0' && ch <= '9' && num < maxlen)
1935                 return 1;
1936         if (num < maxlen - 1 || num > maxlen)
1937                 goto oops;
1938         if (ch < 'x' || ch > 'y') {
1939 oops:
1940                 if (!spk_killed)
1941                         synth_printf(" %s\n", spk_msg_get(MSG_GOTO_CANCELED));
1942                 goto_buf[num = 0] = '\0';
1943                 spk_special_handler = NULL;
1944                 return 1;
1945         }
1946
1947         goto_pos = simple_strtoul(goto_buf, &cp, 10);
1948
1949         if (*cp == 'x') {
1950                 if (*goto_buf < '0')
1951                         goto_pos += spk_x;
1952                 else if (goto_pos > 0)
1953                         goto_pos--;
1954
1955                 if (goto_pos >= vc->vc_cols)
1956                         goto_pos = vc->vc_cols - 1;
1957                 goto_x = 1;
1958         } else {
1959                 if (*goto_buf < '0')
1960                         goto_pos += spk_y;
1961                 else if (goto_pos > 0)
1962                         goto_pos--;
1963
1964                 if (goto_pos >= vc->vc_rows)
1965                         goto_pos = vc->vc_rows - 1;
1966                 goto_x = 0;
1967         }
1968         goto_buf[num = 0] = '\0';
1969 do_goto:
1970         spk_special_handler = NULL;
1971         spk_parked |= 0x01;
1972         if (goto_x) {
1973                 spk_pos -= spk_x * 2;
1974                 spk_x = goto_pos;
1975                 spk_pos += goto_pos * 2;
1976                 say_word(vc);
1977         } else {
1978                 spk_y = goto_pos;
1979                 spk_pos = vc->vc_origin + (goto_pos * vc->vc_size_row);
1980                 say_line(vc);
1981         }
1982         return 1;
1983 }
1984
1985 static void speakup_goto(struct vc_data *vc)
1986 {
1987         if (spk_special_handler != NULL) {
1988                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1989                 return;
1990         }
1991         synth_printf("%s\n", spk_msg_get(MSG_GOTO));
1992         spk_special_handler = handle_goto;
1993 }
1994
1995 static void speakup_help(struct vc_data *vc)
1996 {
1997         spk_handle_help(vc, KT_SPKUP, SPEAKUP_HELP, 0);
1998 }
1999
2000 static void do_nothing(struct vc_data *vc)
2001 {
2002         return;                 /* flush done in do_spkup */
2003 }
2004
2005 static u_char key_speakup, spk_key_locked;
2006
2007 static void speakup_lock(struct vc_data *vc)
2008 {
2009         if (!spk_key_locked) {
2010                 spk_key_locked = 16;
2011                 key_speakup = 16;
2012         } else {
2013                 spk_key_locked = 0;
2014                 key_speakup = 0;
2015         }
2016 }
2017
2018 typedef void (*spkup_hand) (struct vc_data *);
2019 static spkup_hand spkup_handler[] = {
2020         /* must be ordered same as defines in speakup.h */
2021         do_nothing, speakup_goto, speech_kill, speakup_shut_up,
2022         speakup_cut, speakup_paste, say_first_char, say_last_char,
2023         say_char, say_prev_char, say_next_char,
2024         say_word, say_prev_word, say_next_word,
2025         say_line, say_prev_line, say_next_line,
2026         top_edge, bottom_edge, left_edge, right_edge,
2027         spell_word, spell_word, say_screen,
2028         say_position, say_attributes,
2029         speakup_off, speakup_parked, say_line,  /* this is for indent */
2030         say_from_top, say_to_bottom,
2031         say_from_left, say_to_right,
2032         say_char_num, speakup_bits, speakup_bits, say_phonetic_char,
2033         speakup_bits, speakup_bits, speakup_bits,
2034         speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say,
2035         speakup_lock, speakup_help, toggle_cursoring, read_all_doc, NULL
2036 };
2037
2038 static void do_spkup(struct vc_data *vc, u_char value)
2039 {
2040         if (spk_killed && value != SPEECH_KILL)
2041                 return;
2042         spk_keydown = 0;
2043         spk_lastkey = 0;
2044         spk_shut_up &= 0xfe;
2045         this_speakup_key = value;
2046         if (value < SPKUP_MAX_FUNC && spkup_handler[value]) {
2047                 spk_do_flush();
2048                 (*spkup_handler[value]) (vc);
2049         } else {
2050                 if (inc_dec_var(value) < 0)
2051                         bleep(9);
2052         }
2053 }
2054
2055 static const char *pad_chars = "0123456789+-*/\015,.?()";
2056
2057 static int
2058 speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym,
2059             int up_flag)
2060 {
2061         unsigned long flags;
2062         int kh;
2063         u_char *key_info;
2064         u_char type = KTYP(keysym), value = KVAL(keysym), new_key = 0;
2065         u_char shift_info, offset;
2066         int ret = 0;
2067
2068         if (synth == NULL)
2069                 return 0;
2070
2071         spin_lock_irqsave(&speakup_info.spinlock, flags);
2072         tty = vc->port.tty;
2073         if (type >= 0xf0)
2074                 type -= 0xf0;
2075         if (type == KT_PAD
2076                 && (vt_get_leds(fg_console, VC_NUMLOCK))) {
2077                 if (up_flag) {
2078                         spk_keydown = 0;
2079                         goto out;
2080                 }
2081                 value = spk_lastkey = pad_chars[value];
2082                 spk_keydown++;
2083                 spk_parked &= 0xfe;
2084                 goto no_map;
2085         }
2086         if (keycode >= MAX_KEY)
2087                 goto no_map;
2088         key_info = spk_our_keys[keycode];
2089         if (!key_info)
2090                 goto no_map;
2091         /* Check valid read all mode keys */
2092         if ((cursor_track == read_all_mode) && (!up_flag)) {
2093                 switch (value) {
2094                 case KVAL(K_DOWN):
2095                 case KVAL(K_UP):
2096                 case KVAL(K_LEFT):
2097                 case KVAL(K_RIGHT):
2098                 case KVAL(K_PGUP):
2099                 case KVAL(K_PGDN):
2100                         break;
2101                 default:
2102                         stop_read_all(vc);
2103                         break;
2104                 }
2105         }
2106         shift_info = (shift_state & 0x0f) + key_speakup;
2107         offset = spk_shift_table[shift_info];
2108         if (offset) {
2109                 new_key = key_info[offset];
2110                 if (new_key) {
2111                         ret = 1;
2112                         if (new_key == SPK_KEY) {
2113                                 if (!spk_key_locked)
2114                                         key_speakup = (up_flag) ? 0 : 16;
2115                                 if (up_flag || spk_killed)
2116                                         goto out;
2117                                 spk_shut_up &= 0xfe;
2118                                 spk_do_flush();
2119                                 goto out;
2120                         }
2121                         if (up_flag)
2122                                 goto out;
2123                         if (last_keycode == keycode &&
2124                             time_after(last_spk_jiffy + MAX_DELAY, jiffies)) {
2125                                 spk_close_press = 1;
2126                                 offset = spk_shift_table[shift_info + 32];
2127                                 /* double press? */
2128                                 if (offset && key_info[offset])
2129                                         new_key = key_info[offset];
2130                         }
2131                         last_keycode = keycode;
2132                         last_spk_jiffy = jiffies;
2133                         type = KT_SPKUP;
2134                         value = new_key;
2135                 }
2136         }
2137 no_map:
2138         if (type == KT_SPKUP && spk_special_handler == NULL) {
2139                 do_spkup(vc, new_key);
2140                 spk_close_press = 0;
2141                 ret = 1;
2142                 goto out;
2143         }
2144         if (up_flag || spk_killed || type == KT_SHIFT)
2145                 goto out;
2146         spk_shut_up &= 0xfe;
2147         kh = (value == KVAL(K_DOWN))
2148             || (value == KVAL(K_UP))
2149             || (value == KVAL(K_LEFT))
2150             || (value == KVAL(K_RIGHT));
2151         if ((cursor_track != read_all_mode) || !kh)
2152                 if (!spk_no_intr)
2153                         spk_do_flush();
2154         if (spk_special_handler) {
2155                 if (type == KT_SPEC && value == 1) {
2156                         value = '\n';
2157                         type = KT_LATIN;
2158                 } else if (type == KT_LETTER)
2159                         type = KT_LATIN;
2160                 else if (value == 0x7f)
2161                         value = 8;      /* make del = backspace */
2162                 ret = (*spk_special_handler) (vc, type, value, keycode);
2163                 spk_close_press = 0;
2164                 if (ret < 0)
2165                         bleep(9);
2166                 goto out;
2167         }
2168         last_keycode = 0;
2169 out:
2170         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
2171         return ret;
2172 }
2173
2174 static int keyboard_notifier_call(struct notifier_block *nb,
2175                                   unsigned long code, void *_param)
2176 {
2177         struct keyboard_notifier_param *param = _param;
2178         struct vc_data *vc = param->vc;
2179         int up = !param->down;
2180         int ret = NOTIFY_OK;
2181         static int keycode;     /* to hold the current keycode */
2182
2183         if (vc->vc_mode == KD_GRAPHICS)
2184                 return ret;
2185
2186         /*
2187          * First, determine whether we are handling a fake keypress on
2188          * the current processor.  If we are, then return NOTIFY_OK,
2189          * to pass the keystroke up the chain.  This prevents us from
2190          * trying to take the Speakup lock while it is held by the
2191          * processor on which the simulated keystroke was generated.
2192          * Also, the simulated keystrokes should be ignored by Speakup.
2193          */
2194
2195         if (speakup_fake_key_pressed())
2196                 return ret;
2197
2198         switch (code) {
2199         case KBD_KEYCODE:
2200                 /* speakup requires keycode and keysym currently */
2201                 keycode = param->value;
2202                 break;
2203         case KBD_UNBOUND_KEYCODE:
2204                 /* not used yet */
2205                 break;
2206         case KBD_UNICODE:
2207                 /* not used yet */
2208                 break;
2209         case KBD_KEYSYM:
2210                 if (speakup_key(vc, param->shift, keycode, param->value, up))
2211                         ret = NOTIFY_STOP;
2212                 else if (KTYP(param->value) == KT_CUR)
2213                         ret = pre_handle_cursor(vc, KVAL(param->value), up);
2214                 break;
2215         case KBD_POST_KEYSYM:{
2216                         unsigned char type = KTYP(param->value) - 0xf0;
2217                         unsigned char val = KVAL(param->value);
2218
2219                         switch (type) {
2220                         case KT_SHIFT:
2221                                 do_handle_shift(vc, val, up);
2222                                 break;
2223                         case KT_LATIN:
2224                         case KT_LETTER:
2225                                 do_handle_latin(vc, val, up);
2226                                 break;
2227                         case KT_CUR:
2228                                 do_handle_cursor(vc, val, up);
2229                                 break;
2230                         case KT_SPEC:
2231                                 do_handle_spec(vc, val, up);
2232                                 break;
2233                         }
2234                         break;
2235                 }
2236         }
2237         return ret;
2238 }
2239
2240 static int vt_notifier_call(struct notifier_block *nb,
2241                             unsigned long code, void *_param)
2242 {
2243         struct vt_notifier_param *param = _param;
2244         struct vc_data *vc = param->vc;
2245
2246         switch (code) {
2247         case VT_ALLOCATE:
2248                 if (vc->vc_mode == KD_TEXT)
2249                         speakup_allocate(vc);
2250                 break;
2251         case VT_DEALLOCATE:
2252                 speakup_deallocate(vc);
2253                 break;
2254         case VT_WRITE:
2255                 if (param->c == '\b')
2256                         speakup_bs(vc);
2257                 else if (param->c < 0x100) {
2258                         char d = param->c;
2259
2260                         speakup_con_write(vc, &d, 1);
2261                 }
2262                 break;
2263         case VT_UPDATE:
2264                 speakup_con_update(vc);
2265                 break;
2266         }
2267         return NOTIFY_OK;
2268 }
2269
2270 /* called by: module_exit() */
2271 static void __exit speakup_exit(void)
2272 {
2273         int i;
2274
2275         unregister_keyboard_notifier(&keyboard_notifier_block);
2276         unregister_vt_notifier(&vt_notifier_block);
2277         speakup_unregister_devsynth();
2278         speakup_cancel_paste();
2279         del_timer_sync(&cursor_timer);
2280         kthread_stop(speakup_task);
2281         speakup_task = NULL;
2282         mutex_lock(&spk_mutex);
2283         synth_release();
2284         mutex_unlock(&spk_mutex);
2285
2286         speakup_kobj_exit();
2287
2288         for (i = 0; i < MAX_NR_CONSOLES; i++)
2289                 kfree(speakup_console[i]);
2290
2291         speakup_remove_virtual_keyboard();
2292
2293         for (i = 0; i < MAXVARS; i++)
2294                 speakup_unregister_var(i);
2295
2296         for (i = 0; i < 256; i++) {
2297                 if (spk_characters[i] != spk_default_chars[i])
2298                         kfree(spk_characters[i]);
2299         }
2300
2301         spk_free_user_msgs();
2302 }
2303
2304 /* call by: module_init() */
2305 static int __init speakup_init(void)
2306 {
2307         int i;
2308         long err = 0;
2309         struct st_spk_t *first_console;
2310         struct vc_data *vc = vc_cons[fg_console].d;
2311         struct var_t *var;
2312
2313         /* These first few initializations cannot fail. */
2314         spk_initialize_msgs();  /* Initialize arrays for i18n. */
2315         spk_reset_default_chars();
2316         spk_reset_default_chartab();
2317         spk_strlwr(synth_name);
2318         spk_vars[0].u.n.high = vc->vc_cols;
2319         for (var = spk_vars; var->var_id != MAXVARS; var++)
2320                 speakup_register_var(var);
2321         for (var = synth_time_vars;
2322              (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
2323                 speakup_register_var(var);
2324         for (i = 1; spk_punc_info[i].mask != 0; i++)
2325                 spk_set_mask_bits(NULL, i, 2);
2326
2327         spk_set_key_info(spk_key_defaults, spk_key_buf);
2328
2329         /* From here on out, initializations can fail. */
2330         err = speakup_add_virtual_keyboard();
2331         if (err)
2332                 goto error_virtkeyboard;
2333
2334         first_console = kzalloc(sizeof(*first_console), GFP_KERNEL);
2335         if (!first_console) {
2336                 err = -ENOMEM;
2337                 goto error_alloc;
2338         }
2339
2340         speakup_console[vc->vc_num] = first_console;
2341         speakup_date(vc);
2342
2343         for (i = 0; i < MAX_NR_CONSOLES; i++)
2344                 if (vc_cons[i].d) {
2345                         err = speakup_allocate(vc_cons[i].d);
2346                         if (err)
2347                                 goto error_kobjects;
2348                 }
2349
2350         if (spk_quiet_boot)
2351                 spk_shut_up |= 0x01;
2352
2353         err = speakup_kobj_init();
2354         if (err)
2355                 goto error_kobjects;
2356
2357         synth_init(synth_name);
2358         speakup_register_devsynth();
2359         /*
2360          * register_devsynth might fail, but this error is not fatal.
2361          * /dev/synth is an extra feature; the rest of Speakup
2362          * will work fine without it.
2363          */
2364
2365         err = register_keyboard_notifier(&keyboard_notifier_block);
2366         if (err)
2367                 goto error_kbdnotifier;
2368         err = register_vt_notifier(&vt_notifier_block);
2369         if (err)
2370                 goto error_vtnotifier;
2371
2372         speakup_task = kthread_create(speakup_thread, NULL, "speakup");
2373
2374         if (IS_ERR(speakup_task)) {
2375                 err = PTR_ERR(speakup_task);
2376                 goto error_task;
2377         }
2378
2379         set_user_nice(speakup_task, 10);
2380         wake_up_process(speakup_task);
2381
2382         pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
2383         pr_info("synth name on entry is: %s\n", synth_name);
2384         goto out;
2385
2386 error_task:
2387         unregister_vt_notifier(&vt_notifier_block);
2388
2389 error_vtnotifier:
2390         unregister_keyboard_notifier(&keyboard_notifier_block);
2391         del_timer(&cursor_timer);
2392
2393 error_kbdnotifier:
2394         speakup_unregister_devsynth();
2395         mutex_lock(&spk_mutex);
2396         synth_release();
2397         mutex_unlock(&spk_mutex);
2398         speakup_kobj_exit();
2399
2400 error_kobjects:
2401         for (i = 0; i < MAX_NR_CONSOLES; i++)
2402                 kfree(speakup_console[i]);
2403
2404 error_alloc:
2405         speakup_remove_virtual_keyboard();
2406
2407 error_virtkeyboard:
2408         for (i = 0; i < MAXVARS; i++)
2409                 speakup_unregister_var(i);
2410
2411         for (i = 0; i < 256; i++) {
2412                 if (spk_characters[i] != spk_default_chars[i])
2413                         kfree(spk_characters[i]);
2414         }
2415
2416         spk_free_user_msgs();
2417
2418 out:
2419         return err;
2420 }
2421
2422 module_init(speakup_init);
2423 module_exit(speakup_exit);