#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 voidscreenflush(void){ flushmemscreen(flushr); flushr = Rect(10000, 10000, -10000, -10000);} static voidaddflush(Rectangle r){ if(flushr.min.x >= flushr.max.x) flushr = r; else combinerect(&flushr, r);} static voidscreenwin(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 intisresized(void *arg){ return resize.f != 0;} static voidresizeproc(void *arg){ USED(arg); for(;;){ sleep(&resize.z, isresized, nil); qlock(&drawlock); resize.f = 0; if(gscreen == nil || badrect(resize.r) || 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); }} voidscreenresize(Rectangle r){ qlock(&drawlock); resize.r = r; resize.f = 1; wakeup(&resize.z); qunlock(&drawlock);} voidterminit(void){ memdefont = getmemdefont(); screenwin(); screenputs = termscreenputs; kproc("resize", resizeproc, nil);} static voidscroll(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 voidscreenputc(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 voidtermscreenputs(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);}
#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)
|| 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);
}