Merge remote-tracking branches 'regmap/topic/const' and 'regmap/topic/hwspinlock...
[sfrench/cifs-2.6.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 int in_keyboard_notifier;
1380
1381 static void start_read_all_timer(struct vc_data *vc, int command);
1382
1383 enum {
1384         RA_NOTHING,
1385         RA_NEXT_SENT,
1386         RA_PREV_LINE,
1387         RA_NEXT_LINE,
1388         RA_PREV_SENT,
1389         RA_DOWN_ARROW,
1390         RA_TIMER,
1391         RA_FIND_NEXT_SENT,
1392         RA_FIND_PREV_SENT,
1393 };
1394
1395 static void kbd_fakekey2(struct vc_data *vc, int command)
1396 {
1397         del_timer(&cursor_timer);
1398         speakup_fake_down_arrow();
1399         start_read_all_timer(vc, command);
1400 }
1401
1402 static void read_all_doc(struct vc_data *vc)
1403 {
1404         if ((vc->vc_num != fg_console) || !synth || spk_shut_up)
1405                 return;
1406         if (!synth_supports_indexing())
1407                 return;
1408         if (cursor_track != read_all_mode)
1409                 prev_cursor_track = cursor_track;
1410         cursor_track = read_all_mode;
1411         spk_reset_index_count(0);
1412         if (get_sentence_buf(vc, 0) == -1) {
1413                 del_timer(&cursor_timer);
1414                 if (!in_keyboard_notifier)
1415                         speakup_fake_down_arrow();
1416                 start_read_all_timer(vc, RA_DOWN_ARROW);
1417         } else {
1418                 say_sentence_num(0, 0);
1419                 synth_insert_next_index(0);
1420                 start_read_all_timer(vc, RA_TIMER);
1421         }
1422 }
1423
1424 static void stop_read_all(struct vc_data *vc)
1425 {
1426         del_timer(&cursor_timer);
1427         cursor_track = prev_cursor_track;
1428         spk_shut_up &= 0xfe;
1429         spk_do_flush();
1430 }
1431
1432 static void start_read_all_timer(struct vc_data *vc, int command)
1433 {
1434         struct var_t *cursor_timeout;
1435
1436         cursor_con = vc->vc_num;
1437         read_all_key = command;
1438         cursor_timeout = spk_get_var(CURSOR_TIME);
1439         mod_timer(&cursor_timer,
1440                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1441 }
1442
1443 static void handle_cursor_read_all(struct vc_data *vc, int command)
1444 {
1445         int indcount, sentcount, rv, sn;
1446
1447         switch (command) {
1448         case RA_NEXT_SENT:
1449                 /* Get Current Sentence */
1450                 spk_get_index_count(&indcount, &sentcount);
1451                 /*printk("%d %d  ", indcount, sentcount); */
1452                 spk_reset_index_count(sentcount + 1);
1453                 if (indcount == 1) {
1454                         if (!say_sentence_num(sentcount + 1, 0)) {
1455                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1456                                 return;
1457                         }
1458                         synth_insert_next_index(0);
1459                 } else {
1460                         sn = 0;
1461                         if (!say_sentence_num(sentcount + 1, 1)) {
1462                                 sn = 1;
1463                                 spk_reset_index_count(sn);
1464                         } else {
1465                                 synth_insert_next_index(0);
1466                         }
1467                         if (!say_sentence_num(sn, 0)) {
1468                                 kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1469                                 return;
1470                         }
1471                         synth_insert_next_index(0);
1472                 }
1473                 start_read_all_timer(vc, RA_TIMER);
1474                 break;
1475         case RA_PREV_SENT:
1476                 break;
1477         case RA_NEXT_LINE:
1478                 read_all_doc(vc);
1479                 break;
1480         case RA_PREV_LINE:
1481                 break;
1482         case RA_DOWN_ARROW:
1483                 if (get_sentence_buf(vc, 0) == -1) {
1484                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1485                 } else {
1486                         say_sentence_num(0, 0);
1487                         synth_insert_next_index(0);
1488                         start_read_all_timer(vc, RA_TIMER);
1489                 }
1490                 break;
1491         case RA_FIND_NEXT_SENT:
1492                 rv = get_sentence_buf(vc, 0);
1493                 if (rv == -1)
1494                         read_all_doc(vc);
1495                 if (rv == 0) {
1496                         kbd_fakekey2(vc, RA_FIND_NEXT_SENT);
1497                 } else {
1498                         say_sentence_num(1, 0);
1499                         synth_insert_next_index(0);
1500                         start_read_all_timer(vc, RA_TIMER);
1501                 }
1502                 break;
1503         case RA_FIND_PREV_SENT:
1504                 break;
1505         case RA_TIMER:
1506                 spk_get_index_count(&indcount, &sentcount);
1507                 if (indcount < 2)
1508                         kbd_fakekey2(vc, RA_DOWN_ARROW);
1509                 else
1510                         start_read_all_timer(vc, RA_TIMER);
1511                 break;
1512         }
1513 }
1514
1515 static int pre_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1516 {
1517         unsigned long flags;
1518
1519         spin_lock_irqsave(&speakup_info.spinlock, flags);
1520         if (cursor_track == read_all_mode) {
1521                 spk_parked &= 0xfe;
1522                 if (!synth || up_flag || spk_shut_up) {
1523                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1524                         return NOTIFY_STOP;
1525                 }
1526                 del_timer(&cursor_timer);
1527                 spk_shut_up &= 0xfe;
1528                 spk_do_flush();
1529                 start_read_all_timer(vc, value + 1);
1530                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1531                 return NOTIFY_STOP;
1532         }
1533         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1534         return NOTIFY_OK;
1535 }
1536
1537 static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag)
1538 {
1539         unsigned long flags;
1540         struct var_t *cursor_timeout;
1541
1542         spin_lock_irqsave(&speakup_info.spinlock, flags);
1543         spk_parked &= 0xfe;
1544         if (!synth || up_flag || spk_shut_up || cursor_track == CT_Off) {
1545                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1546                 return;
1547         }
1548         spk_shut_up &= 0xfe;
1549         if (spk_no_intr)
1550                 spk_do_flush();
1551 /* the key press flushes if !no_inter but we want to flush on cursor
1552  * moves regardless of no_inter state
1553  */
1554         is_cursor = value + 1;
1555         old_cursor_pos = vc->vc_pos;
1556         old_cursor_x = vc->vc_x;
1557         old_cursor_y = vc->vc_y;
1558         speakup_console[vc->vc_num]->ht.cy = vc->vc_y;
1559         cursor_con = vc->vc_num;
1560         if (cursor_track == CT_Highlight)
1561                 reset_highlight_buffers(vc);
1562         cursor_timeout = spk_get_var(CURSOR_TIME);
1563         mod_timer(&cursor_timer,
1564                   jiffies + msecs_to_jiffies(cursor_timeout->u.n.value));
1565         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1566 }
1567
1568 static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
1569 {
1570         int i, bi, hi;
1571         int vc_num = vc->vc_num;
1572
1573         bi = (vc->vc_attr & 0x70) >> 4;
1574         hi = speakup_console[vc_num]->ht.highsize[bi];
1575
1576         i = 0;
1577         if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1578                 speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
1579                 speakup_console[vc_num]->ht.rx[bi] = vc->vc_x;
1580                 speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;
1581         }
1582         while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
1583                 if (ic[i] > 32) {
1584                         speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
1585                         hi++;
1586                 } else if ((ic[i] == 32) && (hi != 0)) {
1587                         if (speakup_console[vc_num]->ht.highbuf[bi][hi - 1] !=
1588                             32) {
1589                                 speakup_console[vc_num]->ht.highbuf[bi][hi] =
1590                                     ic[i];
1591                                 hi++;
1592                         }
1593                 }
1594                 i++;
1595         }
1596         speakup_console[vc_num]->ht.highsize[bi] = hi;
1597 }
1598
1599 static void reset_highlight_buffers(struct vc_data *vc)
1600 {
1601         int i;
1602         int vc_num = vc->vc_num;
1603
1604         for (i = 0; i < 8; i++)
1605                 speakup_console[vc_num]->ht.highsize[i] = 0;
1606 }
1607
1608 static int count_highlight_color(struct vc_data *vc)
1609 {
1610         int i, bg;
1611         int cc;
1612         int vc_num = vc->vc_num;
1613         u16 ch;
1614         u16 *start = (u16 *)vc->vc_origin;
1615
1616         for (i = 0; i < 8; i++)
1617                 speakup_console[vc_num]->ht.bgcount[i] = 0;
1618
1619         for (i = 0; i < vc->vc_rows; i++) {
1620                 u16 *end = start + vc->vc_cols * 2;
1621                 u16 *ptr;
1622
1623                 for (ptr = start; ptr < end; ptr++) {
1624                         ch = get_attributes(vc, ptr);
1625                         bg = (ch & 0x70) >> 4;
1626                         speakup_console[vc_num]->ht.bgcount[bg]++;
1627                 }
1628                 start += vc->vc_size_row;
1629         }
1630
1631         cc = 0;
1632         for (i = 0; i < 8; i++)
1633                 if (speakup_console[vc_num]->ht.bgcount[i] > 0)
1634                         cc++;
1635         return cc;
1636 }
1637
1638 static int get_highlight_color(struct vc_data *vc)
1639 {
1640         int i, j;
1641         unsigned int cptr[8];
1642         int vc_num = vc->vc_num;
1643
1644         for (i = 0; i < 8; i++)
1645                 cptr[i] = i;
1646
1647         for (i = 0; i < 7; i++)
1648                 for (j = i + 1; j < 8; j++)
1649                         if (speakup_console[vc_num]->ht.bgcount[cptr[i]] >
1650                             speakup_console[vc_num]->ht.bgcount[cptr[j]])
1651                                 swap(cptr[i], cptr[j]);
1652
1653         for (i = 0; i < 8; i++)
1654                 if (speakup_console[vc_num]->ht.bgcount[cptr[i]] != 0)
1655                         if (speakup_console[vc_num]->ht.highsize[cptr[i]] > 0)
1656                                 return cptr[i];
1657         return -1;
1658 }
1659
1660 static int speak_highlight(struct vc_data *vc)
1661 {
1662         int hc, d;
1663         int vc_num = vc->vc_num;
1664
1665         if (count_highlight_color(vc) == 1)
1666                 return 0;
1667         hc = get_highlight_color(vc);
1668         if (hc != -1) {
1669                 d = vc->vc_y - speakup_console[vc_num]->ht.cy;
1670                 if ((d == 1) || (d == -1))
1671                         if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y)
1672                                 return 0;
1673                 spk_parked |= 0x01;
1674                 spk_do_flush();
1675                 spkup_write(speakup_console[vc_num]->ht.highbuf[hc],
1676                             speakup_console[vc_num]->ht.highsize[hc]);
1677                 spk_pos = spk_cp = speakup_console[vc_num]->ht.rpos[hc];
1678                 spk_x = spk_cx = speakup_console[vc_num]->ht.rx[hc];
1679                 spk_y = spk_cy = speakup_console[vc_num]->ht.ry[hc];
1680                 return 1;
1681         }
1682         return 0;
1683 }
1684
1685 static void cursor_done(u_long data)
1686 {
1687         struct vc_data *vc = vc_cons[cursor_con].d;
1688         unsigned long flags;
1689
1690         del_timer(&cursor_timer);
1691         spin_lock_irqsave(&speakup_info.spinlock, flags);
1692         if (cursor_con != fg_console) {
1693                 is_cursor = 0;
1694                 goto out;
1695         }
1696         speakup_date(vc);
1697         if (win_enabled) {
1698                 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
1699                     vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
1700                         spk_keydown = 0;
1701                         is_cursor = 0;
1702                         goto out;
1703                 }
1704         }
1705         if (cursor_track == read_all_mode) {
1706                 handle_cursor_read_all(vc, read_all_key);
1707                 goto out;
1708         }
1709         if (cursor_track == CT_Highlight) {
1710                 if (speak_highlight(vc)) {
1711                         spk_keydown = 0;
1712                         is_cursor = 0;
1713                         goto out;
1714                 }
1715         }
1716         if (cursor_track == CT_Window)
1717                 speakup_win_say(vc);
1718         else if (is_cursor == 1 || is_cursor == 4)
1719                 say_line_from_to(vc, 0, vc->vc_cols, 0);
1720         else
1721                 say_char(vc);
1722         spk_keydown = 0;
1723         is_cursor = 0;
1724 out:
1725         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1726 }
1727
1728 /* called by: vt_notifier_call() */
1729 static void speakup_bs(struct vc_data *vc)
1730 {
1731         unsigned long flags;
1732
1733         if (!speakup_console[vc->vc_num])
1734                 return;
1735         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1736                 /* Speakup output, discard */
1737                 return;
1738         if (!spk_parked)
1739                 speakup_date(vc);
1740         if (spk_shut_up || !synth) {
1741                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1742                 return;
1743         }
1744         if (vc->vc_num == fg_console && spk_keydown) {
1745                 spk_keydown = 0;
1746                 if (!is_cursor)
1747                         say_char(vc);
1748         }
1749         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1750 }
1751
1752 /* called by: vt_notifier_call() */
1753 static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
1754 {
1755         unsigned long flags;
1756
1757         if ((vc->vc_num != fg_console) || spk_shut_up || !synth)
1758                 return;
1759         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1760                 /* Speakup output, discard */
1761                 return;
1762         if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1))
1763                 bleep(3);
1764         if ((is_cursor) || (cursor_track == read_all_mode)) {
1765                 if (cursor_track == CT_Highlight)
1766                         update_color_buffer(vc, str, len);
1767                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1768                 return;
1769         }
1770         if (win_enabled) {
1771                 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&
1772                     vc->vc_y >= win_top && vc->vc_y <= win_bottom) {
1773                         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1774                         return;
1775                 }
1776         }
1777
1778         spkup_write(str, len);
1779         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1780 }
1781
1782 static void speakup_con_update(struct vc_data *vc)
1783 {
1784         unsigned long flags;
1785
1786         if (!speakup_console[vc->vc_num] || spk_parked)
1787                 return;
1788         if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1789                 /* Speakup output, discard */
1790                 return;
1791         speakup_date(vc);
1792         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1793 }
1794
1795 static void do_handle_spec(struct vc_data *vc, u_char value, char up_flag)
1796 {
1797         unsigned long flags;
1798         int on_off = 2;
1799         char *label;
1800
1801         if (!synth || up_flag || spk_killed)
1802                 return;
1803         spin_lock_irqsave(&speakup_info.spinlock, flags);
1804         spk_shut_up &= 0xfe;
1805         if (spk_no_intr)
1806                 spk_do_flush();
1807         switch (value) {
1808         case KVAL(K_CAPS):
1809                 label = spk_msg_get(MSG_KEYNAME_CAPSLOCK);
1810                 on_off = vt_get_leds(fg_console, VC_CAPSLOCK);
1811                 break;
1812         case KVAL(K_NUM):
1813                 label = spk_msg_get(MSG_KEYNAME_NUMLOCK);
1814                 on_off = vt_get_leds(fg_console, VC_NUMLOCK);
1815                 break;
1816         case KVAL(K_HOLD):
1817                 label = spk_msg_get(MSG_KEYNAME_SCROLLLOCK);
1818                 on_off = vt_get_leds(fg_console, VC_SCROLLOCK);
1819                 if (speakup_console[vc->vc_num])
1820                         speakup_console[vc->vc_num]->tty_stopped = on_off;
1821                 break;
1822         default:
1823                 spk_parked &= 0xfe;
1824                 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1825                 return;
1826         }
1827         if (on_off < 2)
1828                 synth_printf("%s %s\n",
1829                              label, spk_msg_get(MSG_STATUS_START + on_off));
1830         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1831 }
1832
1833 static int inc_dec_var(u_char value)
1834 {
1835         struct st_var_header *p_header;
1836         struct var_t *var_data;
1837         char num_buf[32];
1838         char *cp = num_buf;
1839         char *pn;
1840         int var_id = (int)value - VAR_START;
1841         int how = (var_id & 1) ? E_INC : E_DEC;
1842
1843         var_id = var_id / 2 + FIRST_SET_VAR;
1844         p_header = spk_get_var_header(var_id);
1845         if (!p_header)
1846                 return -1;
1847         if (p_header->var_type != VAR_NUM)
1848                 return -1;
1849         var_data = p_header->data;
1850         if (spk_set_num_var(1, p_header, how) != 0)
1851                 return -1;
1852         if (!spk_close_press) {
1853                 for (pn = p_header->name; *pn; pn++) {
1854                         if (*pn == '_')
1855                                 *cp = SPACE;
1856                         else
1857                                 *cp++ = *pn;
1858                 }
1859         }
1860         snprintf(cp, sizeof(num_buf) - (cp - num_buf), " %d ",
1861                  var_data->u.n.value);
1862         synth_printf("%s", num_buf);
1863         return 0;
1864 }
1865
1866 static void speakup_win_set(struct vc_data *vc)
1867 {
1868         char info[40];
1869
1870         if (win_start > 1) {
1871                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_ALREADY_SET));
1872                 return;
1873         }
1874         if (spk_x < win_left || spk_y < win_top) {
1875                 synth_printf("%s\n", spk_msg_get(MSG_END_BEFORE_START));
1876                 return;
1877         }
1878         if (win_start && spk_x == win_left && spk_y == win_top) {
1879                 win_left = 0;
1880                 win_right = vc->vc_cols - 1;
1881                 win_bottom = spk_y;
1882                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_LINE),
1883                          (int)win_top + 1);
1884         } else {
1885                 if (!win_start) {
1886                         win_top = spk_y;
1887                         win_left = spk_x;
1888                 } else {
1889                         win_bottom = spk_y;
1890                         win_right = spk_x;
1891                 }
1892                 snprintf(info, sizeof(info), spk_msg_get(MSG_WINDOW_BOUNDARY),
1893                          (win_start) ?
1894                                 spk_msg_get(MSG_END) : spk_msg_get(MSG_START),
1895                          (int)spk_y + 1, (int)spk_x + 1);
1896         }
1897         synth_printf("%s\n", info);
1898         win_start++;
1899 }
1900
1901 static void speakup_win_clear(struct vc_data *vc)
1902 {
1903         win_top = 0;
1904         win_bottom = 0;
1905         win_left = 0;
1906         win_right = 0;
1907         win_start = 0;
1908         synth_printf("%s\n", spk_msg_get(MSG_WINDOW_CLEARED));
1909 }
1910
1911 static void speakup_win_enable(struct vc_data *vc)
1912 {
1913         if (win_start < 2) {
1914                 synth_printf("%s\n", spk_msg_get(MSG_NO_WINDOW));
1915                 return;
1916         }
1917         win_enabled ^= 1;
1918         if (win_enabled)
1919                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCED));
1920         else
1921                 synth_printf("%s\n", spk_msg_get(MSG_WINDOW_SILENCE_DISABLED));
1922 }
1923
1924 static void speakup_bits(struct vc_data *vc)
1925 {
1926         int val = this_speakup_key - (FIRST_EDIT_BITS - 1);
1927
1928         if (spk_special_handler || val < 1 || val > 6) {
1929                 synth_printf("%s\n", spk_msg_get(MSG_ERROR));
1930                 return;
1931         }
1932         pb_edit = &spk_punc_info[val];
1933         synth_printf(spk_msg_get(MSG_EDIT_PROMPT), pb_edit->name);
1934         spk_special_handler = edit_bits;
1935 }
1936
1937 static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key)
1938 {
1939         static u_char goto_buf[8];
1940         static int num;
1941         int maxlen;
1942         char *cp;
1943         u16 wch;
1944
1945         if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
1946                 goto do_goto;
1947         if (type == KT_LATIN && ch == '\n')
1948                 goto do_goto;
1949         if (type != 0)
1950                 goto oops;
1951         if (ch == 8) {
1952                 u16 wch;
1953
1954                 if (num == 0)
1955                         return -1;
1956                 wch = goto_buf[--num];
1957                 goto_buf[num] = '\0';
1958                 spkup_write(&wch, 1);
1959                 return 1;
1960         }
1961         if (ch < '+' || ch > 'y')
1962                 goto oops;
1963         wch = ch;
1964         goto_buf[num++] = ch;
1965         goto_buf[num] = '\0';
1966         spkup_write(&wch, 1);
1967         maxlen = (*goto_buf >= '0') ? 3 : 4;
1968         if ((ch == '+' || ch == '-') && num == 1)
1969                 return 1;
1970         if (ch >= '0' && ch <= '9' && num < maxlen)
1971                 return 1;
1972         if (num < maxlen - 1 || num > maxlen)
1973                 goto oops;
1974         if (ch < 'x' || ch > 'y') {
1975 oops:
1976                 if (!spk_killed)
1977                         synth_printf(" %s\n", spk_msg_get(MSG_GOTO_CANCELED));
1978                 goto_buf[num = 0] = '\0';
1979                 spk_special_handler = NULL;
1980                 return 1;
1981         }
1982
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 == NULL)
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 = spk_lastkey = pad_chars[value];
2118                 spk_keydown++;
2119                 spk_parked &= 0xfe;
2120                 goto no_map;
2121         }
2122         if (keycode >= MAX_KEY)
2123                 goto no_map;
2124         key_info = spk_our_keys[keycode];
2125         if (!key_info)
2126                 goto no_map;
2127         /* Check valid read all mode keys */
2128         if ((cursor_track == read_all_mode) && (!up_flag)) {
2129                 switch (value) {
2130                 case KVAL(K_DOWN):
2131                 case KVAL(K_UP):
2132                 case KVAL(K_LEFT):
2133                 case KVAL(K_RIGHT):
2134                 case KVAL(K_PGUP):
2135                 case KVAL(K_PGDN):
2136                         break;
2137                 default:
2138                         stop_read_all(vc);
2139                         break;
2140                 }
2141         }
2142         shift_info = (shift_state & 0x0f) + key_speakup;
2143         offset = spk_shift_table[shift_info];
2144         if (offset) {
2145                 new_key = key_info[offset];
2146                 if (new_key) {
2147                         ret = 1;
2148                         if (new_key == SPK_KEY) {
2149                                 if (!spk_key_locked)
2150                                         key_speakup = (up_flag) ? 0 : 16;
2151                                 if (up_flag || spk_killed)
2152                                         goto out;
2153                                 spk_shut_up &= 0xfe;
2154                                 spk_do_flush();
2155                                 goto out;
2156                         }
2157                         if (up_flag)
2158                                 goto out;
2159                         if (last_keycode == keycode &&
2160                             time_after(last_spk_jiffy + MAX_DELAY, jiffies)) {
2161                                 spk_close_press = 1;
2162                                 offset = spk_shift_table[shift_info + 32];
2163                                 /* double press? */
2164                                 if (offset && key_info[offset])
2165                                         new_key = key_info[offset];
2166                         }
2167                         last_keycode = keycode;
2168                         last_spk_jiffy = jiffies;
2169                         type = KT_SPKUP;
2170                         value = new_key;
2171                 }
2172         }
2173 no_map:
2174         if (type == KT_SPKUP && !spk_special_handler) {
2175                 do_spkup(vc, new_key);
2176                 spk_close_press = 0;
2177                 ret = 1;
2178                 goto out;
2179         }
2180         if (up_flag || spk_killed || type == KT_SHIFT)
2181                 goto out;
2182         spk_shut_up &= 0xfe;
2183         kh = (value == KVAL(K_DOWN)) ||
2184             (value == KVAL(K_UP)) ||
2185             (value == KVAL(K_LEFT)) ||
2186             (value == KVAL(K_RIGHT));
2187         if ((cursor_track != read_all_mode) || !kh)
2188                 if (!spk_no_intr)
2189                         spk_do_flush();
2190         if (spk_special_handler) {
2191                 if (type == KT_SPEC && value == 1) {
2192                         value = '\n';
2193                         type = KT_LATIN;
2194                 } else if (type == KT_LETTER) {
2195                         type = KT_LATIN;
2196                 } else if (value == 0x7f) {
2197                         value = 8;      /* make del = backspace */
2198                 }
2199                 ret = (*spk_special_handler) (vc, type, value, keycode);
2200                 spk_close_press = 0;
2201                 if (ret < 0)
2202                         bleep(9);
2203                 goto out;
2204         }
2205         last_keycode = 0;
2206 out:
2207         spin_unlock_irqrestore(&speakup_info.spinlock, flags);
2208         return ret;
2209 }
2210
2211 static int keyboard_notifier_call(struct notifier_block *nb,
2212                                   unsigned long code, void *_param)
2213 {
2214         struct keyboard_notifier_param *param = _param;
2215         struct vc_data *vc = param->vc;
2216         int up = !param->down;
2217         int ret = NOTIFY_OK;
2218         static int keycode;     /* to hold the current keycode */
2219
2220         in_keyboard_notifier = 1;
2221
2222         if (vc->vc_mode == KD_GRAPHICS)
2223                 goto out;
2224
2225         /*
2226          * First, determine whether we are handling a fake keypress on
2227          * the current processor.  If we are, then return NOTIFY_OK,
2228          * to pass the keystroke up the chain.  This prevents us from
2229          * trying to take the Speakup lock while it is held by the
2230          * processor on which the simulated keystroke was generated.
2231          * Also, the simulated keystrokes should be ignored by Speakup.
2232          */
2233
2234         if (speakup_fake_key_pressed())
2235                 goto out;
2236
2237         switch (code) {
2238         case KBD_KEYCODE:
2239                 /* speakup requires keycode and keysym currently */
2240                 keycode = param->value;
2241                 break;
2242         case KBD_UNBOUND_KEYCODE:
2243                 /* not used yet */
2244                 break;
2245         case KBD_UNICODE:
2246                 /* not used yet */
2247                 break;
2248         case KBD_KEYSYM:
2249                 if (speakup_key(vc, param->shift, keycode, param->value, up))
2250                         ret = NOTIFY_STOP;
2251                 else if (KTYP(param->value) == KT_CUR)
2252                         ret = pre_handle_cursor(vc, KVAL(param->value), up);
2253                 break;
2254         case KBD_POST_KEYSYM:{
2255                         unsigned char type = KTYP(param->value) - 0xf0;
2256                         unsigned char val = KVAL(param->value);
2257
2258                         switch (type) {
2259                         case KT_SHIFT:
2260                                 do_handle_shift(vc, val, up);
2261                                 break;
2262                         case KT_LATIN:
2263                         case KT_LETTER:
2264                                 do_handle_latin(vc, val, up);
2265                                 break;
2266                         case KT_CUR:
2267                                 do_handle_cursor(vc, val, up);
2268                                 break;
2269                         case KT_SPEC:
2270                                 do_handle_spec(vc, val, up);
2271                                 break;
2272                         }
2273                         break;
2274                 }
2275         }
2276 out:
2277         in_keyboard_notifier = 0;
2278         return ret;
2279 }
2280
2281 static int vt_notifier_call(struct notifier_block *nb,
2282                             unsigned long code, void *_param)
2283 {
2284         struct vt_notifier_param *param = _param;
2285         struct vc_data *vc = param->vc;
2286
2287         switch (code) {
2288         case VT_ALLOCATE:
2289                 if (vc->vc_mode == KD_TEXT)
2290                         speakup_allocate(vc, GFP_ATOMIC);
2291                 break;
2292         case VT_DEALLOCATE:
2293                 speakup_deallocate(vc);
2294                 break;
2295         case VT_WRITE:
2296                 if (param->c == '\b') {
2297                         speakup_bs(vc);
2298                 } else {
2299                         u16 d = param->c;
2300
2301                         speakup_con_write(vc, &d, 1);
2302                 }
2303                 break;
2304         case VT_UPDATE:
2305                 speakup_con_update(vc);
2306                 break;
2307         }
2308         return NOTIFY_OK;
2309 }
2310
2311 /* called by: module_exit() */
2312 static void __exit speakup_exit(void)
2313 {
2314         int i;
2315
2316         unregister_keyboard_notifier(&keyboard_notifier_block);
2317         unregister_vt_notifier(&vt_notifier_block);
2318         speakup_unregister_devsynth();
2319         speakup_cancel_paste();
2320         del_timer_sync(&cursor_timer);
2321         kthread_stop(speakup_task);
2322         speakup_task = NULL;
2323         mutex_lock(&spk_mutex);
2324         synth_release();
2325         mutex_unlock(&spk_mutex);
2326         spk_ttyio_unregister_ldisc();
2327
2328         speakup_kobj_exit();
2329
2330         for (i = 0; i < MAX_NR_CONSOLES; i++)
2331                 kfree(speakup_console[i]);
2332
2333         speakup_remove_virtual_keyboard();
2334
2335         for (i = 0; i < MAXVARS; i++)
2336                 speakup_unregister_var(i);
2337
2338         for (i = 0; i < 256; i++) {
2339                 if (spk_characters[i] != spk_default_chars[i])
2340                         kfree(spk_characters[i]);
2341         }
2342
2343         spk_free_user_msgs();
2344 }
2345
2346 /* call by: module_init() */
2347 static int __init speakup_init(void)
2348 {
2349         int i;
2350         long err = 0;
2351         struct vc_data *vc = vc_cons[fg_console].d;
2352         struct var_t *var;
2353
2354         /* These first few initializations cannot fail. */
2355         spk_initialize_msgs();  /* Initialize arrays for i18n. */
2356         spk_reset_default_chars();
2357         spk_reset_default_chartab();
2358         spk_strlwr(synth_name);
2359         spk_vars[0].u.n.high = vc->vc_cols;
2360         for (var = spk_vars; var->var_id != MAXVARS; var++)
2361                 speakup_register_var(var);
2362         for (var = synth_time_vars;
2363              (var->var_id >= 0) && (var->var_id < MAXVARS); var++)
2364                 speakup_register_var(var);
2365         for (i = 1; spk_punc_info[i].mask != 0; i++)
2366                 spk_set_mask_bits(NULL, i, 2);
2367
2368         spk_set_key_info(spk_key_defaults, spk_key_buf);
2369
2370         /* From here on out, initializations can fail. */
2371         err = speakup_add_virtual_keyboard();
2372         if (err)
2373                 goto error_virtkeyboard;
2374
2375         for (i = 0; i < MAX_NR_CONSOLES; i++)
2376                 if (vc_cons[i].d) {
2377                         err = speakup_allocate(vc_cons[i].d, GFP_KERNEL);
2378                         if (err)
2379                                 goto error_kobjects;
2380                 }
2381
2382         if (spk_quiet_boot)
2383                 spk_shut_up |= 0x01;
2384
2385         err = speakup_kobj_init();
2386         if (err)
2387                 goto error_kobjects;
2388
2389         spk_ttyio_register_ldisc();
2390         synth_init(synth_name);
2391         speakup_register_devsynth();
2392         /*
2393          * register_devsynth might fail, but this error is not fatal.
2394          * /dev/synth is an extra feature; the rest of Speakup
2395          * will work fine without it.
2396          */
2397
2398         err = register_keyboard_notifier(&keyboard_notifier_block);
2399         if (err)
2400                 goto error_kbdnotifier;
2401         err = register_vt_notifier(&vt_notifier_block);
2402         if (err)
2403                 goto error_vtnotifier;
2404
2405         speakup_task = kthread_create(speakup_thread, NULL, "speakup");
2406
2407         if (IS_ERR(speakup_task)) {
2408                 err = PTR_ERR(speakup_task);
2409                 goto error_task;
2410         }
2411
2412         set_user_nice(speakup_task, 10);
2413         wake_up_process(speakup_task);
2414
2415         pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
2416         pr_info("synth name on entry is: %s\n", synth_name);
2417         goto out;
2418
2419 error_task:
2420         unregister_vt_notifier(&vt_notifier_block);
2421
2422 error_vtnotifier:
2423         unregister_keyboard_notifier(&keyboard_notifier_block);
2424         del_timer(&cursor_timer);
2425
2426 error_kbdnotifier:
2427         speakup_unregister_devsynth();
2428         mutex_lock(&spk_mutex);
2429         synth_release();
2430         mutex_unlock(&spk_mutex);
2431         speakup_kobj_exit();
2432
2433 error_kobjects:
2434         for (i = 0; i < MAX_NR_CONSOLES; i++)
2435                 kfree(speakup_console[i]);
2436
2437         speakup_remove_virtual_keyboard();
2438
2439 error_virtkeyboard:
2440         for (i = 0; i < MAXVARS; i++)
2441                 speakup_unregister_var(i);
2442
2443         for (i = 0; i < 256; i++) {
2444                 if (spk_characters[i] != spk_default_chars[i])
2445                         kfree(spk_characters[i]);
2446         }
2447
2448         spk_free_user_msgs();
2449
2450 out:
2451         return err;
2452 }
2453
2454 module_init(speakup_init);
2455 module_exit(speakup_exit);