ref: bcbb3563b4341791753a50a6dff3f6cd2aab0620
dir: /kern/term.c/
#include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include <draw.h> #include <memdraw.h> #include "screen.h" extern Memimage *gscreen; static Memsubfont *memdefont; static Lock screenlock; static Memimage *conscol; static Memimage *back; static Rectangle flushr; static Rectangle window; static Point curpos; static int h; static void termscreenputs(char*, int); static void screenflush(void) { flushmemscreen(flushr); flushr = Rect(10000, 10000, -10000, -10000); } static void addflush(Rectangle r) { if(flushr.min.x >= flushr.max.x) flushr = r; else combinerect(&flushr, r); } static void screenwin(void) { Point p; char *greet; Memimage *grey; qlock(&drawlock); back = memwhite; conscol = memblack; memfillcolor(gscreen, 0x444488FF); h = memdefont->height; window = insetrect(gscreen->clipr, 20); memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); window = insetrect(window, 4); memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S); /* a lot of work to get a grey color */ grey = allocmemimage(Rect(0,0,1,1), CMAP8); grey->flags |= Frepl; grey->clipr = gscreen->r; memfillcolor(grey, 0xAAAAAAFF); memimagedraw(gscreen, Rect(window.min.x, window.min.y, window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S); freememimage(grey); window = insetrect(window, 5); greet = " Plan 9 Console "; p = addpt(window.min, Pt(10, 0)); memimagestring(gscreen, p, conscol, ZP, memdefont, greet); window.min.y += h+6; curpos = window.min; window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; flushmemscreen(gscreen->r); qunlock(&drawlock); termscreenputs(kmesg.buf, kmesg.n); } static struct { Rectangle r; Rendez z; int f; } resize; static int isresized(void *arg) { return resize.f != 0; } static void resizeproc(void *arg) { USED(arg); for(;;){ sleep(&resize.z, isresized, nil); qlock(&drawlock); resize.f = 0; if(gscreen == nil || badrect(resize.r) || eqrect(resize.r, gscreen->clipr)){ qunlock(&drawlock); continue; } screensize(resize.r, gscreen->chan); if(gscreen == nil || rectclip(&resize.r, gscreen->r) == 0 || eqrect(resize.r, gscreen->clipr)){ qunlock(&drawlock); continue; } gscreen->clipr = resize.r; qunlock(&drawlock); screenwin(); deletescreenimage(); resetscreenimage(); osmsleep(1000); } } void screenresize(Rectangle r) { qlock(&drawlock); resize.r = r; resize.f = 1; wakeup(&resize.z); qunlock(&drawlock); } void terminit(void) { memdefont = getmemdefont(); screenwin(); screenputs = termscreenputs; kproc("resize", resizeproc, nil); } static void scroll(void) { int o; Point p; Rectangle r; o = 8*h; r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); p = Pt(window.min.x, window.min.y+o); memimagedraw(gscreen, r, gscreen, p, nil, p, S); r = Rpt(Pt(window.min.x, window.max.y-o), window.max); memimagedraw(gscreen, r, back, ZP, nil, ZP, S); curpos.y -= o; } static void screenputc(char *buf) { Point p; int w, pos; Rectangle r; static int *xp; static int xbuf[256]; if(xp < xbuf || xp >= &xbuf[nelem(xbuf)]) xp = xbuf; switch(buf[0]) { case '\n': if(curpos.y+h >= window.max.y){ scroll(); flushr = window; } curpos.y += h; screenputc("\r"); break; case '\r': xp = xbuf; curpos.x = window.min.x; break; case '\t': p = memsubfontwidth(memdefont, " "); w = p.x; *xp++ = curpos.x; pos = (curpos.x-window.min.x)/w; pos = 8-(pos%8); r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h); memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); addflush(r); curpos.x += pos*w; break; case '\b': if(xp <= xbuf) break; xp--; r = Rect(*xp, curpos.y, curpos.x, curpos.y + h); memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); addflush(r); curpos.x = *xp; break; default: p = memsubfontwidth(memdefont, buf); w = p.x; if(curpos.x >= window.max.x-w) screenputc("\n"); *xp++ = curpos.x; r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h); memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf); addflush(r); curpos.x += w; } } static void termscreenputs(char *s, int n) { static char rb[UTFmax+1]; static int nrb; int locked; char *e; lock(&screenlock); locked = canqlock(&drawlock); e = s + n; while(s < e){ rb[nrb++] = *s++; if(nrb >= UTFmax || fullrune(rb, nrb)){ rb[nrb] = 0; screenputc(rb); nrb = 0; } } if(locked){ screenflush(); qunlock(&drawlock); } unlock(&screenlock); }