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