vt: utf-8 support

This commit is contained in:
cinap_lenrek 2013-10-27 19:05:40 +01:00
parent ecab88b983
commit b831ec005b
3 changed files with 136 additions and 115 deletions

View file

@ -59,14 +59,13 @@ extern void clear(Rectangle);
extern void newline(void); extern void newline(void);
extern int get_next_char(void); extern int get_next_char(void);
extern void ringbell(void); extern void ringbell(void);
extern int number(char *, int *); extern int number(Rune *, int *);
extern void scroll(int,int,int,int); extern void scroll(int,int,int,int);
extern void backup(int); extern void backup(int);
extern void sendnchars(int, char *); extern void sendnchars(int, char *);
extern void sendnchars2(int, char *);
extern Point pt(int, int); extern Point pt(int, int);
extern void funckey(int); extern void funckey(int);
extern void drawstring(Point, char*, int); extern void drawstring(Point, Rune*, int);
extern int debug; extern int debug;
extern int yscrmin, yscrmax; extern int yscrmin, yscrmax;

View file

@ -32,7 +32,7 @@ char *menutext3[] = {
/* variables associated with the screen */ /* variables associated with the screen */
int x, y; /* character positions */ int x, y; /* character positions */
char *backp; Rune *backp;
int backc; int backc;
int atend; int atend;
int nbacklines; int nbacklines;
@ -45,8 +45,8 @@ int peekc;
int cursoron = 1; int cursoron = 1;
Menu menu2; Menu menu2;
Menu menu3; Menu menu3;
char *histp; Rune *histp;
char hist[HISTSIZ]; Rune hist[HISTSIZ];
int yscrmin, yscrmax; int yscrmin, yscrmax;
int attr, defattr; int attr, defattr;
int wctlout; int wctlout;
@ -99,6 +99,7 @@ Biobuf *snarffp = 0;
char *host_buf; char *host_buf;
char *hostp; /* input from host */ char *hostp; /* input from host */
int host_bsize = 2*BSIZE; int host_bsize = 2*BSIZE;
int hostlength; /* amount of input from host */ int hostlength; /* amount of input from host */
char echo_input[BSIZE]; char echo_input[BSIZE];
@ -277,7 +278,7 @@ int
get_next_char(void) get_next_char(void)
{ {
int c = peekc; int c = peekc;
uchar buf[1];
peekc = 0; peekc = 0;
if(c > 0) if(c > 0)
return(c); return(c);
@ -292,11 +293,9 @@ get_next_char(void)
} }
backp = 0; backp = 0;
} }
c = (uchar)waitchar(); c = waitchar();
if(c > 0 && logfd >= 0) { if(c > 0 && logfd >= 0)
buf[0] = c; fprint(logfd, "%C", (Rune)c);
write(logfd, buf, 1);
}
} }
*histp++ = c; *histp++ = c;
if(histp >= &hist[HISTSIZ]) if(histp >= &hist[HISTSIZ])
@ -305,68 +304,89 @@ get_next_char(void)
return(c); return(c);
} }
int char*
canon(char *ep, int c) backrune(char *start, char *cp)
{
char *ep;
ep = cp;
cp -= UTFmax;
if(cp < start)
cp = start;
while(cp < ep){
Rune r;
int n;
n = chartorune(&r, cp);
if(cp + n >= ep)
break;
cp += n;
}
return cp;
}
int
canon(char *ep, Rune c)
{ {
if(c&0200)
return(SCROLL);
switch(c) { switch(c) {
case '\b': case Kdown:
if(sendp > sendbuf) case Kpgdown:
sendp--; return SCROLL;
case '\b':
if(sendp > sendbuf){
sendp = backrune(sendbuf, sendp);
*ep++ = '\b'; *ep++ = '\b';
*ep++ = ' '; *ep++ = ' ';
*ep++ = '\b'; *ep++ = '\b';
break; }
case 0x15: /* ^U line kill */ break;
sendp = sendbuf; case 0x15: /* ^U line kill */
*ep++ = '^'; sendp = sendbuf;
*ep++ = 'U'; *ep++ = '^';
*ep++ = 'U';
*ep++ = '\n';
break;
case 0x17: /* ^W word kill */
while(sendp > sendbuf && !alnum(*sendp)) {
sendp = backrune(sendbuf, sendp);
*ep++ = '\b';
*ep++ = ' ';
*ep++ = '\b';
}
while(sendp > sendbuf && alnum(*sendp)) {
sendp = backrune(sendbuf, sendp);
*ep++ = '\b';
*ep++ = ' ';
*ep++ = '\b';
}
break;
case '\177': /* interrupt */
sendp = sendbuf;
send_interrupt();
return(NEWLINE);
case '\021': /* quit */
case '\r':
case '\n':
if(sendp < &sendbuf[BSIZE])
*sendp++ = '\n';
sendnchars((int)(sendp-sendbuf), sendbuf);
sendp = sendbuf;
if(c == '\n' || c == '\r')
*ep++ = '\n'; *ep++ = '\n';
break; *ep = 0;
case 0x17: /* ^W word kill */ return(NEWLINE);
while(sendp > sendbuf && !alnum(*sendp)) { case '\004': /* EOT */
*ep++ = '\b'; if(sendp == sendbuf) {
*ep++ = ' '; sendnchars(0,sendbuf);
*ep++ = '\b';
sendp--;
}
while(sendp > sendbuf && alnum(*sendp)) {
*ep++ = '\b';
*ep++ = ' ';
*ep++ = '\b';
sendp--;
}
break;
case '\177': /* interrupt */
sendp = sendbuf;
send_interrupt();
return(NEWLINE);
case '\021': /* quit */
case '\r':
case '\n':
if(sendp < &sendbuf[512])
*sendp++ = '\n';
sendnchars((int)(sendp-sendbuf), sendbuf);
sendp = sendbuf;
if(c == '\n' || c == '\r') {
*ep++ = '\n';
}
*ep = 0; *ep = 0;
return(NEWLINE); return(NEWLINE);
case '\004': /* EOT */ }
if(sendp == sendbuf) { /* fall through */
sendnchars(0,sendbuf); default:
*ep = 0; if(sendp < &sendbuf[BSIZE-UTFmax])
return(NEWLINE); sendp += runetochar(sendp, &c);
} ep += runetochar(ep, &c);
/* fall through */ break;
default:
if(sendp < &sendbuf[512])
*sendp++ = c;
*ep++ = c;
break;
} }
*ep = 0; *ep = 0;
return(OTHER); return(OTHER);
@ -380,7 +400,7 @@ sendfk(char *name)
for(i=0; fk[i].name; i++) for(i=0; fk[i].name; i++)
if(strcmp(name, fk[i].name)==0){ if(strcmp(name, fk[i].name)==0){
sendnchars2(strlen(fk[i].sequence), fk[i].sequence); sendnchars(strlen(fk[i].sequence), fk[i].sequence);
return; return;
} }
} }
@ -390,13 +410,10 @@ waitchar(void)
{ {
Event e; Event e;
int c; int c;
char c2;
int newmouse; int newmouse;
int wasblocked; int wasblocked;
int kbdchar = -1; Rune kbdchar = 0;
char echobuf[3*BSIZE]; char echobuf[4*BSIZE];
static int lastc = -1;
for(;;) { for(;;) {
if(resize_flag) if(resize_flag)
@ -407,26 +424,31 @@ waitchar(void)
if(ecanmouse() && (button2() || button3())) if(ecanmouse() && (button2() || button3()))
readmenu(); readmenu();
if(snarffp) { if(snarffp) {
if((c = Bgetc(snarffp)) < 0) { static Rune lastc = ~0;
if((c = Bgetrune(snarffp)) < 0) {
if(lastc != '\n') if(lastc != '\n')
write(outfd,"\n",1); write(outfd,"\n",1);
Bterm(snarffp); Bterm(snarffp);
snarffp = 0; snarffp = 0;
if(lastc != '\n') { if(lastc != '\n') {
lastc = -1; lastc = ~0;
return('\n'); return('\n');
} }
lastc = -1; lastc = ~0;
continue; continue;
} }
lastc = c; lastc = c;
c2 = c; write(outfd, echobuf, runetochar(echobuf, &lastc));
write(outfd, &c2, 1);
return(c); return(c);
} }
if(!blocked && host_avail()) if(!blocked && host_avail())
return(rcvchar()); return(rcvchar());
if(kbdchar > 0) { if(kbdchar > 0) {
if(backc){
backc = 0;
backup(backc);
}
if(blocked) if(blocked)
resize(); resize();
if(cs->raw) { if(cs->raw) {
@ -494,8 +516,7 @@ waitchar(void)
sendnchars(1, echobuf); sendnchars(1, echobuf);
break; break;
default: default:
echobuf[0] = kbdchar; sendnchars(runetochar(echobuf, &kbdchar), echobuf);
sendnchars(1, echobuf);
break; break;
} }
} else if(canon(echobuf,kbdchar) == SCROLL) { } else if(canon(echobuf,kbdchar) == SCROLL) {
@ -504,7 +525,7 @@ waitchar(void)
} else } else
strcat(echo_input,echobuf); strcat(echo_input,echobuf);
blocked = 0; blocked = 0;
kbdchar = -1; kbdchar = 0;
continue; continue;
} }
curson(wasblocked); /* turn on cursor while we're waiting */ curson(wasblocked); /* turn on cursor while we're waiting */
@ -682,8 +703,8 @@ readmenu(void)
void void
backup(int count) backup(int count)
{ {
register n; Rune *cp;
register char *cp; int n;
eresized(0); eresized(0);
if(count == 0 && !pagemode) { if(count == 0 && !pagemode) {
@ -747,7 +768,7 @@ bigscroll(void) /* scroll up half a page */
} }
int int
number(char *p, int *got) number(Rune *p, int *got)
{ {
int c, n = 0; int c, n = 0;
@ -766,13 +787,6 @@ number(char *p, int *got)
void void
sendnchars(int n,char *p) sendnchars(int n,char *p)
{
sendnchars2(n, p);
p[n+1] = 0;
}
void
sendnchars2(int n,char *p)
{ {
if(write(outfd,p,n) < 0) { if(write(outfd,p,n) < 0) {
close(outfd); close(outfd);
@ -786,35 +800,44 @@ sendnchars2(int n,char *p)
int int
host_avail(void) host_avail(void)
{ {
return(*echop || ((hostp - host_buf) < hostlength)); if(*echop != 0 && fullrune(echop, strlen(echop)))
return 1;
if((hostp - host_buf) < hostlength)
return fullrune(hostp, hostlength - (hostp - host_buf));
return 0;
} }
int int
rcvchar(void) rcvchar(void)
{ {
int c; Rune r;
if(*echop) {
c = *echop++; if(*echop != 0) {
if(!*echop) { echop += chartorune(&r, echop);
if(*echop == 0) {
echop = echo_input; echop = echo_input;
*echop = 0; *echop = 0;
} }
return c; return r;
} }
return *hostp++; hostp += chartorune(&r, hostp);
return r;
} }
void void
set_host(Event *e) set_host(Event *e)
{ {
hostlength = e->n; hostlength -= (hostp - host_buf);
if(hostlength > 0)
memmove(host_buf, hostp, hostlength);
hostlength += e->n;
if(hostlength >= host_bsize) { if(hostlength >= host_bsize) {
host_bsize = BSIZE*((hostlength + BSIZE)/BSIZE); host_bsize = BSIZE*((hostlength + BSIZE)/BSIZE);
host_buf = realloc(host_buf,host_bsize); host_buf = realloc(host_buf, host_bsize);
} }
memmove(host_buf + hostlength - e->n, e->data, e->n);
host_buf[hostlength] = 0;
hostp = host_buf; hostp = host_buf;
memmove(host_buf,e->data,hostlength);
host_buf[hostlength]=0;
} }
void void
@ -854,12 +877,12 @@ funckey(int key)
return; return;
if(fk[key].name == 0) if(fk[key].name == 0)
return; return;
sendnchars2(strlen(fk[key].sequence), fk[key].sequence); sendnchars(strlen(fk[key].sequence), fk[key].sequence);
} }
void void
drawstring(Point p, char *str, int attr) drawstring(Point p, Rune *str, int attr)
{ {
int i; int i;
Image *txt, *bg, *tmp; Image *txt, *bg, *tmp;
@ -877,6 +900,6 @@ drawstring(Point p, char *str, int attr)
txt = hicolors[i]; txt = hicolors[i];
} }
draw(screen, Rpt(p, addpt(p, stringsize(font, str))), bg, nil, p); draw(screen, Rpt(p, addpt(p, runestringsize(font, str))), bg, nil, p);
string(screen, p, txt, ZP, font, str); runestring(screen, p, txt, ZP, font, str);
} }

View file

@ -133,7 +133,7 @@ fixops(int *operand)
void void
emulate(void) emulate(void)
{ {
char buf[BUFS+1]; Rune buf[BUFS+1];
int i; int i;
int n; int n;
int c; int c;
@ -328,8 +328,8 @@ print("resetterminal\n");
*/ */
case 'Z': case 'Z':
Ident: Ident:
sendnchars2(7, "\033[?1;2c"); /* VT100 with AVO option */ sendnchars(7, "\033[?1;2c"); /* VT100 with AVO option */
// sendnchars2(5, "\033[?6c"); /* VT102 (insert/delete-char, etc.) */ // sendnchars(5, "\033[?6c"); /* VT102 (insert/delete-char, etc.) */
break; break;
/* /*
@ -532,11 +532,11 @@ print("resetterminal\n");
case 'n': case 'n':
switch(operand[0]){ switch(operand[0]){
case 5: /* status */ case 5: /* status */
sendnchars2(4, "\033[0n"); /* terminal ok */ sendnchars(4, "\033[0n"); /* terminal ok */
break; break;
case 6: /* cursor position */ case 6: /* cursor position */
sendnchars2(sprint(buf, "\033[%d;%dR", sendnchars(sprint((char*)buf, "\033[%d;%dR",
originrelative ? y+1 - yscrmin : y+1, x+1), buf); originrelative ? y+1 - yscrmin : y+1, x+1), (char*)buf);
break; break;
} }
break; break;
@ -573,7 +573,7 @@ print("resetterminal\n");
* x - report terminal parameters * x - report terminal parameters
*/ */
case 'x': case 'x':
sendnchars2(20, "\033[3;1;1;120;120;1;0x"); sendnchars(20, "\033[3;1;1;120;120;1;0x");
break; break;
/* /*
@ -847,8 +847,8 @@ print("unknown command '%c' (0x%x)\n", dch, dch);
default: /* ordinary char */ default: /* ordinary char */
Default: Default:
if(isgraphics && gmap[(uchar) buf[0]]) if(isgraphics && buf[0] < nelem(gmap) && gmap[buf[0]])
buf[0] = gmap[(uchar) buf[0]]; buf[0] = gmap[buf[0]];
/* line wrap */ /* line wrap */
if (x > xmax){ if (x > xmax){
@ -867,7 +867,6 @@ Default:
c = 0; c = 0;
} }
buf[n] = 0; buf[n] = 0;
// clear(Rpt(pt(x,y), pt(x+n, y+1)));
drawstring(pt(x, y), buf, attr); drawstring(pt(x, y), buf, attr);
x += n; x += n;
peekc = c; peekc = c;