GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / accessibility / 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 int spk_cur_phonetic;
69 char spk_str_caps_start[MAXVARLEN + 1] = "\0";
70 char spk_str_caps_stop[MAXVARLEN + 1] = "\0";
71 char spk_str_pause[MAXVARLEN + 1] = "\0";
72 bool spk_paused;
73 const struct st_bits_data spk_punc_info[] = {
74         {"none", "", 0},
75         {"some", "/$%&@", SOME},
76         {"most", "$%&#()=+*/@^<>|\\", MOST},
77         {"all", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", PUNC},
78         {"delimiters", "", B_WDLM},
79         {"repeats", "()", CH_RPT},
80         {"extended numeric", "", B_EXNUM},
81         {"symbols", "", B_SYM},
82         {NULL, NULL}
83 };
84
85 static char mark_cut_flag;
86 #define MAX_KEY 160
87 static u_char *spk_shift_table;
88 u_char *spk_our_keys[MAX_KEY];
89 u_char spk_key_buf[600];
90 const u_char spk_key_defaults[] = {
91 #include "speakupmap.h"
92 };
93
94 /* cursor track modes, must be ordered same as cursor_msgs in enum msg_index_t */
95 enum cursor_track {
96         CT_Off = 0,
97         CT_On,
98         CT_Highlight,
99         CT_Window,
100         CT_Max,
101         read_all_mode = CT_Max,
102 };
103
104 /* Speakup Cursor Track Variables */
105 static enum cursor_track cursor_track = 1, prev_cursor_track = 1;
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, true);
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->state.x;
267         spk_y = spk_cy = vc->state.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         ret = speakup_set_selection(tty);
361
362         switch (ret) {
363         case 0:
364                 break;          /* no error */
365         case -EFAULT:
366                 pr_warn("%sEFAULT\n", err_buf);
367                 break;
368         case -EINVAL:
369                 pr_warn("%sEINVAL\n", err_buf);
370                 break;
371         case -ENOMEM:
372                 pr_warn("%sENOMEM\n", err_buf);
373                 break;
374         }
375 }
376
377 static void speakup_paste(struct vc_data *vc)
378 {
379         if (mark_cut_flag) {
380                 mark_cut_flag = 0;
381                 synth_printf("%s\n", spk_msg_get(MSG_MARK_CLEARED));
382         } else {
383                 synth_printf("%s\n", spk_msg_get(MSG_PASTE));
384                 speakup_paste_selection(tty);
385         }
386 }
387
388 static void say_attributes(struct vc_data *vc)
389 {
390         int fg = spk_attr & 0x0f;
391         int bg = spk_attr >> 4;
392
393         synth_printf("%s", spk_msg_get(MSG_COLORS_START + fg));
394         if (bg > 7) {
395                 synth_printf(" %s ", spk_msg_get(MSG_ON_BLINKING));
396                 bg -= 8;
397         } else {
398                 synth_printf(" %s ", spk_msg_get(MSG_ON));
399         }
400         synth_printf("%s\n", spk_msg_get(MSG_COLORS_START + bg));
401 }
402
403 /* must be ordered same as edge_msgs in enum msg_index_t */
404 enum edge {
405         edge_none = 0,
406         edge_top,
407         edge_bottom,
408         edge_left,
409         edge_right,
410         edge_quiet
411 };
412
413 static void announce_edge(struct vc_data *vc, enum edge msg_id)
414 {
415         if (spk_bleeps & 1)
416                 bleep(spk_y);
417         if ((spk_bleeps & 2) && (msg_id < edge_quiet))
418                 synth_printf("%s\n",
419                              spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
420 }
421
422 static void speak_char(u16 ch)
423 {
424         char *cp;
425         struct var_t *direct = spk_get_var(DIRECT);
426
427         if (ch >= 0x100 || (direct && direct->u.n.value)) {
428                 if (ch < 0x100 && IS_CHAR(ch, B_CAP)) {
429                         spk_pitch_shift++;
430                         synth_printf("%s", spk_str_caps_start);
431                 }
432                 synth_putwc_s(ch);
433                 if (ch < 0x100 && IS_CHAR(ch, B_CAP))
434                         synth_printf("%s", spk_str_caps_stop);
435                 return;
436         }
437
438         cp = spk_characters[ch];
439         if (!cp) {
440                 pr_info("%s: cp == NULL!\n", __func__);
441                 return;
442         }
443         if (IS_CHAR(ch, B_CAP)) {
444                 spk_pitch_shift++;
445                 synth_printf("%s %s %s",
446                              spk_str_caps_start, cp, spk_str_caps_stop);
447         } else {
448                 if (*cp == '^') {
449                         cp++;
450                         synth_printf(" %s%s ", spk_msg_get(MSG_CTRL), cp);
451                 } else {
452                         synth_printf(" %s ", cp);
453                 }
454         }
455 }
456
457 static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs)
458 {
459         u16 ch = ' ';
460
461         if (vc && pos) {
462                 u16 w;
463                 u16 c;
464
465                 pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, true);
466                 w = scr_readw(pos);
467                 c = w & 0xff;
468
469                 if (w & vc->vc_hi_font_mask) {
470                         w &= ~vc->vc_hi_font_mask;
471                         c |= 0x100;
472                 }
473
474                 ch = inverse_translate(vc, c, true);
475                 *attribs = (w & 0xff00) >> 8;
476         }
477         return ch;
478 }
479
480 static void say_char(struct vc_data *vc)
481 {
482         u16 ch;
483
484         spk_old_attr = spk_attr;
485         ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
486         if (spk_attr != spk_old_attr) {
487                 if (spk_attrib_bleep & 1)
488                         bleep(spk_y);
489                 if (spk_attrib_bleep & 2)
490                         say_attributes(vc);
491         }
492         speak_char(ch);
493 }
494
495 static void say_phonetic_char(struct vc_data *vc)
496 {
497         u16 ch;
498
499         spk_old_attr = spk_attr;
500         ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
501         if (ch <= 0x7f && isalpha(ch)) {
502                 ch &= 0x1f;
503                 synth_printf("%s\n", phonetic[--ch]);
504         } else {
505                 if (ch < 0x100 && IS_CHAR(ch, B_NUM))
506                         synth_printf("%s ", spk_msg_get(MSG_NUMBER));
507                 speak_char(ch);
508         }
509 }
510
511 static void say_prev_char(struct vc_data *vc)
512 {
513         spk_parked |= 0x01;
514         if (spk_x == 0) {
515                 announce_edge(vc, edge_left);
516                 return;
517         }
518         spk_x--;
519         spk_pos -= 2;
520         say_char(vc);
521 }
522
523 static void say_next_char(struct vc_data *vc)
524 {
525         spk_parked |= 0x01;
526         if (spk_x == vc->vc_cols - 1) {
527                 announce_edge(vc, edge_right);
528                 return;
529         }
530         spk_x++;
531         spk_pos += 2;
532         say_char(vc);
533 }
534
535 /* get_word - will first check to see if the character under the
536  * reading cursor is a space and if spk_say_word_ctl is true it will
537  * return the word space.  If spk_say_word_ctl is not set it will check to
538  * see if there is a word starting on the next position to the right
539  * and return that word if it exists.  If it does not exist it will
540  * move left to the beginning of any previous word on the line or the
541  * beginning off the line whichever comes first..
542  */
543
544 static u_long get_word(struct vc_data *vc)
545 {
546         u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
547         u16 ch;
548         u16 attr_ch;
549         u_char temp;
550
551         spk_old_attr = spk_attr;
552         ch = get_char(vc, (u_short *)tmp_pos, &temp);
553
554 /* decided to take out the sayword if on a space (mis-information */
555         if (spk_say_word_ctl && ch == SPACE) {
556                 *buf = '\0';
557                 synth_printf("%s\n", spk_msg_get(MSG_SPACE));
558                 return 0;
559         } else if (tmpx < vc->vc_cols - 2 &&
560                    (ch == SPACE || ch == 0 || (ch < 0x100 && IS_WDLM(ch))) &&
561                    get_char(vc, (u_short *)tmp_pos + 1, &temp) > SPACE) {
562                 tmp_pos += 2;
563                 tmpx++;
564         } else {
565                 while (tmpx > 0) {
566                         ch = get_char(vc, (u_short *)tmp_pos - 1, &temp);
567                         if ((ch == SPACE || ch == 0 ||
568                              (ch < 0x100 && IS_WDLM(ch))) &&
569                             get_char(vc, (u_short *)tmp_pos, &temp) > SPACE)
570                                 break;
571                         tmp_pos -= 2;
572                         tmpx--;
573                 }
574         }
575         attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
576         buf[cnt++] = attr_ch;
577         while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) {
578                 tmp_pos += 2;
579                 tmpx++;
580                 ch = get_char(vc, (u_short *)tmp_pos, &temp);
581                 if (ch == SPACE || ch == 0 ||
582                     (buf[cnt - 1] < 0x100 && IS_WDLM(buf[cnt - 1]) &&
583                      ch > SPACE))
584                         break;
585                 buf[cnt++] = ch;
586         }
587         buf[cnt] = '\0';
588         return cnt;
589 }
590
591 static void say_word(struct vc_data *vc)
592 {
593         u_long cnt = get_word(vc);
594         u_short saved_punc_mask = spk_punc_mask;
595
596         if (cnt == 0)
597                 return;
598         spk_punc_mask = PUNC;
599         buf[cnt++] = SPACE;
600         spkup_write(buf, cnt);
601         spk_punc_mask = saved_punc_mask;
602 }
603
604 static void say_prev_word(struct vc_data *vc)
605 {
606         u_char temp;
607         u16 ch;
608         enum edge edge_said = edge_none;
609         u_short last_state = 0, state = 0;
610
611         spk_parked |= 0x01;
612
613         if (spk_x == 0) {
614                 if (spk_y == 0) {
615                         announce_edge(vc, edge_top);
616                         return;
617                 }
618                 spk_y--;
619                 spk_x = vc->vc_cols;
620                 edge_said = edge_quiet;
621         }
622         while (1) {
623                 if (spk_x == 0) {
624                         if (spk_y == 0) {
625                                 edge_said = edge_top;
626                                 break;
627                         }
628                         if (edge_said != edge_quiet)
629                                 edge_said = edge_left;
630                         if (state > 0)
631                                 break;
632                         spk_y--;
633                         spk_x = vc->vc_cols - 1;
634                 } else {
635                         spk_x--;
636                 }
637                 spk_pos -= 2;
638                 ch = get_char(vc, (u_short *)spk_pos, &temp);
639                 if (ch == SPACE || ch == 0)
640                         state = 0;
641                 else if (ch < 0x100 && IS_WDLM(ch))
642                         state = 1;
643                 else
644                         state = 2;
645                 if (state < last_state) {
646                         spk_pos += 2;
647                         spk_x++;
648                         break;
649                 }
650                 last_state = state;
651         }
652         if (spk_x == 0 && edge_said == edge_quiet)
653                 edge_said = edge_left;
654         if (edge_said > edge_none && edge_said < edge_quiet)
655                 announce_edge(vc, edge_said);
656         say_word(vc);
657 }
658
659 static void say_next_word(struct vc_data *vc)
660 {
661         u_char temp;
662         u16 ch;
663         enum edge edge_said = edge_none;
664         u_short last_state = 2, state = 0;
665
666         spk_parked |= 0x01;
667         if (spk_x == vc->vc_cols - 1 && spk_y == vc->vc_rows - 1) {
668                 announce_edge(vc, edge_bottom);
669                 return;
670         }
671         while (1) {
672                 ch = get_char(vc, (u_short *)spk_pos, &temp);
673                 if (ch == SPACE || ch == 0)
674                         state = 0;
675                 else if (ch < 0x100 && IS_WDLM(ch))
676                         state = 1;
677                 else
678                         state = 2;
679                 if (state > last_state)
680                         break;
681                 if (spk_x >= vc->vc_cols - 1) {
682                         if (spk_y == vc->vc_rows - 1) {
683                                 edge_said = edge_bottom;
684                                 break;
685                         }
686                         state = 0;
687                         spk_y++;
688                         spk_x = 0;
689                         edge_said = edge_right;
690                 } else {
691                         spk_x++;
692                 }
693                 spk_pos += 2;
694                 last_state = state;
695         }
696         if (edge_said > edge_none)
697                 announce_edge(vc, edge_said);
698         say_word(vc);
699 }
700
701 static void spell_word(struct vc_data *vc)
702 {
703         static char const *delay_str[] = { "", ",", ".", ". .", ". . ." };
704         u16 *cp = buf;
705         char *cp1;
706         char *str_cap = spk_str_caps_stop;
707         char *last_cap = spk_str_caps_stop;
708         struct var_t *direct = spk_get_var(DIRECT);
709         u16 ch;
710
711         if (!get_word(vc))
712                 return;
713         while ((ch = *cp)) {
714                 if (cp != buf)
715                         synth_printf(" %s ", delay_str[spk_spell_delay]);
716                 /* FIXME: Non-latin1 considered as lower case */
717                 if (ch < 0x100 && IS_CHAR(ch, B_CAP)) {
718                         str_cap = spk_str_caps_start;
719                         if (*spk_str_caps_stop)
720                                 spk_pitch_shift++;
721                         else    /* synth has no pitch */
722                                 last_cap = spk_str_caps_stop;
723                 } else {
724                         str_cap = spk_str_caps_stop;
725                 }
726                 if (str_cap != last_cap) {
727                         synth_printf("%s", str_cap);
728                         last_cap = str_cap;
729                 }
730                 if (ch >= 0x100 || (direct && direct->u.n.value)) {
731                         synth_putwc_s(ch);
732                 } else if (this_speakup_key == SPELL_PHONETIC &&
733                     ch <= 0x7f && isalpha(ch)) {
734                         ch &= 0x1f;
735                         cp1 = phonetic[--ch];
736                         synth_printf("%s", cp1);
737                 } else {
738                         cp1 = spk_characters[ch];
739                         if (*cp1 == '^') {
740                                 synth_printf("%s", spk_msg_get(MSG_CTRL));
741                                 cp1++;
742                         }
743                         synth_printf("%s", cp1);
744                 }
745                 cp++;
746         }
747         if (str_cap != spk_str_caps_stop)
748                 synth_printf("%s", spk_str_caps_stop);
749 }
750
751 static int get_line(struct vc_data *vc)
752 {
753         u_long tmp = spk_pos - (spk_x * 2);
754         int i = 0;
755         u_char tmp2;
756
757         spk_old_attr = spk_attr;
758         spk_attr = get_attributes(vc, (u_short *)spk_pos);
759         for (i = 0; i < vc->vc_cols; i++) {
760                 buf[i] = get_char(vc, (u_short *)tmp, &tmp2);
761                 tmp += 2;
762         }
763         for (--i; i >= 0; i--)
764                 if (buf[i] != SPACE)
765                         break;
766         return ++i;
767 }
768
769 static void say_line(struct vc_data *vc)
770 {
771         int i = get_line(vc);
772         u16 *cp;
773         u_short saved_punc_mask = spk_punc_mask;
774
775         if (i == 0) {
776                 synth_printf("%s\n", spk_msg_get(MSG_BLANK));
777                 return;
778         }
779         buf[i++] = '\n';
780         if (this_speakup_key == SAY_LINE_INDENT) {
781                 cp = buf;
782                 while (*cp == SPACE)
783                         cp++;
784                 synth_printf("%zd, ", (cp - buf) + 1);
785         }
786         spk_punc_mask = spk_punc_masks[spk_reading_punc];
787         spkup_write(buf, i);
788         spk_punc_mask = saved_punc_mask;
789 }
790
791 static void say_prev_line(struct vc_data *vc)
792 {
793         spk_parked |= 0x01;
794         if (spk_y == 0) {
795                 announce_edge(vc, edge_top);
796                 return;
797         }
798         spk_y--;
799         spk_pos -= vc->vc_size_row;
800         say_line(vc);
801 }
802
803 static void say_next_line(struct vc_data *vc)
804 {
805         spk_parked |= 0x01;
806         if (spk_y == vc->vc_rows - 1) {
807                 announce_edge(vc, edge_bottom);
808                 return;
809         }
810         spk_y++;
811         spk_pos += vc->vc_size_row;
812         say_line(vc);
813 }
814
815 static int say_from_to(struct vc_data *vc, u_long from, u_long to,
816                        int read_punc)
817 {
818         int i = 0;
819         u_char tmp;
820         u_short saved_punc_mask = spk_punc_mask;
821
822         spk_old_attr = spk_attr;
823         spk_attr = get_attributes(vc, (u_short *)from);
824         while (from < to) {
825                 buf[i++] = get_char(vc, (u_short *)from, &tmp);
826                 from += 2;
827                 if (i >= vc->vc_size_row)
828                         break;
829         }
830         for (--i; i >= 0; i--)
831                 if (buf[i] != SPACE)
832                         break;
833         buf[++i] = SPACE;
834         buf[++i] = '\0';
835         if (i < 1)
836                 return i;
837         if (read_punc)
838                 spk_punc_mask = spk_punc_info[spk_reading_punc].mask;
839         spkup_write(buf, i);
840         if (read_punc)
841                 spk_punc_mask = saved_punc_mask;
842         return i - 1;
843 }
844
845 static void say_line_from_to(struct vc_data *vc, u_long from, u_long to,
846                              int read_punc)
847 {
848         u_long start = vc->vc_origin + (spk_y * vc->vc_size_row);
849         u_long end = start + (to * 2);
850
851         start += from * 2;
852         if (say_from_to(vc, start, end, read_punc) <= 0)
853                 if (cursor_track != read_all_mode)
854                         synth_printf("%s\n", spk_msg_get(MSG_BLANK));
855 }
856
857 /* Sentence Reading Commands */
858
859 static int currsentence;
860 static int numsentences[2];
861 static u16 *sentbufend[2];
862 static u16 *sentmarks[2][10];
863 static int currbuf;
864 static int bn;
865 static u16 sentbuf[2][256];
866
867 static int say_sentence_num(int num, int prev)
868 {
869         bn = currbuf;
870         currsentence = num + 1;
871         if (prev && --bn == -1)
872                 bn = 1;
873
874         if (num > numsentences[bn])
875                 return 0;
876
877         spkup_write(sentmarks[bn][num], sentbufend[bn] - sentmarks[bn][num]);
878         return 1;
879 }
880
881 static int get_sentence_buf(struct vc_data *vc, int read_punc)
882 {
883         u_long start, end;
884         int i, bn;
885         u_char tmp;
886
887         currbuf++;
888         if (currbuf == 2)
889                 currbuf = 0;
890         bn = currbuf;
891         start = vc->vc_origin + ((spk_y) * vc->vc_size_row);
892         end = vc->vc_origin + ((spk_y) * vc->vc_size_row) + vc->vc_cols * 2;
893
894         numsentences[bn] = 0;
895         sentmarks[bn][0] = &sentbuf[bn][0];
896         i = 0;
897         spk_old_attr = spk_attr;
898         spk_attr = get_attributes(vc, (u_short *)start);
899
900         while (start < end) {
901                 sentbuf[bn][i] = get_char(vc, (u_short *)start, &tmp);
902                 if (i > 0) {
903                         if (sentbuf[bn][i] == SPACE &&
904                             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,
1239                          (unsigned int)(sizeof(spk_key_buf)));
1240                 return -EINVAL;
1241         }
1242         memset(k_buffer, 0, SHIFT_TBL_SIZE);
1243         memset(spk_our_keys, 0, sizeof(spk_our_keys));
1244         spk_shift_table = k_buffer;
1245         spk_our_keys[0] = spk_shift_table;
1246         cp1 += SHIFT_TBL_SIZE;
1247         memcpy(cp1, cp, key_data_len + 3);
1248         /* get num_keys, states and data */
1249         cp1 += 2;               /* now pointing at shift states */
1250         for (i = 1; i <= states; i++) {
1251                 ch = *cp1++;
1252                 if (ch >= SHIFT_TBL_SIZE) {
1253                         pr_debug("(%d) not valid shift state (max_allowed = %d)\n",
1254                                  ch, SHIFT_TBL_SIZE);
1255                         return -EINVAL;
1256                 }
1257                 spk_shift_table[ch] = i;
1258         }
1259         keymap_flags = *cp1++;
1260         while ((ch = *cp1)) {
1261                 if (ch >= MAX_KEY) {
1262                         pr_debug("(%d), not valid key, (max_allowed = %d)\n",
1263                                  ch, MAX_KEY);
1264                         return -EINVAL;
1265                 }
1266                 spk_our_keys[ch] = cp1;
1267                 cp1 += states + 1;
1268         }
1269         return 0;
1270 }
1271
1272 enum spk_vars_id {
1273         BELL_POS_ID = 0, SPELL_DELAY_ID, ATTRIB_BLEEP_ID,
1274         BLEEPS_ID, BLEEP_TIME_ID, PUNC_LEVEL_ID,
1275         READING_PUNC_ID, CURSOR_TIME_ID, SAY_CONTROL_ID,
1276         SAY_WORD_CTL_ID, NO_INTERRUPT_ID, KEY_ECHO_ID,
1277         CUR_PHONETIC_ID, V_LAST_VAR_ID, NB_ID
1278 };
1279
1280 static struct var_t spk_vars[NB_ID] = {
1281         /* bell must be first to set high limit */
1282         [BELL_POS_ID] = { BELL_POS, .u.n = {NULL, 0, 0, 0, 0, 0, NULL} },
1283         [SPELL_DELAY_ID] = { SPELL_DELAY, .u.n = {NULL, 0, 0, 4, 0, 0, NULL} },
1284         [ATTRIB_BLEEP_ID] = { ATTRIB_BLEEP, .u.n = {NULL, 1, 0, 3, 0, 0, NULL} },
1285         [BLEEPS_ID] = { BLEEPS, .u.n = {NULL, 3, 0, 3, 0, 0, NULL} },
1286         [BLEEP_TIME_ID] = { BLEEP_TIME, .u.n = {NULL, 30, 1, 200, 0, 0, NULL} },
1287         [PUNC_LEVEL_ID] = { PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1288         [READING_PUNC_ID] = { READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1289         [CURSOR_TIME_ID] = { CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
1290         [SAY_CONTROL_ID] = { SAY_CONTROL, TOGGLE_0},
1291         [SAY_WORD_CTL_ID] = {SAY_WORD_CTL, TOGGLE_0},
1292         [NO_INTERRUPT_ID] = { NO_INTERRUPT, TOGGLE_0},
1293         [KEY_ECHO_ID] = { KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
1294         [CUR_PHONETIC_ID] = { CUR_PHONETIC, .u.n = {NULL, 0, 0, 1, 0, 0, NULL} },
1295         V_LAST_VAR
1296 };
1297
1298 static void toggle_cursoring(struct vc_data *vc)
1299 {
1300         if (cursor_track == read_all_mode)
1301                 cursor_track = prev_cursor_track;
1302         if (++cursor_track >= CT_Max)
1303                 cursor_track = 0;
1304         synth_printf("%s\n", spk_msg_get(MSG_CURSOR_MSGS_START + cursor_track));
1305 }
1306
1307 void spk_reset_default_chars(void)
1308 {
1309         int i;
1310
1311         /* First, free any non-default */
1312         for (i = 0; i < 256; i++) {
1313                 if (spk_characters[i] &&
1314                     (spk_characters[i] != spk_default_chars[i]))
1315                         kfree(spk_characters[i]);
1316         }
1317
1318         memcpy(spk_characters, spk_default_chars, sizeof(spk_default_chars));
1319 }
1320
1321 void spk_reset_default_chartab(void)
1322 {
1323         memcpy(spk_chartab, default_chartab, sizeof(default_chartab));
1324 }
1325
1326 static const struct st_bits_data *pb_edit;
1327
1328 static int edit_bits(struct vc_data *vc, u_char type, u_char ch, u_short key)
1329 {
1330         short mask = pb_edit->mask, ch_type = spk_chartab[ch];
1331
1332         if (type != KT_LATIN || (ch_type & B_NUM) || ch < SPACE)
1333                 return -1;
1334         if (ch == SPACE) {
1335                 synth_printf("%s\n", spk_msg_get(MSG_EDIT_DONE));
1336                 spk_special_handler = NULL;
1337                 return 1;
1338         }
1339         if (mask < PUNC && !(ch_type & PUNC))
1340                 return -1;
1341         spk_chartab[ch] ^= mask;
1342         speak_char(ch);
1343         synth_printf(" %s\n",
1344                      (spk_chartab[ch] & mask) ? spk_msg_get(MSG_ON) :
1345                      spk_msg_get(MSG_OFF));
1346         return 1;
1347 }
1348
1349 /* Allocation concurrency is protected by the console semaphore */
1350 static int speakup_allocate(struct vc_data *vc, gfp_t gfp_flags)
1351 {
1352         int vc_num;
1353
1354         vc_num = vc->vc_num;
1355         if (!speakup_console[vc_num]) {
1356                 speakup_console[vc_num] = kzalloc(sizeof(*speakup_console[0]),
1357                                                   gfp_flags);
1358                 if (!speakup_console[vc_num])
1359                         return -ENOMEM;
1360                 speakup_date(vc);
1361         } else if (!spk_parked) {
1362                 speakup_date(vc);
1363         }
1364
1365         return 0;
1366 }
1367
1368 static void speakup_deallocate(struct vc_data *vc)
1369 {
1370         int vc_num;
1371
1372         vc_num = vc->vc_num;
1373         kfree(speakup_console[vc_num]);
1374         speakup_console[vc_num] = NULL;
1375 }
1376
1377 enum read_all_command {
1378         RA_NEXT_SENT = KVAL(K_DOWN)+1,
1379         RA_PREV_LINE = KVAL(K_LEFT)+1,
1380         RA_NEXT_LINE = KVAL(K_RIGHT)+1,
1381         RA_PREV_SENT = KVAL(K_UP)+1,
1382         RA_DOWN_ARROW,
1383         RA_TIMER,
1384         RA_FIND_NEXT_SENT,
1385         RA_FIND_PREV_SENT,
1386 };
1387
1388 static u_char is_cursor;
1389 static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
1390 static int cursor_con;
1391
1392 static void reset_highlight_buffers(struct vc_data *);
1393
1394 static enum read_all_command read_all_key;
1395
1396 static int in_keyboard_notifier;
1397
1398 static void start_read_all_timer(struct vc_data *vc, enum read_all_command command);
1399
1400 static void kbd_fakekey2(struct vc_data *vc, enum read_all_command command)
1401 {
1402         del_timer(&cursor_timer);
1403         speakup_fake_down_arrow();
1404         start_read_all_timer(vc, command);
1405 }
1406
1407 static void read_all_doc(struct vc_data *vc)
1408 {
1409         if ((vc->vc_num != fg_console) || !synth || spk_shut_up)
1410                 return;
1411         if (!synth_supports_indexing())
1412                 return;
1413         if (cursor_track != read_all_mode)
1414                 prev_cursor_track = cursor_track;
1415         cursor_track = read_all_mode;
1416         spk_reset_index_count(0);
1417         if (get_sentence_buf(vc, 0) == -1) {
1418                 del_timer(&cursor_timer);
1419                 if (!in_keyboard_notifier)
1420                         speakup_fake_down_arrow();
1421                 start_read_all_timer(vc, RA_DOWN_ARROW);
1422         } else {
1423                 say_sentence_num(0, 0);
1424                 synth_insert_next_index(0);
1425                 start_read_all_timer(vc, RA_TIMER);
1426         }
1427 }
1428
1429 static void stop_read_all(struct vc_data *vc)
1430 {
1431         del_timer(&cursor_timer);
1432         cursor_track = prev_cursor_track;
1433         spk_shut_up &= 0xfe;
1434         spk_do_flush();
1435 }
1436
1437 static void start_read_all_timer(struct vc_data *vc, enum read_all_command command)
1438 {
1439         struct var_t *cursor_timeout;
1440
1441         cursor_con = vc->vc_num;
1442         read_all_key = command;
1443         cursor_timeout = spk_get_var(CURSOR_TIME);
1444         mod_timer(&cursor_timer,
1445                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1446 }
1447
1448 static void handle_cursor_read_all(struct vc_data *vc, enum read_all_command command)
1449 {
1450         int indcount, sentcount, rv, sn;
1451
1452         switch (command) {
1453         case RA_NEXT_SENT:
1454                 /* Get Current Sentence */
1455                 spk_get_index_count(&indcount, &sentcount);
1456                 /*printk("%d %d  ", indcount, sentcount); */
1457                 spk_reset_index_count(sentcount + 1);
1458                 if (indcount == 1) {
1459                         if (!say_sentence_num(sentcount + 1, 0)) {
1460                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1461                                 return;
1462                         }
1463                         synth_insert_next_index(0);
1464                 } else {
1465                         sn = 0;
1466                         if (!say_sentence_num(sentcount + 1, 1)) {
1467                                 sn = 1;
1468                                 spk_reset_index_count(sn);
1469                         } else {
1470                                 synth_insert_next_index(0);
1471                         }
1472                         if (!say_sentence_num(sn, 0)) {
1473                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1474                                 return;
1475                         }
1476                         synth_insert_next_index(0);
1477                 }
1478                 start_read_all_timer(vc, RA_TIMER);
1479                 break;
1480         case RA_PREV_SENT:
1481                 break;
1482         case RA_NEXT_LINE:
1483                 read_all_doc(vc);
1484                 break;
1485         case RA_PREV_LINE:
1486                 break;
1487         case RA_DOWN_ARROW:
1488                 if (get_sentence_buf(vc, 0) == -1) {
1489                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1490                 } else {
1491                         say_sentence_num(0, 0);
1492                         synth_insert_next_index(0);
1493                         start_read_all_timer(vc, RA_TIMER);
1494                 }
1495                 break;
1496         case RA_FIND_NEXT_SENT:
1497                 rv = get_sentence_buf(vc, 0);
1498                 if (rv == -1)
1499                         read_all_doc(vc);
1500                 if (rv == 0) {
1501                         kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1502                 } else {
1503                         say_sentence_num(1, 0);
1504                         synth_insert_next_index(0);
1505                         start_read_all_timer(vc, RA_TIMER);
1506                 }
1507                 break;
1508         case RA_FIND_PREV_SENT:
1509                 break;
1510         case RA_TIMER:
1511                 spk_get_index_count(&indcount, &sentcount);
1512                 if (indcount < 2)
1513                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1514                 else
1515                         start_read_all_timer(vc, RA_TIMER);
1516                 break;
1517         }
1518 }
1519
1520 static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1521 {
1522         unsigned long flags;
1523
1524         spin_lock_irqsave(&speakup_info.spinlock, flags);
1525         if (cursor_track == read_all_mode) {
1526                 spk_parked &= 0xfe;
1527                 if (!synth || up_flag || spk_shut_up) {
1528                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1529                         return NOTIFY_STOP;
1530                 }
1531                 del_timer(&cursor_timer);
1532                 spk_shut_up &= 0xfe;
1533                 spk_do_flush();
1534                 start_read_all_timer(vc, value + 1);
1535                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1536                 return NOTIFY_STOP;
1537         }
1538         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1539         return NOTIFY_OK;
1540 }
1541
1542 static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1543 {
1544         unsigned long flags;
1545         struct var_t *cursor_timeout;
1546
1547         spin_lock_irqsave(&speakup_info.spinlock, flags);
1548         spk_parked &= 0xfe;
1549         if (!synth || up_flag || spk_shut_up || cursor_track == CT_Off) {
1550                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1551                 return;
1552         }
1553         spk_shut_up &= 0xfe;
1554         if (spk_no_intr)
1555                 spk_do_flush();
1556 /* the key press flushes if !no_inter but we want to flush on cursor
1557  * moves regardless of no_inter state
1558  */
1559         is_cursor = value + 1;
1560         old_cursor_pos = vc->vc_pos;
1561         old_cursor_x = vc->state.x;
1562         old_cursor_y = vc->state.y;
1563         speakup_console[vc->vc_num]->ht.cy = vc->state.y;
1564         cursor_con = vc->vc_num;
1565         if (cursor_track == CT_Highlight)
1566                 reset_highlight_buffers(vc);
1567         cursor_timeout = spk_get_var(CURSOR_TIME);
1568         mod_timer(&cursor_timer,
1569                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1570         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1571 }
1572
1573 static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
1574 {
1575         int i, bi, hi;
1576         int vc_num = vc->vc_num;
1577
1578         bi = (vc->vc_attr & 0x70) >> 4;
1579         hi = speakup_console[vc_num]->ht.highsize[bi];
1580
1581         i = 0;
1582         if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1583                 speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
1584                 speakup_console[vc_num]->ht.rx[bi] = vc->state.x;
1585                 speakup_console[vc_num]->ht.ry[bi] = vc->state.y;
1586         }
1587         while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
1588                 if (ic[i] > 32) {
1589                         speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
1590                         hi++;
1591                 } else if ((ic[i] == 32) && (hi != 0)) {
1592                         if (speakup_console[vc_num]->ht.highbuf[bi][hi - 1] !=
1593                             32) {
1594                                 speakup_console[vc_num]->ht.highbuf[bi][hi] =
1595                                     ic[i];
1596                                 hi++;
1597                         }
1598                 }
1599                 i++;
1600         }
1601         speakup_console[vc_num]->ht.highsize[bi] = hi;
1602 }
1603
1604 static void reset_highlight_buffers(struct vc_data *vc)
1605 {
1606         int i;
1607         int vc_num = vc->vc_num;
1608
1609         for (i = 0; i < 8; i++)
1610                 speakup_console[vc_num]->ht.highsize[i] = 0;
1611 }
1612
1613 static int count_highlight_color(struct vc_data *vc)
1614 {
1615         int i, bg;
1616         int cc;
1617         int vc_num = vc->vc_num;
1618         u16 ch;
1619         u16 *start = (u16 *)vc->vc_origin;
1620
1621         for (i = 0; i < 8; i++)
1622                 speakup_console[vc_num]->ht.bgcount[i] = 0;
1623
1624         for (i = 0; i < vc->vc_rows; i++) {
1625                 u16 *end = start + vc->vc_cols * 2;
1626                 u16 *ptr;
1627
1628                 for (ptr = start; ptr < end; ptr++) {
1629                         ch = get_attributes(vc, ptr);
1630                         bg = (ch & 0x70) >> 4;
1631                         speakup_console[vc_num]->ht.bgcount[bg]++;
1632                 }
1633                 start += vc->vc_size_row;
1634         }
1635
1636         cc = 0;
1637         for (i = 0; i < 8; i++)
1638                 if (speakup_console[vc_num]->ht.bgcount[i] > 0)
1639                         cc++;
1640         return cc;
1641 }
1642
1643 static int get_highlight_color(struct vc_data *vc)
1644 {
1645         int i, j;
1646         unsigned int cptr[8];
1647         int vc_num = vc->vc_num;
1648
1649         for (i = 0; i < 8; i++)
1650                 cptr[i] = i;
1651
1652         for (i = 0; i < 7; i++)
1653                 for (j = i + 1; j < 8; j++)
1654                         if (speakup_console[vc_num]->ht.bgcount[cptr[i]] >
1655                             speakup_console[vc_num]->ht.bgcount[cptr[j]])
1656                                 swap(cptr[i], cptr[j]);
1657
1658         for (i = 0; i < 8; i++)
1659                 if (speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
1660                         if (speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
1661                                 return cptr[i];
1662         return -1;
1663 }
1664
1665 static int speak_highlight(struct vc_data *vc)
1666 {
1667         int hc, d;
1668         int vc_num = vc->vc_num;
1669
1670         if (count_highlight_color(vc) == 1)
1671                 return 0;
1672         hc = get_highlight_color(vc);
1673         if (hc != -1) {
1674                 d = vc->state.y - speakup_console[vc_num]->ht.cy;
1675                 if ((d == 1) || (d == -1))
1676                         if (speakup_console[vc_num]->ht.ry[hc] != vc->state.y)
1677                                 return 0;
1678                 spk_parked |= 0x01;
1679                 spk_do_flush();
1680                 spkup_write(speakup_console[vc_num]->ht.highbuf[hc],
1681                             speakup_console[vc_num]->ht.highsize[hc]);
1682                 spk_pos = spk_cp = speakup_console[vc_num]->ht.rpos[hc];
1683                 spk_x = spk_cx = speakup_console[vc_num]->ht.rx[hc];
1684                 spk_y = spk_cy = speakup_console[vc_num]->ht.ry[hc];
1685                 return 1;
1686         }
1687         return 0;
1688 }
1689
1690 static void cursor_done(struct timer_list *unused)
1691 {
1692         struct vc_data *vc = vc_cons[cursor_con].d;
1693         unsigned long flags;
1694
1695         del_timer(&cursor_timer);
1696         spin_lock_irqsave(&speakup_info.spinlock, flags);
1697         if (cursor_con != fg_console) {
1698                 is_cursor = 0;
1699                 goto out;
1700         }
1701         speakup_date(vc);
1702         if (win_enabled) {
1703                 if (vc->state.x >= win_left && vc->state.x <= win_right &&
1704                     vc->state.y >= win_top && vc->state.y <= win_bottom) {
1705                         spk_keydown = 0;
1706                         is_cursor = 0;
1707                         goto out;
1708                 }
1709         }
1710         if (cursor_track == read_all_mode) {
1711                 handle_cursor_read_all(vc, read_all_key);
1712                 goto out;
1713         }
1714         if (cursor_track == CT_Highlight) {
1715                 if (speak_highlight(vc)) {
1716                         spk_keydown = 0;
1717                         is_cursor = 0;
1718                         goto out;
1719                 }
1720         }
1721         if (cursor_track == CT_Window)
1722                 speakup_win_say(vc);
1723         else if (is_cursor == 1 || is_cursor == 4)
1724                 say_line_from_to(vc, 0, vc->vc_cols, 0);
1725         else {
1726                 if (spk_cur_phonetic == 1)
1727                         say_phonetic_char(vc);
1728                 else
1729                         say_char(vc);
1730         }
1731         spk_keydown = 0;
1732         is_cursor = 0;
1733 out:
1734         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1735 }
1736
1737 /* called by: vt_notifier_call() */
1738 static void speakup_bs(struct vc_data *vc)
1739 {
1740         unsigned long flags;
1741
1742         if (!speakup_console[vc->vc_num])
1743                 return;
1744         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1745                 /* Speakup output, discard */
1746                 return;
1747         if (!spk_parked)
1748                 speakup_date(vc);
1749         if (spk_shut_up || !synth) {
1750                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1751                 return;
1752         }
1753         if (vc->vc_num == fg_console && spk_keydown) {
1754                 spk_keydown = 0;
1755                 if (!is_cursor)
1756                         say_char(vc);
1757         }
1758         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1759 }
1760
1761 /* called by: vt_notifier_call() */
1762 static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
1763 {
1764         unsigned long flags;
1765
1766         if ((vc->vc_num != fg_console) || spk_shut_up || !synth)
1767                 return;
1768         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1769                 /* Speakup output, discard */
1770                 return;
1771         if (spk_bell_pos && spk_keydown && (vc->state.x == spk_bell_pos - 1))
1772                 bleep(3);
1773         if ((is_cursor) || (cursor_track == read_all_mode)) {
1774                 if (cursor_track == CT_Highlight)
1775                         update_color_buffer(vc, str, len);
1776                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1777                 return;
1778         }
1779         if (win_enabled) {
1780                 if (vc->state.x >= win_left && vc->state.x <= win_right &&
1781                     vc->state.y >= win_top && vc->state.y <= win_bottom) {
1782                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1783                         return;
1784                 }
1785         }
1786
1787         spkup_write(str, len);
1788         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1789 }
1790
1791 static void speakup_con_update(struct vc_data *vc)
1792 {
1793         unsigned long flags;
1794
1795         if (!speakup_console[vc->vc_num] || spk_parked || !synth)
1796                 return;
1797         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1798                 /* Speakup output, discard */
1799                 return;
1800         speakup_date(vc);
1801         if (vc->vc_mode == KD_GRAPHICS && !spk_paused && spk_str_pause[0]) {
1802                 synth_printf("%s", spk_str_pause);
1803                 spk_paused = true;
1804         }
1805         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1806 }
1807
1808 static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag)
1809 {
1810         unsigned long flags;
1811         int on_off = 2;
1812         char *label;
1813
1814         if (!synth || up_flag || spk_killed)
1815                 return;
1816         spin_lock_irqsave(&speakup_info.spinlock, flags);
1817         spk_shut_up &= 0xfe;
1818         if (spk_no_intr)
1819                 spk_do_flush();
1820         switch (value) {
1821         case KVAL(K_CAPS):
1822                 label = spk_msg_get(MSG_KEYNAME_CAPSLOCK);
1823                 on_off = vt_get_leds(fg_console, VC_CAPSLOCK);
1824                 break;
1825         case KVAL(K_NUM):
1826                 label = spk_msg_get(MSG_KEYNAME_NUMLOCK);
1827                 on_off = vt_get_leds(fg_console, VC_NUMLOCK);
1828                 break;
1829         case KVAL(K_HOLD):
1830                 label = spk_msg_get(MSG_KEYNAME_SCROLLLOCK);
1831                 on_off = vt_get_leds(fg_console, VC_SCROLLOCK);
1832                 if (speakup_console[vc->vc_num])
1833                         speakup_console[vc->vc_num]->tty_stopped = on_off;
1834                 break;
1835         default:
1836                 spk_parked &= 0xfe;
1837                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1838                 return;
1839         }
1840         if (on_off < 2)
1841                 synth_printf("%s %s\n",
1842                              label, spk_msg_get(MSG_STATUS_START + on_off));
1843         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1844 }
1845
1846 static int inc_dec_var(u_char value)
1847 {
1848         struct st_var_header *p_header;
1849         struct var_t *var_data;
1850         char num_buf[32];
1851         char *cp = num_buf;
1852         char *pn;
1853         int var_id = (int)value - VAR_START;
1854         int how = (var_id & 1) ? E_INC : E_DEC;
1855
1856         var_id = var_id / 2 + FIRST_SET_VAR;
1857         p_header = spk_get_var_header(var_id);
1858         if (!p_header)
1859                 return -1;
1860         if (p_header->var_type != VAR_NUM)
1861                 return -1;
1862         var_data = p_header->data;
1863         if (spk_set_num_var(1, p_header, how) != 0)
1864                 return -1;
1865         if (!spk_close_press) {
1866                 for (pn = p_header->name; *pn; pn++) {
1867                         if (*pn == '_')
1868                                 *cp = SPACE;
1869                         else
1870                                 *cp++ = *pn;
1871                 }
1872         }
1873         snprintf(cp, sizeof(num_buf) - (cp - num_buf), " %d ",
1874                  var_data->u.n.value);
1875         synth_printf("%s", num_buf);
1876         return 0;
1877 }
1878
1879 static void speakup_win_set(struct vc_data *vc)
1880 {
1881         char info[40];
1882
1883         if (win_start > 1) {
1884                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_ALREADY_SET));
1885                 return;
1886         }
1887         if (spk_x < win_left || spk_y < win_top) {
1888                 synth_printf("%s\n", spk_msg_get(MSG_END_BEFORE_START));
1889                 return;
1890         }
1891         if (win_start && spk_x == win_left && spk_y == win_top) {
1892                 win_left = 0;
1893                 win_right = vc->vc_cols - 1;
1894                 win_bottom = spk_y;
1895                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_LINE),
1896                          (int)win_top + 1);
1897         } else {
1898                 if (!win_start) {
1899                         win_top = spk_y;
1900                         win_left = spk_x;
1901                 } else {
1902                         win_bottom = spk_y;
1903                         win_right = spk_x;
1904                 }
1905                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_BOUNDARY),
1906                          (win_start) ?
1907                                 spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
1908                          (int)spk_y + 1, (int)spk_x + 1);
1909         }
1910         synth_printf("%s\n", info);
1911         win_start++;
1912 }
1913
1914 static void speakup_win_clear(struct vc_data *vc)
1915 {
1916         win_top = 0;
1917         win_bottom = 0;
1918         win_left = 0;
1919         win_right = 0;
1920         win_start = 0;
1921         synth_printf("%s\n", spk_msg_get(MSG_WINDOW_CLEARED));
1922 }
1923
1924 static void speakup_win_enable(struct vc_data *vc)
1925 {
1926         if (win_start < 2) {
1927                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
1928                 return;
1929         }
1930         win_enabled ^= 1;
1931         if (win_enabled)
1932                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCED));
1933         else
1934                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCE_DISABLED));
1935 }
1936
1937 static void speakup_bits(struct vc_data *vc)
1938 {
1939         int val = this_speakup_key - (FIRST_EDIT_BITS - 1);
1940
1941         if (spk_special_handler || val < 1 || val > 6) {
1942                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1943                 return;
1944         }
1945         pb_edit = &spk_punc_info[val];
1946         synth_printf(spk_msg_get(MSG_EDIT_PROMPT), pb_edit->name);
1947         spk_special_handler = edit_bits;
1948 }
1949
1950 static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
1951 {
1952         static u_char goto_buf[8];
1953         static int num;
1954         int maxlen;
1955         char *cp;
1956         u16 wch;
1957
1958         if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
1959                 goto do_goto;
1960         if (type == KT_LATIN && ch == '\n')
1961                 goto do_goto;
1962         if (type != 0)
1963                 goto oops;
1964         if (ch == 8) {
1965                 u16 wch;
1966
1967                 if (num == 0)
1968                         return -1;
1969                 wch = goto_buf[--num];
1970                 goto_buf[num] = '\0';
1971                 spkup_write(&wch, 1);
1972                 return 1;
1973         }
1974         if (ch < '+' || ch > 'y')
1975                 goto oops;
1976         wch = ch;
1977         goto_buf[num++] = ch;
1978         goto_buf[num] = '\0';
1979         spkup_write(&wch, 1);
1980         maxlen = (*goto_buf >= '0') ? 3 : 4;
1981         if ((ch == '+' || ch == '-') && num == 1)
1982                 return 1;
1983         if (ch >= '0' && ch <= '9' && num < maxlen)
1984                 return 1;
1985         if (num < maxlen - 1 || num > maxlen)
1986                 goto oops;
1987         if (ch < 'x' || ch > 'y') {
1988 oops:
1989                 if (!spk_killed)
1990                         synth_printf(" %s\n", spk_msg_get(MSG_GOTO_CANCELED));
1991                 goto_buf[num = 0] = '\0';
1992                 spk_special_handler = NULL;
1993                 return 1;
1994         }
1995
1996         /* Do not replace with kstrtoul: here we need cp to be updated */
1997         goto_pos = simple_strtoul(goto_buf, &cp, 10);
1998
1999         if (*cp == 'x') {
2000                 if (*goto_buf < '0')
2001                         goto_pos += spk_x;
2002                 else if (goto_pos > 0)
2003                         goto_pos--;
2004
2005                 if (goto_pos >= vc->vc_cols)
2006                         goto_pos = vc->vc_cols - 1;
2007                 goto_x = 1;
2008         } else {
2009                 if (*goto_buf < '0')
2010                         goto_pos += spk_y;
2011                 else if (goto_pos > 0)
2012                         goto_pos--;
2013
2014                 if (goto_pos >= vc->vc_rows)
2015                         goto_pos = vc->vc_rows - 1;
2016                 goto_x = 0;
2017         }
2018         goto_buf[num = 0] = '\0';
2019 do_goto:
2020         spk_special_handler = NULL;
2021         spk_parked |= 0x01;
2022         if (goto_x) {
2023                 spk_pos -= spk_x * 2;
2024                 spk_x = goto_pos;
2025                 spk_pos += goto_pos * 2;
2026                 say_word(vc);
2027         } else {
2028                 spk_y = goto_pos;
2029                 spk_pos = vc->vc_origin + (goto_pos * vc->vc_size_row);
2030                 say_line(vc);
2031         }
2032         return 1;
2033 }
2034
2035 static void speakup_goto(struct vc_data *vc)
2036 {
2037         if (spk_special_handler) {
2038                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
2039                 return;
2040         }
2041         synth_printf("%s\n", spk_msg_get(MSG_GOTO));
2042         spk_special_handler = handle_goto;
2043 }
2044
2045 static void speakup_help(struct vc_data *vc)
2046 {
2047         spk_handle_help(vc, KT_SPKUP, SPEAKUP_HELP, 0);
2048 }
2049
2050 static void do_nothing(struct vc_data *vc)
2051 {
2052         return;                 /* flush done in do_spkup */
2053 }
2054
2055 static u_char key_speakup, spk_key_locked;
2056
2057 static void speakup_lock(struct vc_data *vc)
2058 {
2059         if (!spk_key_locked) {
2060                 spk_key_locked = 16;
2061                 key_speakup = 16;
2062         } else {
2063                 spk_key_locked = 0;
2064                 key_speakup = 0;
2065         }
2066 }
2067
2068 typedef void (*spkup_hand) (struct vc_data *);
2069 static spkup_hand spkup_handler[] = {
2070         /* must be ordered same as defines in speakup.h */
2071         do_nothing, speakup_goto, speech_kill, speakup_shut_up,
2072         speakup_cut, speakup_paste, say_first_char, say_last_char,
2073         say_char, say_prev_char, say_next_char,
2074         say_word, say_prev_word, say_next_word,
2075         say_line, say_prev_line, say_next_line,
2076         top_edge, bottom_edge, left_edge, right_edge,
2077         spell_word, spell_word, say_screen,
2078         say_position, say_attributes,
2079         speakup_off, speakup_parked, say_line,  /* this is for indent */
2080         say_from_top, say_to_bottom,
2081         say_from_left, say_to_right,
2082         say_char_num, speakup_bits, speakup_bits, say_phonetic_char,
2083         speakup_bits, speakup_bits, speakup_bits,
2084         speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say,
2085         speakup_lock, speakup_help, toggle_cursoring, read_all_doc, NULL
2086 };
2087
2088 static void do_spkup(struct vc_data *vc, u_char value)
2089 {
2090         if (spk_killed && value != SPEECH_KILL)
2091                 return;
2092         spk_keydown = 0;
2093         spk_lastkey = 0;
2094         spk_shut_up &= 0xfe;
2095         this_speakup_key = value;
2096         if (value < SPKUP_MAX_FUNC && spkup_handler[value]) {
2097                 spk_do_flush();
2098                 (*spkup_handler[value]) (vc);
2099         } else {
2100                 if (inc_dec_var(value) < 0)
2101                         bleep(9);
2102         }
2103 }
2104
2105 static const char *pad_chars = "0123456789+-*/\015,.?()";
2106
2107 static int
2108 speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym,
2109             int up_flag)
2110 {
2111         unsigned long flags;
2112         int kh;
2113         u_char *key_info;
2114         u_char type = KTYP(keysym), value = KVAL(keysym), new_key = 0;
2115         u_char shift_info, offset;
2116         int ret = 0;
2117
2118         if (!synth)
2119                 return 0;
2120
2121         spin_lock_irqsave(&speakup_info.spinlock, flags);
2122         tty = vc->port.tty;
2123         if (type >= 0xf0)
2124                 type -= 0xf0;
2125         if (type == KT_PAD &&
2126             (vt_get_leds(fg_console, VC_NUMLOCK))) {
2127                 if (up_flag) {
2128                         spk_keydown = 0;
2129                         goto out;
2130                 }
2131                 value = pad_chars[value];
2132                 spk_lastkey = value;
2133                 spk_keydown++;
2134                 spk_parked &= 0xfe;
2135                 goto no_map;
2136         }
2137         if (keycode >= MAX_KEY)
2138                 goto no_map;
2139         key_info = spk_our_keys[keycode];
2140         if (!key_info)
2141                 goto no_map;
2142         /* Check valid read all mode keys */
2143         if ((cursor_track == read_all_mode) && (!up_flag)) {
2144                 switch (value) {
2145                 case KVAL(K_DOWN):
2146                 case KVAL(K_UP):
2147                 case KVAL(K_LEFT):
2148                 case KVAL(K_RIGHT):
2149                 case KVAL(K_PGUP):
2150                 case KVAL(K_PGDN):
2151                         break;
2152                 default:
2153                         stop_read_all(vc);
2154                         break;
2155                 }
2156         }
2157         shift_info = (shift_state & 0x0f) + key_speakup;
2158         offset = spk_shift_table[shift_info];
2159         if (offset) {
2160                 new_key = key_info[offset];
2161                 if (new_key) {
2162                         ret = 1;
2163                         if (new_key == SPK_KEY) {
2164                                 if (!spk_key_locked)
2165                                         key_speakup = (up_flag) ? 0 : 16;
2166                                 if (up_flag || spk_killed)
2167                                         goto out;
2168                                 spk_shut_up &= 0xfe;
2169                                 spk_do_flush();
2170                                 goto out;
2171                         }
2172                         if (up_flag)
2173                                 goto out;
2174                         if (last_keycode == keycode &&
2175                             time_after(last_spk_jiffy + MAX_DELAY, jiffies)) {
2176                                 spk_close_press = 1;
2177                                 offset = spk_shift_table[shift_info + 32];
2178                                 /* double press? */
2179                                 if (offset && key_info[offset])
2180                                         new_key = key_info[offset];
2181                         }
2182                         last_keycode = keycode;
2183                         last_spk_jiffy = jiffies;
2184                         type = KT_SPKUP;
2185                         value = new_key;
2186                 }
2187         }
2188 no_map:
2189         if (type == KT_SPKUP && !spk_special_handler) {
2190                 do_spkup(vc, new_key);
2191                 spk_close_press = 0;
2192                 ret = 1;
2193                 goto out;
2194         }
2195         if (up_flag || spk_killed || type == KT_SHIFT)
2196                 goto out;
2197         spk_shut_up &= 0xfe;
2198         kh = (value == KVAL(K_DOWN)) ||
2199             (value == KVAL(K_UP)) ||
2200             (value == KVAL(K_LEFT)) ||
2201             (value == KVAL(K_RIGHT));
2202         if ((cursor_track != read_all_mode) || !kh)
2203                 if (!spk_no_intr)
2204                         spk_do_flush();
2205         if (spk_special_handler) {
2206                 if (type == KT_SPEC && value == 1) {
2207                         value = '\n';
2208                         type = KT_LATIN;
2209                 } else if (type == KT_LETTER) {
2210                         type = KT_LATIN;
2211                 } else if (value == 0x7f) {
2212                         value = 8;      /* make del = backspace */
2213                 }
2214                 ret = (*spk_special_handler) (vc, type, value, keycode);
2215                 spk_close_press = 0;
2216                 if (ret < 0)
2217                         bleep(9);
2218                 goto out;
2219         }
2220         last_keycode = 0;
2221 out:
2222         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
2223         return ret;
2224 }
2225
2226 static int keyboard_notifier_call(struct notifier_block *nb,
2227                                   unsigned long code, void *_param)
2228 {
2229         struct keyboard_notifier_param *param = _param;
2230         struct vc_data *vc = param->vc;
2231         int up = !param->down;
2232         int ret = NOTIFY_OK;
2233         static int keycode;     /* to hold the current keycode */
2234
2235         in_keyboard_notifier = 1;
2236
2237         if (vc->vc_mode == KD_GRAPHICS)
2238                 goto out;
2239
2240         /*
2241          * First, determine whether we are handling a fake keypress on
2242          * the current processor.  If we are, then return NOTIFY_OK,
2243          * to pass the keystroke up the chain.  This prevents us from
2244          * trying to take the Speakup lock while it is held by the
2245          * processor on which the simulated keystroke was generated.
2246          * Also, the simulated keystrokes should be ignored by Speakup.
2247          */
2248
2249         if (speakup_fake_key_pressed())
2250                 goto out;
2251
2252         switch (code) {
2253         case KBD_KEYCODE:
2254                 /* speakup requires keycode and keysym currently */
2255                 keycode = param->value;
2256                 break;
2257         case KBD_UNBOUND_KEYCODE:
2258                 /* not used yet */
2259                 break;
2260         case KBD_UNICODE:
2261                 /* not used yet */
2262                 break;
2263         case KBD_KEYSYM:
2264                 if (speakup_key(vc, param->shift, keycode, param->value, up))
2265                         ret = NOTIFY_STOP;
2266                 else if (KTYP(param->value) == KT_CUR)
2267                         ret = pre_handle_cursor(vc, KVAL(param->value), up);
2268                 break;
2269         case KBD_POST_KEYSYM:{
2270                         unsigned char type = KTYP(param->value) - 0xf0;
2271                         unsigned char val = KVAL(param->value);
2272
2273                         switch (type) {
2274                         case KT_SHIFT:
2275                                 do_handle_shift(vc, val, up);
2276                                 break;
2277                         case KT_LATIN:
2278                         case KT_LETTER:
2279                                 do_handle_latin(vc, val, up);
2280                                 break;
2281                         case KT_CUR:
2282                                 do_handle_cursor(vc, val, up);
2283                                 break;
2284                         case KT_SPEC:
2285                                 do_handle_spec(vc, val, up);
2286                                 break;
2287                         }
2288                         break;
2289                 }
2290         }
2291 out:
2292         in_keyboard_notifier = 0;
2293         return ret;
2294 }
2295
2296 static int vt_notifier_call(struct notifier_block *nb,
2297                             unsigned long code, void *_param)
2298 {
2299         struct vt_notifier_param *param = _param;
2300         struct vc_data *vc = param->vc;
2301
2302         switch (code) {
2303         case VT_ALLOCATE:
2304                 if (vc->vc_mode == KD_TEXT)
2305                         speakup_allocate(vc, GFP_ATOMIC);
2306                 break;
2307         case VT_DEALLOCATE:
2308                 speakup_deallocate(vc);
2309                 break;
2310         case VT_WRITE:
2311                 if (param->c == '\b') {
2312                         speakup_bs(vc);
2313                 } else {
2314                         u16 d = param->c;
2315
2316                         speakup_con_write(vc, &d, 1);
2317                 }
2318                 break;
2319         case VT_UPDATE:
2320                 speakup_con_update(vc);
2321                 break;
2322         }
2323         return NOTIFY_OK;
2324 }
2325
2326 /* called by: module_exit() */
2327 static void __exit speakup_exit(void)
2328 {
2329         int i;
2330
2331         unregister_keyboard_notifier(&keyboard_notifier_block);
2332         unregister_vt_notifier(&vt_notifier_block);
2333         speakup_unregister_devsynth();
2334         speakup_cancel_selection();
2335         speakup_cancel_paste();
2336         del_timer_sync(&cursor_timer);
2337         kthread_stop(speakup_task);
2338         speakup_task = NULL;
2339         mutex_lock(&spk_mutex);
2340         synth_release();
2341         mutex_unlock(&spk_mutex);
2342         spk_ttyio_unregister_ldisc();
2343
2344         speakup_kobj_exit();
2345
2346         for (i = 0; i < MAX_NR_CONSOLES; i++)
2347                 kfree(speakup_console[i]);
2348
2349         speakup_remove_virtual_keyboard();
2350
2351         for (i = 0; i < MAXVARS; i++)
2352                 speakup_unregister_var(i);
2353
2354         for (i = 0; i < 256; i++) {
2355                 if (spk_characters[i] != spk_default_chars[i])
2356                         kfree(spk_characters[i]);
2357         }
2358
2359         spk_free_user_msgs();
2360 }
2361
2362 /* call by: module_init() */
2363 static int __init speakup_init(void)
2364 {
2365         int i;
2366         long err = 0;
2367         struct vc_data *vc = vc_cons[fg_console].d;
2368         struct var_t *var;
2369
2370         /* These first few initializations cannot fail. */
2371         spk_initialize_msgs();  /* Initialize arrays for i18n. */
2372         spk_reset_default_chars();
2373         spk_reset_default_chartab();
2374         spk_strlwr(synth_name);
2375         spk_vars[0].u.n.high = vc->vc_cols;
2376         for (var = spk_vars; var->var_id != MAXVARS; var++)
2377                 speakup_register_var(var);
2378         for (var = synth_time_vars;
2379              (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
2380                 speakup_register_var(var);
2381         for (i = 1; spk_punc_info[i].mask != 0; i++)
2382                 spk_set_mask_bits(NULL, i, 2);
2383
2384         spk_set_key_info(spk_key_defaults, spk_key_buf);
2385
2386         /* From here on out, initializations can fail. */
2387         err = speakup_add_virtual_keyboard();
2388         if (err)
2389                 goto error_virtkeyboard;
2390
2391         for (i = 0; i < MAX_NR_CONSOLES; i++)
2392                 if (vc_cons[i].d) {
2393                         err = speakup_allocate(vc_cons[i].d, GFP_KERNEL);
2394                         if (err)
2395                                 goto error_kobjects;
2396                 }
2397
2398         if (spk_quiet_boot)
2399                 spk_shut_up |= 0x01;
2400
2401         err = speakup_kobj_init();
2402         if (err)
2403                 goto error_kobjects;
2404
2405         spk_ttyio_register_ldisc();
2406         synth_init(synth_name);
2407         speakup_register_devsynth();
2408         /*
2409          * register_devsynth might fail, but this error is not fatal.
2410          * /dev/synth is an extra feature; the rest of Speakup
2411          * will work fine without it.
2412          */
2413
2414         err = register_keyboard_notifier(&keyboard_notifier_block);
2415         if (err)
2416                 goto error_kbdnotifier;
2417         err = register_vt_notifier(&vt_notifier_block);
2418         if (err)
2419                 goto error_vtnotifier;
2420
2421         speakup_task = kthread_create(speakup_thread, NULL, "speakup");
2422
2423         if (IS_ERR(speakup_task)) {
2424                 err = PTR_ERR(speakup_task);
2425                 goto error_task;
2426         }
2427
2428         set_user_nice(speakup_task, 10);
2429         wake_up_process(speakup_task);
2430
2431         pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
2432         pr_info("synth name on entry is: %s\n", synth_name);
2433         goto out;
2434
2435 error_task:
2436         unregister_vt_notifier(&vt_notifier_block);
2437
2438 error_vtnotifier:
2439         unregister_keyboard_notifier(&keyboard_notifier_block);
2440         del_timer(&cursor_timer);
2441
2442 error_kbdnotifier:
2443         speakup_unregister_devsynth();
2444         mutex_lock(&spk_mutex);
2445         synth_release();
2446         mutex_unlock(&spk_mutex);
2447         speakup_kobj_exit();
2448
2449 error_kobjects:
2450         for (i = 0; i < MAX_NR_CONSOLES; i++)
2451                 kfree(speakup_console[i]);
2452
2453         speakup_remove_virtual_keyboard();
2454
2455 error_virtkeyboard:
2456         for (i = 0; i < MAXVARS; i++)
2457                 speakup_unregister_var(i);
2458
2459         for (i = 0; i < 256; i++) {
2460                 if (spk_characters[i] != spk_default_chars[i])
2461                         kfree(spk_characters[i]);
2462         }
2463
2464         spk_free_user_msgs();
2465
2466 out:
2467         return err;
2468 }
2469
2470 module_param_named(bell_pos, spk_vars[BELL_POS_ID].u.n.default_val, int, 0444);
2471 module_param_named(spell_delay, spk_vars[SPELL_DELAY_ID].u.n.default_val, int, 0444);
2472 module_param_named(attrib_bleep, spk_vars[ATTRIB_BLEEP_ID].u.n.default_val, int, 0444);
2473 module_param_named(bleeps, spk_vars[BLEEPS_ID].u.n.default_val, int, 0444);
2474 module_param_named(bleep_time, spk_vars[BLEEP_TIME_ID].u.n.default_val, int, 0444);
2475 module_param_named(punc_level, spk_vars[PUNC_LEVEL_ID].u.n.default_val, int, 0444);
2476 module_param_named(reading_punc, spk_vars[READING_PUNC_ID].u.n.default_val, int, 0444);
2477 module_param_named(cursor_time, spk_vars[CURSOR_TIME_ID].u.n.default_val, int, 0444);
2478 module_param_named(say_control, spk_vars[SAY_CONTROL_ID].u.n.default_val, int, 0444);
2479 module_param_named(say_word_ctl, spk_vars[SAY_WORD_CTL_ID].u.n.default_val, int, 0444);
2480 module_param_named(no_interrupt, spk_vars[NO_INTERRUPT_ID].u.n.default_val, int, 0444);
2481 module_param_named(key_echo, spk_vars[KEY_ECHO_ID].u.n.default_val, int, 0444);
2482 module_param_named(cur_phonetic, spk_vars[CUR_PHONETIC_ID].u.n.default_val, int, 0444);
2483
2484 MODULE_PARM_DESC(bell_pos, "This works much like a typewriter bell. If for example 72 is echoed to bell_pos, it will beep the PC speaker when typing on a line past character 72.");
2485 MODULE_PARM_DESC(spell_delay, "This controls how fast a word is spelled when speakup's spell word review command is pressed.");
2486 MODULE_PARM_DESC(attrib_bleep, "Beeps the PC speaker when there is an attribute change such as background color when using speakup review commands. One = on, zero = off.");
2487 MODULE_PARM_DESC(bleeps, "This controls whether one hears beeps through the PC speaker when using speakup review commands.");
2488 MODULE_PARM_DESC(bleep_time, "This controls the duration of the PC speaker beeps speakup produces.");
2489 MODULE_PARM_DESC(punc_level, "Controls the level of punctuation spoken as the screen is displayed, not reviewed.");
2490 MODULE_PARM_DESC(reading_punc, "It controls the level of punctuation when reviewing the screen with speakup's screen review commands.");
2491 MODULE_PARM_DESC(cursor_time, "This controls cursor delay when using arrow keys.");
2492 MODULE_PARM_DESC(say_control, "This controls if speakup speaks shift, alt and control when those keys are pressed or not.");
2493 MODULE_PARM_DESC(say_word_ctl, "Sets the say_word_ctl on load.");
2494 MODULE_PARM_DESC(no_interrupt, "Controls if typing interrupts output from speakup.");
2495 MODULE_PARM_DESC(key_echo, "Controls if speakup speaks keys when they are typed. One = on zero = off or don't echo keys.");
2496 MODULE_PARM_DESC(cur_phonetic, "Controls if speakup speaks letters phonetically during navigation. One = on zero = off or don't speak phonetically.");
2497
2498 module_init(speakup_init);
2499 module_exit(speakup_exit);