shithub: libacme

ref: 1bced94ed0ad5e160db18e553e2e0a58b158035b
dir: /event.c/

View raw version
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <bio.h>

#include "acme.h"

static int
aeventgetnum(Biobuf *bio)
{
	int c, n;
	
	n = 0;
	while('0' <= (c = Bgetc(bio)) && c <= '9')
		n = n*10+(c-'0');
	if(c != ' ') {
		werrstr("event number syntax: %c", c);
		return -1;
	}
	
	return n;
}

static int
aeventgetdata(Biobuf *bio, AEvent *ev)
{
	int i, runes, len;
	Rune r;
	
	len = 0;
	runes = aeventgetnum(bio);
	for(i = 0; i < runes; i++) {
		if((r = Bgetrune(bio)) == -1)
			break;
		len += runetochar(ev->text + len, &r);
	}
	
	ev->text[len] = '\0';
	return len;
}

static int
aeventnext(Biobuf *bio, AEvent *ev)
{
	int flags;
	
	flags = 0;
	
Again:
	ev->origin = Bgetc(bio);
	ev->type = Bgetc(bio);
	ev->q0 = aeventgetnum(bio);
	ev->q1 = aeventgetnum(bio);
	ev->flags = aeventgetnum(bio);
	ev->ntext = aeventgetdata(bio, ev);
	if(Bgetc(bio) != '\n') {
		werrstr("unterminated mesage");
		return -1;
	}
	
	if(ev->flags & 0x2) {
		ev->p = ev->q0;
		flags = ev->flags;
		goto Again;
	}
	
	ev->flags |= flags;
	return ev->origin;
}

static void
aeventproc(void *aux)
{
	AWin *w;
	Channel *c;
	Biobuf bio;
	AEvent ev;
	
	w = aux;
	c = w->eventc;
	Binit(&bio, w->eventfd, OREAD);
	
	while(aeventnext(&bio, &ev)) {
		if(send(c, &ev) < 0) {
			Bterm(&bio);
			exits(nil);
		}
	}
}

Channel *
aeventlisten(AWin *w)
{
	if(w->eventc)
		return w->eventc;
		
	w->eventc = chancreate(sizeof(AEvent), 0);
	proccreate(aeventproc, w, 4096);
	
	return w->eventc;
}

void
aeventstop(AWin *w)
{
	if(w->eventc) {
		chanclose(w->eventc);
		w->eventc = nil;
	}
}

void
aeventsend(AWin *w, AEvent *ev)
{
	if(ev->flags & 0x2)
		fprint(w->eventfd, "%c%c%d %d\n", ev->origin, ev->type, ev->p, ev->p);
	else
		fprint(w->eventfd, "%c%c%d %d\n", ev->origin, ev->type, ev->q0, ev->q1);
}