shithub: acme

Download patch

ref: 9f07a97070837031998539b1e40d7d402235eacf
parent: 4b9503c5f0dc1db6bd8c1a9861d78ed300db58ff
author: glenda <glenda@cirno>
date: Tue Mar 25 13:25:17 EDT 2025

start of porting kbdfs to acme. we can receive input, now we just need to actually display it as text

--- a/acme.c
+++ b/acme.c
@@ -15,7 +15,7 @@
 	#include "edit.h"
 
 void	mousethread(void*);
-void	keyboardthread(void*);
+void	keyboardtap(void*);
 void	waitthread(void*);
 void	xfidallocthread(void*);
 void	newwindowthread(void*);
@@ -30,6 +30,8 @@
 int		plumbsendfd;
 int		plumbeditfd;
 
+Channel	*kbdchan;	/* chan(char*); */
+
 enum{
 	NSnarf = 1000	/* less than 1024, I/O buffer size */
 };
@@ -42,6 +44,7 @@
 void	acmeerrorinit(void);
 void	readfile(Column*, char*);
 int	shutdown(void*, char*);
+Channel* initkbd(void);
 
 void
 derror(Display*, char *errorstr)
@@ -184,11 +187,11 @@
 		threadexitsall("mouse");
 	}
 	mouse = mousectl;
-	keyboardctl = initkeyboard(nil);
-	if(keyboardctl == nil){
-		fprint(2, "acme: can't initialize keyboard: %r\n");
-		threadexitsall("keyboard");
-	}
+	kbdchan = initkbd();
+	if(kbdchan == nil)
+		error("can't find keyboard");
+	opentap = chancreate(sizeof(Channel*), 0);
+	closetap = chancreate(sizeof(Channel*), 0);
 	mainpid = getpid();
 	plumbeditfd = plumbopen("edit", OREAD|OCEXEC);
 	if(plumbeditfd >= 0){
@@ -234,7 +237,7 @@
 	flushimage(display, 1);
 
 	acmeerrorinit();
-	threadcreate(keyboardthread, nil, STACK);
+	threadcreate(keyboardtap, nil, STACK);
 	threadcreate(mousethread, nil, STACK);
 	threadcreate(waitthread, nil, STACK);
 	threadcreate(xfidallocthread, nil, STACK);
@@ -367,64 +370,152 @@
 }
 
 void
-keyboardthread(void *)
+keyboardtap(void*)
 {
-	Rune r;
-	Timer *timer;
-	Text *t;
-	enum { KTimer, KKey, NKALT };
-	static Alt alts[NKALT+1];
+	Window *cur = nil;
+	Channel *c;
+	char *s, *t;
 
-	alts[KTimer].c = nil;
-	alts[KTimer].v = nil;
-	alts[KTimer].op = CHANNOP;
-	alts[KKey].c = keyboardctl->c;
-	alts[KKey].v = &r;
-	alts[KKey].op = CHANRCV;
-	alts[NKALT].op = CHANEND;
+	enum { Akbd, Aopen, Aclose, Awrite, NALT };
+	Alt alts[NALT+1] = {
+		[Akbd]	{.c = kbdchan, .v = &s, .op = CHANRCV},
+		[Aopen] {.c = opentap, .v = &c, .op = CHANRCV},
+		[Aclose]{.c = closetap, .v = &c, .op = CHANRCV},
+		[Awrite]{.c = nil, .v = &s, .op = CHANNOP},
+		[NALT]	{.op = CHANEND},
+	};
 
-	timer = nil;
-	typetext = nil;
-	threadsetname("keyboardthread");
+	threadsetname("keyboardtap");
+
 	for(;;){
 		switch(alt(alts)){
-		case KTimer:
-			timerstop(timer);
-			t = typetext;
-			if(t!=nil && t->what==Tag){
-				winlock(t->w, 'K');
-				wincommit(t->w, t);
-				winunlock(t->w);
-				flushimage(display, 1);
+		case Akbd:
+			if(*s == 'k' || *s == 'K'){
+				shiftdown = utfrune(s+1, Kshift) != nil;
+				print("shift\n");
 			}
-			alts[KTimer].c = nil;
-			alts[KTimer].op = CHANNOP;
+			if(totap == nil)
+				goto Bypass;
+			if(input != nil && input != cur){	/* context change */
+				char *z = smprint("z%d", input->id);
+				if(nbsendp(totap, z) != 1){
+					free(z);
+					goto Bypass;
+				}
+			}
+			cur = input;
+			if(nbsendp(totap, s) != 1)
+				goto Bypass;
 			break;
-		case KKey:
-		casekeyboard:
-			typetext = rowtype(&row, r, mouse->xy);
-			t = typetext;
-			if(t!=nil && t->col!=nil && !(r==Kdown || r==Kleft || r==Kright))	/* scrolling doesn't change activecol */
-				activecol = t->col;
-			if(t!=nil && t->w!=nil)
-				t->w->body.file->curtext = &t->w->body;
-			if(timer != nil)
-				timercancel(timer);
-			if(t!=nil && t->what==Tag) {
-				timer = timerstart(500);
-				alts[KTimer].c = timer->c;
-				alts[KTimer].op = CHANRCV;
-			}else{
-				timer = nil;
-				alts[KTimer].c = nil;
-				alts[KTimer].op = CHANNOP;
+		case Aopen:
+			if(c == fromtap){
+				alts[Awrite].c = c;
+				alts[Awrite].op = CHANRCV;
 			}
-			if(nbrecv(keyboardctl->c, &r) > 0)
-				goto casekeyboard;
-			flushimage(display, 1);
 			break;
+		case Aclose:
+			if(c == fromtap){
+				fromtap = nil;
+				alts[Awrite].c = nil;
+				alts[Awrite].op = CHANNOP;
+			}
+			if(c == totap)
+				totap = nil;
+			while(nbrecv(c, &t))
+				free(t);
+			chanfree(c);
+			break;
+		case Awrite:
+			if(input != cur){
+				free(s);
+				break;
+			}
+		Bypass:
+			cur = input;
+			if(cur == nil){
+				free(s);
+				break;
+			}
+			sendp(cur->ck, s);
+			break;
 		}
 	}
+}
+
+static void
+kbdproc(void *arg)
+{
+	Channel *c = arg;
+	char buf[1024], *p, *e;
+	int fd, cfd, kfd, n;
+
+	threadsetname("kbdproc");
+
+	if((fd = open("/dev/cons", OREAD)) < 0){
+		chanprint(c, "%r");
+		return;
+	}
+	if((cfd = open("/dev/consctl", OWRITE)) < 0){
+		chanprint(c, "%r");
+		return;
+	}
+	fprint(cfd, "rawon");
+
+	if(sendp(c, nil) <= 0)
+		return;
+
+	if((kfd = open("/dev/kbd", OREAD)) >= 0){
+		close(fd);
+
+		/* only serve a kbd file per window when we got one */
+		servekbd = 1;
+
+		/* read kbd state */
+		while((n = read(kfd, buf, sizeof(buf)-1)) > 0){
+			e = buf+n;
+			e[-1] = 0;
+			e[0] = 0;
+			for(p = buf; p < e; p += strlen(p)+1)
+				chanprint(c, "%s", p);
+		}
+	} else {
+		/* read single characters */
+		p = buf;
+		for(;;){
+			Rune r;
+
+			e = buf + sizeof(buf);
+			if((n = read(fd, p, e-p)) <= 0)
+				break;
+			e = p + n;
+			while(p < e && fullrune(p, e - p)){
+				p += chartorune(&r, p);
+				if(r)
+					chanprint(c, "c%C", r);
+			}
+			n = e - p;
+			memmove(buf, p, n);
+			p = buf + n;
+		}
+	}
+	// send(exitchan, nil);
+}
+
+Channel*
+initkbd(void)
+{
+	Channel *c;
+	char *e;
+
+	c = chancreate(sizeof(char*), 16);
+	procrfork(kbdproc, c, STACK, RFCFDG);
+	if(e = recvp(c)){
+		chanfree(c);
+		c = nil;
+		werrstr("%s", e);
+		free(e);
+	}
+	return c;
 }
 
 void
--- a/dat.h
+++ b/dat.h
@@ -8,6 +8,8 @@
 	Qeditout,
 	Qindex,
 	Qlabel,
+	Qkbd,
+	Qtap,
 	Qlog,
 	Qnew,
 
@@ -54,7 +56,9 @@
 typedef	struct	Timer Timer;
 typedef	struct	Window Window;
 typedef	struct	Xfid Xfid;
+typedef struct	Kbdreadmesg Kbdreadmesg;
 
+
 struct Runestr
 {
 	Rune	*r;
@@ -279,6 +283,8 @@
 	int		tagexpand;
 	int		taglines;
 	Rectangle	tagtop;
+	Channel		*ck;		/* chan(char*) */
+	uchar	kbdopen;
 };
 
 void	wininit(Window*, Window*, Rectangle);
@@ -557,6 +563,9 @@
 int			messagesize;		/* negotiated in 9P version setup */
 int			globalindent[NINDENT];
 Rune		*delcmd;			/* what command deleted the window. eg, Del, Delete, Delmesg */
+Window		*input;
+int			servekbd;
+int			shiftdown;
 
 Channel	*cplumb;		/* chan(Plumbmsg*) */
 Channel	*cwait;		/* chan(Waitmsg) */
@@ -571,5 +580,11 @@
 Channel	*cerr;		/* chan(char*) */
 Channel	*cedit;		/* chan(int) */
 Channel	*cwarn;		/* chan(void*)[1] (really chan(unit)[1]) */
+Channel	*kbdread;	/* chan(Consreadmesg) */
+Channel *opentap;	/* open fromtap or totap */
+Channel *closetap;	/* close fromtap or totap */
+Channel	*fromtap;	/* keyboard output from the tap program */
+Channel *totap;		/* our keyboard input to tap program */
+
 
 #define	STACK	8192
--- a/wind.c
+++ b/wind.c
@@ -89,7 +89,7 @@
 		textsetselect(&w->body, clone->body.q0, clone->body.q1);
 		winsettag(w);
 	}
-
+	
 }
 
 int
--