GNU Linux-libre 4.19.264-gnu1
[releases.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 && sentbuf[bn][i - 1] == '.' &&
905                             numsentences[bn] < 9) {
906                                 /* Sentence Marker */
907                                 numsentences[bn]++;
908                                 sentmarks[bn][numsentences[bn]] =
909                                     &sentbuf[bn][i];
910                         }
911                 }
912                 i++;
913                 start += 2;
914                 if (i >= vc->vc_size_row)
915                         break;
916         }
917
918         for (--i; i >= 0; i--)
919                 if (sentbuf[bn][i] != SPACE)
920                         break;
921
922         if (i < 1)
923                 return -1;
924
925         sentbuf[bn][++i] = SPACE;
926         sentbuf[bn][++i] = '\0';
927
928         sentbufend[bn] = &sentbuf[bn][i];
929         return numsentences[bn];
930 }
931
932 static void say_screen_from_to(struct vc_data *vc, u_long from, u_long to)
933 {
934         u_long start = vc->vc_origin, end;
935
936         if (from > 0)
937                 start += from * vc->vc_size_row;
938         if (to > vc->vc_rows)
939                 to = vc->vc_rows;
940         end = vc->vc_origin + (to * vc->vc_size_row);
941         for (from = start; from < end; from = to) {
942                 to = from + vc->vc_size_row;
943                 say_from_to(vc, from, to, 1);
944         }
945 }
946
947 static void say_screen(struct vc_data *vc)
948 {
949         say_screen_from_to(vc, 0, vc->vc_rows);
950 }
951
952 static void speakup_win_say(struct vc_data *vc)
953 {
954         u_long start, end, from, to;
955
956         if (win_start < 2) {
957                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
958                 return;
959         }
960         start = vc->vc_origin + (win_top * vc->vc_size_row);
961         end = vc->vc_origin + (win_bottom * vc->vc_size_row);
962         while (start <= end) {
963                 from = start + (win_left * 2);
964                 to = start + (win_right * 2);
965                 say_from_to(vc, from, to, 1);
966                 start += vc->vc_size_row;
967         }
968 }
969
970 static void top_edge(struct vc_data *vc)
971 {
972         spk_parked |= 0x01;
973         spk_pos = vc->vc_origin + 2 * spk_x;
974         spk_y = 0;
975         say_line(vc);
976 }
977
978 static void bottom_edge(struct vc_data *vc)
979 {
980         spk_parked |= 0x01;
981         spk_pos += (vc->vc_rows - spk_y - 1) * vc->vc_size_row;
982         spk_y = vc->vc_rows - 1;
983         say_line(vc);
984 }
985
986 static void left_edge(struct vc_data *vc)
987 {
988         spk_parked |= 0x01;
989         spk_pos -= spk_x * 2;
990         spk_x = 0;
991         say_char(vc);
992 }
993
994 static void right_edge(struct vc_data *vc)
995 {
996         spk_parked |= 0x01;
997         spk_pos += (vc->vc_cols - spk_x - 1) * 2;
998         spk_x = vc->vc_cols - 1;
999         say_char(vc);
1000 }
1001
1002 static void say_first_char(struct vc_data *vc)
1003 {
1004         int i, len = get_line(vc);
1005         u16 ch;
1006
1007         spk_parked |= 0x01;
1008         if (len == 0) {
1009                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
1010                 return;
1011         }
1012         for (i = 0; i < len; i++)
1013                 if (buf[i] != SPACE)
1014                         break;
1015         ch = buf[i];
1016         spk_pos -= (spk_x - i) * 2;
1017         spk_x = i;
1018         synth_printf("%d, ", ++i);
1019         speak_char(ch);
1020 }
1021
1022 static void say_last_char(struct vc_data *vc)
1023 {
1024         int len = get_line(vc);
1025         u16 ch;
1026
1027         spk_parked |= 0x01;
1028         if (len == 0) {
1029                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
1030                 return;
1031         }
1032         ch = buf[--len];
1033         spk_pos -= (spk_x - len) * 2;
1034         spk_x = len;
1035         synth_printf("%d, ", ++len);
1036         speak_char(ch);
1037 }
1038
1039 static void say_position(struct vc_data *vc)
1040 {
1041         synth_printf(spk_msg_get(MSG_POS_INFO), spk_y + 1, spk_x + 1,
1042                      vc->vc_num + 1);
1043         synth_printf("\n");
1044 }
1045
1046 /* Added by brianb */
1047 static void say_char_num(struct vc_data *vc)
1048 {
1049         u_char tmp;
1050         u16 ch = get_char(vc, (u_short *)spk_pos, &tmp);
1051
1052         synth_printf(spk_msg_get(MSG_CHAR_INFO), ch, ch);
1053 }
1054
1055 /* these are stub functions to keep keyboard.c happy. */
1056
1057 static void say_from_top(struct vc_data *vc)
1058 {
1059         say_screen_from_to(vc, 0, spk_y);
1060 }
1061
1062 static void say_to_bottom(struct vc_data *vc)
1063 {
1064         say_screen_from_to(vc, spk_y, vc->vc_rows);
1065 }
1066
1067 static void say_from_left(struct vc_data *vc)
1068 {
1069         say_line_from_to(vc, 0, spk_x, 1);
1070 }
1071
1072 static void say_to_right(struct vc_data *vc)
1073 {
1074         say_line_from_to(vc, spk_x, vc->vc_cols, 1);
1075 }
1076
1077 /* end of stub functions. */
1078
1079 static void spkup_write(const u16 *in_buf, int count)
1080 {
1081         static int rep_count;
1082         static u16 ch = '\0', old_ch = '\0';
1083         static u_short char_type, last_type;
1084         int in_count = count;
1085
1086         spk_keydown = 0;
1087         while (count--) {
1088                 if (cursor_track == read_all_mode) {
1089                         /* Insert Sentence Index */
1090                         if ((in_buf == sentmarks[bn][currsentence]) &&
1091                             (currsentence <= numsentences[bn]))
1092                                 synth_insert_next_index(currsentence++);
1093                 }
1094                 ch = *in_buf++;
1095                 if (ch < 0x100)
1096                         char_type = spk_chartab[ch];
1097                 else
1098                         char_type = ALPHA;
1099                 if (ch == old_ch && !(char_type & B_NUM)) {
1100                         if (++rep_count > 2)
1101                                 continue;
1102                 } else {
1103                         if ((last_type & CH_RPT) && rep_count > 2) {
1104                                 synth_printf(" ");
1105                                 synth_printf(spk_msg_get(MSG_REPEAT_DESC),
1106                                              ++rep_count);
1107                                 synth_printf(" ");
1108                         }
1109                         rep_count = 0;
1110                 }
1111                 if (ch == spk_lastkey) {
1112                         rep_count = 0;
1113                         if (spk_key_echo == 1 && ch >= MINECHOCHAR)
1114                                 speak_char(ch);
1115                 } else if (char_type & B_ALPHA) {
1116                         if ((synth_flags & SF_DEC) && (last_type & PUNC))
1117                                 synth_buffer_add(SPACE);
1118                         synth_putwc_s(ch);
1119                 } else if (char_type & B_NUM) {
1120                         rep_count = 0;
1121                         synth_putwc_s(ch);
1122                 } else if (char_type & spk_punc_mask) {
1123                         speak_char(ch);
1124                         char_type &= ~PUNC;     /* for dec nospell processing */
1125                 } else if (char_type & SYNTH_OK) {
1126                         /* these are usually puncts like . and , which synth
1127                          * needs for expression.
1128                          * suppress multiple to get rid of long pauses and
1129                          * clear repeat count
1130                          * so if someone has
1131                          * repeats on you don't get nothing repeated count
1132                          */
1133                         if (ch != old_ch)
1134                                 synth_putwc_s(ch);
1135                         else
1136                                 rep_count = 0;
1137                 } else {
1138 /* send space and record position, if next is num overwrite space */
1139                         if (old_ch != ch)
1140                                 synth_buffer_add(SPACE);
1141                         else
1142                                 rep_count = 0;
1143                 }
1144                 old_ch = ch;
1145                 last_type = char_type;
1146         }
1147         spk_lastkey = 0;
1148         if (in_count > 2 && rep_count > 2) {
1149                 if (last_type & CH_RPT) {
1150                         synth_printf(" ");
1151                         synth_printf(spk_msg_get(MSG_REPEAT_DESC2),
1152                                      ++rep_count);
1153                         synth_printf(" ");
1154                 }
1155                 rep_count = 0;
1156         }
1157 }
1158
1159 static const int NUM_CTL_LABELS = (MSG_CTL_END - MSG_CTL_START + 1);
1160
1161 static void read_all_doc(struct vc_data *vc);
1162 static void cursor_done(struct timer_list *unused);
1163 static DEFINE_TIMER(cursor_timer, cursor_done);
1164
1165 static void do_handle_shift(struct vc_data *vc, u_char value, char up_flag)
1166 {
1167         unsigned long flags;
1168
1169         if (!synth || up_flag || spk_killed)
1170                 return;
1171         spin_lock_irqsave(&speakup_info.spinlock, flags);
1172         if (cursor_track == read_all_mode) {
1173                 switch (value) {
1174                 case KVAL(K_SHIFT):
1175                         del_timer(&cursor_timer);
1176                         spk_shut_up &= 0xfe;
1177                         spk_do_flush();
1178                         read_all_doc(vc);
1179                         break;
1180                 case KVAL(K_CTRL):
1181                         del_timer(&cursor_timer);
1182                         cursor_track = prev_cursor_track;
1183                         spk_shut_up &= 0xfe;
1184                         spk_do_flush();
1185                         break;
1186                 }
1187         } else {
1188                 spk_shut_up &= 0xfe;
1189                 spk_do_flush();
1190         }
1191         if (spk_say_ctrl && value < NUM_CTL_LABELS)
1192                 synth_printf("%s", spk_msg_get(MSG_CTL_START + value));
1193         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1194 }
1195
1196 static void do_handle_latin(struct vc_data *vc, u_char value, char up_flag)
1197 {
1198         unsigned long flags;
1199
1200         spin_lock_irqsave(&speakup_info.spinlock, flags);
1201         if (up_flag) {
1202                 spk_lastkey = 0;
1203                 spk_keydown = 0;
1204                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1205                 return;
1206         }
1207         if (!synth || spk_killed) {
1208                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1209                 return;
1210         }
1211         spk_shut_up &= 0xfe;
1212         spk_lastkey = value;
1213         spk_keydown++;
1214         spk_parked &= 0xfe;
1215         if (spk_key_echo == 2 && value >= MINECHOCHAR)
1216                 speak_char(value);
1217         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1218 }
1219
1220 int spk_set_key_info(const u_char *key_info, u_char *k_buffer)
1221 {
1222         int i = 0, states, key_data_len;
1223         const u_char *cp = key_info;
1224         u_char *cp1 = k_buffer;
1225         u_char ch, version, num_keys;
1226
1227         version = *cp++;
1228         if (version != KEY_MAP_VER) {
1229                 pr_debug("version found %d should be %d\n",
1230                          version, KEY_MAP_VER);
1231                 return -EINVAL;
1232         }
1233         num_keys = *cp;
1234         states = (int)cp[1];
1235         key_data_len = (states + 1) * (num_keys + 1);
1236         if (key_data_len + SHIFT_TBL_SIZE + 4 >= sizeof(spk_key_buf)) {
1237                 pr_debug("too many key_infos (%d over %u)\n",
1238                          key_data_len + SHIFT_TBL_SIZE + 4, (unsigned int)(sizeof(spk_key_buf)));
1239                 return -EINVAL;
1240         }
1241         memset(k_buffer, 0, SHIFT_TBL_SIZE);
1242         memset(spk_our_keys, 0, sizeof(spk_our_keys));
1243         spk_shift_table = k_buffer;
1244         spk_our_keys[0] = spk_shift_table;
1245         cp1 += SHIFT_TBL_SIZE;
1246         memcpy(cp1, cp, key_data_len + 3);
1247         /* get num_keys, states and data */
1248         cp1 += 2;               /* now pointing at shift states */
1249         for (i = 1; i <= states; i++) {
1250                 ch = *cp1++;
1251                 if (ch >= SHIFT_TBL_SIZE) {
1252                         pr_debug("(%d) not valid shift state (max_allowed = %d)\n", ch,
1253                                  SHIFT_TBL_SIZE);
1254                         return -EINVAL;
1255                 }
1256                 spk_shift_table[ch] = i;
1257         }
1258         keymap_flags = *cp1++;
1259         while ((ch = *cp1)) {
1260                 if (ch >= MAX_KEY) {
1261                         pr_debug("(%d), not valid key, (max_allowed = %d)\n", ch, MAX_KEY);
1262                         return -EINVAL;
1263                 }
1264                 spk_our_keys[ch] = cp1;
1265                 cp1 += states + 1;
1266         }
1267         return 0;
1268 }
1269
1270 static struct var_t spk_vars[] = {
1271         /* bell must be first to set high limit */
1272         {BELL_POS, .u.n = {NULL, 0, 0, 0, 0, 0, NULL} },
1273         {SPELL_DELAY, .u.n = {NULL, 0, 0, 4, 0, 0, NULL} },
1274         {ATTRIB_BLEEP, .u.n = {NULL, 1, 0, 3, 0, 0, NULL} },
1275         {BLEEPS, .u.n = {NULL, 3, 0, 3, 0, 0, NULL} },
1276         {BLEEP_TIME, .u.n = {NULL, 30, 1, 200, 0, 0, NULL} },
1277         {PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1278         {READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1279         {CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
1280         {SAY_CONTROL, TOGGLE_0},
1281         {SAY_WORD_CTL, TOGGLE_0},
1282         {NO_INTERRUPT, TOGGLE_0},
1283         {KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
1284         V_LAST_VAR
1285 };
1286
1287 static void toggle_cursoring(struct vc_data *vc)
1288 {
1289         if (cursor_track == read_all_mode)
1290                 cursor_track = prev_cursor_track;
1291         if (++cursor_track >= CT_Max)
1292                 cursor_track = 0;
1293         synth_printf("%s\n", spk_msg_get(MSG_CURSOR_MSGS_START + cursor_track));
1294 }
1295
1296 void spk_reset_default_chars(void)
1297 {
1298         int i;
1299
1300         /* First, free any non-default */
1301         for (i = 0; i < 256; i++) {
1302                 if (spk_characters[i] &&
1303                     (spk_characters[i] != spk_default_chars[i]))
1304                         kfree(spk_characters[i]);
1305         }
1306
1307         memcpy(spk_characters, spk_default_chars, sizeof(spk_default_chars));
1308 }
1309
1310 void spk_reset_default_chartab(void)
1311 {
1312         memcpy(spk_chartab, default_chartab, sizeof(default_chartab));
1313 }
1314
1315 static const struct st_bits_data *pb_edit;
1316
1317 static int edit_bits(struct vc_data *vc, u_char type, u_char ch, u_short key)
1318 {
1319         short mask = pb_edit->mask, ch_type = spk_chartab[ch];
1320
1321         if (type != KT_LATIN || (ch_type & B_NUM) || ch < SPACE)
1322                 return -1;
1323         if (ch == SPACE) {
1324                 synth_printf("%s\n", spk_msg_get(MSG_EDIT_DONE));
1325                 spk_special_handler = NULL;
1326                 return 1;
1327         }
1328         if (mask < PUNC && !(ch_type & PUNC))
1329                 return -1;
1330         spk_chartab[ch] ^= mask;
1331         speak_char(ch);
1332         synth_printf(" %s\n",
1333                      (spk_chartab[ch] & mask) ? spk_msg_get(MSG_ON) :
1334                      spk_msg_get(MSG_OFF));
1335         return 1;
1336 }
1337
1338 /* Allocation concurrency is protected by the console semaphore */
1339 static int speakup_allocate(struct vc_data *vc, gfp_t gfp_flags)
1340 {
1341         int vc_num;
1342
1343         vc_num = vc->vc_num;
1344         if (!speakup_console[vc_num]) {
1345                 speakup_console[vc_num] = kzalloc(sizeof(*speakup_console[0]),
1346                                                   gfp_flags);
1347                 if (!speakup_console[vc_num])
1348                         return -ENOMEM;
1349                 speakup_date(vc);
1350         } else if (!spk_parked) {
1351                 speakup_date(vc);
1352         }
1353
1354         return 0;
1355 }
1356
1357 static void speakup_deallocate(struct vc_data *vc)
1358 {
1359         int vc_num;
1360
1361         vc_num = vc->vc_num;
1362         kfree(speakup_console[vc_num]);
1363         speakup_console[vc_num] = NULL;
1364 }
1365
1366 static u_char is_cursor;
1367 static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
1368 static int cursor_con;
1369
1370 static void reset_highlight_buffers(struct vc_data *);
1371
1372 static int read_all_key;
1373
1374 static int in_keyboard_notifier;
1375
1376 static void start_read_all_timer(struct vc_data *vc, int command);
1377
1378 enum {
1379         RA_NOTHING,
1380         RA_NEXT_SENT,
1381         RA_PREV_LINE,
1382         RA_NEXT_LINE,
1383         RA_PREV_SENT,
1384         RA_DOWN_ARROW,
1385         RA_TIMER,
1386         RA_FIND_NEXT_SENT,
1387         RA_FIND_PREV_SENT,
1388 };
1389
1390 static void kbd_fakekey2(struct vc_data *vc, int command)
1391 {
1392         del_timer(&cursor_timer);
1393         speakup_fake_down_arrow();
1394         start_read_all_timer(vc, command);
1395 }
1396
1397 static void read_all_doc(struct vc_data *vc)
1398 {
1399         if ((vc->vc_num != fg_console) || !synth || spk_shut_up)
1400                 return;
1401         if (!synth_supports_indexing())
1402                 return;
1403         if (cursor_track != read_all_mode)
1404                 prev_cursor_track = cursor_track;
1405         cursor_track = read_all_mode;
1406         spk_reset_index_count(0);
1407         if (get_sentence_buf(vc, 0) == -1) {
1408                 del_timer(&cursor_timer);
1409                 if (!in_keyboard_notifier)
1410                         speakup_fake_down_arrow();
1411                 start_read_all_timer(vc, RA_DOWN_ARROW);
1412         } else {
1413                 say_sentence_num(0, 0);
1414                 synth_insert_next_index(0);
1415                 start_read_all_timer(vc, RA_TIMER);
1416         }
1417 }
1418
1419 static void stop_read_all(struct vc_data *vc)
1420 {
1421         del_timer(&cursor_timer);
1422         cursor_track = prev_cursor_track;
1423         spk_shut_up &= 0xfe;
1424         spk_do_flush();
1425 }
1426
1427 static void start_read_all_timer(struct vc_data *vc, int command)
1428 {
1429         struct var_t *cursor_timeout;
1430
1431         cursor_con = vc->vc_num;
1432         read_all_key = command;
1433         cursor_timeout = spk_get_var(CURSOR_TIME);
1434         mod_timer(&cursor_timer,
1435                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1436 }
1437
1438 static void handle_cursor_read_all(struct vc_data *vc, int command)
1439 {
1440         int indcount, sentcount, rv, sn;
1441
1442         switch (command) {
1443         case RA_NEXT_SENT:
1444                 /* Get Current Sentence */
1445                 spk_get_index_count(&indcount, &sentcount);
1446                 /*printk("%d %d  ", indcount, sentcount); */
1447                 spk_reset_index_count(sentcount + 1);
1448                 if (indcount == 1) {
1449                         if (!say_sentence_num(sentcount + 1, 0)) {
1450                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1451                                 return;
1452                         }
1453                         synth_insert_next_index(0);
1454                 } else {
1455                         sn = 0;
1456                         if (!say_sentence_num(sentcount + 1, 1)) {
1457                                 sn = 1;
1458                                 spk_reset_index_count(sn);
1459                         } else {
1460                                 synth_insert_next_index(0);
1461                         }
1462                         if (!say_sentence_num(sn, 0)) {
1463                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1464                                 return;
1465                         }
1466                         synth_insert_next_index(0);
1467                 }
1468                 start_read_all_timer(vc, RA_TIMER);
1469                 break;
1470         case RA_PREV_SENT:
1471                 break;
1472         case RA_NEXT_LINE:
1473                 read_all_doc(vc);
1474                 break;
1475         case RA_PREV_LINE:
1476                 break;
1477         case RA_DOWN_ARROW:
1478                 if (get_sentence_buf(vc, 0) == -1) {
1479                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1480                 } else {
1481                         say_sentence_num(0, 0);
1482                         synth_insert_next_index(0);
1483                         start_read_all_timer(vc, RA_TIMER);
1484                 }
1485                 break;
1486         case RA_FIND_NEXT_SENT:
1487                 rv = get_sentence_buf(vc, 0);
1488                 if (rv == -1)
1489                         read_all_doc(vc);
1490                 if (rv == 0) {
1491                         kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1492                 } else {
1493                         say_sentence_num(1, 0);
1494                         synth_insert_next_index(0);
1495                         start_read_all_timer(vc, RA_TIMER);
1496                 }
1497                 break;
1498         case RA_FIND_PREV_SENT:
1499                 break;
1500         case RA_TIMER:
1501                 spk_get_index_count(&indcount, &sentcount);
1502                 if (indcount < 2)
1503                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1504                 else
1505                         start_read_all_timer(vc, RA_TIMER);
1506                 break;
1507         }
1508 }
1509
1510 static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1511 {
1512         unsigned long flags;
1513
1514         spin_lock_irqsave(&speakup_info.spinlock, flags);
1515         if (cursor_track == read_all_mode) {
1516                 spk_parked &= 0xfe;
1517                 if (!synth || up_flag || spk_shut_up) {
1518                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1519                         return NOTIFY_STOP;
1520                 }
1521                 del_timer(&cursor_timer);
1522                 spk_shut_up &= 0xfe;
1523                 spk_do_flush();
1524                 start_read_all_timer(vc, value + 1);
1525                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1526                 return NOTIFY_STOP;
1527         }
1528         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1529         return NOTIFY_OK;
1530 }
1531
1532 static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1533 {
1534         unsigned long flags;
1535         struct var_t *cursor_timeout;
1536
1537         spin_lock_irqsave(&speakup_info.spinlock, flags);
1538         spk_parked &= 0xfe;
1539         if (!synth || up_flag || spk_shut_up || cursor_track == CT_Off) {
1540                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1541                 return;
1542         }
1543         spk_shut_up &= 0xfe;
1544         if (spk_no_intr)
1545                 spk_do_flush();
1546 /* the key press flushes if !no_inter but we want to flush on cursor
1547  * moves regardless of no_inter state
1548  */
1549         is_cursor = value + 1;
1550         old_cursor_pos = vc->vc_pos;
1551         old_cursor_x = vc->vc_x;
1552         old_cursor_y = vc->vc_y;
1553         speakup_console[vc->vc_num]->ht.cy = vc->vc_y;
1554         cursor_con = vc->vc_num;
1555         if (cursor_track == CT_Highlight)
1556                 reset_highlight_buffers(vc);
1557         cursor_timeout = spk_get_var(CURSOR_TIME);
1558         mod_timer(&cursor_timer,
1559                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1560         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1561 }
1562
1563 static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
1564 {
1565         int i, bi, hi;
1566         int vc_num = vc->vc_num;
1567
1568         bi = (vc->vc_attr & 0x70) >> 4;
1569         hi = speakup_console[vc_num]->ht.highsize[bi];
1570
1571         i = 0;
1572         if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1573                 speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
1574                 speakup_console[vc_num]->ht.rx[bi] = vc->vc_x;
1575                 speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;
1576         }
1577         while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
1578                 if (ic[i] > 32) {
1579                         speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
1580                         hi++;
1581                 } else if ((ic[i] == 32) && (hi != 0)) {
1582                         if (speakup_console[vc_num]->ht.highbuf[bi][hi - 1] !=
1583                             32) {
1584                                 speakup_console[vc_num]->ht.highbuf[bi][hi] =
1585                                     ic[i];
1586                                 hi++;
1587                         }
1588                 }
1589                 i++;
1590         }
1591         speakup_console[vc_num]->ht.highsize[bi] = hi;
1592 }
1593
1594 static void reset_highlight_buffers(struct vc_data *vc)
1595 {
1596         int i;
1597         int vc_num = vc->vc_num;
1598
1599         for (i = 0; i < 8; i++)
1600                 speakup_console[vc_num]->ht.highsize[i] = 0;
1601 }
1602
1603 static int count_highlight_color(struct vc_data *vc)
1604 {
1605         int i, bg;
1606         int cc;
1607         int vc_num = vc->vc_num;
1608         u16 ch;
1609         u16 *start = (u16 *)vc->vc_origin;
1610
1611         for (i = 0; i < 8; i++)
1612                 speakup_console[vc_num]->ht.bgcount[i] = 0;
1613
1614         for (i = 0; i < vc->vc_rows; i++) {
1615                 u16 *end = start + vc->vc_cols * 2;
1616                 u16 *ptr;
1617
1618                 for (ptr = start; ptr < end; ptr++) {
1619                         ch = get_attributes(vc, ptr);
1620                         bg = (ch & 0x70) >> 4;
1621                         speakup_console[vc_num]->ht.bgcount[bg]++;
1622                 }
1623                 start += vc->vc_size_row;
1624         }
1625
1626         cc = 0;
1627         for (i = 0; i < 8; i++)
1628                 if (speakup_console[vc_num]->ht.bgcount[i] > 0)
1629                         cc++;
1630         return cc;
1631 }
1632
1633 static int get_highlight_color(struct vc_data *vc)
1634 {
1635         int i, j;
1636         unsigned int cptr[8];
1637         int vc_num = vc->vc_num;
1638
1639         for (i = 0; i < 8; i++)
1640                 cptr[i] = i;
1641
1642         for (i = 0; i < 7; i++)
1643                 for (j = i + 1; j < 8; j++)
1644                         if (speakup_console[vc_num]->ht.bgcount[cptr[i]] >
1645                             speakup_console[vc_num]->ht.bgcount[cptr[j]])
1646                                 swap(cptr[i], cptr[j]);
1647
1648         for (i = 0; i < 8; i++)
1649                 if (speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
1650                         if (speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
1651                                 return cptr[i];
1652         return -1;
1653 }
1654
1655 static int speak_highlight(struct vc_data *vc)
1656 {
1657         int hc, d;
1658         int vc_num = vc->vc_num;
1659
1660         if (count_highlight_color(vc) == 1)
1661                 return 0;
1662         hc = get_highlight_color(vc);
1663         if (hc != -1) {
1664                 d = vc->vc_y - speakup_console[vc_num]->ht.cy;
1665                 if ((d == 1) || (d == -1))
1666                         if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y)
1667                                 return 0;
1668                 spk_parked |= 0x01;
1669                 spk_do_flush();
1670                 spkup_write(speakup_console[vc_num]->ht.highbuf[hc],
1671                             speakup_console[vc_num]->ht.highsize[hc]);
1672                 spk_pos = spk_cp = speakup_console[vc_num]->ht.rpos[hc];
1673                 spk_x = spk_cx = speakup_console[vc_num]->ht.rx[hc];
1674                 spk_y = spk_cy = speakup_console[vc_num]->ht.ry[hc];
1675                 return 1;
1676         }
1677         return 0;
1678 }
1679
1680 static void cursor_done(struct timer_list *unused)
1681 {
1682         struct vc_data *vc = vc_cons[cursor_con].d;
1683         unsigned long flags;
1684
1685         del_timer(&cursor_timer);
1686         spin_lock_irqsave(&speakup_info.spinlock, flags);
1687         if (cursor_con != fg_console) {
1688                 is_cursor = 0;
1689                 goto out;
1690         }
1691         speakup_date(vc);
1692         if (win_enabled) {
1693                 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
1694                     vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
1695                         spk_keydown = 0;
1696                         is_cursor = 0;
1697                         goto out;
1698                 }
1699         }
1700         if (cursor_track == read_all_mode) {
1701                 handle_cursor_read_all(vc, read_all_key);
1702                 goto out;
1703         }
1704         if (cursor_track == CT_Highlight) {
1705                 if (speak_highlight(vc)) {
1706                         spk_keydown = 0;
1707                         is_cursor = 0;
1708                         goto out;
1709                 }
1710         }
1711         if (cursor_track == CT_Window)
1712                 speakup_win_say(vc);
1713         else if (is_cursor == 1 || is_cursor == 4)
1714                 say_line_from_to(vc, 0, vc->vc_cols, 0);
1715         else
1716                 say_char(vc);
1717         spk_keydown = 0;
1718         is_cursor = 0;
1719 out:
1720         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1721 }
1722
1723 /* called by: vt_notifier_call() */
1724 static void speakup_bs(struct vc_data *vc)
1725 {
1726         unsigned long flags;
1727
1728         if (!speakup_console[vc->vc_num])
1729                 return;
1730         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1731                 /* Speakup output, discard */
1732                 return;
1733         if (!spk_parked)
1734                 speakup_date(vc);
1735         if (spk_shut_up || !synth) {
1736                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1737                 return;
1738         }
1739         if (vc->vc_num == fg_console && spk_keydown) {
1740                 spk_keydown = 0;
1741                 if (!is_cursor)
1742                         say_char(vc);
1743         }
1744         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1745 }
1746
1747 /* called by: vt_notifier_call() */
1748 static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
1749 {
1750         unsigned long flags;
1751
1752         if ((vc->vc_num != fg_console) || spk_shut_up || !synth)
1753                 return;
1754         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1755                 /* Speakup output, discard */
1756                 return;
1757         if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1))
1758                 bleep(3);
1759         if ((is_cursor) || (cursor_track == read_all_mode)) {
1760                 if (cursor_track == CT_Highlight)
1761                         update_color_buffer(vc, str, len);
1762                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1763                 return;
1764         }
1765         if (win_enabled) {
1766                 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
1767                     vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
1768                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1769                         return;
1770                 }
1771         }
1772
1773         spkup_write(str, len);
1774         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1775 }
1776
1777 static void speakup_con_update(struct vc_data *vc)
1778 {
1779         unsigned long flags;
1780
1781         if (!speakup_console[vc->vc_num] || spk_parked)
1782                 return;
1783         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1784                 /* Speakup output, discard */
1785                 return;
1786         speakup_date(vc);
1787         if (vc->vc_mode == KD_GRAPHICS && !spk_paused && spk_str_pause[0]) {
1788                 synth_printf("%s", spk_str_pause);
1789                 spk_paused = true;
1790         }
1791         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1792 }
1793
1794 static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag)
1795 {
1796         unsigned long flags;
1797         int on_off = 2;
1798         char *label;
1799
1800         if (!synth || up_flag || spk_killed)
1801                 return;
1802         spin_lock_irqsave(&speakup_info.spinlock, flags);
1803         spk_shut_up &= 0xfe;
1804         if (spk_no_intr)
1805                 spk_do_flush();
1806         switch (value) {
1807         case KVAL(K_CAPS):
1808                 label = spk_msg_get(MSG_KEYNAME_CAPSLOCK);
1809                 on_off = vt_get_leds(fg_console, VC_CAPSLOCK);
1810                 break;
1811         case KVAL(K_NUM):
1812                 label = spk_msg_get(MSG_KEYNAME_NUMLOCK);
1813                 on_off = vt_get_leds(fg_console, VC_NUMLOCK);
1814                 break;
1815         case KVAL(K_HOLD):
1816                 label = spk_msg_get(MSG_KEYNAME_SCROLLLOCK);
1817                 on_off = vt_get_leds(fg_console, VC_SCROLLOCK);
1818                 if (speakup_console[vc->vc_num])
1819                         speakup_console[vc->vc_num]->tty_stopped = on_off;
1820                 break;
1821         default:
1822                 spk_parked &= 0xfe;
1823                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1824                 return;
1825         }
1826         if (on_off < 2)
1827                 synth_printf("%s %s\n",
1828                              label, spk_msg_get(MSG_STATUS_START + on_off));
1829         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1830 }
1831
1832 static int inc_dec_var(u_char value)
1833 {
1834         struct st_var_header *p_header;
1835         struct var_t *var_data;
1836         char num_buf[32];
1837         char *cp = num_buf;
1838         char *pn;
1839         int var_id = (int)value - VAR_START;
1840         int how = (var_id & 1) ? E_INC : E_DEC;
1841
1842         var_id = var_id / 2 + FIRST_SET_VAR;
1843         p_header = spk_get_var_header(var_id);
1844         if (!p_header)
1845                 return -1;
1846         if (p_header->var_type != VAR_NUM)
1847                 return -1;
1848         var_data = p_header->data;
1849         if (spk_set_num_var(1, p_header, how) != 0)
1850                 return -1;
1851         if (!spk_close_press) {
1852                 for (pn = p_header->name; *pn; pn++) {
1853                         if (*pn == '_')
1854                                 *cp = SPACE;
1855                         else
1856                                 *cp++ = *pn;
1857                 }
1858         }
1859         snprintf(cp, sizeof(num_buf) - (cp - num_buf), " %d ",
1860                  var_data->u.n.value);
1861         synth_printf("%s", num_buf);
1862         return 0;
1863 }
1864
1865 static void speakup_win_set(struct vc_data *vc)
1866 {
1867         char info[40];
1868
1869         if (win_start > 1) {
1870                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_ALREADY_SET));
1871                 return;
1872         }
1873         if (spk_x < win_left || spk_y < win_top) {
1874                 synth_printf("%s\n", spk_msg_get(MSG_END_BEFORE_START));
1875                 return;
1876         }
1877         if (win_start && spk_x == win_left && spk_y == win_top) {
1878                 win_left = 0;
1879                 win_right = vc->vc_cols - 1;
1880                 win_bottom = spk_y;
1881                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_LINE),
1882                          (int)win_top + 1);
1883         } else {
1884                 if (!win_start) {
1885                         win_top = spk_y;
1886                         win_left = spk_x;
1887                 } else {
1888                         win_bottom = spk_y;
1889                         win_right = spk_x;
1890                 }
1891                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_BOUNDARY),
1892                          (win_start) ?
1893                                 spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
1894                          (int)spk_y + 1, (int)spk_x + 1);
1895         }
1896         synth_printf("%s\n", info);
1897         win_start++;
1898 }
1899
1900 static void speakup_win_clear(struct vc_data *vc)
1901 {
1902         win_top = 0;
1903         win_bottom = 0;
1904         win_left = 0;
1905         win_right = 0;
1906         win_start = 0;
1907         synth_printf("%s\n", spk_msg_get(MSG_WINDOW_CLEARED));
1908 }
1909
1910 static void speakup_win_enable(struct vc_data *vc)
1911 {
1912         if (win_start < 2) {
1913                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
1914                 return;
1915         }
1916         win_enabled ^= 1;
1917         if (win_enabled)
1918                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCED));
1919         else
1920                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCE_DISABLED));
1921 }
1922
1923 static void speakup_bits(struct vc_data *vc)
1924 {
1925         int val = this_speakup_key - (FIRST_EDIT_BITS - 1);
1926
1927         if (spk_special_handler || val < 1 || val > 6) {
1928                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1929                 return;
1930         }
1931         pb_edit = &spk_punc_info[val];
1932         synth_printf(spk_msg_get(MSG_EDIT_PROMPT), pb_edit->name);
1933         spk_special_handler = edit_bits;
1934 }
1935
1936 static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
1937 {
1938         static u_char goto_buf[8];
1939         static int num;
1940         int maxlen;
1941         char *cp;
1942         u16 wch;
1943
1944         if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
1945                 goto do_goto;
1946         if (type == KT_LATIN && ch == '\n')
1947                 goto do_goto;
1948         if (type != 0)
1949                 goto oops;
1950         if (ch == 8) {
1951                 u16 wch;
1952
1953                 if (num == 0)
1954                         return -1;
1955                 wch = goto_buf[--num];
1956                 goto_buf[num] = '\0';
1957                 spkup_write(&wch, 1);
1958                 return 1;
1959         }
1960         if (ch < '+' || ch > 'y')
1961                 goto oops;
1962         wch = ch;
1963         goto_buf[num++] = ch;
1964         goto_buf[num] = '\0';
1965         spkup_write(&wch, 1);
1966         maxlen = (*goto_buf >= '0') ? 3 : 4;
1967         if ((ch == '+' || ch == '-') && num == 1)
1968                 return 1;
1969         if (ch >= '0' && ch <= '9' && num < maxlen)
1970                 return 1;
1971         if (num < maxlen - 1 || num > maxlen)
1972                 goto oops;
1973         if (ch < 'x' || ch > 'y') {
1974 oops:
1975                 if (!spk_killed)
1976                         synth_printf(" %s\n", spk_msg_get(MSG_GOTO_CANCELED));
1977                 goto_buf[num = 0] = '\0';
1978                 spk_special_handler = NULL;
1979                 return 1;
1980         }
1981
1982         goto_pos = simple_strtoul(goto_buf, &cp, 10);
1983
1984         if (*cp == 'x') {
1985                 if (*goto_buf < '0')
1986                         goto_pos += spk_x;
1987                 else if (goto_pos > 0)
1988                         goto_pos--;
1989
1990                 if (goto_pos >= vc->vc_cols)
1991                         goto_pos = vc->vc_cols - 1;
1992                 goto_x = 1;
1993         } else {
1994                 if (*goto_buf < '0')
1995                         goto_pos += spk_y;
1996                 else if (goto_pos > 0)
1997                         goto_pos--;
1998
1999                 if (goto_pos >= vc->vc_rows)
2000                         goto_pos = vc->vc_rows - 1;
2001                 goto_x = 0;
2002         }
2003         goto_buf[num = 0] = '\0';
2004 do_goto:
2005         spk_special_handler = NULL;
2006         spk_parked |= 0x01;
2007         if (goto_x) {
2008                 spk_pos -= spk_x * 2;
2009                 spk_x = goto_pos;
2010                 spk_pos += goto_pos * 2;
2011                 say_word(vc);
2012         } else {
2013                 spk_y = goto_pos;
2014                 spk_pos = vc->vc_origin + (goto_pos * vc->vc_size_row);
2015                 say_line(vc);
2016         }
2017         return 1;
2018 }
2019
2020 static void speakup_goto(struct vc_data *vc)
2021 {
2022         if (spk_special_handler) {
2023                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
2024                 return;
2025         }
2026         synth_printf("%s\n", spk_msg_get(MSG_GOTO));
2027         spk_special_handler = handle_goto;
2028 }
2029
2030 static void speakup_help(struct vc_data *vc)
2031 {
2032         spk_handle_help(vc, KT_SPKUP, SPEAKUP_HELP, 0);
2033 }
2034
2035 static void do_nothing(struct vc_data *vc)
2036 {
2037         return;                 /* flush done in do_spkup */
2038 }
2039
2040 static u_char key_speakup, spk_key_locked;
2041
2042 static void speakup_lock(struct vc_data *vc)
2043 {
2044         if (!spk_key_locked) {
2045                 spk_key_locked = 16;
2046                 key_speakup = 16;
2047         } else {
2048                 spk_key_locked = 0;
2049                 key_speakup = 0;
2050         }
2051 }
2052
2053 typedef void (*spkup_hand) (struct vc_data *);
2054 static spkup_hand spkup_handler[] = {
2055         /* must be ordered same as defines in speakup.h */
2056         do_nothing, speakup_goto, speech_kill, speakup_shut_up,
2057         speakup_cut, speakup_paste, say_first_char, say_last_char,
2058         say_char, say_prev_char, say_next_char,
2059         say_word, say_prev_word, say_next_word,
2060         say_line, say_prev_line, say_next_line,
2061         top_edge, bottom_edge, left_edge, right_edge,
2062         spell_word, spell_word, say_screen,
2063         say_position, say_attributes,
2064         speakup_off, speakup_parked, say_line,  /* this is for indent */
2065         say_from_top, say_to_bottom,
2066         say_from_left, say_to_right,
2067         say_char_num, speakup_bits, speakup_bits, say_phonetic_char,
2068         speakup_bits, speakup_bits, speakup_bits,
2069         speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say,
2070         speakup_lock, speakup_help, toggle_cursoring, read_all_doc, NULL
2071 };
2072
2073 static void do_spkup(struct vc_data *vc, u_char value)
2074 {
2075         if (spk_killed && value != SPEECH_KILL)
2076                 return;
2077         spk_keydown = 0;
2078         spk_lastkey = 0;
2079         spk_shut_up &= 0xfe;
2080         this_speakup_key = value;
2081         if (value < SPKUP_MAX_FUNC && spkup_handler[value]) {
2082                 spk_do_flush();
2083                 (*spkup_handler[value]) (vc);
2084         } else {
2085                 if (inc_dec_var(value) < 0)
2086                         bleep(9);
2087         }
2088 }
2089
2090 static const char *pad_chars = "0123456789+-*/\015,.?()";
2091
2092 static int
2093 speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym,
2094             int up_flag)
2095 {
2096         unsigned long flags;
2097         int kh;
2098         u_char *key_info;
2099         u_char type = KTYP(keysym), value = KVAL(keysym), new_key = 0;
2100         u_char shift_info, offset;
2101         int ret = 0;
2102
2103         if (!synth)
2104                 return 0;
2105
2106         spin_lock_irqsave(&speakup_info.spinlock, flags);
2107         tty = vc->port.tty;
2108         if (type >= 0xf0)
2109                 type -= 0xf0;
2110         if (type == KT_PAD &&
2111             (vt_get_leds(fg_console, VC_NUMLOCK))) {
2112                 if (up_flag) {
2113                         spk_keydown = 0;
2114                         goto out;
2115                 }
2116                 value = spk_lastkey = pad_chars[value];
2117                 spk_keydown++;
2118                 spk_parked &= 0xfe;
2119                 goto no_map;
2120         }
2121         if (keycode >= MAX_KEY)
2122                 goto no_map;
2123         key_info = spk_our_keys[keycode];
2124         if (!key_info)
2125                 goto no_map;
2126         /* Check valid read all mode keys */
2127         if ((cursor_track == read_all_mode) && (!up_flag)) {
2128                 switch (value) {
2129                 case KVAL(K_DOWN):
2130                 case KVAL(K_UP):
2131                 case KVAL(K_LEFT):
2132                 case KVAL(K_RIGHT):
2133                 case KVAL(K_PGUP):
2134                 case KVAL(K_PGDN):
2135                         break;
2136                 default:
2137                         stop_read_all(vc);
2138                         break;
2139                 }
2140         }
2141         shift_info = (shift_state & 0x0f) + key_speakup;
2142         offset = spk_shift_table[shift_info];
2143         if (offset) {
2144                 new_key = key_info[offset];
2145                 if (new_key) {
2146                         ret = 1;
2147                         if (new_key == SPK_KEY) {
2148                                 if (!spk_key_locked)
2149                                         key_speakup = (up_flag) ? 0 : 16;
2150                                 if (up_flag || spk_killed)
2151                                         goto out;
2152                                 spk_shut_up &= 0xfe;
2153                                 spk_do_flush();
2154                                 goto out;
2155                         }
2156                         if (up_flag)
2157                                 goto out;
2158                         if (last_keycode == keycode &&
2159                             time_after(last_spk_jiffy + MAX_DELAY, jiffies)) {
2160                                 spk_close_press = 1;
2161                                 offset = spk_shift_table[shift_info + 32];
2162                                 /* double press? */
2163                                 if (offset && key_info[offset])
2164                                         new_key = key_info[offset];
2165                         }
2166                         last_keycode = keycode;
2167                         last_spk_jiffy = jiffies;
2168                         type = KT_SPKUP;
2169                         value = new_key;
2170                 }
2171         }
2172 no_map:
2173         if (type == KT_SPKUP && !spk_special_handler) {
2174                 do_spkup(vc, new_key);
2175                 spk_close_press = 0;
2176                 ret = 1;
2177                 goto out;
2178         }
2179         if (up_flag || spk_killed || type == KT_SHIFT)
2180                 goto out;
2181         spk_shut_up &= 0xfe;
2182         kh = (value == KVAL(K_DOWN)) ||
2183             (value == KVAL(K_UP)) ||
2184             (value == KVAL(K_LEFT)) ||
2185             (value == KVAL(K_RIGHT));
2186         if ((cursor_track != read_all_mode) || !kh)
2187                 if (!spk_no_intr)
2188                         spk_do_flush();
2189         if (spk_special_handler) {
2190                 if (type == KT_SPEC && value == 1) {
2191                         value = '\n';
2192                         type = KT_LATIN;
2193                 } else if (type == KT_LETTER) {
2194                         type = KT_LATIN;
2195                 } else if (value == 0x7f) {
2196                         value = 8;      /* make del = backspace */
2197                 }
2198                 ret = (*spk_special_handler) (vc, type, value, keycode);
2199                 spk_close_press = 0;
2200                 if (ret < 0)
2201                         bleep(9);
2202                 goto out;
2203         }
2204         last_keycode = 0;
2205 out:
2206         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
2207         return ret;
2208 }
2209
2210 static int keyboard_notifier_call(struct notifier_block *nb,
2211                                   unsigned long code, void *_param)
2212 {
2213         struct keyboard_notifier_param *param = _param;
2214         struct vc_data *vc = param->vc;
2215         int up = !param->down;
2216         int ret = NOTIFY_OK;
2217         static int keycode;     /* to hold the current keycode */
2218
2219         in_keyboard_notifier = 1;
2220
2221         if (vc->vc_mode == KD_GRAPHICS)
2222                 goto out;
2223
2224         /*
2225          * First, determine whether we are handling a fake keypress on
2226          * the current processor.  If we are, then return NOTIFY_OK,
2227          * to pass the keystroke up the chain.  This prevents us from
2228          * trying to take the Speakup lock while it is held by the
2229          * processor on which the simulated keystroke was generated.
2230          * Also, the simulated keystrokes should be ignored by Speakup.
2231          */
2232
2233         if (speakup_fake_key_pressed())
2234                 goto out;
2235
2236         switch (code) {
2237         case KBD_KEYCODE:
2238                 /* speakup requires keycode and keysym currently */
2239                 keycode = param->value;
2240                 break;
2241         case KBD_UNBOUND_KEYCODE:
2242                 /* not used yet */
2243                 break;
2244         case KBD_UNICODE:
2245                 /* not used yet */
2246                 break;
2247         case KBD_KEYSYM:
2248                 if (speakup_key(vc, param->shift, keycode, param->value, up))
2249                         ret = NOTIFY_STOP;
2250                 else if (KTYP(param->value) == KT_CUR)
2251                         ret = pre_handle_cursor(vc, KVAL(param->value), up);
2252                 break;
2253         case KBD_POST_KEYSYM:{
2254                         unsigned char type = KTYP(param->value) - 0xf0;
2255                         unsigned char val = KVAL(param->value);
2256
2257                         switch (type) {
2258                         case KT_SHIFT:
2259                                 do_handle_shift(vc, val, up);
2260                                 break;
2261                         case KT_LATIN:
2262                         case KT_LETTER:
2263                                 do_handle_latin(vc, val, up);
2264                                 break;
2265                         case KT_CUR:
2266                                 do_handle_cursor(vc, val, up);
2267                                 break;
2268                         case KT_SPEC:
2269                                 do_handle_spec(vc, val, up);
2270                                 break;
2271                         }
2272                         break;
2273                 }
2274         }
2275 out:
2276         in_keyboard_notifier = 0;
2277         return ret;
2278 }
2279
2280 static int vt_notifier_call(struct notifier_block *nb,
2281                             unsigned long code, void *_param)
2282 {
2283         struct vt_notifier_param *param = _param;
2284         struct vc_data *vc = param->vc;
2285
2286         switch (code) {
2287         case VT_ALLOCATE:
2288                 if (vc->vc_mode == KD_TEXT)
2289                         speakup_allocate(vc, GFP_ATOMIC);
2290                 break;
2291         case VT_DEALLOCATE:
2292                 speakup_deallocate(vc);
2293                 break;
2294         case VT_WRITE:
2295                 if (param->c == '\b') {
2296                         speakup_bs(vc);
2297                 } else {
2298                         u16 d = param->c;
2299
2300                         speakup_con_write(vc, &d, 1);
2301                 }
2302                 break;
2303         case VT_UPDATE:
2304                 speakup_con_update(vc);
2305                 break;
2306         }
2307         return NOTIFY_OK;
2308 }
2309
2310 /* called by: module_exit() */
2311 static void __exit speakup_exit(void)
2312 {
2313         int i;
2314
2315         unregister_keyboard_notifier(&keyboard_notifier_block);
2316         unregister_vt_notifier(&vt_notifier_block);
2317         speakup_unregister_devsynth();
2318         speakup_cancel_paste();
2319         del_timer_sync(&cursor_timer);
2320         kthread_stop(speakup_task);
2321         speakup_task = NULL;
2322         mutex_lock(&spk_mutex);
2323         synth_release();
2324         mutex_unlock(&spk_mutex);
2325         spk_ttyio_unregister_ldisc();
2326
2327         speakup_kobj_exit();
2328
2329         for (i = 0; i < MAX_NR_CONSOLES; i++)
2330                 kfree(speakup_console[i]);
2331
2332         speakup_remove_virtual_keyboard();
2333
2334         for (i = 0; i < MAXVARS; i++)
2335                 speakup_unregister_var(i);
2336
2337         for (i = 0; i < 256; i++) {
2338                 if (spk_characters[i] != spk_default_chars[i])
2339                         kfree(spk_characters[i]);
2340         }
2341
2342         spk_free_user_msgs();
2343 }
2344
2345 /* call by: module_init() */
2346 static int __init speakup_init(void)
2347 {
2348         int i;
2349         long err = 0;
2350         struct vc_data *vc = vc_cons[fg_console].d;
2351         struct var_t *var;
2352
2353         /* These first few initializations cannot fail. */
2354         spk_initialize_msgs();  /* Initialize arrays for i18n. */
2355         spk_reset_default_chars();
2356         spk_reset_default_chartab();
2357         spk_strlwr(synth_name);
2358         spk_vars[0].u.n.high = vc->vc_cols;
2359         for (var = spk_vars; var->var_id != MAXVARS; var++)
2360                 speakup_register_var(var);
2361         for (var = synth_time_vars;
2362              (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
2363                 speakup_register_var(var);
2364         for (i = 1; spk_punc_info[i].mask != 0; i++)
2365                 spk_set_mask_bits(NULL, i, 2);
2366
2367         spk_set_key_info(spk_key_defaults, spk_key_buf);
2368
2369         /* From here on out, initializations can fail. */
2370         err = speakup_add_virtual_keyboard();
2371         if (err)
2372                 goto error_virtkeyboard;
2373
2374         for (i = 0; i < MAX_NR_CONSOLES; i++)
2375                 if (vc_cons[i].d) {
2376                         err = speakup_allocate(vc_cons[i].d, GFP_KERNEL);
2377                         if (err)
2378                                 goto error_kobjects;
2379                 }
2380
2381         if (spk_quiet_boot)
2382                 spk_shut_up |= 0x01;
2383
2384         err = speakup_kobj_init();
2385         if (err)
2386                 goto error_kobjects;
2387
2388         spk_ttyio_register_ldisc();
2389         synth_init(synth_name);
2390         speakup_register_devsynth();
2391         /*
2392          * register_devsynth might fail, but this error is not fatal.
2393          * /dev/synth is an extra feature; the rest of Speakup
2394          * will work fine without it.
2395          */
2396
2397         err = register_keyboard_notifier(&keyboard_notifier_block);
2398         if (err)
2399                 goto error_kbdnotifier;
2400         err = register_vt_notifier(&vt_notifier_block);
2401         if (err)
2402                 goto error_vtnotifier;
2403
2404         speakup_task = kthread_create(speakup_thread, NULL, "speakup");
2405
2406         if (IS_ERR(speakup_task)) {
2407                 err = PTR_ERR(speakup_task);
2408                 goto error_task;
2409         }
2410
2411         set_user_nice(speakup_task, 10);
2412         wake_up_process(speakup_task);
2413
2414         pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
2415         pr_info("synth name on entry is: %s\n", synth_name);
2416         goto out;
2417
2418 error_task:
2419         unregister_vt_notifier(&vt_notifier_block);
2420
2421 error_vtnotifier:
2422         unregister_keyboard_notifier(&keyboard_notifier_block);
2423         del_timer(&cursor_timer);
2424
2425 error_kbdnotifier:
2426         speakup_unregister_devsynth();
2427         mutex_lock(&spk_mutex);
2428         synth_release();
2429         mutex_unlock(&spk_mutex);
2430         speakup_kobj_exit();
2431
2432 error_kobjects:
2433         for (i = 0; i < MAX_NR_CONSOLES; i++)
2434                 kfree(speakup_console[i]);
2435
2436         speakup_remove_virtual_keyboard();
2437
2438 error_virtkeyboard:
2439         for (i = 0; i < MAXVARS; i++)
2440                 speakup_unregister_var(i);
2441
2442         for (i = 0; i < 256; i++) {
2443                 if (spk_characters[i] != spk_default_chars[i])
2444                         kfree(spk_characters[i]);
2445         }
2446
2447         spk_free_user_msgs();
2448
2449 out:
2450         return err;
2451 }
2452
2453 module_init(speakup_init);
2454 module_exit(speakup_exit);