ref: 08ea6d85c432f1ea27a96bb4e68b9d79f64674b6
parent: 8788c5737b73f1ea7d8fada2ef03e4ed29432af8
author: Jacob Moody <moody@posixcafe.org>
date: Fri Sep 30 01:51:00 EDT 2022
ktrans: listen on lang port for plumber This also does some slight style normalization and removes the Msg struct in favor of just using a plain char array. The previous kbdsink fprint calls were incorrect and was not passing upon the null bytes.
--- a/sys/src/cmd/ktrans/main.c
+++ b/sys/src/cmd/ktrans/main.c
@@ -2,6 +2,7 @@
#include <libc.h>
#include <ctype.h>
#include <bio.h>
+#include <plumb.h>
#include <thread.h>
#include "hash.h"
@@ -275,32 +276,28 @@
return hmapget(*h, s, m);
}
-typedef struct Msg Msg;
-struct Msg {
- char code;
- char buf[64];
-};
-static Channel *dictch;
-static Channel *output;
-static Channel *input;
-static char backspace[64];
+enum { Msgsize = 64 };
+static Channel *dictch;
+static Channel *output;
+static Channel *input;
+static char backspace[Msgsize];
static int
emitutf(Channel *out, char *u, int nrune)
{
- Msg m;
+ char b[Msgsize];
char *e;
- m.code = 'c';
- e = pushutf(m.buf, m.buf + sizeof m.buf, u, nrune);
- send(out, &m);
- return e - m.buf;
+ b[0] = 'c';
+ e = pushutf(b+1, b + Msgsize - 1, u, nrune);
+ send(out, b);
+ return e - b;
}
static void
dictthread(void*)
{
- Msg m;
+ char m[Msgsize];
Rune r;
int n;
char *p;
@@ -325,8 +322,8 @@
resetstr(&last, &line, &okuri, nil);
threadsetname("dict");
- while(recv(dictch, &m) != -1){
- for(p = m.buf; *p; p += n){
+ while(recv(dictch, m) != -1){
+ for(p = m+1; *p; p += n){
n = chartorune(&r, p);
if(r != ''){
if(selected >= 0){
@@ -441,7 +438,7 @@
}
}
-int
+static int
telexlkup(Str *line, Str *out)
{
Map lkup;
@@ -454,7 +451,6 @@
if(hmapget(telex, buf, &lkup) < 0)
return -1;
- assert(lkup.leadstomore == 1);
if(utflen(line->b) < 2)
return 2;
@@ -480,7 +476,7 @@
keythread(void*)
{
int lang;
- Msg m;
+ char m[Msgsize];
Map lkup;
char *p;
int n, ln, rn;
@@ -487,9 +483,7 @@
Rune r;
char peek[UTFmax+1];
Str line, tbuf;
- int mode;
- mode = 0;
peek[0] = lang = deflang;
resetstr(&line, nil);
if(lang == LangJP || lang == LangZH)
@@ -496,18 +490,18 @@
emitutf(dictch, peek, 1);
threadsetname("keytrans");
- while(recv(input, &m) != -1){
- if(m.code == 'z'){
+ while(recv(input, m) != -1){
+ if(m[0] == 'z'){
emitutf(dictch, "", 1);
resetstr(&line, nil);
continue;
}
- if(m.code != 'c'){
- send(output, &m);
+ if(m[0] != 'c'){
+ send(output, m);
continue;
}
- for(p = m.buf; *p; p += n){
+ for(p = m+1; *p; p += n){
n = chartorune(&r, p);
if(checklang(&lang, r)){
emitutf(dictch, "", 1);
@@ -527,12 +521,8 @@
resetstr(&line, nil);
continue;
}
- if(lang == LangJP && isupper(*p)){
+ if(lang == LangJP && isupper(*p))
*p = tolower(*p);
- mode++;
- } else {
- mode = 0;
- }
}
emitutf(output, p, 1);
@@ -590,10 +580,10 @@
static int kbdin;
static int kbdout;
-void
+static void
kbdtap(void*)
{
- Msg msg;
+ char m[Msgsize];
char buf[128];
char *p, *e;
int n;
@@ -600,14 +590,12 @@
threadsetname("kbdtap");
for(;;){
-Drop:
+ Drop:
n = read(kbdin, buf, sizeof buf);
if(n < 0)
break;
for(p = buf; p < buf+n;){
- msg.code = p[0];
- p++;
- switch(msg.code){
+ switch(*p){
case 'c': case 'k': case 'K':
case 'z':
break;
@@ -614,38 +602,73 @@
default:
goto Drop;
}
- e = utfecpy(msg.buf, msg.buf + sizeof msg.buf, p);
- p += e - msg.buf;
+ *m = *p++;
+ e = utfecpy(m+1, m + Msgsize - 1, p);
+ p += e - m;
p++;
- if(send(input, &msg) == -1)
+ if(send(input, m) == -1)
return;
}
}
}
-void
+static void
kbdsink(void*)
{
- Msg m;
+ char in[Msgsize];
+ char out[Msgsize];
char *p;
+ int n;
Rune rn;
+ out[0] = 'c';
threadsetname("kbdsink");
- while(recv(output, &m) != -1){
- if(m.code != 'c'){
- fprint(kbdout, "%c%s", m.code, m.buf);
+ while(recv(output, in) != -1){
+ if(in[0] != 'c'){
+ if(write(kbdout, in, strlen(in)+1) < 0)
+ break;
continue;
}
- p = m.buf;
- for(;;){
- p += chartorune(&rn, p);
+
+ for(p = in+1; *p; p += n){
+ n = chartorune(&rn, p);
if(rn == Runeerror || rn == '\0')
break;
- fprint(kbdout, "c%C", rn);
+ memmove(out+1, p, n);
+ out[1+n] = '\0';
+ if(write(kbdout, out, 1+n+1) < 0)
+ break;
}
}
}
+static int plumbfd;
+
+static void
+plumbproc(void*)
+{
+ char m[Msgsize];
+ Plumbmsg *p;
+
+ threadsetname("plumbproc");
+ for(; p = plumbrecv(plumbfd); plumbfree(p)){
+ if(p->ndata > sizeof m - 1)
+ continue;
+ memmove(m, p->data, p->ndata);
+ m[p->ndata] = '\0';
+
+ m[1] = parselang(m);
+ if(m[1] == -1)
+ continue;
+ m[0] = 'c';
+ m[2] = '\0';
+
+ if(send(input, m) == -1)
+ break;
+ }
+ plumbfree(p);
+}
+
void
usage(void)
{
@@ -704,9 +727,13 @@
hangul = openmap("/lib/ktrans/hangul.map");
telex = openmap("/lib/ktrans/telex.map");
- dictch = chancreate(sizeof(Msg), 0);
- input = chancreate(sizeof(Msg), 0);
- output = chancreate(sizeof(Msg), 0);
+ dictch = chancreate(Msgsize, 0);
+ input = chancreate(Msgsize, 0);
+ output = chancreate(Msgsize, 0);
+
+ plumbfd = plumbopen("lang", OREAD);
+ if(plumbfd >= 0)
+ proccreate(plumbproc, nil, mainstacksize);
proccreate(kbdtap, nil, mainstacksize);
proccreate(kbdsink, nil, mainstacksize);