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