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