337 lines
5.9 KiB
C
337 lines
5.9 KiB
C
|
#include "u.h"
|
||
|
#include "../port/lib.h"
|
||
|
#include "mem.h"
|
||
|
#include "dat.h"
|
||
|
#include "fns.h"
|
||
|
|
||
|
#define Image IMAGE
|
||
|
#include <draw.h>
|
||
|
#include <memdraw.h>
|
||
|
#include <cursor.h>
|
||
|
#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;
|
||
|
}
|
||
|
}
|