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