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