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