linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 0/3] speakup: support 16bit unicode screen reading
@ 2017-03-02  1:53 Samuel Thibault
  2017-03-02  1:53 ` [patch 1/3] speakup: extend synth buffer to 16bit unicode characters Samuel Thibault
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Samuel Thibault @ 2017-03-02  1:53 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Chris Brannon, Kirk Reiser, William Hubbs, devel, linux-kernel, speakup

Hello,

This patch series adds 16bit unicode support to speakup, through three
patches:

- extend synth buffer to 16bit unicode characters
- convert screen reading to 16bit characters
- add unicode variant of /dev/softsynth

Samuel

-- 
Samuel
<erno> hm. I've lost a machine.. literally _lost_. it responds to ping, it works completely, I just can't figure out where in my apartment it is.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [patch 1/3] speakup: extend synth buffer to 16bit unicode characters
  2017-03-02  1:53 [patch 0/3] speakup: support 16bit unicode screen reading Samuel Thibault
@ 2017-03-02  1:53 ` Samuel Thibault
  2017-03-03 18:39   ` Chris Brannon
  2017-03-02  1:53 ` [patch 2/3] speakup: convert screen reading to 16bit characters Samuel Thibault
  2017-03-02  1:53 ` [patch 3/3] speakup: add unicode variant of /dev/softsynth Samuel Thibault
  2 siblings, 1 reply; 9+ messages in thread
From: Samuel Thibault @ 2017-03-02  1:53 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Chris Brannon, Kirk Reiser, William Hubbs, devel, linux-kernel,
	speakup, Samuel Thibault

[-- Attachment #1: buffer-u16 --]
[-- Type: text/plain, Size: 9729 bytes --]

This extends the synth buffer slots to 16bit, so as to hold 16bit
unicode characters.

synth_buffer_getc and synth_buffer_peek now return 16bit characters.
Speech synthesizers which do not support characters beyond latin1 can
use the synth_buffer_skip_nonlatin1() helper to skip the non-latin1
characters before getting or peeking. All synthesizers are made to use
it for now.

This makes synth_buffer_add take a 16bit character. For simplicity for
now, synth_printf is left to using latin1 formats and strings.
synth_putwc, synth_putwc_s, synth_putws and synth_putws_s helpers are
however added to put 16bit characters and strings.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

Index: linux-4.10/drivers/staging/speakup/spk_priv.h
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/spk_priv.h
+++ linux-4.10/drivers/staging/speakup/spk_priv.h
@@ -48,8 +48,9 @@ unsigned char spk_serial_in_nowait(void)
 int spk_serial_out(const char ch);
 void spk_serial_release(void);
 
-char synth_buffer_getc(void);
-char synth_buffer_peek(void);
+void synth_buffer_skip_nonlatin1(void);
+u16 synth_buffer_getc(void);
+u16 synth_buffer_peek(void);
 int synth_buffer_empty(void);
 struct var_t *spk_get_var(enum var_id_t var_id);
 ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -64,6 +65,10 @@ void spk_synth_flush(struct spk_synth *s
 int spk_synth_is_alive_nop(struct spk_synth *synth);
 int spk_synth_is_alive_restart(struct spk_synth *synth);
 void synth_printf(const char *buf, ...);
+void synth_putwc(u16 wc);
+void synth_putwc_s(u16 wc);
+void synth_putws(const u16 *buf);
+void synth_putws_s(const u16 *buf);
 int synth_request_region(u_long, u_long);
 int synth_release_region(u_long, u_long);
 int synth_add(struct spk_synth *in_synth);
Index: linux-4.10/drivers/staging/speakup/speakup.h
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup.h
+++ linux-4.10/drivers/staging/speakup/speakup.h
@@ -70,7 +70,7 @@ void synth_release(void);
 
 void spk_do_flush(void);
 void speakup_start_ttys(void);
-void synth_buffer_add(char ch);
+void synth_buffer_add(u16 ch);
 void synth_buffer_clear(void);
 void speakup_clear_selection(void);
 int speakup_set_selection(struct tty_struct *tty);
Index: linux-4.10/drivers/staging/speakup/synth.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/synth.c
+++ linux-4.10/drivers/staging/speakup/synth.c
@@ -109,6 +109,7 @@ void spk_do_catch_up(struct spk_synth *s
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
@@ -255,6 +256,35 @@ void synth_printf(const char *fmt, ...)
 }
 EXPORT_SYMBOL_GPL(synth_printf);
 
+void synth_putwc(u16 wc)
+{
+	synth_buffer_add(wc);
+}
+EXPORT_SYMBOL_GPL(synth_putwc);
+
+void synth_putwc_s(u16 wc)
+{
+	synth_buffer_add(wc);
+	synth_start();
+}
+EXPORT_SYMBOL_GPL(synth_putwc_s);
+
+void synth_putws(const u16 *buf)
+{
+	const u16 *p;
+
+	for (p = buf; *p; p++)
+		synth_buffer_add(*p);
+}
+EXPORT_SYMBOL_GPL(synth_putws);
+
+void synth_putws_s(const u16 *buf)
+{
+	synth_putws(buf);
+	synth_start();
+}
+EXPORT_SYMBOL_GPL(synth_putws_s);
+
 static int index_count;
 static int sentence_count;
 
Index: linux-4.10/drivers/staging/speakup/buffers.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/buffers.c
+++ linux-4.10/drivers/staging/speakup/buffers.c
@@ -7,10 +7,10 @@
 
 #define SYNTH_BUF_SIZE 8192	/* currently 8K bytes */
 
-static u_char synth_buffer[SYNTH_BUF_SIZE];	/* guess what this is for! */
-static u_char *buff_in = synth_buffer;
-static u_char *buff_out = synth_buffer;
-static u_char *buffer_end = synth_buffer + SYNTH_BUF_SIZE - 1;
+static u16 synth_buffer[SYNTH_BUF_SIZE];	/* guess what this is for! */
+static u16 *buff_in = synth_buffer;
+static u16 *buff_out = synth_buffer;
+static u16 *buffer_end = synth_buffer + SYNTH_BUF_SIZE - 1;
 
 /* These try to throttle applications by stopping the TTYs
  * Note: we need to make sure that we will restart them eventually, which is
@@ -44,13 +44,13 @@ static void speakup_stop_ttys(void)
 
 static int synth_buffer_free(void)
 {
-	int bytes_free;
+	int chars_free;
 
 	if (buff_in >= buff_out)
-		bytes_free = SYNTH_BUF_SIZE - (buff_in - buff_out);
+		chars_free = SYNTH_BUF_SIZE - (buff_in - buff_out);
 	else
-		bytes_free = buff_out - buff_in;
-	return bytes_free;
+		chars_free = buff_out - buff_in;
+	return chars_free;
 }
 
 int synth_buffer_empty(void)
@@ -59,7 +59,7 @@ int synth_buffer_empty(void)
 }
 EXPORT_SYMBOL_GPL(synth_buffer_empty);
 
-void synth_buffer_add(char ch)
+void synth_buffer_add(u16 ch)
 {
 	if (!synth->alive) {
 		/* This makes sure that we won't stop TTYs if there is no synth
@@ -78,9 +78,9 @@ void synth_buffer_add(char ch)
 		buff_in = synth_buffer;
 }
 
-char synth_buffer_getc(void)
+u16 synth_buffer_getc(void)
 {
-	char ch;
+	u16 ch;
 
 	if (buff_out == buff_in)
 		return 0;
@@ -91,7 +91,7 @@ char synth_buffer_getc(void)
 }
 EXPORT_SYMBOL_GPL(synth_buffer_getc);
 
-char synth_buffer_peek(void)
+u16 synth_buffer_peek(void)
 {
 	if (buff_out == buff_in)
 		return 0;
@@ -99,6 +99,18 @@ char synth_buffer_peek(void)
 }
 EXPORT_SYMBOL_GPL(synth_buffer_peek);
 
+void synth_buffer_skip_nonlatin1(void)
+{
+	while (buff_out != buff_in) {
+		if (*buff_out < 0x100)
+			return;
+		buff_out++;
+		if (buff_out > buffer_end)
+			buff_out = synth_buffer;
+	}
+}
+EXPORT_SYMBOL_GPL(synth_buffer_skip_nonlatin1);
+
 void synth_buffer_clear(void)
 {
 	buff_in = synth_buffer;
Index: linux-4.10/drivers/staging/speakup/speakup_acntpc.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_acntpc.c
+++ linux-4.10/drivers/staging/speakup/speakup_acntpc.c
@@ -196,6 +196,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_apollo.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_apollo.c
+++ linux-4.10/drivers/staging/speakup/speakup_apollo.c
@@ -160,6 +160,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_decext.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_decext.c
+++ linux-4.10/drivers/staging/speakup/speakup_decext.c
@@ -175,6 +175,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_decpc.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_decpc.c
+++ linux-4.10/drivers/staging/speakup/speakup_decpc.c
@@ -392,6 +392,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_dectlk.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_dectlk.c
+++ linux-4.10/drivers/staging/speakup/speakup_dectlk.c
@@ -239,6 +239,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_dtlk.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_dtlk.c
+++ linux-4.10/drivers/staging/speakup/speakup_dtlk.c
@@ -209,6 +209,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_keypc.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_keypc.c
+++ linux-4.10/drivers/staging/speakup/speakup_keypc.c
@@ -198,6 +198,7 @@ spin_lock_irqsave(&speakup_info.spinlock
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_soft.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_soft.c
+++ linux-4.10/drivers/staging/speakup/speakup_soft.c
@@ -213,6 +213,7 @@ static ssize_t softsynth_read(struct fil
 	spin_lock_irqsave(&speakup_info.spinlock, flags);
 	while (1) {
 		prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE);
+		synth_buffer_skip_nonlatin1();
 		if (!synth_buffer_empty() || speakup_info.flushing)
 			break;
 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [patch 2/3] speakup: convert screen reading to 16bit characters
  2017-03-02  1:53 [patch 0/3] speakup: support 16bit unicode screen reading Samuel Thibault
  2017-03-02  1:53 ` [patch 1/3] speakup: extend synth buffer to 16bit unicode characters Samuel Thibault
@ 2017-03-02  1:53 ` Samuel Thibault
  2017-03-04  8:50   ` Okash Khawaja
  2017-03-04  8:59   ` Okash Khawaja
  2017-03-02  1:53 ` [patch 3/3] speakup: add unicode variant of /dev/softsynth Samuel Thibault
  2 siblings, 2 replies; 9+ messages in thread
From: Samuel Thibault @ 2017-03-02  1:53 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Chris Brannon, Kirk Reiser, William Hubbs, devel, linux-kernel,
	speakup, Samuel Thibault

