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