#include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #define Image IMAGE #include #include #include #include "screen.h" enum { Tabstop = 4, Scroll = 8, }; Memimage *gscreen; static Memdata xgdata; static Memimage xgscreen; static Memimage *conscol; static Memimage *back; static Memsubfont *memdefont; static Lock screenlock; static Point curpos; static int h, w; static Rectangle window; static void myscreenputs(char *s, int n); static void screenputc(char *buf); static void screenwin(void); enum { CMaccelerated, CMlinear, }; static Cmdtab mousectlmsg[] = { CMaccelerated, "accelerated", 0, CMlinear, "linear", 1, }; void mousectl(Cmdbuf *cb) { Cmdtab *ct; ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg)); switch(ct->index){ case CMaccelerated: mouseaccelerate(cb->nf == 1? 1: atoi(cb->f[1])); break; case CMlinear: mouseaccelerate(0); break; } } void cursoron(void) { swcursorhide(0); swcursordraw(mousexy()); } void cursoroff(void) { swcursorhide(0); } void setcursor(Cursor* curs) { swcursorload(curs); } int hwdraw(Memdrawparam *par) { Memimage *dst, *src, *mask; if((dst = par->dst) == nil || dst->data == nil) return 0; if((src = par->src) && src->data == nil) src = nil; if((mask = par->mask) && mask->data == nil) mask = nil; if(dst->data->bdata == xgdata.bdata) swcursoravoid(par->r); if(src && src->data->bdata == xgdata.bdata) swcursoravoid(par->sr); if(mask && mask->data->bdata == xgdata.bdata) swcursoravoid(par->mr); return 0; } int screeninit(int width, int height, int depth) { ulong chan; switch(depth){ default: return -1; case 32: chan = XRGB32; break; case 24: chan = RGB24; break; case 16: chan = RGB16; break; } memsetchan(&xgscreen, chan); xgscreen.r = Rect(0, 0, width, height); xgscreen.clipr = xgscreen.r; xgscreen.depth = depth; xgscreen.width = wordsperline(xgscreen.r, xgscreen.depth); xgdata.bdata = fbmemalloc(xgscreen.width*sizeof(ulong)*height); xgdata.ref = 1; xgscreen.data = &xgdata; gscreen = &xgscreen; conf.monitor = 1; memimageinit(); memdefont = getmemdefont(); screenwin(); myscreenputs(kmesg.buf, kmesg.n); screenputs = myscreenputs; swcursorinit(); return 0; } void flushmemscreen(Rectangle) { } Memdata* attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen) { if(gscreen == nil) return nil; *r = gscreen->r; *d = gscreen->depth; *chan = gscreen->chan; *width = gscreen->width; *softscreen = 0; gscreen->data->ref++; return gscreen->data; } void getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) { USED(p, pr, pg, pb); } int setcolor(ulong p, ulong r, ulong g, ulong b) { USED(p, r, g, b); return 0; } static void myscreenputs(char *s, int n) { int i; Rune r; char buf[4]; if(!islo()) { /* don't deadlock trying to print in interrupt */ if(!canlock(&screenlock)) return; } else lock(&screenlock); while(n > 0){ i = chartorune(&r, s); if(i == 0){ s++; --n; continue; } memmove(buf, s, i); buf[i] = 0; n -= i; s += i; screenputc(buf); } unlock(&screenlock); } static void screenwin(void) { char *greet; Memimage *orange; Point p, q; Rectangle r; back = memblack; conscol = memwhite; orange = allocmemimage(Rect(0, 0, 1, 1), RGB16); orange->flags |= Frepl; orange->clipr = gscreen->r; orange->data->bdata[0] = 0x40; /* magic: colour? */ orange->data->bdata[1] = 0xfd; /* magic: colour? */ w = memdefont->info[' '].width; h = memdefont->height; r = gscreen->r; memimagedraw(gscreen, r, memwhite, ZP, memopaque, ZP, S); window = insetrect(r, 4); memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); memimagedraw(gscreen, Rect(window.min.x, window.min.y, window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S); freememimage(orange); window = insetrect(window, 5); greet = " Plan 9 Console "; p = addpt(window.min, Pt(10, 0)); q = memsubfontwidth(memdefont, greet); memimagestring(gscreen, p, conscol, ZP, memdefont, greet); flushmemscreen(r); window.min.y += h + 6; curpos = window.min; window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h; } static void scroll(void) { int o; Point p; Rectangle r; o = Scroll*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); flushmemscreen(r); r = Rpt(Pt(window.min.x, window.max.y-o), window.max); memimagedraw(gscreen, r, back, ZP, nil, ZP, S); flushmemscreen(r); curpos.y -= o; } static void screenputc(char *buf) { int w; uint pos; Point p; 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(); curpos.y += h; screenputc("\r"); break; case '\r': xp = xbuf; curpos.x = window.min.x; break; case '\t': p = memsubfontwidth(memdefont, " "); w = p.x; if (curpos.x >= window.max.x - Tabstop * w) screenputc("\n"); pos = (curpos.x - window.min.x) / w; pos = Tabstop - pos % Tabstop; *xp++ = curpos.x; 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); flushmemscreen(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); flushmemscreen(r); curpos.x = *xp; break; case '\0': 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); flushmemscreen(r); curpos.x += w; break; } }