plan9port/src/libdraw/init.c
rsc 670dd11a8a be more faithful to plan 9 environment --
allocate window on top of screen.
2005-03-18 18:55:47 +00:00

209 lines
3.9 KiB
C

#include <u.h>
#include <libc.h>
#include <draw.h>
Display *display;
Font *font;
Image *screen;
int _drawdebug;
static char deffontname[] = "*default*";
Screen *_screen;
int debuglockdisplay = 1;
static void
drawshutdown(void)
{
Display *d;
d = display;
if(d){
display = nil;
closedisplay(d);
}
}
int
initdraw(void (*error)(Display*, char*), char *fontname, char *label)
{
Subfont *df;
char buf[128];
display = _initdisplay(error, label); /* sets screen too */
if(display == nil)
return -1;
lockdisplay(display);
display->screenimage = display->image;
/*
* Set up default font
*/
df = getdefont(display);
display->defaultsubfont = df;
if(df == nil){
fprint(2, "imageinit: can't open default subfont: %r\n");
Error:
closedisplay(display);
display = nil;
return -1;
}
if(fontname == nil)
fontname = getenv("font"); /* leak */
/*
* Build fonts with caches==depth of screen, for speed.
* If conversion were faster, we'd use 0 and save memory.
*/
if(fontname == nil){
snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent,
df->n-1, deffontname);
//BUG: Need something better for this installsubfont("*default*", df);
font = buildfont(display, buf, deffontname);
if(font == nil){
fprint(2, "initdraw: can't open default font: %r\n");
goto Error;
}
}else{
font = openfont(display, fontname); /* BUG: grey fonts */
if(font == nil){
fprint(2, "initdraw: can't open font %s: %r\n", fontname);
goto Error;
}
}
display->defaultfont = font;
display->white = allocimage(display, Rect(0,0,1,1), GREY1, 1, DWhite);
display->black = allocimage(display, Rect(0,0,1,1), GREY1, 1, DBlack);
if(display->white == nil || display->black == nil){
fprint(2, "initdraw: can't allocate white and black");
goto Error;
}
display->opaque = display->white;
display->transparent = display->black;
_screen = allocscreen(display->image, display->white, 0);
screen = _allocwindow(nil, _screen, display->image->r, Refnone, DWhite);
display->screenimage = screen;
draw(screen, screen->r, display->black, nil, ZP);
flushimage(display, 1);
atexit(drawshutdown);
return 1;
}
/*
* Call with d unlocked.
* Note that disp->defaultfont and defaultsubfont are not freed here.
*/
void
closedisplay(Display *disp)
{
int fd;
char buf[128];
if(disp == nil)
return;
if(disp == display)
display = nil;
if(disp->oldlabel[0]){
snprint(buf, sizeof buf, "%s/label", disp->windir);
fd = open(buf, OWRITE);
if(fd >= 0){
write(fd, disp->oldlabel, strlen(disp->oldlabel));
close(fd);
}
}
free(disp->devdir);
free(disp->windir);
freeimage(disp->white);
freeimage(disp->black);
free(disp);
}
void
lockdisplay(Display *disp)
{
if(debuglockdisplay){
/* avoid busy looping; it's rare we collide anyway */
while(!canqlock(&disp->qlock)){
fprint(1, "proc %d waiting for display lock...\n", getpid());
sleep(1000);
}
}else
qlock(&disp->qlock);
}
void
unlockdisplay(Display *disp)
{
qunlock(&disp->qlock);
}
void
drawerror(Display *d, char *s)
{
char err[ERRMAX];
if(d->error)
d->error(d, s);
else{
errstr(err, sizeof err);
fprint(2, "draw: %s: %s\n", s, err);
exits(s);
}
}
static
int
doflush(Display *d)
{
int n;
n = d->bufp-d->buf;
if(n <= 0)
return 1;
if(_drawmsgwrite(d, d->buf, n) != n){
if(_drawdebug)
fprint(2, "flushimage fail: d=%p: %r\n", d); /**/
d->bufp = d->buf; /* might as well; chance of continuing */
return -1;
}
d->bufp = d->buf;
return 1;
}
int
flushimage(Display *d, int visible)
{
if(visible){
*d->bufp++ = 'v'; /* five bytes always reserved for this */
if(d->_isnewdisplay){
BPLONG(d->bufp, d->screenimage->id);
d->bufp += 4;
}
}
return doflush(d);
}
uchar*
bufimage(Display *d, int n)
{
uchar *p;
if(n<0 || n>d->bufsize){
abort();
werrstr("bad count in bufimage");
return 0;
}
if(d->bufp+n > d->buf+d->bufsize)
if(doflush(d) < 0)
return 0;
p = d->bufp;
d->bufp += n;
return p;
}