shithub: eesp

ref: 856542c51fbe7a4d55e292ad91714f58907d6869
dir: /libenter.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <keyboard.h>
#include "genenter.h"

typedef struct Enterdata Enterdata;
struct Enterdata {
	Mousectl *mc;
	Keyboardctl *kc;
	Screen *scr;
	Alt a[3];
};

static int
einitsave(Enterparams *p)
{
	Enterdata *d = (Enterdata*)p->aux;
	if(d->scr){
		if(p->b == nil)
			p->b = allocwindow(d->scr, p->r, Refbackup, DWhite);
		if(p->b == nil)
			d->scr = nil;
	}
	if(d->scr == nil && p->save == nil){
		if(p->b == nil)
			p->b = screen;
		p->save = allocimage(display, p->r, p->b->chan, 0, DNofill);
		if(p->save == nil)
			return 1;
		draw(p->save, p->r, p->b, nil, p->r.min);
	}
	return 0;
}

static int
egetevent(Enterparams *p)
{
	Enterdata *d = (Enterdata*)p->aux;
	
	switch(alt(d->a)){
	case 0:
		return Gkeyboard;
	case 1:
		return Gmouse;
	}
	return -1;
}

static void
eloopcleanup(Enterparams *p)
{
	if(p->b != screen){
		freeimage(p->b);
		p->b = nil;
	} else {
		draw(p->b, p->save->r, p->save, nil, p->save->r.min);
		freeimage(p->save);
		p->save = nil;
	}
}

static void
ecleanup(Enterparams *p)
{
	replclipr(screen, 0, p->sc);
}

int
enter(char *ask, char *buf, int len, Mousectl *mc, Keyboardctl *kc, Screen *scr)
{
	Enterparams p;
	Enterdata d;
	int n;
	
	p.sc = screen->clipr;
	replclipr(screen, 0, screen->r);
	n = 0;
	if(kc){
		while(nbrecv(kc->c, nil) == 1)
			;
		d.a[n].op = CHANRCV;
		d.a[n].c = kc->c;
		d.a[n].v = &p.k;
		n++;
	}
	if(mc){
		p.o = mc->xy;
		d.a[n].op = CHANRCV;
		d.a[n].c = mc->c;
		d.a[n].v = &p.m;
		n++;
	}
	d.a[n].op = CHANEND;
	d.a[n].c = nil;
	d.a[n].v = nil;
	
	d.mc = mc;
	d.kc = kc;
	d.scr = scr;
	p.aux = &d;
	p.initsave = einitsave;
	p.getevent = egetevent;
	p.loopcleanup = eloopcleanup;
	p.cleanup = ecleanup;
	return _genenter(ask, buf, len, &p);
}