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