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