aboutsummaryrefslogtreecommitdiff
path: root/src/libdraw/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdraw/init.c')
-rw-r--r--src/libdraw/init.c203
1 files changed, 203 insertions, 0 deletions
diff --git a/src/libdraw/init.c b/src/libdraw/init.c
new file mode 100644
index 00000000..0cf590d8
--- /dev/null
+++ b/src/libdraw/init.c
@@ -0,0 +1,203 @@
+#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 = 0;
+
+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;
+
+ display->image = display->screenimage;
+ screen = display->screenimage;
+
+ /*
+ * 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;
+ 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);
+ qunlock(&disp->qlock);
+ 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;
+}
+