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