#include <u.h>
#include <libc.h>
#include <draw.h>
#define NODEFINE
#include <9pm/u.h>
#include <9pm/libc.h>
#include <9pm/memdraw.h>
#include <9pm/cursor.h>
#include <9pm/ns.h>
#include <9pm/thread.h>
#include <9pm/screen.h>
static int mousefd;
static int cursorfd;
static void reshaped(void);
static Rectangle
screenrect(void)
{
int fd;
char buf[12*5];
fd = open("/dev/screen", OREAD);
if(fd == -1)
fd = open("/mnt/term/dev/screen", OREAD);
if(fd == -1)
pm_sysfatal("can't open /dev/screen: %r\n");
if(read(fd, buf, sizeof buf) != sizeof buf)
pm_sysfatal("can't read /dev/screen: %r\n");
close(fd);
return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));
}
static int nresize;
static void
mouseproc(void*)
{
char buf[50];
char *f[5];
Point p;
if((mousefd = open("/dev/mouse", ORDWR)) < 0){
fprint(2, "warning: no mouse\n");
return;
}
if((cursorfd = open("/dev/cursor", ORDWR)) < 0){
fprint(2, "warning: no cursor\n");
return;
}
while(read(mousefd, buf, 49) == 49) {
if(buf[0] == 'r'){
nresize++;
pm_resizescreenimage();
}
if(tokenize(buf, f, nelem(f)) < 5)
continue;
p.x = atoi(f[1]);
p.y = atoi(f[2]);
p = subpt(p, screen->r.min);
pm_mousetrack(p, atoi(f[3]), atoi(f[4]));
}
}
static void
kbdproc(void*)
{
int fd, kfd, n, l;
char buf[32], *p;
Rune r;
if((fd = open("/dev/consctl", OWRITE)) < 0)
fprint(2, "warning: cannot set raw mode\n");
else
fprint(fd, "rawon");
if((kfd = open("/dev/cons", OREAD)) < 0){
fprint(2, "warning: cannot read /dev/cons\n");
return;
}
while((n = read(kfd, buf, sizeof buf)) >= 0) {
p = buf;
while(n > 0) {
l = chartorune(&r, p);
p += l;
n -= l;
pm_kbdputc(r);
}
}
}
void
pm_cursorload(Cursor *c)
{
char curs[2*4+2*2*16];
if(c == nil)
write(cursorfd, curs, 0);
else{
BPLONG(curs+0*4, c->offset.x);
BPLONG(curs+1*4, c->offset.y);
memmove(curs+2*4, c->clr, 2*2*16);
write(cursorfd, curs, sizeof curs);
}
}
int
pm_cursormove(Point p)
{
char buf[30];
p = addpt(p, screen->r.min);
snprint(buf, sizeof buf, "m%d %d", p.x, p.y);
if(write(mousefd, buf, strlen(buf)) != strlen(buf)){
fprint(2, "write %d failed; %r\n", mousefd);
abort();
}
return 0; /* success? */
}
void
pm_mousectl(Cmdbuf *c)
{
USED(c);
pm_error("no mouse ctls supported");
}
Memimage*
pm_attachscreen(int *softscreen)
{
if(initdraw(0, 0, "drawterm") < 0)
sysfatal("plan9 initdraw: %r");
*softscreen = 1;
memimageinit();
proccreate(mouseproc, nil, 8192);
proccreate(kbdproc, nil, 8192);
pm_gscreen = allocmemimage(Rect(0, 0, Dx(screen->r), Dy(screen->r)), screen->chan);
if(pm_gscreen == nil)
sysfatal("cannot allocate memimage: %r");
pm_drawconsinit();
return pm_gscreen;
}
void
pm_detachscreen(Memimage *m)
{
USED(m);
}
Memimage*
pm_reattachscreen(Memimage *m, int *softscreen)
{
*softscreen = 1;
if(getwindow(display, Refnone) < 0){
fprint(2,"can't reattach to window");
return m;
}
m = allocmemimage(Rect(0, 0, Dx(screen->r), Dy(screen->r)), screen->chan);
if(m == nil)
sysfatal("cannot allocate memimage: %r");
pm_gscreen = m;
return m;
}
#define CHUNK 7500
/*
* Like loadimage, but doesn't require the source data to be just the
* given rectangle. Lines in data are assumed to be bpl bytes wide.
*/
static int
myloadimage(Image *i, Rectangle r, uchar *data, int ndata, int bpl)
{
long dy;
int n, subbpl, y;
uchar *a;
if(r.max.x > i->r.max.x)
r.max.x = i->r.max.x;
if(r.max.y > i->r.max.y)
r.max.y = i->r.max.y;
if(!rectinrect(r, i->r)){
fprint(2, "myloadimage: bad rectangle\n");
return -1;
}
subbpl = bytesperline(r, i->depth);
n = bpl*(Dy(r)-1)+subbpl;
if(n > ndata){
fprint(2, "myloadimage: insufficient data\n");
return -1;
}
ndata = 0;
while(r.max.y > r.min.y){
dy = r.max.y - r.min.y;
if(dy*subbpl > CHUNK)
dy = CHUNK/subbpl;
if(dy <= 0){
fprint(2, "myloadimage: image too wide for buffer (CHUNK=%d, subbpl=%d)\n",
CHUNK, subbpl);
return -1;
}
n = dy*subbpl;
a = bufimage(i->display, 21+n);
if(a == nil){
fprint(2, "myloadimage: bufimage %d failed (dy=%d, subbpl=%d)", 21+n, dy, subbpl);
return -1;
}
a[0] = 'y';
BPLONG(a+1, i->id);
BPLONG(a+5, r.min.x);
BPLONG(a+9, r.min.y);
BPLONG(a+13, r.max.x);
BPLONG(a+17, r.min.y+dy);
for(y=0; y<dy; y++){
memmove(a+21+y*subbpl, data, subbpl);
data += bpl;
ndata += subbpl;
r.min.y++;
}
}
if(flushimage(i->display, 0) < 0)
return -1;
return ndata;
}
void
pm_flushmemscreen(Rectangle r)
{
if(rectclip(&r, pm_gscreen->r) == 0)
return;
myloadimage(screen, rectaddpt(r, screen->r.min), byteaddr(pm_gscreen, r.min), 1<<30, sizeof(ulong)*pm_gscreen->width);
flushimage(display, 1);
}
syntax highlighted by Code2HTML, v. 0.9.1