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