GNU Linux-libre 5.10.153-gnu1
[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 char spk_str_caps_start[MAXVARLEN + 1] = "\0";
69 char spk_str_caps_stop[MAXVARLEN + 1] = "\0";
70 char spk_str_pause[MAXVARLEN + 1] = "\0";
71 bool spk_paused;
72 const struct st_bits_data spk_punc_info[] = {
73         {"none", "", 0},
74         {"some", "/$%&@", SOME},
75         {"most", "$%&#()=+*/@^<>|\\", MOST},
76         {"all", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", PUNC},
77         {"delimiters", "", B_WDLM},
78         {"repeats", "()", CH_RPT},
79         {"extended numeric", "", B_EXNUM},
80         {"symbols", "", B_SYM},
81         {NULL, NULL}
82 };
83
84 static char mark_cut_flag;
85 #define MAX_KEY 160
86 static u_char *spk_shift_table;
87 u_char *spk_our_keys[MAX_KEY];
88 u_char spk_key_buf[600];
89 const u_char spk_key_defaults[] = {
90 #include "speakupmap.h"
91 };
92
93 /* Speakup Cursor Track Variables */
94 static int cursor_track = 1, prev_cursor_track = 1;
95
96 /* cursor track modes, must be ordered same as cursor_msgs */
97 enum {
98         CT_Off = 0,
99         CT_On,
100         CT_Highlight,
101         CT_Window,
102         CT_Max
103 };
104
105 #define read_all_mode CT_Max
106
107 static struct tty_struct *tty;
108
109 static void spkup_write(const u16 *in_buf, int count);
110
111 static char *phonetic[] = {
112         "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel",
113         "india", "juliett", "keelo", "leema", "mike", "november", "oscar",
114             "papa",
115         "keh beck", "romeo", "sierra", "tango", "uniform", "victer", "whiskey",
116         "x ray", "yankee", "zulu"
117 };
118
119 /* array of 256 char pointers (one for each character description)
120  * initialized to default_chars and user selectable via
121  * /proc/speakup/characters
122  */
123 char *spk_characters[256];
124
125 char *spk_default_chars[256] = {
126 /*000*/ "null", "^a", "^b", "^c", "^d", "^e", "^f", "^g",
127 /*008*/ "^h", "^i", "^j", "^k", "^l", "^m", "^n", "^o",
128 /*016*/ "^p", "^q", "^r", "^s", "^t", "^u", "^v", "^w",
129 /*024*/ "^x", "^y", "^z", "control", "control", "control", "control",
130             "control",
131 /*032*/ "space", "bang!", "quote", "number", "dollar", "percent", "and",
132             "tick",
133 /*040*/ "left paren", "right paren", "star", "plus", "comma", "dash",
134             "dot",
135         "slash",
136 /*048*/ "zero", "one", "two", "three", "four", "five", "six", "seven",
137         "eight", "nine",
138 /*058*/ "colon", "semmy", "less", "equals", "greater", "question", "at",
139 /*065*/ "EIGH", "B", "C", "D", "E", "F", "G",
140 /*072*/ "H", "I", "J", "K", "L", "M", "N", "O",
141 /*080*/ "P", "Q", "R", "S", "T", "U", "V", "W", "X",
142 /*089*/ "Y", "ZED", "left bracket", "backslash", "right bracket",
143             "caret",
144         "line",
145 /*096*/ "accent", "a", "b", "c", "d", "e", "f", "g",
146 /*104*/ "h", "i", "j", "k", "l", "m", "n", "o",
147 /*112*/ "p", "q", "r", "s", "t", "u", "v", "w",
148 /*120*/ "x", "y", "zed", "left brace", "bar", "right brace", "tihlduh",
149 /*127*/ "del", "control", "control", "control", "control", "control",
150             "control", "control", "control", "control", "control",
151 /*138*/ "control", "control", "control", "control", "control",
152             "control", "control", "control", "control", "control",
153             "control", "control",
154 /*150*/ "control", "control", "control", "control", "control",
155             "control", "control", "control", "control", "control",
156 /*160*/ "nbsp", "inverted bang",
157 /*162*/ "cents", "pounds", "currency", "yen", "broken bar", "section",
158 /*168*/ "diaeresis", "copyright", "female ordinal", "double left angle",
159 /*172*/ "not", "soft hyphen", "registered", "macron",
160 /*176*/ "degrees", "plus or minus", "super two", "super three",
161 /*180*/ "acute accent", "micro", "pilcrow", "middle dot",
162 /*184*/ "cedilla", "super one", "male ordinal", "double right angle",
163 /*188*/ "one quarter", "one half", "three quarters",
164             "inverted question",
165 /*192*/ "A GRAVE", "A ACUTE", "A CIRCUMFLEX", "A TILDE", "A OOMLAUT",
166             "A RING",
167 /*198*/ "AE", "C CIDELLA", "E GRAVE", "E ACUTE", "E CIRCUMFLEX",
168             "E OOMLAUT",
169 /*204*/ "I GRAVE", "I ACUTE", "I CIRCUMFLEX", "I OOMLAUT", "ETH",
170             "N TILDE",
171 /*210*/ "O GRAVE", "O ACUTE", "O CIRCUMFLEX", "O TILDE", "O OOMLAUT",
172 /*215*/ "multiplied by", "O STROKE", "U GRAVE", "U ACUTE",
173             "U CIRCUMFLEX",
174 /*220*/ "U OOMLAUT", "Y ACUTE", "THORN", "sharp s", "a grave",
175 /*225*/ "a acute", "a circumflex", "a tilde", "a oomlaut", "a ring",
176 /*230*/ "ae", "c cidella", "e grave", "e acute",
177 /*234*/ "e circumflex", "e oomlaut", "i grave", "i acute",
178             "i circumflex",
179 /*239*/ "i oomlaut", "eth", "n tilde", "o grave", "o acute",
180             "o circumflex",
181 /*245*/ "o tilde", "o oomlaut", "divided by", "o stroke", "u grave",
182             "u acute",
183 /* 251 */ "u circumflex", "u oomlaut", "y acute", "thorn", "y oomlaut"
184 };
185
186 /* array of 256 u_short (one for each character)
187  * initialized to default_chartab and user selectable via
188  * /sys/module/speakup/parameters/chartab
189  */
190 u_short spk_chartab[256];
191
192 static u_short default_chartab[256] = {
193         B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 0-7 */
194         B_CTL, B_CTL, A_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 8-15 */
195         B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /*16-23 */
196         B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, B_CTL, /* 24-31 */
197         WDLM, A_PUNC, PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC,     /*  !"#$%&' */
198         PUNC, PUNC, PUNC, PUNC, A_PUNC, A_PUNC, A_PUNC, PUNC,   /* ()*+, -./ */
199         NUM, NUM, NUM, NUM, NUM, NUM, NUM, NUM, /* 01234567 */
200         NUM, NUM, A_PUNC, PUNC, PUNC, PUNC, PUNC, A_PUNC,       /* 89:;<=>? */
201         PUNC, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP,  /* @ABCDEFG */
202         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* HIJKLMNO */
203         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* PQRSTUVW */
204         A_CAP, A_CAP, A_CAP, PUNC, PUNC, PUNC, PUNC, PUNC,      /* XYZ[\]^_ */
205         PUNC, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA,  /* `abcdefg */
206         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* hijklmno */
207         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* pqrstuvw */
208         ALPHA, ALPHA, ALPHA, PUNC, PUNC, PUNC, PUNC, 0, /* xyz{|}~ */
209         B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 128-134 */
210         B_SYM,  /* 135 */
211         B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 136-142 */
212         B_CAPSYM,       /* 143 */
213         B_CAPSYM, B_CAPSYM, B_SYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, /* 144-150 */
214         B_SYM,  /* 151 */
215         B_SYM, B_SYM, B_CAPSYM, B_CAPSYM, B_SYM, B_SYM, B_SYM, /*152-158 */
216         B_SYM,  /* 159 */
217         WDLM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_CAPSYM, /* 160-166 */
218         B_SYM,  /* 167 */
219         B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 168-175 */
220         B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 176-183 */
221         B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, B_SYM, /* 184-191 */
222         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* 192-199 */
223         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, /* 200-207 */
224         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, B_SYM, /* 208-215 */
225         A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, A_CAP, ALPHA, /* 216-223 */
226         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* 224-231 */
227         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, /* 232-239 */
228         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, B_SYM, /* 240-247 */
229         ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA, ALPHA  /* 248-255 */
230 };
231
232 struct task_struct *speakup_task;
233 struct bleep spk_unprocessed_sound;
234 static int spk_keydown;
235 static u16 spk_lastkey;
236 static u_char spk_close_press, keymap_flags;
237 static u_char last_keycode, this_speakup_key;
238 static u_long last_spk_jiffy;
239
240 struct st_spk_t *speakup_console[MAX_NR_CONSOLES];
241
242 DEFINE_MUTEX(spk_mutex);
243
244 static int keyboard_notifier_call(struct notifier_block *,
245                                   unsigned long code, void *param);
246
247 static struct notifier_block keyboard_notifier_block = {
248         .notifier_call = keyboard_notifier_call,
249 };
250
251 static int vt_notifier_call(struct notifier_block *,
252                             unsigned long code, void *param);
253
254 static struct notifier_block vt_notifier_block = {
255         .notifier_call = vt_notifier_call,
256 };
257
258 static unsigned char get_attributes(struct vc_data *vc, u16 *pos)
259 {
260         pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, 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         if (fg > 8) {
394                 synth_printf("%s ", spk_msg_get(MSG_BRIGHT));
395                 fg -= 8;
396         }
397         synth_printf("%s", spk_msg_get(MSG_COLORS_START + fg));
398         if (bg > 7) {
399                 synth_printf(" %s ", spk_msg_get(MSG_ON_BLINKING));
400                 bg -= 8;
401         } else {
402                 synth_printf(" %s ", spk_msg_get(MSG_ON));
403         }
404         synth_printf("%s\n", spk_msg_get(MSG_COLORS_START + bg));
405 }
406
407 enum {
408         edge_top = 1,
409         edge_bottom,
410         edge_left,
411         edge_right,
412         edge_quiet
413 };
414
415 static void announce_edge(struct vc_data *vc, int msg_id)
416 {
417         if (spk_bleeps & 1)
418                 bleep(spk_y);
419         if ((spk_bleeps & 2) && (msg_id < edge_quiet))
420                 synth_printf("%s\n",
421                              spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
422 }
423
424 static void speak_char(u16 ch)
425 {
426         char *cp;
427         struct var_t *direct = spk_get_var(DIRECT);
428
429         if (ch >= 0x100 || (direct && direct->u.n.value)) {
430                 if (ch < 0x100 && IS_CHAR(ch, B_CAP)) {
431                         spk_pitch_shift++;
432                         synth_printf("%s", spk_str_caps_start);
433                 }
434                 synth_putwc_s(ch);
435                 if (ch < 0x100 && IS_CHAR(ch, B_CAP))
436                         synth_printf("%s", spk_str_caps_stop);
437                 return;
438         }
439
440         cp = spk_characters[ch];
441         if (!cp) {
442                 pr_info("%s: cp == NULL!\n", __func__);
443                 return;
444         }
445         if (IS_CHAR(ch, B_CAP)) {
446                 spk_pitch_shift++;
447                 synth_printf("%s %s %s",
448                              spk_str_caps_start, cp, spk_str_caps_stop);
449         } else {
450                 if (*cp == '^') {
451                         cp++;
452                         synth_printf(" %s%s ", spk_msg_get(MSG_CTRL), cp);
453                 } else {
454                         synth_printf(" %s ", cp);
455                 }
456         }
457 }
458
459 static u16 get_char(struct vc_data *vc, u16 *pos, u_char *attribs)
460 {
461         u16 ch = ' ';
462
463         if (vc && pos) {
464                 u16 w;
465                 u16 c;
466
467                 pos = screen_pos(vc, pos - (u16 *)vc->vc_origin, true);
468                 w = scr_readw(pos);
469                 c = w & 0xff;
470
471                 if (w & vc->vc_hi_font_mask) {
472                         w &= ~vc->vc_hi_font_mask;
473                         c |= 0x100;
474                 }
475
476                 ch = inverse_translate(vc, c, 1);
477                 *attribs = (w & 0xff00) >> 8;
478         }
479         return ch;
480 }
481
482 static void say_char(struct vc_data *vc)
483 {
484         u16 ch;
485
486         spk_old_attr = spk_attr;
487         ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
488         if (spk_attr != spk_old_attr) {
489                 if (spk_attrib_bleep & 1)
490                         bleep(spk_y);
491                 if (spk_attrib_bleep & 2)
492                         say_attributes(vc);
493         }
494         speak_char(ch);
495 }
496
497 static void say_phonetic_char(struct vc_data *vc)
498 {
499         u16 ch;
500
501         spk_old_attr = spk_attr;
502         ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
503         if (ch <= 0x7f && isalpha(ch)) {
504                 ch &= 0x1f;
505                 synth_printf("%s\n", phonetic[--ch]);
506         } else {
507                 if (ch < 0x100 && IS_CHAR(ch, B_NUM))
508                         synth_printf("%s ", spk_msg_get(MSG_NUMBER));
509                 speak_char(ch);
510         }
511 }
512
513 static void say_prev_char(struct vc_data *vc)
514 {
515         spk_parked |= 0x01;
516         if (spk_x == 0) {
517                 announce_edge(vc, edge_left);
518                 return;
519         }
520         spk_x--;
521         spk_pos -= 2;
522         say_char(vc);
523 }
524
525 static void say_next_char(struct vc_data *vc)
526 {
527         spk_parked |= 0x01;
528         if (spk_x == vc->vc_cols - 1) {
529                 announce_edge(vc, edge_right);
530                 return;
531         }
532         spk_x++;
533         spk_pos += 2;
534         say_char(vc);
535 }
536
537 /* get_word - will first check to see if the character under the
538  * reading cursor is a space and if spk_say_word_ctl is true it will
539  * return the word space.  If spk_say_word_ctl is not set it will check to
540  * see if there is a word starting on the next position to the right
541  * and return that word if it exists.  If it does not exist it will
542  * move left to the beginning of any previous word on the line or the
543  * beginning off the line whichever comes first..
544  */
545
546 static u_long get_word(struct vc_data *vc)
547 {
548         u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
549         u16 ch;
550         u16 attr_ch;
551         u_char temp;
552
553         spk_old_attr = spk_attr;
554         ch = get_char(vc, (u_short *)tmp_pos, &temp);
555
556 /* decided to take out the sayword if on a space (mis-information */
557         if (spk_say_word_ctl && ch == SPACE) {
558                 *buf = '\0';
559                 synth_printf("%s\n", spk_msg_get(MSG_SPACE));
560                 return 0;
561         } else if (tmpx < vc->vc_cols - 2 &&
562                    (ch == SPACE || ch == 0 || (ch < 0x100 && IS_WDLM(ch))) &&
563                    get_char(vc, (u_short *)tmp_pos + 1, &temp) > SPACE) {
564                 tmp_pos += 2;
565                 tmpx++;
566         } else {
567                 while (tmpx > 0) {
568                         ch = get_char(vc, (u_short *)tmp_pos - 1, &temp);
569                         if ((ch == SPACE || ch == 0 ||
570                              (ch < 0x100 && IS_WDLM(ch))) &&
571                             get_char(vc, (u_short *)tmp_pos, &temp) > SPACE)
572                                 break;
573                         tmp_pos -= 2;
574                         tmpx--;
575                 }
576         }
577         attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
578         buf[cnt++] = attr_ch;
579         while (tmpx < vc->vc_cols - 1) {
580                 tmp_pos += 2;
581                 tmpx++;
582                 ch = get_char(vc, (u_short *)tmp_pos, &temp);
583                 if (ch == SPACE || ch == 0 ||
584                     (buf[cnt - 1] < 0x100 && IS_WDLM(buf[cnt - 1]) &&
585                      ch > SPACE))
586                         break;
587                 buf[cnt++] = ch;
588         }
589         buf[cnt] = '\0';
590         return cnt;
591 }
592
593 static void say_word(struct vc_data *vc)
594 {
595         u_long cnt = get_word(vc);
596         u_short saved_punc_mask = spk_punc_mask;
597
598         if (cnt == 0)
599                 return;
600         spk_punc_mask = PUNC;
601         buf[cnt++] = SPACE;
602         spkup_write(buf, cnt);
603         spk_punc_mask = saved_punc_mask;
604 }
605
606 static void say_prev_word(struct vc_data *vc)
607 {
608         u_char temp;
609         u16 ch;
610         u_short edge_said = 0, last_state = 0, state = 0;
611
612         spk_parked |= 0x01;
613
614         if (spk_x == 0) {
615                 if (spk_y == 0) {
616                         announce_edge(vc, edge_top);
617                         return;
618                 }
619                 spk_y--;
620                 spk_x = vc->vc_cols;
621                 edge_said = edge_quiet;
622         }
623         while (1) {
624                 if (spk_x == 0) {
625                         if (spk_y == 0) {
626                                 edge_said = edge_top;
627                                 break;
628                         }
629                         if (edge_said != edge_quiet)
630                                 edge_said = edge_left;
631                         if (state > 0)
632                                 break;
633                         spk_y--;
634                         spk_x = vc->vc_cols - 1;
635                 } else {
636                         spk_x--;
637                 }
638                 spk_pos -= 2;
639                 ch = get_char(vc, (u_short *)spk_pos, &temp);
640                 if (ch == SPACE || ch == 0)
641                         state = 0;
642                 else if (ch < 0x100 && IS_WDLM(ch))
643                         state = 1;
644                 else
645                         state = 2;
646                 if (state < last_state) {
647                         spk_pos += 2;
648                         spk_x++;
649                         break;
650                 }
651                 last_state = state;
652         }
653         if (spk_x == 0 && edge_said == edge_quiet)
654                 edge_said = edge_left;
655         if (edge_said > 0 && edge_said < edge_quiet)
656                 announce_edge(vc, edge_said);
657         say_word(vc);
658 }
659
660 static void say_next_word(struct vc_data *vc)
661 {
662         u_char temp;
663         u16 ch;
664         u_short edge_said = 0, 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 > 0)
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 static struct var_t spk_vars[] = {
1273         /* bell must be first to set high limit */
1274         {BELL_POS, .u.n = {NULL, 0, 0, 0, 0, 0, NULL} },
1275         {SPELL_DELAY, .u.n = {NULL, 0, 0, 4, 0, 0, NULL} },
1276         {ATTRIB_BLEEP, .u.n = {NULL, 1, 0, 3, 0, 0, NULL} },
1277         {BLEEPS, .u.n = {NULL, 3, 0, 3, 0, 0, NULL} },
1278         {BLEEP_TIME, .u.n = {NULL, 30, 1, 200, 0, 0, NULL} },
1279         {PUNC_LEVEL, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1280         {READING_PUNC, .u.n = {NULL, 1, 0, 4, 0, 0, NULL} },
1281         {CURSOR_TIME, .u.n = {NULL, 120, 50, 600, 0, 0, NULL} },
1282         {SAY_CONTROL, TOGGLE_0},
1283         {SAY_WORD_CTL, TOGGLE_0},
1284         {NO_INTERRUPT, TOGGLE_0},
1285         {KEY_ECHO, .u.n = {NULL, 1, 0, 2, 0, 0, NULL} },
1286         V_LAST_VAR
1287 };
1288
1289 static void toggle_cursoring(struct vc_data *vc)
1290 {
1291         if (cursor_track == read_all_mode)
1292                 cursor_track = prev_cursor_track;
1293         if (++cursor_track >= CT_Max)
1294                 cursor_track = 0;
1295         synth_printf("%s\n", spk_msg_get(MSG_CURSOR_MSGS_START + cursor_track));
1296 }
1297
1298 void spk_reset_default_chars(void)
1299 {
1300         int i;
1301
1302         /* First, free any non-default */
1303         for (i = 0; i < 256; i++) {
1304                 if (spk_characters[i] &&
1305                     (spk_characters[i] != spk_default_chars[i]))
1306                         kfree(spk_characters[i]);
1307         }
1308
1309         memcpy(spk_characters, spk_default_chars, sizeof(spk_default_chars));
1310 }
1311
1312 void spk_reset_default_chartab(void)
1313 {
1314         memcpy(spk_chartab, default_chartab, sizeof(default_chartab));
1315 }
1316
1317 static const struct st_bits_data *pb_edit;
1318
1319 static int edit_bits(struct vc_data *vc, u_char type, u_char ch, u_short key)
1320 {
1321         short mask = pb_edit->mask, ch_type = spk_chartab[ch];
1322
1323         if (type != KT_LATIN || (ch_type & B_NUM) || ch < SPACE)
1324                 return -1;
1325         if (ch == SPACE) {
1326                 synth_printf("%s\n", spk_msg_get(MSG_EDIT_DONE));
1327                 spk_special_handler = NULL;
1328                 return 1;
1329         }
1330         if (mask < PUNC && !(ch_type & PUNC))
1331                 return -1;
1332         spk_chartab[ch] ^= mask;
1333         speak_char(ch);
1334         synth_printf(" %s\n",
1335                      (spk_chartab[ch] & mask) ? spk_msg_get(MSG_ON) :
1336                      spk_msg_get(MSG_OFF));
1337         return 1;
1338 }
1339
1340 /* Allocation concurrency is protected by the console semaphore */
1341 static int speakup_allocate(struct vc_data *vc, gfp_t gfp_flags)
1342 {
1343         int vc_num;
1344
1345         vc_num = vc->vc_num;
1346         if (!speakup_console[vc_num]) {
1347                 speakup_console[vc_num] = kzalloc(sizeof(*speakup_console[0]),
1348                                                   gfp_flags);
1349                 if (!speakup_console[vc_num])
1350                         return -ENOMEM;
1351                 speakup_date(vc);
1352         } else if (!spk_parked) {
1353                 speakup_date(vc);
1354         }
1355
1356         return 0;
1357 }
1358
1359 static void speakup_deallocate(struct vc_data *vc)
1360 {
1361         int vc_num;
1362
1363         vc_num = vc->vc_num;
1364         kfree(speakup_console[vc_num]);
1365         speakup_console[vc_num] = NULL;
1366 }
1367
1368 static u_char is_cursor;
1369 static u_long old_cursor_pos, old_cursor_x, old_cursor_y;
1370 static int cursor_con;
1371
1372 static void reset_highlight_buffers(struct vc_data *);
1373
1374 static int read_all_key;
1375
1376 static int in_keyboard_notifier;
1377
1378 static void start_read_all_timer(struct vc_data *vc, int command);
1379
1380 enum {
1381         RA_NOTHING,
1382         RA_NEXT_SENT,
1383         RA_PREV_LINE,
1384         RA_NEXT_LINE,
1385         RA_PREV_SENT,
1386         RA_DOWN_ARROW,
1387         RA_TIMER,
1388         RA_FIND_NEXT_SENT,
1389         RA_FIND_PREV_SENT,
1390 };
1391
1392 static void kbd_fakekey2(struct vc_data *vc, int command)
1393 {
1394         del_timer(&cursor_timer);
1395         speakup_fake_down_arrow();
1396         start_read_all_timer(vc, command);
1397 }
1398
1399 static void read_all_doc(struct vc_data *vc)
1400 {
1401         if ((vc->vc_num != fg_console) || !synth || spk_shut_up)
1402                 return;
1403         if (!synth_supports_indexing())
1404                 return;
1405         if (cursor_track != read_all_mode)
1406                 prev_cursor_track = cursor_track;
1407         cursor_track = read_all_mode;
1408         spk_reset_index_count(0);
1409         if (get_sentence_buf(vc, 0) == -1) {
1410                 del_timer(&cursor_timer);
1411                 if (!in_keyboard_notifier)
1412                         speakup_fake_down_arrow();
1413                 start_read_all_timer(vc, RA_DOWN_ARROW);
1414         } else {
1415                 say_sentence_num(0, 0);
1416                 synth_insert_next_index(0);
1417                 start_read_all_timer(vc, RA_TIMER);
1418         }
1419 }
1420
1421 static void stop_read_all(struct vc_data *vc)
1422 {
1423         del_timer(&cursor_timer);
1424         cursor_track = prev_cursor_track;
1425         spk_shut_up &= 0xfe;
1426         spk_do_flush();
1427 }
1428
1429 static void start_read_all_timer(struct vc_data *vc, int command)
1430 {
1431         struct var_t *cursor_timeout;
1432
1433         cursor_con = vc->vc_num;
1434         read_all_key = command;
1435         cursor_timeout = spk_get_var(CURSOR_TIME);
1436         mod_timer(&cursor_timer,
1437                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1438 }
1439
1440 static void handle_cursor_read_all(struct vc_data *vc, int command)
1441 {
1442         int indcount, sentcount, rv, sn;
1443
1444         switch (command) {
1445         case RA_NEXT_SENT:
1446                 /* Get Current Sentence */
1447                 spk_get_index_count(&indcount, &sentcount);
1448                 /*printk("%d %d  ", indcount, sentcount); */
1449                 spk_reset_index_count(sentcount + 1);
1450                 if (indcount == 1) {
1451                         if (!say_sentence_num(sentcount + 1, 0)) {
1452                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1453                                 return;
1454                         }
1455                         synth_insert_next_index(0);
1456                 } else {
1457                         sn = 0;
1458                         if (!say_sentence_num(sentcount + 1, 1)) {
1459                                 sn = 1;
1460                                 spk_reset_index_count(sn);
1461                         } else {
1462                                 synth_insert_next_index(0);
1463                         }
1464                         if (!say_sentence_num(sn, 0)) {
1465                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1466                                 return;
1467                         }
1468                         synth_insert_next_index(0);
1469                 }
1470                 start_read_all_timer(vc, RA_TIMER);
1471                 break;
1472         case RA_PREV_SENT:
1473                 break;
1474         case RA_NEXT_LINE:
1475                 read_all_doc(vc);
1476                 break;
1477         case RA_PREV_LINE:
1478                 break;
1479         case RA_DOWN_ARROW:
1480                 if (get_sentence_buf(vc, 0) == -1) {
1481                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1482                 } else {
1483                         say_sentence_num(0, 0);
1484                         synth_insert_next_index(0);
1485                         start_read_all_timer(vc, RA_TIMER);
1486                 }
1487                 break;
1488         case RA_FIND_NEXT_SENT:
1489                 rv = get_sentence_buf(vc, 0);
1490                 if (rv == -1)
1491                         read_all_doc(vc);
1492                 if (rv == 0) {
1493                         kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1494                 } else {
1495                         say_sentence_num(1, 0);
1496                         synth_insert_next_index(0);
1497                         start_read_all_timer(vc, RA_TIMER);
1498                 }
1499                 break;
1500         case RA_FIND_PREV_SENT:
1501                 break;
1502         case RA_TIMER:
1503                 spk_get_index_count(&indcount, &sentcount);
1504                 if (indcount < 2)
1505                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1506                 else
1507                         start_read_all_timer(vc, RA_TIMER);
1508                 break;
1509         }
1510 }
1511
1512 static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1513 {
1514         unsigned long flags;
1515
1516         spin_lock_irqsave(&speakup_info.spinlock, flags);
1517         if (cursor_track == read_all_mode) {
1518                 spk_parked &= 0xfe;
1519                 if (!synth || up_flag || spk_shut_up) {
1520                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1521                         return NOTIFY_STOP;
1522                 }
1523                 del_timer(&cursor_timer);
1524                 spk_shut_up &= 0xfe;
1525                 spk_do_flush();
1526                 start_read_all_timer(vc, value + 1);
1527                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1528                 return NOTIFY_STOP;
1529         }
1530         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1531         return NOTIFY_OK;
1532 }
1533
1534 static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1535 {
1536         unsigned long flags;
1537         struct var_t *cursor_timeout;
1538
1539         spin_lock_irqsave(&speakup_info.spinlock, flags);
1540         spk_parked &= 0xfe;
1541         if (!synth || up_flag || spk_shut_up || cursor_track == CT_Off) {
1542                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1543                 return;
1544         }
1545         spk_shut_up &= 0xfe;
1546         if (spk_no_intr)
1547                 spk_do_flush();
1548 /* the key press flushes if !no_inter but we want to flush on cursor
1549  * moves regardless of no_inter state
1550  */
1551         is_cursor = value + 1;
1552         old_cursor_pos = vc->vc_pos;
1553         old_cursor_x = vc->state.x;
1554         old_cursor_y = vc->state.y;
1555         speakup_console[vc->vc_num]->ht.cy = vc->state.y;
1556         cursor_con = vc->vc_num;
1557         if (cursor_track == CT_Highlight)
1558                 reset_highlight_buffers(vc);
1559         cursor_timeout = spk_get_var(CURSOR_TIME);
1560         mod_timer(&cursor_timer,
1561                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1562         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1563 }
1564
1565 static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
1566 {
1567         int i, bi, hi;
1568         int vc_num = vc->vc_num;
1569
1570         bi = (vc->vc_attr & 0x70) >> 4;
1571         hi = speakup_console[vc_num]->ht.highsize[bi];
1572
1573         i = 0;
1574         if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1575                 speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
1576                 speakup_console[vc_num]->ht.rx[bi] = vc->state.x;
1577                 speakup_console[vc_num]->ht.ry[bi] = vc->state.y;
1578         }
1579         while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
1580                 if (ic[i] > 32) {
1581                         speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
1582                         hi++;
1583                 } else if ((ic[i] == 32) && (hi != 0)) {
1584                         if (speakup_console[vc_num]->ht.highbuf[bi][hi - 1] !=
1585                             32) {
1586                                 speakup_console[vc_num]->ht.highbuf[bi][hi] =
1587                                     ic[i];
1588                                 hi++;
1589                         }
1590                 }
1591                 i++;
1592         }
1593         speakup_console[vc_num]->ht.highsize[bi] = hi;
1594 }
1595
1596 static void reset_highlight_buffers(struct vc_data *vc)
1597 {
1598         int i;
1599         int vc_num = vc->vc_num;
1600
1601         for (i = 0; i < 8; i++)
1602                 speakup_console[vc_num]->ht.highsize[i] = 0;
1603 }
1604
1605 static int count_highlight_color(struct vc_data *vc)
1606 {
1607         int i, bg;
1608         int cc;
1609         int vc_num = vc->vc_num;
1610         u16 ch;
1611         u16 *start = (u16 *)vc->vc_origin;
1612
1613         for (i = 0; i < 8; i++)
1614                 speakup_console[vc_num]->ht.bgcount[i] = 0;
1615
1616         for (i = 0; i < vc->vc_rows; i++) {
1617                 u16 *end = start + vc->vc_cols * 2;
1618                 u16 *ptr;
1619
1620                 for (ptr = start; ptr < end; ptr++) {
1621                         ch = get_attributes(vc, ptr);
1622                         bg = (ch & 0x70) >> 4;
1623                         speakup_console[vc_num]->ht.bgcount[bg]++;
1624                 }
1625                 start += vc->vc_size_row;
1626         }
1627
1628         cc = 0;
1629         for (i = 0; i < 8; i++)
1630                 if (speakup_console[vc_num]->ht.bgcount[i] > 0)
1631                         cc++;
1632         return cc;
1633 }
1634
1635 static int get_highlight_color(struct vc_data *vc)
1636 {
1637         int i, j;
1638         unsigned int cptr[8];
1639         int vc_num = vc->vc_num;
1640
1641         for (i = 0; i < 8; i++)
1642                 cptr[i] = i;
1643
1644         for (i = 0; i < 7; i++)
1645                 for (j = i + 1; j < 8; j++)
1646                         if (speakup_console[vc_num]->ht.bgcount[cptr[i]] >
1647                             speakup_console[vc_num]->ht.bgcount[cptr[j]])
1648                                 swap(cptr[i], cptr[j]);
1649
1650         for (i = 0; i < 8; i++)
1651                 if (speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
1652                         if (speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
1653                                 return cptr[i];
1654         return -1;
1655 }
1656
1657 static int speak_highlight(struct vc_data *vc)
1658 {
1659         int hc, d;
1660         int vc_num = vc->vc_num;
1661
1662         if (count_highlight_color(vc) == 1)
1663                 return 0;
1664         hc = get_highlight_color(vc);
1665         if (hc != -1) {
1666                 d = vc->state.y - speakup_console[vc_num]->ht.cy;
1667                 if ((d == 1) || (d == -1))
1668                         if (speakup_console[vc_num]->ht.ry[hc] != vc->state.y)
1669                                 return 0;
1670                 spk_parked |= 0x01;
1671                 spk_do_flush();
1672                 spkup_write(speakup_console[vc_num]->ht.highbuf[hc],
1673                             speakup_console[vc_num]->ht.highsize[hc]);
1674                 spk_pos = spk_cp = speakup_console[vc_num]->ht.rpos[hc];
1675                 spk_x = spk_cx = speakup_console[vc_num]->ht.rx[hc];
1676                 spk_y = spk_cy = speakup_console[vc_num]->ht.ry[hc];
1677                 return 1;
1678         }
1679         return 0;
1680 }
1681
1682 static void cursor_done(struct timer_list *unused)
1683 {
1684         struct vc_data *vc = vc_cons[cursor_con].d;
1685         unsigned long flags;
1686
1687         del_timer(&cursor_timer);
1688         spin_lock_irqsave(&speakup_info.spinlock, flags);
1689         if (cursor_con != fg_console) {
1690                 is_cursor = 0;
1691                 goto out;
1692         }
1693         speakup_date(vc);
1694         if (win_enabled) {
1695                 if (vc->state.x >= win_left && vc->state.x <= win_right &&
1696                     vc->state.y >= win_top && vc->state.y <= win_bottom) {
1697                         spk_keydown = 0;
1698                         is_cursor = 0;
1699                         goto out;
1700                 }
1701         }
1702         if (cursor_track == read_all_mode) {
1703                 handle_cursor_read_all(vc, read_all_key);
1704                 goto out;
1705         }
1706         if (cursor_track == CT_Highlight) {
1707                 if (speak_highlight(vc)) {
1708                         spk_keydown = 0;
1709                         is_cursor = 0;
1710                         goto out;
1711                 }
1712         }
1713         if (cursor_track == CT_Window)
1714                 speakup_win_say(vc);
1715         else if (is_cursor == 1 || is_cursor == 4)
1716                 say_line_from_to(vc, 0, vc->vc_cols, 0);
1717         else
1718                 say_char(vc);
1719         spk_keydown = 0;
1720         is_cursor = 0;
1721 out:
1722         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1723 }
1724
1725 /* called by: vt_notifier_call() */
1726 static void speakup_bs(struct vc_data *vc)
1727 {
1728         unsigned long flags;
1729
1730         if (!speakup_console[vc->vc_num])
1731                 return;
1732         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1733                 /* Speakup output, discard */
1734                 return;
1735         if (!spk_parked)
1736                 speakup_date(vc);
1737         if (spk_shut_up || !synth) {
1738                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1739                 return;
1740         }
1741         if (vc->vc_num == fg_console && spk_keydown) {
1742                 spk_keydown = 0;
1743                 if (!is_cursor)
1744                         say_char(vc);
1745         }
1746         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1747 }
1748
1749 /* called by: vt_notifier_call() */
1750 static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
1751 {
1752         unsigned long flags;
1753
1754         if ((vc->vc_num != fg_console) || spk_shut_up || !synth)
1755                 return;
1756         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1757                 /* Speakup output, discard */
1758                 return;
1759         if (spk_bell_pos && spk_keydown && (vc->state.x == spk_bell_pos - 1))
1760                 bleep(3);
1761         if ((is_cursor) || (cursor_track == read_all_mode)) {
1762                 if (cursor_track == CT_Highlight)
1763                         update_color_buffer(vc, str, len);
1764                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1765                 return;
1766         }
1767         if (win_enabled) {
1768                 if (vc->state.x >= win_left && vc->state.x <= win_right &&
1769                     vc->state.y >= win_top && vc->state.y <= win_bottom) {
1770                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1771                         return;
1772                 }
1773         }
1774
1775         spkup_write(str, len);
1776         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1777 }
1778
1779 static void speakup_con_update(struct vc_data *vc)
1780 {
1781         unsigned long flags;
1782
1783         if (!speakup_console[vc->vc_num] || spk_parked)
1784                 return;
1785         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1786                 /* Speakup output, discard */
1787                 return;
1788         speakup_date(vc);
1789         if (vc->vc_mode == KD_GRAPHICS && !spk_paused && spk_str_pause[0]) {
1790                 synth_printf("%s", spk_str_pause);
1791                 spk_paused = true;
1792         }
1793         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1794 }
1795
1796 static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag)
1797 {
1798         unsigned long flags;
1799         int on_off = 2;
1800         char *label;
1801
1802         if (!synth || up_flag || spk_killed)
1803                 return;
1804         spin_lock_irqsave(&speakup_info.spinlock, flags);
1805         spk_shut_up &= 0xfe;
1806         if (spk_no_intr)
1807                 spk_do_flush();
1808         switch (value) {
1809         case KVAL(K_CAPS):
1810                 label = spk_msg_get(MSG_KEYNAME_CAPSLOCK);
1811                 on_off = vt_get_leds(fg_console, VC_CAPSLOCK);
1812                 break;
1813         case KVAL(K_NUM):
1814                 label = spk_msg_get(MSG_KEYNAME_NUMLOCK);
1815                 on_off = vt_get_leds(fg_console, VC_NUMLOCK);
1816                 break;
1817         case KVAL(K_HOLD):
1818                 label = spk_msg_get(MSG_KEYNAME_SCROLLLOCK);
1819                 on_off = vt_get_leds(fg_console, VC_SCROLLOCK);
1820                 if (speakup_console[vc->vc_num])
1821                         speakup_console[vc->vc_num]->tty_stopped = on_off;
1822                 break;
1823         default:
1824                 spk_parked &= 0xfe;
1825                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1826                 return;
1827         }
1828         if (on_off < 2)
1829                 synth_printf("%s %s\n",
1830                              label, spk_msg_get(MSG_STATUS_START + on_off));
1831         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1832 }
1833
1834 static int inc_dec_var(u_char value)
1835 {
1836         struct st_var_header *p_header;
1837         struct var_t *var_data;
1838         char num_buf[32];
1839         char *cp = num_buf;
1840         char *pn;
1841         int var_id = (int)value - VAR_START;
1842         int how = (var_id & 1) ? E_INC : E_DEC;
1843
1844         var_id = var_id / 2 + FIRST_SET_VAR;
1845         p_header = spk_get_var_header(var_id);
1846         if (!p_header)
1847                 return -1;
1848         if (p_header->var_type != VAR_NUM)
1849                 return -1;
1850         var_data = p_header->data;
1851         if (spk_set_num_var(1, p_header, how) != 0)
1852                 return -1;
1853         if (!spk_close_press) {
1854                 for (pn = p_header->name; *pn; pn++) {
1855                         if (*pn == '_')
1856                                 *cp = SPACE;
1857                         else
1858                                 *cp++ = *pn;
1859                 }
1860         }
1861         snprintf(cp, sizeof(num_buf) - (cp - num_buf), " %d ",
1862                  var_data->u.n.value);
1863         synth_printf("%s", num_buf);
1864         return 0;
1865 }
1866
1867 static void speakup_win_set(struct vc_data *vc)
1868 {
1869         char info[40];
1870
1871         if (win_start > 1) {
1872                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_ALREADY_SET));
1873                 return;
1874         }
1875         if (spk_x < win_left || spk_y < win_top) {
1876                 synth_printf("%s\n", spk_msg_get(MSG_END_BEFORE_START));
1877                 return;
1878         }
1879         if (win_start && spk_x == win_left && spk_y == win_top) {
1880                 win_left = 0;
1881                 win_right = vc->vc_cols - 1;
1882                 win_bottom = spk_y;
1883                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_LINE),
1884                          (int)win_top + 1);
1885         } else {
1886                 if (!win_start) {
1887                         win_top = spk_y;
1888                         win_left = spk_x;
1889                 } else {
1890                         win_bottom = spk_y;
1891                         win_right = spk_x;
1892                 }
1893                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_BOUNDARY),
1894                          (win_start) ?
1895                                 spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
1896                          (int)spk_y + 1, (int)spk_x + 1);
1897         }
1898         synth_printf("%s\n", info);
1899         win_start++;
1900 }
1901
1902 static void speakup_win_clear(struct vc_data *vc)
1903 {
1904         win_top = 0;
1905         win_bottom = 0;
1906         win_left = 0;
1907         win_right = 0;
1908         win_start = 0;
1909         synth_printf("%s\n", spk_msg_get(MSG_WINDOW_CLEARED));
1910 }
1911
1912 static void speakup_win_enable(struct vc_data *vc)
1913 {
1914         if (win_start < 2) {
1915                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
1916                 return;
1917         }
1918         win_enabled ^= 1;
1919         if (win_enabled)
1920                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCED));
1921         else
1922                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCE_DISABLED));
1923 }
1924
1925 static void speakup_bits(struct vc_data *vc)
1926 {
1927         int val = this_speakup_key - (FIRST_EDIT_BITS - 1);
1928
1929         if (spk_special_handler || val < 1 || val > 6) {
1930                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1931                 return;
1932         }
1933         pb_edit = &spk_punc_info[val];
1934         synth_printf(spk_msg_get(MSG_EDIT_PROMPT), pb_edit->name);
1935         spk_special_handler = edit_bits;
1936 }
1937
1938 static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
1939 {
1940         static u_char goto_buf[8];
1941         static int num;
1942         int maxlen;
1943         char *cp;
1944         u16 wch;
1945
1946         if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
1947                 goto do_goto;
1948         if (type == KT_LATIN && ch == '\n')
1949                 goto do_goto;
1950         if (type != 0)
1951                 goto oops;
1952         if (ch == 8) {
1953                 u16 wch;
1954
1955                 if (num == 0)
1956                         return -1;
1957                 wch = goto_buf[--num];
1958                 goto_buf[num] = '\0';
1959                 spkup_write(&wch, 1);
1960                 return 1;
1961         }
1962         if (ch < '+' || ch > 'y')
1963                 goto oops;
1964         wch = ch;
1965         goto_buf[num++] = ch;
1966         goto_buf[num] = '\0';
1967         spkup_write(&wch, 1);
1968         maxlen = (*goto_buf >= '0') ? 3 : 4;
1969         if ((ch == '+' || ch == '-') && num == 1)
1970                 return 1;
1971         if (ch >= '0' && ch <= '9' && num < maxlen)
1972                 return 1;
1973         if (num < maxlen - 1 || num > maxlen)
1974                 goto oops;
1975         if (ch < 'x' || ch > 'y') {
1976 oops:
1977                 if (!spk_killed)
1978                         synth_printf(" %s\n", spk_msg_get(MSG_GOTO_CANCELED));
1979                 goto_buf[num = 0] = '\0';
1980                 spk_special_handler = NULL;
1981                 return 1;
1982         }
1983
1984         /* Do not replace with kstrtoul: here we need cp to be updated */
1985         goto_pos = simple_strtoul(goto_buf, &cp, 10);
1986
1987         if (*cp == 'x') {
1988                 if (*goto_buf < '0')
1989                         goto_pos += spk_x;
1990                 else if (goto_pos > 0)
1991                         goto_pos--;
1992
1993                 if (goto_pos >= vc->vc_cols)
1994                         goto_pos = vc->vc_cols - 1;
1995                 goto_x = 1;
1996         } else {
1997                 if (*goto_buf < '0')
1998                         goto_pos += spk_y;
1999                 else if (goto_pos > 0)
2000                         goto_pos--;
2001
2002                 if (goto_pos >= vc->vc_rows)
2003                         goto_pos = vc->vc_rows - 1;
2004                 goto_x = 0;
2005         }
2006         goto_buf[num = 0] = '\0';
2007 do_goto:
2008         spk_special_handler = NULL;
2009         spk_parked |= 0x01;
2010         if (goto_x) {
2011                 spk_pos -= spk_x * 2;
2012                 spk_x = goto_pos;
2013                 spk_pos += goto_pos * 2;
2014                 say_word(vc);
2015         } else {
2016                 spk_y = goto_pos;
2017                 spk_pos = vc->vc_origin + (goto_pos * vc->vc_size_row);
2018                 say_line(vc);
2019         }
2020         return 1;
2021 }
2022
2023 static void speakup_goto(struct vc_data *vc)
2024 {
2025         if (spk_special_handler) {
2026                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
2027                 return;
2028         }
2029         synth_printf("%s\n", spk_msg_get(MSG_GOTO));
2030         spk_special_handler = handle_goto;
2031 }
2032
2033 static void speakup_help(struct vc_data *vc)
2034 {
2035         spk_handle_help(vc, KT_SPKUP, SPEAKUP_HELP, 0);
2036 }
2037
2038 static void do_nothing(struct vc_data *vc)
2039 {
2040         return;                 /* flush done in do_spkup */
2041 }
2042
2043 static u_char key_speakup, spk_key_locked;
2044
2045 static void speakup_lock(struct vc_data *vc)
2046 {
2047         if (!spk_key_locked) {
2048                 spk_key_locked = 16;
2049                 key_speakup = 16;
2050         } else {
2051                 spk_key_locked = 0;
2052                 key_speakup = 0;
2053         }
2054 }
2055
2056 typedef void (*spkup_hand) (struct vc_data *);
2057 static spkup_hand spkup_handler[] = {
2058         /* must be ordered same as defines in speakup.h */
2059         do_nothing, speakup_goto, speech_kill, speakup_shut_up,
2060         speakup_cut, speakup_paste, say_first_char, say_last_char,
2061         say_char, say_prev_char, say_next_char,
2062         say_word, say_prev_word, say_next_word,
2063         say_line, say_prev_line, say_next_line,
2064         top_edge, bottom_edge, left_edge, right_edge,
2065         spell_word, spell_word, say_screen,
2066         say_position, say_attributes,
2067         speakup_off, speakup_parked, say_line,  /* this is for indent */
2068         say_from_top, say_to_bottom,
2069         say_from_left, say_to_right,
2070         say_char_num, speakup_bits, speakup_bits, say_phonetic_char,
2071         speakup_bits, speakup_bits, speakup_bits,
2072         speakup_win_set, speakup_win_clear, speakup_win_enable, speakup_win_say,
2073         speakup_lock, speakup_help, toggle_cursoring, read_all_doc, NULL
2074 };
2075
2076 static void do_spkup(struct vc_data *vc, u_char value)
2077 {
2078         if (spk_killed && value != SPEECH_KILL)
2079                 return;
2080         spk_keydown = 0;
2081         spk_lastkey = 0;
2082         spk_shut_up &= 0xfe;
2083         this_speakup_key = value;
2084         if (value < SPKUP_MAX_FUNC && spkup_handler[value]) {
2085                 spk_do_flush();
2086                 (*spkup_handler[value]) (vc);
2087         } else {
2088                 if (inc_dec_var(value) < 0)
2089                         bleep(9);
2090         }
2091 }
2092
2093 static const char *pad_chars = "0123456789+-*/\015,.?()";
2094
2095 static int
2096 speakup_key(struct vc_data *vc, int shift_state, int keycode, u_short keysym,
2097             int up_flag)
2098 {
2099         unsigned long flags;
2100         int kh;
2101         u_char *key_info;
2102         u_char type = KTYP(keysym), value = KVAL(keysym), new_key = 0;
2103         u_char shift_info, offset;
2104         int ret = 0;
2105
2106         if (!synth)
2107                 return 0;
2108
2109         spin_lock_irqsave(&speakup_info.spinlock, flags);
2110         tty = vc->port.tty;
2111         if (type >= 0xf0)
2112                 type -= 0xf0;
2113         if (type == KT_PAD &&
2114             (vt_get_leds(fg_console, VC_NUMLOCK))) {
2115                 if (up_flag) {
2116                         spk_keydown = 0;
2117                         goto out;
2118                 }
2119                 value = pad_chars[value];
2120                 spk_lastkey = value;
2121                 spk_keydown++;
2122                 spk_parked &= 0xfe;
2123                 goto no_map;
2124         }
2125         if (keycode >= MAX_KEY)
2126                 goto no_map;
2127         key_info = spk_our_keys[keycode];
2128         if (!key_info)
2129                 goto no_map;
2130         /* Check valid read all mode keys */
2131         if ((cursor_track == read_all_mode) && (!up_flag)) {
2132                 switch (value) {
2133                 case KVAL(K_DOWN):
2134                 case KVAL(K_UP):
2135                 case KVAL(K_LEFT):
2136                 case KVAL(K_RIGHT):
2137                 case KVAL(K_PGUP):
2138                 case KVAL(K_PGDN):
2139                         break;
2140                 default:
2141                         stop_read_all(vc);
2142                         break;
2143                 }
2144         }
2145         shift_info = (shift_state & 0x0f) + key_speakup;
2146         offset = spk_shift_table[shift_info];
2147         if (offset) {
2148                 new_key = key_info[offset];
2149                 if (new_key) {
2150                         ret = 1;
2151                         if (new_key == SPK_KEY) {
2152                                 if (!spk_key_locked)
2153                                         key_speakup = (up_flag) ? 0 : 16;
2154                                 if (up_flag || spk_killed)
2155                                         goto out;
2156                                 spk_shut_up &= 0xfe;
2157                                 spk_do_flush();
2158                                 goto out;
2159                         }
2160                         if (up_flag)
2161                                 goto out;
2162                         if (last_keycode == keycode &&
2163                             time_after(last_spk_jiffy + MAX_DELAY, jiffies)) {
2164                                 spk_close_press = 1;
2165                                 offset = spk_shift_table[shift_info + 32];
2166                                 /* double press? */
2167                                 if (offset && key_info[offset])
2168                                         new_key = key_info[offset];
2169                         }
2170                         last_keycode = keycode;
2171                         last_spk_jiffy = jiffies;
2172                         type = KT_SPKUP;
2173                         value = new_key;
2174                 }
2175         }
2176 no_map:
2177         if (type == KT_SPKUP && !spk_special_handler) {
2178                 do_spkup(vc, new_key);
2179                 spk_close_press = 0;
2180                 ret = 1;
2181                 goto out;
2182         }
2183         if (up_flag || spk_killed || type == KT_SHIFT)
2184                 goto out;
2185         spk_shut_up &= 0xfe;
2186         kh = (value == KVAL(K_DOWN)) ||
2187             (value == KVAL(K_UP)) ||
2188             (value == KVAL(K_LEFT)) ||
2189             (value == KVAL(K_RIGHT));
2190         if ((cursor_track != read_all_mode) || !kh)
2191                 if (!spk_no_intr)
2192                         spk_do_flush();
2193         if (spk_special_handler) {
2194                 if (type == KT_SPEC && value == 1) {
2195                         value = '\n';
2196                         type = KT_LATIN;
2197                 } else if (type == KT_LETTER) {
2198                         type = KT_LATIN;
2199                 } else if (value == 0x7f) {
2200                         value = 8;      /* make del = backspace */
2201                 }
2202                 ret = (*spk_special_handler) (vc, type, value, keycode);
2203                 spk_close_press = 0;
2204                 if (ret < 0)
2205                         bleep(9);
2206                 goto out;
2207         }
2208         last_keycode = 0;
2209 out:
2210         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
2211         return ret;
2212 }
2213
2214 static int keyboard_notifier_call(struct notifier_block *nb,
2215                                   unsigned long code, void *_param)
2216 {
2217         struct keyboard_notifier_param *param = _param;
2218         struct vc_data *vc = param->vc;
2219         int up = !param->down;
2220         int ret = NOTIFY_OK;
2221         static int keycode;     /* to hold the current keycode */
2222
2223         in_keyboard_notifier = 1;
2224
2225         if (vc->vc_mode == KD_GRAPHICS)
2226                 goto out;
2227
2228         /*
2229          * First, determine whether we are handling a fake keypress on
2230          * the current processor.  If we are, then return NOTIFY_OK,
2231          * to pass the keystroke up the chain.  This prevents us from
2232          * trying to take the Speakup lock while it is held by the
2233          * processor on which the simulated keystroke was generated.
2234          * Also, the simulated keystrokes should be ignored by Speakup.
2235          */
2236
2237         if (speakup_fake_key_pressed())
2238                 goto out;
2239
2240         switch (code) {
2241         case KBD_KEYCODE:
2242                 /* speakup requires keycode and keysym currently */
2243                 keycode = param->value;
2244                 break;
2245         case KBD_UNBOUND_KEYCODE:
2246                 /* not used yet */
2247                 break;
2248         case KBD_UNICODE:
2249                 /* not used yet */
2250                 break;
2251         case KBD_KEYSYM:
2252                 if (speakup_key(vc, param->shift, keycode, param->value, up))
2253                         ret = NOTIFY_STOP;
2254                 else if (KTYP(param->value) == KT_CUR)
2255                         ret = pre_handle_cursor(vc, KVAL(param->value), up);
2256                 break;
2257         case KBD_POST_KEYSYM:{
2258                         unsigned char type = KTYP(param->value) - 0xf0;
2259                         unsigned char val = KVAL(param->value);
2260
2261                         switch (type) {
2262                         case KT_SHIFT:
2263                                 do_handle_shift(vc, val, up);
2264                                 break;
2265                         case KT_LATIN:
2266                         case KT_LETTER:
2267                                 do_handle_latin(vc, val, up);
2268                                 break;
2269                         case KT_CUR:
2270                                 do_handle_cursor(vc, val, up);
2271                                 break;
2272                         case KT_SPEC:
2273                                 do_handle_spec(vc, val, up);
2274                                 break;
2275                         }
2276                         break;
2277                 }
2278         }
2279 out:
2280         in_keyboard_notifier = 0;
2281         return ret;
2282 }
2283
2284 static int vt_notifier_call(struct notifier_block *nb,
2285                             unsigned long code, void *_param)
2286 {
2287         struct vt_notifier_param *param = _param;
2288         struct vc_data *vc = param->vc;
2289
2290         switch (code) {
2291         case VT_ALLOCATE:
2292                 if (vc->vc_mode == KD_TEXT)
2293                         speakup_allocate(vc, GFP_ATOMIC);
2294                 break;
2295         case VT_DEALLOCATE:
2296                 speakup_deallocate(vc);
2297                 break;
2298         case VT_WRITE:
2299                 if (param->c == '\b') {
2300                         speakup_bs(vc);
2301                 } else {
2302                         u16 d = param->c;
2303
2304                         speakup_con_write(vc, &d, 1);
2305                 }
2306                 break;
2307         case VT_UPDATE:
2308                 speakup_con_update(vc);
2309                 break;
2310         }
2311         return NOTIFY_OK;
2312 }
2313
2314 /* called by: module_exit() */
2315 static void __exit speakup_exit(void)
2316 {
2317         int i;
2318
2319         unregister_keyboard_notifier(&keyboard_notifier_block);
2320         unregister_vt_notifier(&vt_notifier_block);
2321         speakup_unregister_devsynth();
2322         speakup_cancel_selection();
2323         speakup_cancel_paste();
2324         del_timer_sync(&cursor_timer);
2325         kthread_stop(speakup_task);
2326         speakup_task = NULL;
2327         mutex_lock(&spk_mutex);
2328         synth_release();
2329         mutex_unlock(&spk_mutex);
2330         spk_ttyio_unregister_ldisc();
2331
2332         speakup_kobj_exit();
2333
2334         for (i = 0; i < MAX_NR_CONSOLES; i++)
2335                 kfree(speakup_console[i]);
2336
2337         speakup_remove_virtual_keyboard();
2338
2339         for (i = 0; i < MAXVARS; i++)
2340                 speakup_unregister_var(i);
2341
2342         for (i = 0; i < 256; i++) {
2343                 if (spk_characters[i] != spk_default_chars[i])
2344                         kfree(spk_characters[i]);
2345         }
2346
2347         spk_free_user_msgs();
2348 }
2349
2350 /* call by: module_init() */
2351 static int __init speakup_init(void)
2352 {
2353         int i;
2354         long err = 0;
2355         struct vc_data *vc = vc_cons[fg_console].d;
2356         struct var_t *var;
2357
2358         /* These first few initializations cannot fail. */
2359         spk_initialize_msgs();  /* Initialize arrays for i18n. */
2360         spk_reset_default_chars();
2361         spk_reset_default_chartab();
2362         spk_strlwr(synth_name);
2363         spk_vars[0].u.n.high = vc->vc_cols;
2364         for (var = spk_vars; var->var_id != MAXVARS; var++)
2365                 speakup_register_var(var);
2366         for (var = synth_time_vars;
2367              (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
2368                 speakup_register_var(var);
2369         for (i = 1; spk_punc_info[i].mask != 0; i++)
2370                 spk_set_mask_bits(NULL, i, 2);
2371
2372         spk_set_key_info(spk_key_defaults, spk_key_buf);
2373
2374         /* From here on out, initializations can fail. */
2375         err = speakup_add_virtual_keyboard();
2376         if (err)
2377                 goto error_virtkeyboard;
2378
2379         for (i = 0; i < MAX_NR_CONSOLES; i++)
2380                 if (vc_cons[i].d) {
2381                         err = speakup_allocate(vc_cons[i].d, GFP_KERNEL);
2382                         if (err)
2383                                 goto error_kobjects;
2384                 }
2385
2386         if (spk_quiet_boot)
2387                 spk_shut_up |= 0x01;
2388
2389         err = speakup_kobj_init();
2390         if (err)
2391                 goto error_kobjects;
2392
2393         spk_ttyio_register_ldisc();
2394         synth_init(synth_name);
2395         speakup_register_devsynth();
2396         /*
2397          * register_devsynth might fail, but this error is not fatal.
2398          * /dev/synth is an extra feature; the rest of Speakup
2399          * will work fine without it.
2400          */
2401
2402         err = register_keyboard_notifier(&keyboard_notifier_block);
2403         if (err)
2404                 goto error_kbdnotifier;
2405         err = register_vt_notifier(&vt_notifier_block);
2406         if (err)
2407                 goto error_vtnotifier;
2408
2409         speakup_task = kthread_create(speakup_thread, NULL, "speakup");
2410
2411         if (IS_ERR(speakup_task)) {
2412                 err = PTR_ERR(speakup_task);
2413                 goto error_task;
2414         }
2415
2416         set_user_nice(speakup_task, 10);
2417         wake_up_process(speakup_task);
2418
2419         pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
2420         pr_info("synth name on entry is: %s\n", synth_name);
2421         goto out;
2422
2423 error_task:
2424         unregister_vt_notifier(&vt_notifier_block);
2425
2426 error_vtnotifier:
2427         unregister_keyboard_notifier(&keyboard_notifier_block);
2428         del_timer(&cursor_timer);
2429
2430 error_kbdnotifier:
2431         speakup_unregister_devsynth();
2432         mutex_lock(&spk_mutex);
2433         synth_release();
2434         mutex_unlock(&spk_mutex);
2435         speakup_kobj_exit();
2436
2437 error_kobjects:
2438         for (i = 0; i < MAX_NR_CONSOLES; i++)
2439                 kfree(speakup_console[i]);
2440
2441         speakup_remove_virtual_keyboard();
2442
2443 error_virtkeyboard:
2444         for (i = 0; i < MAXVARS; i++)
2445                 speakup_unregister_var(i);
2446
2447         for (i = 0; i < 256; i++) {
2448                 if (spk_characters[i] != spk_default_chars[i])
2449                         kfree(spk_characters[i]);
2450         }
2451
2452         spk_free_user_msgs();
2453
2454 out:
2455         return err;
2456 }
2457
2458 module_init(speakup_init);
2459 module_exit(speakup_exit);