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