[-- Attachment #1: speakup-u16 --]
[-- Type: text/plain, Size: 14421 bytes --]

This adds 16bit character support to most of the screen reading by
extending characters to u16 throughout the code.

Non-latin1 characters are assumed to be alphabetic type for now.

non-latin1 vt_notifier_call-provided characters are not ignored any
more, and the 16bit character returned by get_char is not truncated any
more. For simplicity, speak_char still only supports latin1 characters.
Its direct mode however does support 16bit characters, so in practice
this will not be a limitation, non-latin1 languages will be handled by
the synthesizer. spelling words does not support direct mode yet, for
simplicity for now it will ignore 16bit characters.

For simplicity again, speakup messages are left in latin1 for now.

Some coding style is fixed along the way.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

Index: linux-4.10/drivers/staging/speakup/main.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/main.c
+++ linux-4.10/drivers/staging/speakup/main.c
@@ -67,7 +67,7 @@ MODULE_PARM_DESC(quiet, "Do not announce
 special_func spk_special_handler;
 
 short spk_pitch_shift, synth_flags;
-static char buf[256];
+static u16 buf[256];
 int spk_attrib_bleep, spk_bleeps, spk_bleep_time = 10;
 int spk_no_intr, spk_spell_delay;
 int spk_key_echo, spk_say_word_ctl;
@@ -112,7 +112,7 @@ enum {
 
 static struct tty_struct *tty;
 
-static void spkup_write(const char *in_buf, int count);
+static void spkup_write(const u16 *in_buf, int count);
 
 static char *phonetic[] = {
 	"alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel",
@@ -238,7 +238,8 @@ static u_short default_chartab[256] = {
 struct task_struct *speakup_task;
 struct bleep spk_unprocessed_sound;
 static int spk_keydown;
-static u_char spk_lastkey, spk_close_press, keymap_flags;
+static u16 spk_lastkey;
+static u_char spk_close_press, keymap_flags;
 static u_char last_keycode, this_speakup_key;
 static u_long last_spk_jiffy;
 
@@ -426,9 +427,9 @@ static void announce_edge(struct vc_data
 			spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
 }
 
-static void speak_char(u_char ch)
+static void speak_char(u16 ch)
 {
-	char *cp = spk_characters[ch];
+	char *cp;
 	struct var_t *direct = spk_get_var(DIRECT);
 
 	if (direct && direct->u.n.value) {
@@ -436,11 +437,15 @@ static void speak_char(u_char ch)
 			spk_pitch_shift++;
 			synth_printf("%s", spk_str_caps_start);
 		}
-		synth_printf("%c", ch);
+		synth_putwc_s(ch);
 		if (IS_CHAR(ch, B_CAP))
 			synth_printf("%s", spk_str_caps_stop);
 		return;
 	}
+
+	if (ch >= 0x100)
+		return;
+	cp = spk_characters[ch];
 	if (cp == NULL) {
 		pr_info("speak_char: cp == NULL!\n");
 		return;
@@ -486,7 +491,7 @@ static u16 get_char(struct vc_data *vc,
 
 static void say_char(struct vc_data *vc)
 {
-	u_short ch;
+	u16 ch;
 
 	spk_old_attr = spk_attr;
 	ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
@@ -496,20 +501,20 @@ static void say_char(struct vc_data *vc)
 		if (spk_attrib_bleep & 2)
 			say_attributes(vc);
 	}
-	speak_char(ch & 0xff);
+	speak_char(ch);
 }
 
 static void say_phonetic_char(struct vc_data *vc)
 {
-	u_short ch;
+	u16 ch;
 
 	spk_old_attr = spk_attr;
 	ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
-	if (isascii(ch) && isalpha(ch)) {
+	if (ch <= 0x7f && isalpha(ch)) {
 		ch &= 0x1f;
 		synth_printf("%s\n", phonetic[--ch]);
 	} else {
-		if (IS_CHAR(ch, B_NUM))
+		if (ch < 0x100 && IS_CHAR(ch, B_NUM))
 			synth_printf("%s ", spk_msg_get(MSG_NUMBER));
 		speak_char(ch);
 	}
@@ -551,42 +556,42 @@ static void say_next_char(struct vc_data
 static u_long get_word(struct vc_data *vc)
 {
 	u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
-	char ch;
-	u_short attr_ch;
+	u16 ch;
+	u16 attr_ch;
 	u_char temp;
 
 	spk_old_attr = spk_attr;
-	ch = (char)get_char(vc, (u_short *)tmp_pos, &temp);
+	ch = get_char(vc, (u_short *)tmp_pos, &temp);
 
 /* decided to take out the sayword if on a space (mis-information */
 	if (spk_say_word_ctl && ch == SPACE) {
 		*buf = '\0';
 		synth_printf("%s\n", spk_msg_get(MSG_SPACE));
 		return 0;
-	} else if ((tmpx < vc->vc_cols - 2)
-		   && (ch == SPACE || ch == 0 || IS_WDLM(ch))
-		   && ((char)get_char(vc, (u_short *)&tmp_pos + 1, &temp) >
-		       SPACE)) {
+	} else if (tmpx < vc->vc_cols - 2 &&
+		   (ch == SPACE || ch == 0 || (ch < 0x100 && IS_WDLM(ch))) &&
+		   get_char(vc, (u_short *)&tmp_pos + 1, &temp) > SPACE) {
 		tmp_pos += 2;
 		tmpx++;
 	} else
 		while (tmpx > 0) {
-			ch = (char)get_char(vc, (u_short *)tmp_pos - 1, &temp);
-			if ((ch == SPACE || ch == 0 || IS_WDLM(ch))
-			    && ((char)get_char(vc, (u_short *)tmp_pos, &temp) >
-				SPACE))
+			ch = get_char(vc, (u_short *)tmp_pos - 1, &temp);
+			if ((ch == SPACE || ch == 0 ||
+			     (ch < 0x100 && IS_WDLM(ch))) &&
+			    get_char(vc, (u_short *)tmp_pos, &temp) > SPACE)
 				break;
 			tmp_pos -= 2;
 			tmpx--;
 		}
 	attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
-	buf[cnt++] = attr_ch & 0xff;
+	buf[cnt++] = attr_ch;
 	while (tmpx < vc->vc_cols - 1) {
 		tmp_pos += 2;
 		tmpx++;
-		ch = (char)get_char(vc, (u_short *)tmp_pos, &temp);
-		if ((ch == SPACE) || ch == 0
-		    || (IS_WDLM(buf[cnt - 1]) && (ch > SPACE)))
+		ch = get_char(vc, (u_short *)tmp_pos, &temp);
+		if (ch == SPACE || ch == 0 ||
+		    (buf[cnt - 1] < 0x100 && IS_WDLM(buf[cnt - 1]) &&
+		     ch > SPACE))
 			break;
 		buf[cnt++] = ch;
 	}
@@ -610,7 +615,7 @@ static void say_word(struct vc_data *vc)
 static void say_prev_word(struct vc_data *vc)
 {
 	u_char temp;
-	char ch;
+	u16 ch;
 	u_short edge_said = 0, last_state = 0, state = 0;
 
 	spk_parked |= 0x01;
@@ -639,10 +644,10 @@ static void say_prev_word(struct vc_data
 		} else
 			spk_x--;
 		spk_pos -= 2;
-		ch = (char)get_char(vc, (u_short *)spk_pos, &temp);
+		ch = get_char(vc, (u_short *)spk_pos, &temp);
 		if (ch == SPACE || ch == 0)
 			state = 0;
-		else if (IS_WDLM(ch))
+		else if (ch < 0x100 && IS_WDLM(ch))
 			state = 1;
 		else
 			state = 2;
@@ -663,7 +668,7 @@ static void say_prev_word(struct vc_data
 static void say_next_word(struct vc_data *vc)
 {
 	u_char temp;
-	char ch;
+	u16 ch;
 	u_short edge_said = 0, last_state = 2, state = 0;
 
 	spk_parked |= 0x01;
@@ -672,10 +677,10 @@ static void say_next_word(struct vc_data
 		return;
 	}
 	while (1) {
-		ch = (char)get_char(vc, (u_short *)spk_pos, &temp);
+		ch = get_char(vc, (u_short *)spk_pos, &temp);
 		if (ch == SPACE || ch == 0)
 			state = 0;
-		else if (IS_WDLM(ch))
+		else if (ch < 0x100 && IS_WDLM(ch))
 			state = 1;
 		else
 			state = 2;
@@ -703,13 +708,18 @@ static void say_next_word(struct vc_data
 static void spell_word(struct vc_data *vc)
 {
 	static char const *delay_str[] = { "", ",", ".", ". .", ". . ." };
-	char *cp = buf, *str_cap = spk_str_caps_stop;
-	char *cp1, *last_cap = spk_str_caps_stop;
-	u_char ch;
+	u16 *cp = buf;
+	char *cp1;
+	char *str_cap = spk_str_caps_stop;
+	char *last_cap = spk_str_caps_stop;
+	u16 ch;
 
 	if (!get_word(vc))
 		return;
-	while ((ch = (u_char)*cp)) {
+	while ((ch = *cp)) {
+		if (ch >= 0x100)
+			/* FIXME */
+			continue;
 		if (cp != buf)
 			synth_printf(" %s ", delay_str[spk_spell_delay]);
 		if (IS_CHAR(ch, B_CAP)) {
@@ -724,9 +734,9 @@ static void spell_word(struct vc_data *v
 			synth_printf("%s", str_cap);
 			last_cap = str_cap;
 		}
-		if (this_speakup_key == SPELL_PHONETIC
-		    && (isascii(ch) && isalpha(ch))) {
-			ch &= 31;
+		if (this_speakup_key == SPELL_PHONETIC &&
+		    ch <= 0x7f && isalpha(ch)) {
+			ch &= 0x1f;
 			cp1 = phonetic[--ch];
 		} else {
 			cp1 = spk_characters[ch];
@@ -751,7 +761,7 @@ static int get_line(struct vc_data *vc)
 	spk_old_attr = spk_attr;
 	spk_attr = get_attributes(vc, (u_short *)spk_pos);
 	for (i = 0; i < vc->vc_cols; i++) {
-		buf[i] = (u_char)get_char(vc, (u_short *)tmp, &tmp2);
+		buf[i] = get_char(vc, (u_short *)tmp, &tmp2);
 		tmp += 2;
 	}
 	for (--i; i >= 0; i--)
@@ -763,7 +773,7 @@ static int get_line(struct vc_data *vc)
 static void say_line(struct vc_data *vc)
 {
 	int i = get_line(vc);
-	char *cp;
+	u16 *cp;
 	u_short saved_punc_mask = spk_punc_mask;
 
 	if (i == 0) {
@@ -816,7 +826,7 @@ static int say_from_to(struct vc_data *v
 	spk_old_attr = spk_attr;
 	spk_attr = get_attributes(vc, (u_short *)from);
 	while (from < to) {
-		buf[i++] = (char)get_char(vc, (u_short *)from, &tmp);
+		buf[i++] = get_char(vc, (u_short *)from, &tmp);
 		from += 2;
 		if (i >= vc->vc_size_row)
 			break;
@@ -852,11 +862,11 @@ static void say_line_from_to(struct vc_d
 
 static int currsentence;
 static int numsentences[2];
-static char *sentbufend[2];
-static char *sentmarks[2][10];
+static u16 *sentbufend[2];
+static u16 *sentmarks[2][10];
 static int currbuf;
 static int bn;
-static char sentbuf[2][256];
+static u16 sentbuf[2][256];
 
 static int say_sentence_num(int num, int prev)
 {
@@ -892,7 +902,7 @@ static int get_sentence_buf(struct vc_da
 	spk_attr = get_attributes(vc, (u_short *)start);
 
 	while (start < end) {
-		sentbuf[bn][i] = (char)get_char(vc, (u_short *)start, &tmp);
+		sentbuf[bn][i] = get_char(vc, (u_short *)start, &tmp);
 		if (i > 0) {
 			if (sentbuf[bn][i] == SPACE && sentbuf[bn][i - 1] == '.'
 			    && numsentences[bn] < 9) {
@@ -995,7 +1005,7 @@ static void right_edge(struct vc_data *v
 static void say_first_char(struct vc_data *vc)
 {
 	int i, len = get_line(vc);
-	u_char ch;
+	u16 ch;
 
 	spk_parked |= 0x01;
 	if (len == 0) {
@@ -1015,7 +1025,7 @@ static void say_first_char(struct vc_dat
 static void say_last_char(struct vc_data *vc)
 {
 	int len = get_line(vc);
-	u_char ch;
+	u16 ch;
 
 	spk_parked |= 0x01;
 	if (len == 0) {
@@ -1040,9 +1050,8 @@ static void say_position(struct vc_data
 static void say_char_num(struct vc_data *vc)
 {
 	u_char tmp;
-	u_short ch = get_char(vc, (u_short *)spk_pos, &tmp);
+	u16 ch = get_char(vc, (u_short *)spk_pos, &tmp);
 
-	ch &= 0xff;
 	synth_printf(spk_msg_get(MSG_CHAR_INFO), ch, ch);
 }
 
@@ -1070,10 +1079,10 @@ static void say_to_right(struct vc_data
 
 /* end of stub functions. */
 
-static void spkup_write(const char *in_buf, int count)
+static void spkup_write(const u16 *in_buf, int count)
 {
 	static int rep_count;
-	static u_char ch = '\0', old_ch = '\0';
+	static u16 ch = '\0', old_ch = '\0';
 	static u_short char_type, last_type;
 	int in_count = count;
 
@@ -1085,8 +1094,11 @@ static void spkup_write(const char *in_b
 			    (currsentence <= numsentences[bn]))
 				synth_insert_next_index(currsentence++);
 		}
-		ch = (u_char)*in_buf++;
-		char_type = spk_chartab[ch];
+		ch = *in_buf++;
+		if (ch < 0x100)
+			char_type = spk_chartab[ch];
+		else
+			char_type = ALPHA;
 		if (ch == old_ch && !(char_type & B_NUM)) {
 			if (++rep_count > 2)
 				continue;
@@ -1106,10 +1118,10 @@ static void spkup_write(const char *in_b
 		} else if (char_type & B_ALPHA) {
 			if ((synth_flags & SF_DEC) && (last_type & PUNC))
 				synth_buffer_add(SPACE);
-			synth_printf("%c", ch);
+			synth_putwc_s(ch);
 		} else if (char_type & B_NUM) {
 			rep_count = 0;
-			synth_printf("%c", ch);
+			synth_putwc_s(ch);
 		} else if (char_type & spk_punc_mask) {
 			speak_char(ch);
 			char_type &= ~PUNC;	/* for dec nospell processing */
@@ -1122,7 +1134,7 @@ static void spkup_write(const char *in_b
 			 * repeats on you don't get nothing repeated count
 			 */
 			if (ch != old_ch)
-				synth_printf("%c", ch);
+				synth_putwc_s(ch);
 			else
 				rep_count = 0;
 		} else {
@@ -1533,7 +1545,7 @@ static void do_handle_cursor(struct vc_d
 	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 }
 
-static void update_color_buffer(struct vc_data *vc, const char *ic, int len)
+static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
 {
 	int i, bi, hi;
 	int vc_num = vc->vc_num;
@@ -1548,7 +1560,7 @@ static void update_color_buffer(struct v
 		speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;
 	}
 	while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
-		if ((ic[i] > 32) && (ic[i] < 127)) {
+		if (ic[i] > 32) {
 			speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
 			hi++;
 		} else if ((ic[i] == 32) && (hi != 0)) {
@@ -1718,7 +1730,7 @@ static void speakup_bs(struct vc_data *v
 }
 
 /* called by: vt_notifier_call() */
-static void speakup_con_write(struct vc_data *vc, const char *str, int len)
+static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
 {
 	unsigned long flags;
 
@@ -1908,6 +1920,7 @@ static int handle_goto(struct vc_data *v
 	static int num;
 	int maxlen;
 	char *cp;
+	u16 wch;
 
 	if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
 		goto do_goto;
@@ -1916,18 +1929,20 @@ static int handle_goto(struct vc_data *v
 	if (type != 0)
 		goto oops;
 	if (ch == 8) {
+		u16 wch;
 		if (num == 0)
 			return -1;
-		ch = goto_buf[--num];
+		wch = goto_buf[--num];
 		goto_buf[num] = '\0';
-		spkup_write(&ch, 1);
+		spkup_write(&wch, 1);
 		return 1;
 	}
 	if (ch < '+' || ch > 'y')
 		goto oops;
+	wch = ch;
 	goto_buf[num++] = ch;
 	goto_buf[num] = '\0';
-	spkup_write(&ch, 1);
+	spkup_write(&wch, 1);
 	maxlen = (*goto_buf >= '0') ? 3 : 4;
 	if ((ch == '+' || ch == '-') && num == 1)
 		return 1;
@@ -2254,9 +2269,8 @@ static int vt_notifier_call(struct notif
 	case VT_WRITE:
 		if (param->c == '\b')
 			speakup_bs(vc);
-		else if (param->c < 0x100) {
-			char d = param->c;
-
+		else {
+			u16 d = param->c;
 			speakup_con_write(vc, &d, 1);
 		}
 		break;
Index: linux-4.10/drivers/staging/speakup/spk_types.h
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/spk_types.h
+++ linux-4.10/drivers/staging/speakup/spk_types.h
@@ -55,7 +55,7 @@ struct spk_highlight_color_track {
 	/* Count of each background color */
 	unsigned int bgcount[8];
 	/* Buffer for characters drawn with each background color */
-	char highbuf[8][COLOR_BUFFER_SIZE];
+	u16 highbuf[8][COLOR_BUFFER_SIZE];
 	/* Current index into highbuf */
 	unsigned int highsize[8];
 	/* Reading Position for each color */
Index: linux-4.10/drivers/staging/speakup/speakup.h
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup.h
+++ linux-4.10/drivers/staging/speakup/speakup.h
@@ -38,6 +38,7 @@
 #define B_SYM 0x0800
 #define B_CAPSYM (B_CAP|B_SYM)
 
+/* FIXME: u16 */
 #define IS_WDLM(x) (spk_chartab[((u_char)x)]&B_WDLM)
 #define IS_CHAR(x, type) (spk_chartab[((u_char)x)]&type)
 #define IS_TYPE(x, type) ((spk_chartab[((u_char)x)]&type) == type)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [patch 3/3] speakup: add unicode variant of /dev/softsynth
  2017-03-02  1:53 [patch 0/3] speakup: support 16bit unicode screen reading Samuel Thibault
  2017-03-02  1:53 ` [patch 1/3] speakup: extend synth buffer to 16bit unicode characters Samuel Thibault
  2017-03-02  1:53 ` [patch 2/3] speakup: convert screen reading to 16bit characters Samuel Thibault
@ 2017-03-02  1:53 ` Samuel Thibault
  2017-03-03 18:40   ` Chris Brannon
  2 siblings, 1 reply; 9+ messages in thread
From: Samuel Thibault @ 2017-03-02  1:53 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Chris Brannon, Kirk Reiser, William Hubbs, devel, linux-kernel,
	speakup, Samuel Thibault

[-- Attachment #1: softsynthu --]
[-- Type: text/plain, Size: 5280 bytes --]

This adds /dev/softsynthu, along /dev/softsynth, which emits output in
UTF-8 encoding, thus allowing to support 16bit characters.  Most of the
code is shared, only the read function has to behave differently in
latin1 and in unicode mode.  Since Linux only supports 16bit characters,
we can just hardcode the UTF-8 encoding.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>

Index: linux-4.10/drivers/staging/speakup/speakup_soft.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_soft.c
+++ linux-4.10/drivers/staging/speakup/speakup_soft.c
@@ -29,6 +29,7 @@
 
 #define DRV_VERSION "2.6"
 #define SOFTSYNTH_MINOR 26 /* might as well give it one more than /dev/synth */
+#define SOFTSYNTHU_MINOR 27 /* might as well give it one more than /dev/synth */
 #define PROCSPEECH 0x0d
 #define CLEAR_SYNTH 0x18
 
@@ -37,7 +38,7 @@ static void softsynth_release(void);
 static int softsynth_is_alive(struct spk_synth *synth);
 static unsigned char get_index(void);
 
-static struct miscdevice synth_device;
+static struct miscdevice synth_device, synthu_device;
 static int init_pos;
 static int misc_registered;
 
@@ -199,13 +200,13 @@ static int softsynth_close(struct inode
 	return 0;
 }
 
-static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count,
-			      loff_t *pos)
+static ssize_t softsynthx_read(struct file *fp, char __user *buf, size_t count,
+			       loff_t *pos, int unicode)
 {
 	int chars_sent = 0;
 	char __user *cp;
 	char *init;
-	char ch;
+	u16 ch;
 	int empty;
 	unsigned long flags;
 	DEFINE_WAIT(wait);
@@ -213,7 +214,8 @@ static ssize_t softsynth_read(struct fil
 	spin_lock_irqsave(&speakup_info.spinlock, flags);
 	while (1) {
 		prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE);
-		synth_buffer_skip_nonlatin1();
+		if (!unicode)
+			synth_buffer_skip_nonlatin1();
 		if (!synth_buffer_empty() || speakup_info.flushing)
 			break;
 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
@@ -232,23 +234,57 @@ static ssize_t softsynth_read(struct fil
 
 	cp = buf;
 	init = get_initstring();
-	while (chars_sent < count) {
+
+	/* Keep 3 bytes available for a 16bit UTF-8-encoded character */
+	while (chars_sent <= count - 3) {
 		if (speakup_info.flushing) {
 			speakup_info.flushing = 0;
 			ch = '\x18';
-		} else if (synth_buffer_empty()) {
-			break;
 		} else if (init[init_pos]) {
 			ch = init[init_pos++];
 		} else {
+			if (!unicode)
+				synth_buffer_skip_nonlatin1();
+			if (synth_buffer_empty())
+				break;
 			ch = synth_buffer_getc();
 		}
 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);
-		if (copy_to_user(cp, &ch, 1))
-			return -EFAULT;
+
+		if ((!unicode && ch < 0x100) || (unicode && ch < 0x80)) {
+			u_char c = ch;
+
+			if (copy_to_user(cp, &c, 1))
+				return -EFAULT;
+
+			chars_sent++;
+			cp++;
+		} else if (unicode && ch < 0x800) {
+			u_char s[2] = {
+				0xc0 | (ch >> 6),
+				0x80 | (ch & 0x3f)
+			};
+
+			if (copy_to_user(cp, s, sizeof(s)))
+				return -EFAULT;
+
+			chars_sent += sizeof(s);
+			cp += sizeof(s);
+		} else if (unicode) {
+			u_char s[3] = {
+				0xe0 | (ch >> 12),
+				0x80 | ((ch >> 6) & 0x3f),
+				0x80 | (ch & 0x3f)
+			};
+
+			if (copy_to_user(cp, s, sizeof(s)))
+				return -EFAULT;
+
+			chars_sent += sizeof(s);
+			cp += sizeof(s);
+		}
+
 		spin_lock_irqsave(&speakup_info.spinlock, flags);
-		chars_sent++;
-		cp++;
 	}
 	*pos += chars_sent;
 	empty = synth_buffer_empty();
@@ -260,6 +296,18 @@ static ssize_t softsynth_read(struct fil
 	return chars_sent;
 }
 
+static ssize_t softsynth_read(struct file *fp, char __user *buf, size_t count,
+			      loff_t *pos)
+{
+	return softsynthx_read(fp, buf, count, pos, 0);
+}
+
+static ssize_t softsynthu_read(struct file *fp, char __user *buf, size_t count,
+			       loff_t *pos)
+{
+	return softsynthx_read(fp, buf, count, pos, 1);
+}
+
 static int last_index;
 
 static ssize_t softsynth_write(struct file *fp, const char __user *buf,
@@ -309,6 +357,15 @@ static const struct file_operations soft
 	.release = softsynth_close,
 };
 
+static const struct file_operations softsynthu_fops = {
+	.owner = THIS_MODULE,
+	.poll = softsynth_poll,
+	.read = softsynthu_read,
+	.write = softsynth_write,
+	.open = softsynth_open,
+	.release = softsynth_close,
+};
+
 static int softsynth_probe(struct spk_synth *synth)
 {
 	if (misc_registered != 0)
@@ -322,16 +379,28 @@ static int softsynth_probe(struct spk_sy
 		return -ENODEV;
 	}
 
+	memset(&synthu_device, 0, sizeof(synthu_device));
+	synthu_device.minor = SOFTSYNTHU_MINOR;
+	synthu_device.name = "softsynthu";
+	synthu_device.fops = &softsynthu_fops;
+	if (misc_register(&synthu_device)) {
+		pr_warn("Couldn't initialize miscdevice /dev/softsynth.\n");
+		return -ENODEV;
+	}
+
 	misc_registered = 1;
 	pr_info("initialized device: /dev/softsynth, node (MAJOR 10, MINOR 26)\n");
+	pr_info("initialized device: /dev/softsynthu, node (MAJOR 10, MINOR 27)\n");
 	return 0;
 }
 
 static void softsynth_release(void)
 {
 	misc_deregister(&synth_device);
+	misc_deregister(&synthu_device);
 	misc_registered = 0;
 	pr_info("unregistered /dev/softsynth\n");
+	pr_info("unregistered /dev/softsynthu\n");
 }
 
 static int softsynth_is_alive(struct spk_synth *synth)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 1/3] speakup: extend synth buffer to 16bit unicode characters
  2017-03-02  1:53 ` [patch 1/3] speakup: extend synth buffer to 16bit unicode characters Samuel Thibault
@ 2017-03-03 18:39   ` Chris Brannon
  0 siblings, 0 replies; 9+ messages in thread
From: Chris Brannon @ 2017-03-03 18:39 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: Greg Kroah-Hartman, Kirk Reiser, William Hubbs, devel,
	linux-kernel, speakup

Samuel Thibault <samuel.thibault@ens-lyon.org> writes:

> This extends the synth buffer slots to 16bit, so as to hold 16bit
> unicode characters.
>
> synth_buffer_getc and synth_buffer_peek now return 16bit characters.
> Speech synthesizers which do not support characters beyond latin1 can
> use the synth_buffer_skip_nonlatin1() helper to skip the non-latin1
> characters before getting or peeking. All synthesizers are made to use
> it for now.
>
> This makes synth_buffer_add take a 16bit character. For simplicity for
> now, synth_printf is left to using latin1 formats and strings.
> synth_putwc, synth_putwc_s, synth_putws and synth_putws_s helpers are
> however added to put 16bit characters and strings.
>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>


Reviewed-by: Chris Brannon <chris@the-brannons.com>


Looks good to me.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 3/3] speakup: add unicode variant of /dev/softsynth
  2017-03-02  1:53 ` [patch 3/3] speakup: add unicode variant of /dev/softsynth Samuel Thibault
@ 2017-03-03 18:40   ` Chris Brannon
  0 siblings, 0 replies; 9+ messages in thread
From: Chris Brannon @ 2017-03-03 18:40 UTC (permalink / raw)
  To: Samuel Thibault
  Cc: Greg Kroah-Hartman, Kirk Reiser, William Hubbs, devel,
	linux-kernel, speakup

Samuel Thibault <samuel.thibault@ens-lyon.org> writes:

> This adds /dev/softsynthu, along /dev/softsynth, which emits output in
> UTF-8 encoding, thus allowing to support 16bit characters.  Most of the
> code is shared, only the read function has to behave differently in
> latin1 and in unicode mode.  Since Linux only supports 16bit characters,
> we can just hardcode the UTF-8 encoding.
>
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>


Reviewed-by: Chris Brannon <chris@the-brannons.com>

Looks good to me.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/3] speakup: convert screen reading to 16bit characters
  2017-03-02  1:53 ` [patch 2/3] speakup: convert screen reading to 16bit characters Samuel Thibault
@ 2017-03-04  8:50   ` Okash Khawaja
  2017-03-04  8:59   ` Okash Khawaja
  1 sibling, 0 replies; 9+ messages in thread
From: Okash Khawaja @ 2017-03-04  8:50 UTC (permalink / raw)
  To: Speakup is a screen review system for Linux.
  Cc: Samuel Thibault, Greg Kroah-Hartman, devel, linux-kernel

On Thu, Mar 02, 2017 at 02:53:55AM +0100, Samuel Thibault wrote:
> This adds 16bit character support to most of the screen reading by
> extending characters to u16 throughout the code.
> 
> Non-latin1 characters are assumed to be alphabetic type for now.
> 
> non-latin1 vt_notifier_call-provided characters are not ignored any
> more, and the 16bit character returned by get_char is not truncated any
> more. For simplicity, speak_char still only supports latin1 characters.
> Its direct mode however does support 16bit characters, so in practice
> this will not be a limitation, non-latin1 languages will be handled by
> the synthesizer. spelling words does not support direct mode yet, for
> simplicity for now it will ignore 16bit characters.
> 
> For simplicity again, speakup messages are left in latin1 for now.
> 
> Some coding style is fixed along the way.
> 
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> 
> Index: linux-4.10/drivers/staging/speakup/main.c
> ===================================================================
> --- linux-4.10.orig/drivers/staging/speakup/main.c
> +++ linux-4.10/drivers/staging/speakup/main.c
> @@ -67,7 +67,7 @@ MODULE_PARM_DESC(quiet, "Do not announce
>  special_func spk_special_handler;
>  
>  short spk_pitch_shift, synth_flags;
> -static char buf[256];
> +static u16 buf[256];
>  int spk_attrib_bleep, spk_bleeps, spk_bleep_time = 10;
>  int spk_no_intr, spk_spell_delay;
>  int spk_key_echo, spk_say_word_ctl;
> @@ -112,7 +112,7 @@ enum {
>  
>  static struct tty_struct *tty;
>  
> -static void spkup_write(const char *in_buf, int count);
> +static void spkup_write(const u16 *in_buf, int count);
>  
>  static char *phonetic[] = {
>  	"alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel",
> @@ -238,7 +238,8 @@ static u_short default_chartab[256] = {
>  struct task_struct *speakup_task;
>  struct bleep spk_unprocessed_sound;
>  static int spk_keydown;
> -static u_char spk_lastkey, spk_close_press, keymap_flags;
> +static u16 spk_lastkey;
> +static u_char spk_close_press, keymap_flags;
>  static u_char last_keycode, this_speakup_key;
>  static u_long last_spk_jiffy;
>  
> @@ -426,9 +427,9 @@ static void announce_edge(struct vc_data
>  			spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
>  }
>  
> -static void speak_char(u_char ch)
> +static void speak_char(u16 ch)
>  {
> -	char *cp = spk_characters[ch];
> +	char *cp;
>  	struct var_t *direct = spk_get_var(DIRECT);
>  
>  	if (direct && direct->u.n.value) {
> @@ -436,11 +437,15 @@ static void speak_char(u_char ch)
>  			spk_pitch_shift++;
>  			synth_printf("%s", spk_str_caps_start);
>  		}
> -		synth_printf("%c", ch);
> +		synth_putwc_s(ch);
>  		if (IS_CHAR(ch, B_CAP))
>  			synth_printf("%s", spk_str_caps_stop);
>  		return;
>  	}
> +
> +	if (ch >= 0x100)
> +		return;
> +	cp = spk_characters[ch];
>  	if (cp == NULL) {
>  		pr_info("speak_char: cp == NULL!\n");
>  		return;
> @@ -486,7 +491,7 @@ static u16 get_char(struct vc_data *vc,
>  
>  static void say_char(struct vc_data *vc)
>  {
> -	u_short ch;
> +	u16 ch;
>  
>  	spk_old_attr = spk_attr;
>  	ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
> @@ -496,20 +501,20 @@ static void say_char(struct vc_data *vc)
>  		if (spk_attrib_bleep & 2)
>  			say_attributes(vc);
>  	}
> -	speak_char(ch & 0xff);
> +	speak_char(ch);
>  }
>  
>  static void say_phonetic_char(struct vc_data *vc)
>  {
> -	u_short ch;
> +	u16 ch;
>  
>  	spk_old_attr = spk_attr;
>  	ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
> -	if (isascii(ch) && isalpha(ch)) {
> +	if (ch <= 0x7f && isalpha(ch)) {
>  		ch &= 0x1f;
>  		synth_printf("%s\n", phonetic[--ch]);
>  	} else {
> -		if (IS_CHAR(ch, B_NUM))
> +		if (ch < 0x100 && IS_CHAR(ch, B_NUM))
>  			synth_printf("%s ", spk_msg_get(MSG_NUMBER));
>  		speak_char(ch);
>  	}
> @@ -551,42 +556,42 @@ static void say_next_char(struct vc_data
>  static u_long get_word(struct vc_data *vc)
>  {
>  	u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
> -	char ch;
> -	u_short attr_ch;
> +	u16 ch;
> +	u16 attr_ch;
>  	u_char temp;
>  
>  	spk_old_attr = spk_attr;
> -	ch = (char)get_char(vc, (u_short *)tmp_pos, &temp);
> +	ch = get_char(vc, (u_short *)tmp_pos, &temp);
>  
>  /* decided to take out the sayword if on a space (mis-information */
>  	if (spk_say_word_ctl && ch == SPACE) {
>  		*buf = '\0';
>  		synth_printf("%s\n", spk_msg_get(MSG_SPACE));
>  		return 0;
> -	} else if ((tmpx < vc->vc_cols - 2)
> -		   && (ch == SPACE || ch == 0 || IS_WDLM(ch))
> -		   && ((char)get_char(vc, (u_short *)&tmp_pos + 1, &temp) >
> -		       SPACE)) {
> +	} else if (tmpx < vc->vc_cols - 2 &&
> +		   (ch == SPACE || ch == 0 || (ch < 0x100 && IS_WDLM(ch))) &&
> +		   get_char(vc, (u_short *)&tmp_pos + 1, &temp) > SPACE) {
>  		tmp_pos += 2;
>  		tmpx++;
>  	} else
>  		while (tmpx > 0) {
> -			ch = (char)get_char(vc, (u_short *)tmp_pos - 1, &temp);
> -			if ((ch == SPACE || ch == 0 || IS_WDLM(ch))
> -			    && ((char)get_char(vc, (u_short *)tmp_pos, &temp) >
> -				SPACE))
> +			ch = get_char(vc, (u_short *)tmp_pos - 1, &temp);
> +			if ((ch == SPACE || ch == 0 ||
> +			     (ch < 0x100 && IS_WDLM(ch))) &&
> +			    get_char(vc, (u_short *)tmp_pos, &temp) > SPACE)
>  				break;
>  			tmp_pos -= 2;
>  			tmpx--;
>  		}
>  	attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
> -	buf[cnt++] = attr_ch & 0xff;
> +	buf[cnt++] = attr_ch;
>  	while (tmpx < vc->vc_cols - 1) {
>  		tmp_pos += 2;
>  		tmpx++;
> -		ch = (char)get_char(vc, (u_short *)tmp_pos, &temp);
> -		if ((ch == SPACE) || ch == 0
> -		    || (IS_WDLM(buf[cnt - 1]) && (ch > SPACE)))
> +		ch = get_char(vc, (u_short *)tmp_pos, &temp);
> +		if (ch == SPACE || ch == 0 ||
> +		    (buf[cnt - 1] < 0x100 && IS_WDLM(buf[cnt - 1]) &&
> +		     ch > SPACE))
>  			break;
>  		buf[cnt++] = ch;
>  	}
> @@ -610,7 +615,7 @@ static void say_word(struct vc_data *vc)
>  static void say_prev_word(struct vc_data *vc)
>  {
>  	u_char temp;
> -	char ch;
> +	u16 ch;
>  	u_short edge_said = 0, last_state = 0, state = 0;
>  
>  	spk_parked |= 0x01;
> @@ -639,10 +644,10 @@ static void say_prev_word(struct vc_data
>  		} else
>  			spk_x--;
>  		spk_pos -= 2;
> -		ch = (char)get_char(vc, (u_short *)spk_pos, &temp);
> +		ch = get_char(vc, (u_short *)spk_pos, &temp);
>  		if (ch == SPACE || ch == 0)
>  			state = 0;
> -		else if (IS_WDLM(ch))
> +		else if (ch < 0x100 && IS_WDLM(ch))
>  			state = 1;
>  		else
>  			state = 2;
> @@ -663,7 +668,7 @@ static void say_prev_word(struct vc_data
>  static void say_next_word(struct vc_data *vc)
>  {
>  	u_char temp;
> -	char ch;
> +	u16 ch;
>  	u_short edge_said = 0, last_state = 2, state = 0;
>  
>  	spk_parked |= 0x01;
> @@ -672,10 +677,10 @@ static void say_next_word(struct vc_data
>  		return;
>  	}
>  	while (1) {
> -		ch = (char)get_char(vc, (u_short *)spk_pos, &temp);
> +		ch = get_char(vc, (u_short *)spk_pos, &temp);
>  		if (ch == SPACE || ch == 0)
>  			state = 0;
> -		else if (IS_WDLM(ch))
> +		else if (ch < 0x100 && IS_WDLM(ch))
>  			state = 1;
>  		else
>  			state = 2;
> @@ -703,13 +708,18 @@ static void say_next_word(struct vc_data
>  static void spell_word(struct vc_data *vc)
>  {
>  	static char const *delay_str[] = { "", ",", ".", ". .", ". . ." };
> -	char *cp = buf, *str_cap = spk_str_caps_stop;
> -	char *cp1, *last_cap = spk_str_caps_stop;
> -	u_char ch;
> +	u16 *cp = buf;
> +	char *cp1;
> +	char *str_cap = spk_str_caps_stop;
> +	char *last_cap = spk_str_caps_stop;
> +	u16 ch;
>  
>  	if (!get_word(vc))
>  		return;
> -	while ((ch = (u_char)*cp)) {
> +	while ((ch = *cp)) {
> +		if (ch >= 0x100)
> +			/* FIXME */
> +			continue;
>  		if (cp != buf)
>  			synth_printf(" %s ", delay_str[spk_spell_delay]);
>  		if (IS_CHAR(ch, B_CAP)) {
> @@ -724,9 +734,9 @@ static void spell_word(struct vc_data *v
>  			synth_printf("%s", str_cap);
>  			last_cap = str_cap;
>  		}
> -		if (this_speakup_key == SPELL_PHONETIC
> -		    && (isascii(ch) && isalpha(ch))) {
> -			ch &= 31;
> +		if (this_speakup_key == SPELL_PHONETIC &&
> +		    ch <= 0x7f && isalpha(ch)) {
> +			ch &= 0x1f;
>  			cp1 = phonetic[--ch];
>  		} else {
>  			cp1 = spk_characters[ch];
> @@ -751,7 +761,7 @@ static int get_line(struct vc_data *vc)
>  	spk_old_attr = spk_attr;
>  	spk_attr = get_attributes(vc, (u_short *)spk_pos);
>  	for (i = 0; i < vc->vc_cols; i++) {
> -		buf[i] = (u_char)get_char(vc, (u_short *)tmp, &tmp2);
> +		buf[i] = get_char(vc, (u_short *)tmp, &tmp2);
>  		tmp += 2;
>  	}
>  	for (--i; i >= 0; i--)
> @@ -763,7 +773,7 @@ static int get_line(struct vc_data *vc)
>  static void say_line(struct vc_data *vc)
>  {
>  	int i = get_line(vc);
> -	char *cp;
> +	u16 *cp;
>  	u_short saved_punc_mask = spk_punc_mask;
>  
>  	if (i == 0) {
> @@ -816,7 +826,7 @@ static int say_from_to(struct vc_data *v
>  	spk_old_attr = spk_attr;
>  	spk_attr = get_attributes(vc, (u_short *)from);
>  	while (from < to) {
> -		buf[i++] = (char)get_char(vc, (u_short *)from, &tmp);
> +		buf[i++] = get_char(vc, (u_short *)from, &tmp);
>  		from += 2;
>  		if (i >= vc->vc_size_row)
>  			break;
> @@ -852,11 +862,11 @@ static void say_line_from_to(struct vc_d
>  
>  static int currsentence;
>  static int numsentences[2];
> -static char *sentbufend[2];
> -static char *sentmarks[2][10];
> +static u16 *sentbufend[2];
> +static u16 *sentmarks[2][10];
>  static int currbuf;
>  static int bn;
> -static char sentbuf[2][256];
> +static u16 sentbuf[2][256];
>  
>  static int say_sentence_num(int num, int prev)
>  {
> @@ -892,7 +902,7 @@ static int get_sentence_buf(struct vc_da
>  	spk_attr = get_attributes(vc, (u_short *)start);
>  
>  	while (start < end) {
> -		sentbuf[bn][i] = (char)get_char(vc, (u_short *)start, &tmp);
> +		sentbuf[bn][i] = get_char(vc, (u_short *)start, &tmp);
>  		if (i > 0) {
>  			if (sentbuf[bn][i] == SPACE && sentbuf[bn][i - 1] == '.'
>  			    && numsentences[bn] < 9) {
> @@ -995,7 +1005,7 @@ static void right_edge(struct vc_data *v
>  static void say_first_char(struct vc_data *vc)
>  {
>  	int i, len = get_line(vc);
> -	u_char ch;
> +	u16 ch;
>  
>  	spk_parked |= 0x01;
>  	if (len == 0) {
> @@ -1015,7 +1025,7 @@ static void say_first_char(struct vc_dat
>  static void say_last_char(struct vc_data *vc)
>  {
>  	int len = get_line(vc);
> -	u_char ch;
> +	u16 ch;
>  
>  	spk_parked |= 0x01;
>  	if (len == 0) {
> @@ -1040,9 +1050,8 @@ static void say_position(struct vc_data
>  static void say_char_num(struct vc_data *vc)
>  {
>  	u_char tmp;
> -	u_short ch = get_char(vc, (u_short *)spk_pos, &tmp);
> +	u16 ch = get_char(vc, (u_short *)spk_pos, &tmp);
>  
> -	ch &= 0xff;
>  	synth_printf(spk_msg_get(MSG_CHAR_INFO), ch, ch);
>  }
>  
> @@ -1070,10 +1079,10 @@ static void say_to_right(struct vc_data
>  
>  /* end of stub functions. */
>  
> -static void spkup_write(const char *in_buf, int count)
> +static void spkup_write(const u16 *in_buf, int count)
>  {
>  	static int rep_count;
> -	static u_char ch = '\0', old_ch = '\0';
> +	static u16 ch = '\0', old_ch = '\0';
>  	static u_short char_type, last_type;
>  	int in_count = count;
>  
> @@ -1085,8 +1094,11 @@ static void spkup_write(const char *in_b
>  			    (currsentence <= numsentences[bn]))
>  				synth_insert_next_index(currsentence++);
>  		}
> -		ch = (u_char)*in_buf++;
> -		char_type = spk_chartab[ch];
> +		ch = *in_buf++;
> +		if (ch < 0x100)
> +			char_type = spk_chartab[ch];
> +		else
> +			char_type = ALPHA;
>  		if (ch == old_ch && !(char_type & B_NUM)) {
>  			if (++rep_count > 2)
>  				continue;
> @@ -1106,10 +1118,10 @@ static void spkup_write(const char *in_b
>  		} else if (char_type & B_ALPHA) {
>  			if ((synth_flags & SF_DEC) && (last_type & PUNC))
>  				synth_buffer_add(SPACE);
> -			synth_printf("%c", ch);
> +			synth_putwc_s(ch);
>  		} else if (char_type & B_NUM) {
>  			rep_count = 0;
> -			synth_printf("%c", ch);
> +			synth_putwc_s(ch);
>  		} else if (char_type & spk_punc_mask) {
>  			speak_char(ch);
>  			char_type &= ~PUNC;	/* for dec nospell processing */
> @@ -1122,7 +1134,7 @@ static void spkup_write(const char *in_b
>  			 * repeats on you don't get nothing repeated count
>  			 */
>  			if (ch != old_ch)
> -				synth_printf("%c", ch);
> +				synth_putwc_s(ch);
>  			else
>  				rep_count = 0;
>  		} else {
> @@ -1533,7 +1545,7 @@ static void do_handle_cursor(struct vc_d
>  	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
>  }
>  
> -static void update_color_buffer(struct vc_data *vc, const char *ic, int len)
> +static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
>  {
>  	int i, bi, hi;
>  	int vc_num = vc->vc_num;
> @@ -1548,7 +1560,7 @@ static void update_color_buffer(struct v
>  		speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;
>  	}
>  	while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
> -		if ((ic[i] > 32) && (ic[i] < 127)) {
> +		if (ic[i] > 32) {
>  			speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
>  			hi++;
>  		} else if ((ic[i] == 32) && (hi != 0)) {
> @@ -1718,7 +1730,7 @@ static void speakup_bs(struct vc_data *v
>  }
>  
>  /* called by: vt_notifier_call() */
> -static void speakup_con_write(struct vc_data *vc, const char *str, int len)
> +static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
>  {
>  	unsigned long flags;
>  
> @@ -1908,6 +1920,7 @@ static int handle_goto(struct vc_data *v
>  	static int num;
>  	int maxlen;
>  	char *cp;
> +	u16 wch;
>  
>  	if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
>  		goto do_goto;
> @@ -1916,18 +1929,20 @@ static int handle_goto(struct vc_data *v
>  	if (type != 0)
>  		goto oops;
>  	if (ch == 8) {
> +		u16 wch;
>  		if (num == 0)
>  			return -1;
> -		ch = goto_buf[--num];
> +		wch = goto_buf[--num];
>  		goto_buf[num] = '\0';
> -		spkup_write(&ch, 1);
> +		spkup_write(&wch, 1);
>  		return 1;
>  	}
>  	if (ch < '+' || ch > 'y')
>  		goto oops;
> +	wch = ch;
>  	goto_buf[num++] = ch;
>  	goto_buf[num] = '\0';
> -	spkup_write(&ch, 1);
> +	spkup_write(&wch, 1);
>  	maxlen = (*goto_buf >= '0') ? 3 : 4;
>  	if ((ch == '+' || ch == '-') && num == 1)
>  		return 1;
> @@ -2254,9 +2269,8 @@ static int vt_notifier_call(struct notif
>  	case VT_WRITE:
>  		if (param->c == '\b')
>  			speakup_bs(vc);
> -		else if (param->c < 0x100) {
> -			char d = param->c;
> -
> +		else {
> +			u16 d = param->c;
>  			speakup_con_write(vc, &d, 1);
>  		}
>  		break;
> Index: linux-4.10/drivers/staging/speakup/spk_types.h
> ===================================================================
> --- linux-4.10.orig/drivers/staging/speakup/spk_types.h
> +++ linux-4.10/drivers/staging/speakup/spk_types.h
> @@ -55,7 +55,7 @@ struct spk_highlight_color_track {
>  	/* Count of each background color */
>  	unsigned int bgcount[8];
>  	/* Buffer for characters drawn with each background color */
> -	char highbuf[8][COLOR_BUFFER_SIZE];
> +	u16 highbuf[8][COLOR_BUFFER_SIZE];
>  	/* Current index into highbuf */
>  	unsigned int highsize[8];
>  	/* Reading Position for each color */
> Index: linux-4.10/drivers/staging/speakup/speakup.h
> ===================================================================
> --- linux-4.10.orig/drivers/staging/speakup/speakup.h
> +++ linux-4.10/drivers/staging/speakup/speakup.h
> @@ -38,6 +38,7 @@
>  #define B_SYM 0x0800
>  #define B_CAPSYM (B_CAP|B_SYM)
>  
> +/* FIXME: u16 */
>  #define IS_WDLM(x) (spk_chartab[((u_char)x)]&B_WDLM)
>  #define IS_CHAR(x, type) (spk_chartab[((u_char)x)]&type)
>  #define IS_TYPE(x, type) ((spk_chartab[((u_char)x)]&type) == type)

Reviewed-by: Okash Khawaja <okash.khawaja@gmail.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [patch 2/3] speakup: convert screen reading to 16bit characters
  2017-03-02  1:53 ` [patch 2/3] speakup: convert screen reading to 16bit characters Samuel Thibault
  2017-03-04  8:50   ` Okash Khawaja
@ 2017-03-04  8:59   ` Okash Khawaja
  1 sibling, 0 replies; 9+ messages in thread
From: Okash Khawaja @ 2017-03-04  8:59 UTC (permalink / raw)
  To: Samuel Thibault; +Cc: Greg Kroah-Hartman, devel, speakup, linux-kernel

On Thu, Mar 02, 2017 at 02:53:55AM +0100, Samuel Thibault wrote:
> This adds 16bit character support to most of the screen reading by
> extending characters to u16 throughout the code.
> 
> Non-latin1 characters are assumed to be alphabetic type for now.
> 
> non-latin1 vt_notifier_call-provided characters are not ignored any
> more, and the 16bit character returned by get_char is not truncated any
> more. For simplicity, speak_char still only supports latin1 characters.
> Its direct mode however does support 16bit characters, so in practice
> this will not be a limitation, non-latin1 languages will be handled by
> the synthesizer. spelling words does not support direct mode yet, for
> simplicity for now it will ignore 16bit characters.
> 
> For simplicity again, speakup messages are left in latin1 for now.
> 
> Some coding style is fixed along the way.
> 
> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
> 
> Index: linux-4.10/drivers/staging/speakup/main.c
> ===================================================================
> --- linux-4.10.orig/drivers/staging/speakup/main.c
> +++ linux-4.10/drivers/staging/speakup/main.c
> @@ -67,7 +67,7 @@ MODULE_PARM_DESC(quiet, "Do not announce
>  special_func spk_special_handler;
>  
>  short spk_pitch_shift, synth_flags;
> -static char buf[256];
> +static u16 buf[256];
>  int spk_attrib_bleep, spk_bleeps, spk_bleep_time = 10;
>  int spk_no_intr, spk_spell_delay;
>  int spk_key_echo, spk_say_word_ctl;
> @@ -112,7 +112,7 @@ enum {
>  
>  static struct tty_struct *tty;
>  
> -static void spkup_write(const char *in_buf, int count);
> +static void spkup_write(const u16 *in_buf, int count);
>  
>  static char *phonetic[] = {
>  	"alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel",
> @@ -238,7 +238,8 @@ static u_short default_chartab[256] = {
>  struct task_struct *speakup_task;
>  struct bleep spk_unprocessed_sound;
>  static int spk_keydown;
> -static u_char spk_lastkey, spk_close_press, keymap_flags;
> +static u16 spk_lastkey;
> +static u_char spk_close_press, keymap_flags;
>  static u_char last_keycode, this_speakup_key;
>  static u_long last_spk_jiffy;
>  
> @@ -426,9 +427,9 @@ static void announce_edge(struct vc_data
>  			spk_msg_get(MSG_EDGE_MSGS_START + msg_id - 1));
>  }
>  
> -static void speak_char(u_char ch)
> +static void speak_char(u16 ch)
>  {
> -	char *cp = spk_characters[ch];
> +	char *cp;
>  	struct var_t *direct = spk_get_var(DIRECT);
>  
>  	if (direct && direct->u.n.value) {
> @@ -436,11 +437,15 @@ static void speak_char(u_char ch)
>  			spk_pitch_shift++;
>  			synth_printf("%s", spk_str_caps_start);
>  		}
> -		synth_printf("%c", ch);
> +		synth_putwc_s(ch);
>  		if (IS_CHAR(ch, B_CAP))
>  			synth_printf("%s", spk_str_caps_stop);
>  		return;
>  	}
> +
> +	if (ch >= 0x100)
> +		return;
> +	cp = spk_characters[ch];
>  	if (cp == NULL) {
>  		pr_info("speak_char: cp == NULL!\n");
>  		return;
> @@ -486,7 +491,7 @@ static u16 get_char(struct vc_data *vc,
>  
>  static void say_char(struct vc_data *vc)
>  {
> -	u_short ch;
> +	u16 ch;
>  
>  	spk_old_attr = spk_attr;
>  	ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
> @@ -496,20 +501,20 @@ static void say_char(struct vc_data *vc)
>  		if (spk_attrib_bleep & 2)
>  			say_attributes(vc);
>  	}
> -	speak_char(ch & 0xff);
> +	speak_char(ch);
>  }
>  
>  static void say_phonetic_char(struct vc_data *vc)
>  {
> -	u_short ch;
> +	u16 ch;
>  
>  	spk_old_attr = spk_attr;
>  	ch = get_char(vc, (u_short *)spk_pos, &spk_attr);
> -	if (isascii(ch) && isalpha(ch)) {
> +	if (ch <= 0x7f && isalpha(ch)) {
>  		ch &= 0x1f;
>  		synth_printf("%s\n", phonetic[--ch]);
>  	} else {
> -		if (IS_CHAR(ch, B_NUM))
> +		if (ch < 0x100 && IS_CHAR(ch, B_NUM))
>  			synth_printf("%s ", spk_msg_get(MSG_NUMBER));
>  		speak_char(ch);
>  	}
> @@ -551,42 +556,42 @@ static void say_next_char(struct vc_data
>  static u_long get_word(struct vc_data *vc)
>  {
>  	u_long cnt = 0, tmpx = spk_x, tmp_pos = spk_pos;
> -	char ch;
> -	u_short attr_ch;
> +	u16 ch;
> +	u16 attr_ch;
>  	u_char temp;
>  
>  	spk_old_attr = spk_attr;
> -	ch = (char)get_char(vc, (u_short *)tmp_pos, &temp);
> +	ch = get_char(vc, (u_short *)tmp_pos, &temp);
>  
>  /* decided to take out the sayword if on a space (mis-information */
>  	if (spk_say_word_ctl && ch == SPACE) {
>  		*buf = '\0';
>  		synth_printf("%s\n", spk_msg_get(MSG_SPACE));
>  		return 0;
> -	} else if ((tmpx < vc->vc_cols - 2)
> -		   && (ch == SPACE || ch == 0 || IS_WDLM(ch))
> -		   && ((char)get_char(vc, (u_short *)&tmp_pos + 1, &temp) >
> -		       SPACE)) {
> +	} else if (tmpx < vc->vc_cols - 2 &&
> +		   (ch == SPACE || ch == 0 || (ch < 0x100 && IS_WDLM(ch))) &&
> +		   get_char(vc, (u_short *)&tmp_pos + 1, &temp) > SPACE) {
>  		tmp_pos += 2;
>  		tmpx++;
>  	} else
>  		while (tmpx > 0) {
> -			ch = (char)get_char(vc, (u_short *)tmp_pos - 1, &temp);
> -			if ((ch == SPACE || ch == 0 || IS_WDLM(ch))
> -			    && ((char)get_char(vc, (u_short *)tmp_pos, &temp) >
> -				SPACE))
> +			ch = get_char(vc, (u_short *)tmp_pos - 1, &temp);
> +			if ((ch == SPACE || ch == 0 ||
> +			     (ch < 0x100 && IS_WDLM(ch))) &&
> +			    get_char(vc, (u_short *)tmp_pos, &temp) > SPACE)
>  				break;
>  			tmp_pos -= 2;
>  			tmpx--;
>  		}
>  	attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
> -	buf[cnt++] = attr_ch & 0xff;
> +	buf[cnt++] = attr_ch;
>  	while (tmpx < vc->vc_cols - 1) {
>  		tmp_pos += 2;
>  		tmpx++;
> -		ch = (char)get_char(vc, (u_short *)tmp_pos, &temp);
> -		if ((ch == SPACE) || ch == 0
> -		    || (IS_WDLM(buf[cnt - 1]) && (ch > SPACE)))
> +		ch = get_char(vc, (u_short *)tmp_pos, &temp);
> +		if (ch == SPACE || ch == 0 ||
> +		    (buf[cnt - 1] < 0x100 && IS_WDLM(buf[cnt - 1]) &&
> +		     ch > SPACE))
>  			break;
>  		buf[cnt++] = ch;
>  	}
> @@ -610,7 +615,7 @@ static void say_word(struct vc_data *vc)
>  static void say_prev_word(struct vc_data *vc)
>  {
>  	u_char temp;
> -	char ch;
> +	u16 ch;
>  	u_short edge_said = 0, last_state = 0, state = 0;
>  
>  	spk_parked |= 0x01;
> @@ -639,10 +644,10 @@ static void say_prev_word(struct vc_data
>  		} else
>  			spk_x--;
>  		spk_pos -= 2;
> -		ch = (char)get_char(vc, (u_short *)spk_pos, &temp);
> +		ch = get_char(vc, (u_short *)spk_pos, &temp);
>  		if (ch == SPACE || ch == 0)
>  			state = 0;
> -		else if (IS_WDLM(ch))
> +		else if (ch < 0x100 && IS_WDLM(ch))
>  			state = 1;
>  		else
>  			state = 2;
> @@ -663,7 +668,7 @@ static void say_prev_word(struct vc_data
>  static void say_next_word(struct vc_data *vc)
>  {
>  	u_char temp;
> -	char ch;
> +	u16 ch;
>  	u_short edge_said = 0, last_state = 2, state = 0;
>  
>  	spk_parked |= 0x01;
> @@ -672,10 +677,10 @@ static void say_next_word(struct vc_data
>  		return;
>  	}
>  	while (1) {
> -		ch = (char)get_char(vc, (u_short *)spk_pos, &temp);
> +		ch = get_char(vc, (u_short *)spk_pos, &temp);
>  		if (ch == SPACE || ch == 0)
>  			state = 0;
> -		else if (IS_WDLM(ch))
> +		else if (ch < 0x100 && IS_WDLM(ch))
>  			state = 1;
>  		else
>  			state = 2;
> @@ -703,13 +708,18 @@ static void say_next_word(struct vc_data
>  static void spell_word(struct vc_data *vc)
>  {
>  	static char const *delay_str[] = { "", ",", ".", ". .", ". . ." };
> -	char *cp = buf, *str_cap = spk_str_caps_stop;
> -	char *cp1, *last_cap = spk_str_caps_stop;
> -	u_char ch;
> +	u16 *cp = buf;
> +	char *cp1;
> +	char *str_cap = spk_str_caps_stop;
> +	char *last_cap = spk_str_caps_stop;
> +	u16 ch;
>  
>  	if (!get_word(vc))
>  		return;
> -	while ((ch = (u_char)*cp)) {
> +	while ((ch = *cp)) {
> +		if (ch >= 0x100)
> +			/* FIXME */
> +			continue;
>  		if (cp != buf)
>  			synth_printf(" %s ", delay_str[spk_spell_delay]);
>  		if (IS_CHAR(ch, B_CAP)) {
> @@ -724,9 +734,9 @@ static void spell_word(struct vc_data *v
>  			synth_printf("%s", str_cap);
>  			last_cap = str_cap;
>  		}
> -		if (this_speakup_key == SPELL_PHONETIC
> -		    && (isascii(ch) && isalpha(ch))) {
> -			ch &= 31;
> +		if (this_speakup_key == SPELL_PHONETIC &&
> +		    ch <= 0x7f && isalpha(ch)) {
> +			ch &= 0x1f;
>  			cp1 = phonetic[--ch];
>  		} else {
>  			cp1 = spk_characters[ch];
> @@ -751,7 +761,7 @@ static int get_line(struct vc_data *vc)
>  	spk_old_attr = spk_attr;
>  	spk_attr = get_attributes(vc, (u_short *)spk_pos);
>  	for (i = 0; i < vc->vc_cols; i++) {
> -		buf[i] = (u_char)get_char(vc, (u_short *)tmp, &tmp2);
> +		buf[i] = get_char(vc, (u_short *)tmp, &tmp2);
>  		tmp += 2;
>  	}
>  	for (--i; i >= 0; i--)
> @@ -763,7 +773,7 @@ static int get_line(struct vc_data *vc)
>  static void say_line(struct vc_data *vc)
>  {
>  	int i = get_line(vc);
> -	char *cp;
> +	u16 *cp;
>  	u_short saved_punc_mask = spk_punc_mask;
>  
>  	if (i == 0) {
> @@ -816,7 +826,7 @@ static int say_from_to(struct vc_data *v
>  	spk_old_attr = spk_attr;
>  	spk_attr = get_attributes(vc, (u_short *)from);
>  	while (from < to) {
> -		buf[i++] = (char)get_char(vc, (u_short *)from, &tmp);
> +		buf[i++] = get_char(vc, (u_short *)from, &tmp);
>  		from += 2;
>  		if (i >= vc->vc_size_row)
>  			break;
> @@ -852,11 +862,11 @@ static void say_line_from_to(struct vc_d
>  
>  static int currsentence;
>  static int numsentences[2];
> -static char *sentbufend[2];
> -static char *sentmarks[2][10];
> +static u16 *sentbufend[2];
> +static u16 *sentmarks[2][10];
>  static int currbuf;
>  static int bn;
> -static char sentbuf[2][256];
> +static u16 sentbuf[2][256];
>  
>  static int say_sentence_num(int num, int prev)
>  {
> @@ -892,7 +902,7 @@ static int get_sentence_buf(struct vc_da
>  	spk_attr = get_attributes(vc, (u_short *)start);
>  
>  	while (start < end) {
> -		sentbuf[bn][i] = (char)get_char(vc, (u_short *)start, &tmp);
> +		sentbuf[bn][i] = get_char(vc, (u_short *)start, &tmp);
>  		if (i > 0) {
>  			if (sentbuf[bn][i] == SPACE && sentbuf[bn][i - 1] == '.'
>  			    && numsentences[bn] < 9) {
> @@ -995,7 +1005,7 @@ static void right_edge(struct vc_data *v
>  static void say_first_char(struct vc_data *vc)
>  {
>  	int i, len = get_line(vc);
> -	u_char ch;
> +	u16 ch;
>  
>  	spk_parked |= 0x01;
>  	if (len == 0) {
> @@ -1015,7 +1025,7 @@ static void say_first_char(struct vc_dat
>  static void say_last_char(struct vc_data *vc)
>  {
>  	int len = get_line(vc);
> -	u_char ch;
> +	u16 ch;
>  
>  	spk_parked |= 0x01;
>  	if (len == 0) {
> @@ -1040,9 +1050,8 @@ static void say_position(struct vc_data
>  static void say_char_num(struct vc_data *vc)
>  {
>  	u_char tmp;
> -	u_short ch = get_char(vc, (u_short *)spk_pos, &tmp);
> +	u16 ch = get_char(vc, (u_short *)spk_pos, &tmp);
>  
> -	ch &= 0xff;
>  	synth_printf(spk_msg_get(MSG_CHAR_INFO), ch, ch);
>  }
>  
> @@ -1070,10 +1079,10 @@ static void say_to_right(struct vc_data
>  
>  /* end of stub functions. */
>  
> -static void spkup_write(const char *in_buf, int count)
> +static void spkup_write(const u16 *in_buf, int count)
>  {
>  	static int rep_count;
> -	static u_char ch = '\0', old_ch = '\0';
> +	static u16 ch = '\0', old_ch = '\0';
>  	static u_short char_type, last_type;
>  	int in_count = count;
>  
> @@ -1085,8 +1094,11 @@ static void spkup_write(const char *in_b
>  			    (currsentence <= numsentences[bn]))
>  				synth_insert_next_index(currsentence++);
>  		}
> -		ch = (u_char)*in_buf++;
> -		char_type = spk_chartab[ch];
> +		ch = *in_buf++;
> +		if (ch < 0x100)
> +			char_type = spk_chartab[ch];
> +		else
> +			char_type = ALPHA;
>  		if (ch == old_ch && !(char_type & B_NUM)) {
>  			if (++rep_count > 2)
>  				continue;
> @@ -1106,10 +1118,10 @@ static void spkup_write(const char *in_b
>  		} else if (char_type & B_ALPHA) {
>  			if ((synth_flags & SF_DEC) && (last_type & PUNC))
>  				synth_buffer_add(SPACE);
> -			synth_printf("%c", ch);
> +			synth_putwc_s(ch);
>  		} else if (char_type & B_NUM) {
>  			rep_count = 0;
> -			synth_printf("%c", ch);
> +			synth_putwc_s(ch);
>  		} else if (char_type & spk_punc_mask) {
>  			speak_char(ch);
>  			char_type &= ~PUNC;	/* for dec nospell processing */
> @@ -1122,7 +1134,7 @@ static void spkup_write(const char *in_b
>  			 * repeats on you don't get nothing repeated count
>  			 */
>  			if (ch != old_ch)
> -				synth_printf("%c", ch);
> +				synth_putwc_s(ch);
>  			else
>  				rep_count = 0;
>  		} else {
> @@ -1533,7 +1545,7 @@ static void do_handle_cursor(struct vc_d
>  	spin_unlock_irqrestore(&speakup_info.spinlock, flags);
>  }
>  
> -static void update_color_buffer(struct vc_data *vc, const char *ic, int len)
> +static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len)
>  {
>  	int i, bi, hi;
>  	int vc_num = vc->vc_num;
> @@ -1548,7 +1560,7 @@ static void update_color_buffer(struct v
>  		speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;
>  	}
>  	while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
> -		if ((ic[i] > 32) && (ic[i] < 127)) {
> +		if (ic[i] > 32) {
>  			speakup_console[vc_num]->ht.highbuf[bi][hi] = ic[i];
>  			hi++;
>  		} else if ((ic[i] == 32) && (hi != 0)) {
> @@ -1718,7 +1730,7 @@ static void speakup_bs(struct vc_data *v
>  }
>  
>  /* called by: vt_notifier_call() */
> -static void speakup_con_write(struct vc_data *vc, const char *str, int len)
> +static void speakup_con_write(struct vc_data *vc, u16 *str, int len)
>  {
>  	unsigned long flags;
>  
> @@ -1908,6 +1920,7 @@ static int handle_goto(struct vc_data *v
>  	static int num;
>  	int maxlen;
>  	char *cp;
> +	u16 wch;
>  
>  	if (type == KT_SPKUP && ch == SPEAKUP_GOTO)
>  		goto do_goto;
> @@ -1916,18 +1929,20 @@ static int handle_goto(struct vc_data *v
>  	if (type != 0)
>  		goto oops;
>  	if (ch == 8) {
> +		u16 wch;
>  		if (num == 0)
>  			return -1;
> -		ch = goto_buf[--num];
> +		wch = goto_buf[--num];
>  		goto_buf[num] = '\0';
> -		spkup_write(&ch, 1);
> +		spkup_write(&wch, 1);
>  		return 1;
>  	}
>  	if (ch < '+' || ch > 'y')
>  		goto oops;
> +	wch = ch;
>  	goto_buf[num++] = ch;
>  	goto_buf[num] = '\0';
> -	spkup_write(&ch, 1);
> +	spkup_write(&wch, 1);
>  	maxlen = (*goto_buf >= '0') ? 3 : 4;
>  	if ((ch == '+' || ch == '-') && num == 1)
>  		return 1;
> @@ -2254,9 +2269,8 @@ static int vt_notifier_call(struct notif
>  	case VT_WRITE:
>  		if (param->c == '\b')
>  			speakup_bs(vc);
> -		else if (param->c < 0x100) {
> -			char d = param->c;
> -
> +		else {
> +			u16 d = param->c;
>  			speakup_con_write(vc, &d, 1);
>  		}
>  		break;
> Index: linux-4.10/drivers/staging/speakup/spk_types.h
> ===================================================================
> --- linux-4.10.orig/drivers/staging/speakup/spk_types.h
> +++ linux-4.10/drivers/staging/speakup/spk_types.h
> @@ -55,7 +55,7 @@ struct spk_highlight_color_track {
>  	/* Count of each background color */
>  	unsigned int bgcount[8];
>  	/* Buffer for characters drawn with each background color */
> -	char highbuf[8][COLOR_BUFFER_SIZE];
> +	u16 highbuf[8][COLOR_BUFFER_SIZE];
>  	/* Current index into highbuf */
>  	unsigned int highsize[8];
>  	/* Reading Position for each color */
> Index: linux-4.10/drivers/staging/speakup/speakup.h
> ===================================================================
> --- linux-4.10.orig/drivers/staging/speakup/speakup.h
> +++ linux-4.10/drivers/staging/speakup/speakup.h
> @@ -38,6 +38,7 @@
>  #define B_SYM 0x0800
>  #define B_CAPSYM (B_CAP|B_SYM)
>  
> +/* FIXME: u16 */
>  #define IS_WDLM(x) (spk_chartab[((u_char)x)]&B_WDLM)
>  #define IS_CHAR(x, type) (spk_chartab[((u_char)x)]&type)
>  #define IS_TYPE(x, type) ((spk_chartab[((u_char)x)]&type) == type)

Reviewed-by: Okash Khawaja <okash.khawaja@gmail.com>
> _______________________________________________
> Speakup mailing list
> Speakup@linux-speakup.org
> http://linux-speakup.org/cgi-bin/mailman/listinfo/speakup

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [patch 1/3] speakup: extend synth buffer to 16bit unicode characters
  2017-03-04 14:01 [patch 0/3] speakup: support 16bit unicode screen reading Samuel Thibault
@ 2017-03-04 14:01 ` Samuel Thibault
  0 siblings, 0 replies; 9+ messages in thread
From: Samuel Thibault @ 2017-03-04 14:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: chris, kirk, w.d.hubbs, devel, linux-kernel, speakup, Samuel Thibault

[-- Attachment #1: buffer-u16 --]
[-- Type: text/plain, Size: 9781 bytes --]

This extends the synth buffer slots to 16bit, so as to hold 16bit
unicode characters.

synth_buffer_getc and synth_buffer_peek now return 16bit characters.
Speech synthesizers which do not support characters beyond latin1 can
use the synth_buffer_skip_nonlatin1() helper to skip the non-latin1
characters before getting or peeking. All synthesizers are made to use
it for now.

This makes synth_buffer_add take a 16bit character. For simplicity for
now, synth_printf is left to using latin1 formats and strings.
synth_putwc, synth_putwc_s, synth_putws and synth_putws_s helpers are
however added to put 16bit characters and strings.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Reviewed-by: Chris Brannon <chris@the-brannons.com>

Index: linux-4.10/drivers/staging/speakup/spk_priv.h
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/spk_priv.h
+++ linux-4.10/drivers/staging/speakup/spk_priv.h
@@ -48,8 +48,9 @@ unsigned char spk_serial_in_nowait(void)
 int spk_serial_out(const char ch);
 void spk_serial_release(void);
 
-char synth_buffer_getc(void);
-char synth_buffer_peek(void);
+void synth_buffer_skip_nonlatin1(void);
+u16 synth_buffer_getc(void);
+u16 synth_buffer_peek(void);
 int synth_buffer_empty(void);
 struct var_t *spk_get_var(enum var_id_t var_id);
 ssize_t spk_var_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -64,6 +65,10 @@ void spk_synth_flush(struct spk_synth *s
 int spk_synth_is_alive_nop(struct spk_synth *synth);
 int spk_synth_is_alive_restart(struct spk_synth *synth);
 void synth_printf(const char *buf, ...);
+void synth_putwc(u16 wc);
+void synth_putwc_s(u16 wc);
+void synth_putws(const u16 *buf);
+void synth_putws_s(const u16 *buf);
 int synth_request_region(u_long, u_long);
 int synth_release_region(u_long, u_long);
 int synth_add(struct spk_synth *in_synth);
Index: linux-4.10/drivers/staging/speakup/speakup.h
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup.h
+++ linux-4.10/drivers/staging/speakup/speakup.h
@@ -70,7 +70,7 @@ void synth_release(void);
 
 void spk_do_flush(void);
 void speakup_start_ttys(void);
-void synth_buffer_add(char ch);
+void synth_buffer_add(u16 ch);
 void synth_buffer_clear(void);
 void speakup_clear_selection(void);
 int speakup_set_selection(struct tty_struct *tty);
Index: linux-4.10/drivers/staging/speakup/synth.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/synth.c
+++ linux-4.10/drivers/staging/speakup/synth.c
@@ -109,6 +109,7 @@ void spk_do_catch_up(struct spk_synth *s
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
@@ -255,6 +256,35 @@ void synth_printf(const char *fmt, ...)
 }
 EXPORT_SYMBOL_GPL(synth_printf);
 
+void synth_putwc(u16 wc)
+{
+	synth_buffer_add(wc);
+}
+EXPORT_SYMBOL_GPL(synth_putwc);
+
+void synth_putwc_s(u16 wc)
+{
+	synth_buffer_add(wc);
+	synth_start();
+}
+EXPORT_SYMBOL_GPL(synth_putwc_s);
+
+void synth_putws(const u16 *buf)
+{
+	const u16 *p;
+
+	for (p = buf; *p; p++)
+		synth_buffer_add(*p);
+}
+EXPORT_SYMBOL_GPL(synth_putws);
+
+void synth_putws_s(const u16 *buf)
+{
+	synth_putws(buf);
+	synth_start();
+}
+EXPORT_SYMBOL_GPL(synth_putws_s);
+
 static int index_count;
 static int sentence_count;
 
Index: linux-4.10/drivers/staging/speakup/buffers.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/buffers.c
+++ linux-4.10/drivers/staging/speakup/buffers.c
@@ -7,10 +7,10 @@
 
 #define SYNTH_BUF_SIZE 8192	/* currently 8K bytes */
 
-static u_char synth_buffer[SYNTH_BUF_SIZE];	/* guess what this is for! */
-static u_char *buff_in = synth_buffer;
-static u_char *buff_out = synth_buffer;
-static u_char *buffer_end = synth_buffer + SYNTH_BUF_SIZE - 1;
+static u16 synth_buffer[SYNTH_BUF_SIZE];	/* guess what this is for! */
+static u16 *buff_in = synth_buffer;
+static u16 *buff_out = synth_buffer;
+static u16 *buffer_end = synth_buffer + SYNTH_BUF_SIZE - 1;
 
 /* These try to throttle applications by stopping the TTYs
  * Note: we need to make sure that we will restart them eventually, which is
@@ -44,13 +44,13 @@ static void speakup_stop_ttys(void)
 
 static int synth_buffer_free(void)
 {
-	int bytes_free;
+	int chars_free;
 
 	if (buff_in >= buff_out)
-		bytes_free = SYNTH_BUF_SIZE - (buff_in - buff_out);
+		chars_free = SYNTH_BUF_SIZE - (buff_in - buff_out);
 	else
-		bytes_free = buff_out - buff_in;
-	return bytes_free;
+		chars_free = buff_out - buff_in;
+	return chars_free;
 }
 
 int synth_buffer_empty(void)
@@ -59,7 +59,7 @@ int synth_buffer_empty(void)
 }
 EXPORT_SYMBOL_GPL(synth_buffer_empty);
 
-void synth_buffer_add(char ch)
+void synth_buffer_add(u16 ch)
 {
 	if (!synth->alive) {
 		/* This makes sure that we won't stop TTYs if there is no synth
@@ -78,9 +78,9 @@ void synth_buffer_add(char ch)
 		buff_in = synth_buffer;
 }
 
-char synth_buffer_getc(void)
+u16 synth_buffer_getc(void)
 {
-	char ch;
+	u16 ch;
 
 	if (buff_out == buff_in)
 		return 0;
@@ -91,7 +91,7 @@ char synth_buffer_getc(void)
 }
 EXPORT_SYMBOL_GPL(synth_buffer_getc);
 
-char synth_buffer_peek(void)
+u16 synth_buffer_peek(void)
 {
 	if (buff_out == buff_in)
 		return 0;
@@ -99,6 +99,18 @@ char synth_buffer_peek(void)
 }
 EXPORT_SYMBOL_GPL(synth_buffer_peek);
 
+void synth_buffer_skip_nonlatin1(void)
+{
+	while (buff_out != buff_in) {
+		if (*buff_out < 0x100)
+			return;
+		buff_out++;
+		if (buff_out > buffer_end)
+			buff_out = synth_buffer;
+	}
+}
+EXPORT_SYMBOL_GPL(synth_buffer_skip_nonlatin1);
+
 void synth_buffer_clear(void)
 {
 	buff_in = synth_buffer;
Index: linux-4.10/drivers/staging/speakup/speakup_acntpc.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_acntpc.c
+++ linux-4.10/drivers/staging/speakup/speakup_acntpc.c
@@ -196,6 +196,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_apollo.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_apollo.c
+++ linux-4.10/drivers/staging/speakup/speakup_apollo.c
@@ -160,6 +160,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_decext.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_decext.c
+++ linux-4.10/drivers/staging/speakup/speakup_decext.c
@@ -175,6 +175,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_decpc.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_decpc.c
+++ linux-4.10/drivers/staging/speakup/speakup_decpc.c
@@ -392,6 +392,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_dectlk.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_dectlk.c
+++ linux-4.10/drivers/staging/speakup/speakup_dectlk.c
@@ -239,6 +239,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_dtlk.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_dtlk.c
+++ linux-4.10/drivers/staging/speakup/speakup_dtlk.c
@@ -209,6 +209,7 @@ static void do_catch_up(struct spk_synth
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_keypc.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_keypc.c
+++ linux-4.10/drivers/staging/speakup/speakup_keypc.c
@@ -198,6 +198,7 @@ spin_lock_irqsave(&speakup_info.spinlock
 			synth->flush(synth);
 			continue;
 		}
+		synth_buffer_skip_nonlatin1();
 		if (synth_buffer_empty()) {
 			spin_unlock_irqrestore(&speakup_info.spinlock, flags);
 			break;
Index: linux-4.10/drivers/staging/speakup/speakup_soft.c
===================================================================
--- linux-4.10.orig/drivers/staging/speakup/speakup_soft.c
+++ linux-4.10/drivers/staging/speakup/speakup_soft.c
@@ -213,6 +213,7 @@ static ssize_t softsynth_read(struct fil
 	spin_lock_irqsave(&speakup_info.spinlock, flags);
 	while (1) {
 		prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE);
+		synth_buffer_skip_nonlatin1();
 		if (!synth_buffer_empty() || speakup_info.flushing)
 			break;
 		spin_unlock_irqrestore(&speakup_info.spinlock, flags);

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-03-04 14:02 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-02  1:53 [patch 0/3] speakup: support 16bit unicode screen reading Samuel Thibault
2017-03-02  1:53 ` [patch 1/3] speakup: extend synth buffer to 16bit unicode characters Samuel Thibault
2017-03-03 18:39   ` Chris Brannon
2017-03-02  1:53 ` [patch 2/3] speakup: convert screen reading to 16bit characters Samuel Thibault
2017-03-04  8:50   ` Okash Khawaja
2017-03-04  8:59   ` Okash Khawaja
2017-03-02  1:53 ` [patch 3/3] speakup: add unicode variant of /dev/softsynth Samuel Thibault
2017-03-03 18:40   ` Chris Brannon
2017-03-04 14:01 [patch 0/3] speakup: support 16bit unicode screen reading Samuel Thibault
2017-03-04 14:01 ` [patch 1/3] speakup: extend synth buffer to 16bit unicode characters Samuel Thibault

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).