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