📄 fgui.c
字号:
#include "dat.h"#include <draw.h>#include <mouse.h>#include <keyboard.h>#include <control.h>int ctldeletequits = 1;typedef struct RequestType RequestType;typedef struct Request Request;typedef struct Memory Memory;struct RequestType{ char *file; /* file to read requests from */ void (*f)(Request*); /* request handler */ void (*r)(Controlset*); /* resize handler */ int fd; /* fd = open(file, ORDWR) */ Channel *rc; /* channel requests are multiplexed to */ Controlset *cs;};struct Request{ RequestType *rt; Attr *a; Attr *tag;};struct Memory{ Memory *next; Attr *a; Attr *val;};Memory *mem;static void readreq(void*);static void hide(void);static void unhide(void);static void openkmr(void);static void closekmr(void);static Memory* searchmem(Attr*);static void addmem(Attr*, Attr*);static void confirm(Request*);static void resizeconfirm(Controlset*);static void needkey(Request*);static void resizeneedkey(Controlset*);Control *b_remember;Control *b_accept;Control *b_refuse;RequestType rt[] = { { "/mnt/factotum/confirm", confirm, resizeconfirm, }, { "/mnt/factotum/needkey", needkey, resizeneedkey, }, { 0 },};enum{ ButtonDim= 15,};voidthreadmain(int argc, char *argv[]){ Request r; Channel *rc; RequestType *p; Font *invis; ARGBEGIN{ }ARGEND; if(newwindow("-hide") < 0) sysfatal("newwindow: %r"); fmtinstall('A', _attrfmt); /* create the proc's that read */ rc = chancreate(sizeof(Request), 0); for(p = rt; p->file != 0; p++){ p->fd = -1; p->rc = rc; proccreate(readreq, p, 16*1024); } /* gui initialization */ initdraw(0, 0, "auth/fgui"); initcontrols(); hide(); /* get an invisible font for passwords */ invis = openfont(display, "/lib/font/bit/lucm/passwd.9.font"); if (invis == nil) sysfatal("fgui: %s: %r", "/lib/font/bit/lucm/passwd.9.font"); namectlfont(invis, "invisible"); /* serialize all requests */ for(;;){ if(recv(rc, &r) < 0) break; (*r.rt->f)(&r); _freeattr(r.a); _freeattr(r.tag); } threadexitsall(nil);}/* * read requests and pass them to the main loop */enum{ Requestlen=4096,};static voidreadreq(void *a){ RequestType *rt = a; char *buf, *p; int n; Request r; Attr **l; rt->fd = open(rt->file, ORDWR); if(rt->fd < 0) sysfatal("opening %s: %r", rt->file); rt->cs = nil; buf = malloc(Requestlen); if(buf == nil) sysfatal("allocating read buffer: %r"); r.rt = rt; for(;;){ n = read(rt->fd, buf, Requestlen-1); if(n < 0) break; buf[n] = 0; /* skip verb, parse attributes, and remove tag */ p = strchr(buf, ' '); if(p != nil) p++; else p = buf; r.a = _parseattr(p); /* separate out the tag */ r.tag = nil; for(l = &r.a; *l != nil; l = &(*l)->next) if(strcmp((*l)->name, "tag") == 0){ r.tag = *l; *l = r.tag->next; r.tag->next = nil; break; } /* if no tag, forget it */ if(r.tag == nil){ _freeattr(r.a); continue; } send(rt->rc, &r); }}#ifdef asdfstatic voidreadreq(void *a){ RequestType *rt = a; char *buf, *p; int n; Request r; rt->fd = -1; rt->cs = nil; buf = malloc(Requestlen); if(buf == nil) sysfatal("allocating read buffer: %r"); r.rt = rt; for(;;){ strcpy(buf, "adfasdf=afdasdf asdfasdf=asdfasdf"); r.a = _parseattr(buf); send(rt->rc, &r); sleep(5000); }}#endif asdf/* * open/close the keyboard, mouse and resize channels */static Channel *kbdc;static Channel *mousec;static Channel *resizec;static Keyboardctl *kctl;static Mousectl *mctl;static voidopenkmr(void){ /* get channels for subsequent newcontrolset calls */ kctl = initkeyboard(nil); if(kctl == nil) sysfatal("can't initialize keyboard: %r"); kbdc = kctl->c; mctl = initmouse(nil, screen); if(mctl == nil) sysfatal("can't initialize mouse: %r"); mousec = mctl->c; resizec = mctl->resizec;}static voidclosekmr(void){ Mouse m; while(nbrecv(kbdc, &m) > 0) ; closekeyboard(kctl); while(nbrecv(mousec, &m) > 0) ; closemouse(mctl);}/* * called when the window is resized */voidresizecontrolset(Controlset *cs){ RequestType *p; for(p = rt; p->file != 0; p++){ if(p->cs == cs){ (*p->r)(cs); break; } }}/* * hide window when not in use */static voidunhide(void){ int wctl; wctl = open("/dev/wctl", OWRITE); if(wctl < 0) return; fprint(wctl, "unhide"); close(wctl);}static voidhide(void){ int wctl; int tries; wctl = open("/dev/wctl", OWRITE); if(wctl < 0) return; for(tries = 0; tries < 10; tries++){ if(fprint(wctl, "hide") >= 0) break; sleep(100); } close(wctl);}/* * set up the controls for the confirmation window */static Channel*setupconfirm(Request *r){ Controlset *cs; Channel *c; Attr *a; /* create a new control set for the confirmation */ openkmr(); cs = newcontrolset(screen, kbdc, mousec, resizec); createtext(cs, "msg"); chanprint(cs->ctl, "msg image paleyellow"); chanprint(cs->ctl, "msg border 1"); chanprint(cs->ctl, "msg add 'The following key is being used:'"); for(a = r->a; a != nil; a = a->next) chanprint(cs->ctl, "msg add ' %s = %s'", a->name, a->val); namectlimage(display->white, "i_white"); namectlimage(display->black, "i_black"); b_remember = createbutton(cs, "b_remember"); chanprint(cs->ctl, "b_remember border 1"); chanprint(cs->ctl, "b_remember mask i_white"); chanprint(cs->ctl, "b_remember image i_white"); chanprint(cs->ctl, "b_remember light i_black"); createtext(cs, "t_remember"); chanprint(cs->ctl, "t_remember image white"); chanprint(cs->ctl, "t_remember bordercolor white"); chanprint(cs->ctl, "t_remember add 'Remember this answer for future confirmations'"); b_accept = createtextbutton(cs, "b_accept"); chanprint(cs->ctl, "b_accept border 1"); chanprint(cs->ctl, "b_accept align center"); chanprint(cs->ctl, "b_accept text Accept"); chanprint(cs->ctl, "b_accept image i_white"); chanprint(cs->ctl, "b_accept light i_black"); b_refuse = createtextbutton(cs, "b_refuse"); chanprint(cs->ctl, "b_refuse border 1"); chanprint(cs->ctl, "b_refuse align center"); chanprint(cs->ctl, "b_refuse text Refuse"); chanprint(cs->ctl, "b_refuse image i_white"); chanprint(cs->ctl, "b_refuse light i_black"); c = chancreate(sizeof(char*), 0); controlwire(b_remember, "event", c); controlwire(b_accept, "event", c); controlwire(b_refuse, "event", c); /* make the controls interactive */ activate(b_remember); activate(b_accept); activate(b_refuse); r->rt->cs = cs; unhide(); resizecontrolset(cs); return c;}/* * resize the controls for the confirmation window */static voidresizeconfirm(Controlset *cs){ Rectangle r, mr, nr, ntr, ar, rr; int fontwidth; fontwidth = font->height; /* get usable window rectangle */ if(getwindow(display, Refnone) < 0) ctlerror("resize failed: %r"); r = insetrect(screen->r, 10); /* message box fills everything not needed for buttons */ mr = r; mr.max.y = mr.min.y + font->height*((Dy(mr)-3*ButtonDim-font->height-4)/font->height); /* remember button */ nr.min = Pt(mr.min.x, mr.max.y+ButtonDim); nr.max = Pt(mr.max.x, r.max.y); if(Dx(nr) > ButtonDim) nr.max.x = nr.min.x+ButtonDim; if(Dy(nr) > ButtonDim) nr.max.y = nr.min.y+ButtonDim; ntr.min = Pt(nr.max.x+ButtonDim, nr.min.y); ntr.max = Pt(r.max.x, nr.min.y+font->height); /* accept/refuse buttons */ ar.min = Pt(r.min.x+Dx(r)/2-ButtonDim-6*fontwidth, nr.max.y+ButtonDim); ar.max = Pt(ar.min.x+6*fontwidth, ar.min.y+font->height+4); rr.min = Pt(r.min.x+Dx(r)/2+ButtonDim, nr.max.y+ButtonDim); rr.max = Pt(rr.min.x+6*fontwidth, rr.min.y+font->height+4); /* make the controls visible */ chanprint(cs->ctl, "msg rect %R\nmsg show", mr); chanprint(cs->ctl, "b_remember rect %R\nb_remember show", nr); chanprint(cs->ctl, "t_remember rect %R\nt_remember show", ntr); chanprint(cs->ctl, "b_accept rect %R\nb_accept show", ar); chanprint(cs->ctl, "b_refuse rect %R\nb_refuse show", rr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -