1*7dd7cddfSDavid du Colombier #include <u.h> 2*7dd7cddfSDavid du Colombier #include <libc.h> 3*7dd7cddfSDavid du Colombier #include <draw.h> 4*7dd7cddfSDavid du Colombier 5*7dd7cddfSDavid du Colombier Point ZP; 6*7dd7cddfSDavid du Colombier Rectangle ZR; 7*7dd7cddfSDavid du Colombier Display *display; 8*7dd7cddfSDavid du Colombier Font *font; 9*7dd7cddfSDavid du Colombier Image *screen; 10*7dd7cddfSDavid du Colombier 11*7dd7cddfSDavid du Colombier static char deffontname[] = "*default*"; 12*7dd7cddfSDavid du Colombier Screen *_screen; 13*7dd7cddfSDavid du Colombier 14*7dd7cddfSDavid du Colombier int debuglockdisplay = 0; 15*7dd7cddfSDavid du Colombier 16*7dd7cddfSDavid du Colombier int 17*7dd7cddfSDavid du Colombier Rconv(va_list *arg, Fconv *f) 18*7dd7cddfSDavid du Colombier { 19*7dd7cddfSDavid du Colombier Rectangle r; 20*7dd7cddfSDavid du Colombier char buf[128]; 21*7dd7cddfSDavid du Colombier 22*7dd7cddfSDavid du Colombier r = va_arg(*arg, Rectangle); 23*7dd7cddfSDavid du Colombier sprint(buf, "%P %P", r.min, r.max); 24*7dd7cddfSDavid du Colombier strconv(buf, f); 25*7dd7cddfSDavid du Colombier return 0; 26*7dd7cddfSDavid du Colombier } 27*7dd7cddfSDavid du Colombier 28*7dd7cddfSDavid du Colombier int 29*7dd7cddfSDavid du Colombier Pconv(va_list *arg, Fconv *f) 30*7dd7cddfSDavid du Colombier { 31*7dd7cddfSDavid du Colombier Point p; 32*7dd7cddfSDavid du Colombier char buf[64]; 33*7dd7cddfSDavid du Colombier 34*7dd7cddfSDavid du Colombier p = va_arg(*arg, Point); 35*7dd7cddfSDavid du Colombier sprint(buf, "[%d %d]", p.x, p.y); 36*7dd7cddfSDavid du Colombier strconv(buf, f); 37*7dd7cddfSDavid du Colombier return 0; 38*7dd7cddfSDavid du Colombier } 39*7dd7cddfSDavid du Colombier 40*7dd7cddfSDavid du Colombier static void 41*7dd7cddfSDavid du Colombier drawshutdown(void) 42*7dd7cddfSDavid du Colombier { 43*7dd7cddfSDavid du Colombier Display *d; 44*7dd7cddfSDavid du Colombier 45*7dd7cddfSDavid du Colombier d = display; 46*7dd7cddfSDavid du Colombier if(d){ 47*7dd7cddfSDavid du Colombier display = nil; 48*7dd7cddfSDavid du Colombier closedisplay(d); 49*7dd7cddfSDavid du Colombier } 50*7dd7cddfSDavid du Colombier } 51*7dd7cddfSDavid du Colombier 52*7dd7cddfSDavid du Colombier int 53*7dd7cddfSDavid du Colombier geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref) 54*7dd7cddfSDavid du Colombier { 55*7dd7cddfSDavid du Colombier int fd, n; 56*7dd7cddfSDavid du Colombier Subfont *df; 57*7dd7cddfSDavid du Colombier char buf[128]; 58*7dd7cddfSDavid du Colombier 59*7dd7cddfSDavid du Colombier display = initdisplay(devdir, windir, error); 60*7dd7cddfSDavid du Colombier if(display == nil) 61*7dd7cddfSDavid du Colombier return -1; 62*7dd7cddfSDavid du Colombier 63*7dd7cddfSDavid du Colombier /* 64*7dd7cddfSDavid du Colombier * Set up default font 65*7dd7cddfSDavid du Colombier */ 66*7dd7cddfSDavid du Colombier df = getdefont(display); 67*7dd7cddfSDavid du Colombier display->defaultsubfont = df; 68*7dd7cddfSDavid du Colombier if(df == nil){ 69*7dd7cddfSDavid du Colombier _drawprint(2, "imageinit: can't open default subfont: %r\n"); 70*7dd7cddfSDavid du Colombier Error: 71*7dd7cddfSDavid du Colombier closedisplay(display); 72*7dd7cddfSDavid du Colombier display = nil; 73*7dd7cddfSDavid du Colombier return -1; 74*7dd7cddfSDavid du Colombier } 75*7dd7cddfSDavid du Colombier if(fontname == nil){ 76*7dd7cddfSDavid du Colombier fd = open("/env/font", OREAD); 77*7dd7cddfSDavid du Colombier if(fd >= 0){ 78*7dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf)); 79*7dd7cddfSDavid du Colombier if(n>0 && n<sizeof buf-1){ 80*7dd7cddfSDavid du Colombier buf[n] = 0; 81*7dd7cddfSDavid du Colombier fontname = buf; 82*7dd7cddfSDavid du Colombier } 83*7dd7cddfSDavid du Colombier close(fd); 84*7dd7cddfSDavid du Colombier } 85*7dd7cddfSDavid du Colombier } 86*7dd7cddfSDavid du Colombier /* 87*7dd7cddfSDavid du Colombier * Build fonts with caches==depth of screen, for speed. 88*7dd7cddfSDavid du Colombier * If conversion were faster, we'd use 0 and save memory. 89*7dd7cddfSDavid du Colombier */ 90*7dd7cddfSDavid du Colombier if(fontname == nil){ 91*7dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent, 92*7dd7cddfSDavid du Colombier df->n-1, deffontname); 93*7dd7cddfSDavid du Colombier //BUG: Need something better for this installsubfont("*default*", df); 94*7dd7cddfSDavid du Colombier font = buildfont(display, buf, deffontname); 95*7dd7cddfSDavid du Colombier if(font == nil){ 96*7dd7cddfSDavid du Colombier _drawprint(2, "imageinit: can't open default font: %r\n"); 97*7dd7cddfSDavid du Colombier goto Error; 98*7dd7cddfSDavid du Colombier } 99*7dd7cddfSDavid du Colombier }else{ 100*7dd7cddfSDavid du Colombier font = openfont(display, fontname); /* BUG: grey fonts */ 101*7dd7cddfSDavid du Colombier if(font == nil){ 102*7dd7cddfSDavid du Colombier _drawprint(2, "imageinit: can't open font %s: %r\n", fontname); 103*7dd7cddfSDavid du Colombier goto Error; 104*7dd7cddfSDavid du Colombier } 105*7dd7cddfSDavid du Colombier } 106*7dd7cddfSDavid du Colombier display->defaultfont = font; 107*7dd7cddfSDavid du Colombier 108*7dd7cddfSDavid du Colombier /* 109*7dd7cddfSDavid du Colombier * Write label; ignore errors (we might not be running under rio) 110*7dd7cddfSDavid du Colombier */ 111*7dd7cddfSDavid du Colombier if(label){ 112*7dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/label", display->windir); 113*7dd7cddfSDavid du Colombier fd = open(buf, OREAD); 114*7dd7cddfSDavid du Colombier if(fd >= 0){ 115*7dd7cddfSDavid du Colombier read(fd, display->oldlabel, (sizeof display->oldlabel)-1); 116*7dd7cddfSDavid du Colombier close(fd); 117*7dd7cddfSDavid du Colombier fd = create(buf, OWRITE, 0666); 118*7dd7cddfSDavid du Colombier if(fd >= 0){ 119*7dd7cddfSDavid du Colombier write(fd, label, strlen(label)); 120*7dd7cddfSDavid du Colombier close(fd); 121*7dd7cddfSDavid du Colombier } 122*7dd7cddfSDavid du Colombier } 123*7dd7cddfSDavid du Colombier } 124*7dd7cddfSDavid du Colombier 125*7dd7cddfSDavid du Colombier if(getwindow(display, ref) < 0) 126*7dd7cddfSDavid du Colombier goto Error; 127*7dd7cddfSDavid du Colombier 128*7dd7cddfSDavid du Colombier atexit(drawshutdown); 129*7dd7cddfSDavid du Colombier 130*7dd7cddfSDavid du Colombier return 1; 131*7dd7cddfSDavid du Colombier } 132*7dd7cddfSDavid du Colombier 133*7dd7cddfSDavid du Colombier int 134*7dd7cddfSDavid du Colombier initdraw(void(*error)(Display*, char*), char *fontname , char *label) 135*7dd7cddfSDavid du Colombier { 136*7dd7cddfSDavid du Colombier char *dev = "/dev"; 137*7dd7cddfSDavid du Colombier char dir[DIRLEN]; 138*7dd7cddfSDavid du Colombier 139*7dd7cddfSDavid du Colombier if(stat("/dev/draw/new", dir)<0 && bind("#i", "/dev", MAFTER)<0){ 140*7dd7cddfSDavid du Colombier _drawprint(2, "imageinit: can't bind /dev/draw: %r"); 141*7dd7cddfSDavid du Colombier return -1; 142*7dd7cddfSDavid du Colombier } 143*7dd7cddfSDavid du Colombier return geninitdraw(dev, error, fontname, label, dev, Refnone); 144*7dd7cddfSDavid du Colombier } 145*7dd7cddfSDavid du Colombier 146*7dd7cddfSDavid du Colombier /* 147*7dd7cddfSDavid du Colombier * Attach, or possibly reattach, to window. 148*7dd7cddfSDavid du Colombier * If reattaching, maintain value of screen pointer. 149*7dd7cddfSDavid du Colombier */ 150*7dd7cddfSDavid du Colombier int 151*7dd7cddfSDavid du Colombier getwindow(Display *d, int ref) 152*7dd7cddfSDavid du Colombier { 153*7dd7cddfSDavid du Colombier int n, fd; 154*7dd7cddfSDavid du Colombier char buf[128]; 155*7dd7cddfSDavid du Colombier Image *image; 156*7dd7cddfSDavid du Colombier 157*7dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/winname", d->windir); 158*7dd7cddfSDavid du Colombier fd = open(buf, OREAD); 159*7dd7cddfSDavid du Colombier if(fd<0 || (n=read(fd, buf, 64))<=0){ 160*7dd7cddfSDavid du Colombier screen = display->image; 161*7dd7cddfSDavid du Colombier assert(screen && screen->chan != 0); 162*7dd7cddfSDavid du Colombier return 1; 163*7dd7cddfSDavid du Colombier } 164*7dd7cddfSDavid du Colombier close(fd); 165*7dd7cddfSDavid du Colombier buf[n] = 0; 166*7dd7cddfSDavid du Colombier if(screen != nil){ 167*7dd7cddfSDavid du Colombier _freeimage1(screen); 168*7dd7cddfSDavid du Colombier freeimage(_screen->image); 169*7dd7cddfSDavid du Colombier freescreen(_screen); 170*7dd7cddfSDavid du Colombier _screen = nil; 171*7dd7cddfSDavid du Colombier } 172*7dd7cddfSDavid du Colombier image = namedimage(display, buf); 173*7dd7cddfSDavid du Colombier if(image == 0){ 174*7dd7cddfSDavid du Colombier screen = nil; 175*7dd7cddfSDavid du Colombier return -1; 176*7dd7cddfSDavid du Colombier } 177*7dd7cddfSDavid du Colombier assert(image->chan != 0); 178*7dd7cddfSDavid du Colombier 179*7dd7cddfSDavid du Colombier _screen = allocscreen(image, display->white, 0); 180*7dd7cddfSDavid du Colombier if(_screen == nil){ 181*7dd7cddfSDavid du Colombier screen = nil; 182*7dd7cddfSDavid du Colombier return -1; 183*7dd7cddfSDavid du Colombier } 184*7dd7cddfSDavid du Colombier 185*7dd7cddfSDavid du Colombier screen = _allocwindow(screen, _screen, insetrect(image->r, Borderwidth), ref, DWhite); 186*7dd7cddfSDavid du Colombier if(screen == nil) 187*7dd7cddfSDavid du Colombier return -1; 188*7dd7cddfSDavid du Colombier assert(screen->chan != 0); 189*7dd7cddfSDavid du Colombier return 1; 190*7dd7cddfSDavid du Colombier } 191*7dd7cddfSDavid du Colombier 192*7dd7cddfSDavid du Colombier #define NINFO 12*12 193*7dd7cddfSDavid du Colombier 194*7dd7cddfSDavid du Colombier Display* 195*7dd7cddfSDavid du Colombier initdisplay(char *dev, char *win, void(*error)(Display*, char*)) 196*7dd7cddfSDavid du Colombier { 197*7dd7cddfSDavid du Colombier char buf[128], info[NINFO+1], *t; 198*7dd7cddfSDavid du Colombier int datafd, ctlfd, reffd; 199*7dd7cddfSDavid du Colombier Display *disp; 200*7dd7cddfSDavid du Colombier Image *image; 201*7dd7cddfSDavid du Colombier Dir dir; 202*7dd7cddfSDavid du Colombier ulong chan; 203*7dd7cddfSDavid du Colombier 204*7dd7cddfSDavid du Colombier fmtinstall('P', Pconv); 205*7dd7cddfSDavid du Colombier fmtinstall('R', Rconv); 206*7dd7cddfSDavid du Colombier if(dev == 0) 207*7dd7cddfSDavid du Colombier dev = "/dev"; 208*7dd7cddfSDavid du Colombier if(win == 0) 209*7dd7cddfSDavid du Colombier win = "/dev"; 210*7dd7cddfSDavid du Colombier if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){ 211*7dd7cddfSDavid du Colombier werrstr("initdisplay: directory name too long"); 212*7dd7cddfSDavid du Colombier return nil; 213*7dd7cddfSDavid du Colombier } 214*7dd7cddfSDavid du Colombier t = strdup(win); 215*7dd7cddfSDavid du Colombier if(t == nil) 216*7dd7cddfSDavid du Colombier return nil; 217*7dd7cddfSDavid du Colombier 218*7dd7cddfSDavid du Colombier sprint(buf, "%s/draw/new", dev); 219*7dd7cddfSDavid du Colombier ctlfd = open(buf, ORDWR|OCEXEC); 220*7dd7cddfSDavid du Colombier if(ctlfd < 0){ 221*7dd7cddfSDavid du Colombier if(bind("#i", dev, MAFTER) < 0){ 222*7dd7cddfSDavid du Colombier Error1: 223*7dd7cddfSDavid du Colombier free(t); 224*7dd7cddfSDavid du Colombier werrstr("initdisplay: %s: %r", buf); 225*7dd7cddfSDavid du Colombier return 0; 226*7dd7cddfSDavid du Colombier } 227*7dd7cddfSDavid du Colombier ctlfd = open(buf, ORDWR|OCEXEC); 228*7dd7cddfSDavid du Colombier } 229*7dd7cddfSDavid du Colombier if(ctlfd < 0) 230*7dd7cddfSDavid du Colombier goto Error1; 231*7dd7cddfSDavid du Colombier if(read(ctlfd, info, sizeof info) < NINFO){ 232*7dd7cddfSDavid du Colombier Error2: 233*7dd7cddfSDavid du Colombier close(ctlfd); 234*7dd7cddfSDavid du Colombier goto Error1; 235*7dd7cddfSDavid du Colombier } 236*7dd7cddfSDavid du Colombier 237*7dd7cddfSDavid du Colombier if((chan=strtochan(info+2*12)) == 0){ 238*7dd7cddfSDavid du Colombier werrstr("bad channel in %s", buf); 239*7dd7cddfSDavid du Colombier goto Error2; 240*7dd7cddfSDavid du Colombier } 241*7dd7cddfSDavid du Colombier 242*7dd7cddfSDavid du Colombier sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12)); 243*7dd7cddfSDavid du Colombier datafd = open(buf, ORDWR|OCEXEC); 244*7dd7cddfSDavid du Colombier if(datafd < 0) 245*7dd7cddfSDavid du Colombier goto Error2; 246*7dd7cddfSDavid du Colombier sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12)); 247*7dd7cddfSDavid du Colombier reffd = open(buf, OREAD|OCEXEC); 248*7dd7cddfSDavid du Colombier if(reffd < 0){ 249*7dd7cddfSDavid du Colombier Error3: 250*7dd7cddfSDavid du Colombier close(datafd); 251*7dd7cddfSDavid du Colombier goto Error2; 252*7dd7cddfSDavid du Colombier } 253*7dd7cddfSDavid du Colombier disp = malloc(sizeof(Display)); 254*7dd7cddfSDavid du Colombier if(disp == 0){ 255*7dd7cddfSDavid du Colombier Error4: 256*7dd7cddfSDavid du Colombier close(reffd); 257*7dd7cddfSDavid du Colombier goto Error3; 258*7dd7cddfSDavid du Colombier } 259*7dd7cddfSDavid du Colombier image = malloc(sizeof(Image)); 260*7dd7cddfSDavid du Colombier if(image == 0){ 261*7dd7cddfSDavid du Colombier Error5: 262*7dd7cddfSDavid du Colombier free(disp); 263*7dd7cddfSDavid du Colombier goto Error4; 264*7dd7cddfSDavid du Colombier } 265*7dd7cddfSDavid du Colombier memset(image, 0, sizeof(Image)); 266*7dd7cddfSDavid du Colombier memset(disp, 0, sizeof(Display)); 267*7dd7cddfSDavid du Colombier image->display = disp; 268*7dd7cddfSDavid du Colombier image->id = 0; 269*7dd7cddfSDavid du Colombier image->chan = chan; 270*7dd7cddfSDavid du Colombier image->depth = chantodepth(chan); 271*7dd7cddfSDavid du Colombier image->repl = atoi(info+3*12); 272*7dd7cddfSDavid du Colombier image->r.min.x = atoi(info+4*12); 273*7dd7cddfSDavid du Colombier image->r.min.y = atoi(info+5*12); 274*7dd7cddfSDavid du Colombier image->r.max.x = atoi(info+6*12); 275*7dd7cddfSDavid du Colombier image->r.max.y = atoi(info+7*12); 276*7dd7cddfSDavid du Colombier image->clipr.min.x = atoi(info+8*12); 277*7dd7cddfSDavid du Colombier image->clipr.min.y = atoi(info+9*12); 278*7dd7cddfSDavid du Colombier image->clipr.max.x = atoi(info+10*12); 279*7dd7cddfSDavid du Colombier image->clipr.max.y = atoi(info+11*12); 280*7dd7cddfSDavid du Colombier disp->dirno = atoi(info+0*12); 281*7dd7cddfSDavid du Colombier disp->fd = datafd; 282*7dd7cddfSDavid du Colombier disp->ctlfd = ctlfd; 283*7dd7cddfSDavid du Colombier disp->reffd = reffd; 284*7dd7cddfSDavid du Colombier disp->image = image; 285*7dd7cddfSDavid du Colombier disp->bufp = disp->buf; 286*7dd7cddfSDavid du Colombier disp->error = error; 287*7dd7cddfSDavid du Colombier disp->chan = image->chan; 288*7dd7cddfSDavid du Colombier disp->depth = image->depth; 289*7dd7cddfSDavid du Colombier disp->windir = t; 290*7dd7cddfSDavid du Colombier disp->devdir = strdup(dev); 291*7dd7cddfSDavid du Colombier qlock(&disp->qlock); 292*7dd7cddfSDavid du Colombier disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite); 293*7dd7cddfSDavid du Colombier disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack); 294*7dd7cddfSDavid du Colombier if(disp->white == nil || disp->black == nil){ 295*7dd7cddfSDavid du Colombier free(image); 296*7dd7cddfSDavid du Colombier free(disp->devdir); 297*7dd7cddfSDavid du Colombier free(disp->white); 298*7dd7cddfSDavid du Colombier free(disp->black); 299*7dd7cddfSDavid du Colombier goto Error5; 300*7dd7cddfSDavid du Colombier } 301*7dd7cddfSDavid du Colombier disp->opaque = disp->white; 302*7dd7cddfSDavid du Colombier disp->transparent = disp->black; 303*7dd7cddfSDavid du Colombier if(dirfstat(ctlfd, &dir)>=0 && dir.type=='i'){ 304*7dd7cddfSDavid du Colombier disp->local = 1; 305*7dd7cddfSDavid du Colombier disp->dataqid = dir.qid.path; 306*7dd7cddfSDavid du Colombier } 307*7dd7cddfSDavid du Colombier 308*7dd7cddfSDavid du Colombier assert(disp->chan != 0 && image->chan != 0); 309*7dd7cddfSDavid du Colombier return disp; 310*7dd7cddfSDavid du Colombier } 311*7dd7cddfSDavid du Colombier 312*7dd7cddfSDavid du Colombier /* 313*7dd7cddfSDavid du Colombier * Call with d unlocked. 314*7dd7cddfSDavid du Colombier * Note that disp->defaultfont and defaultsubfont are not freed here. 315*7dd7cddfSDavid du Colombier */ 316*7dd7cddfSDavid du Colombier void 317*7dd7cddfSDavid du Colombier closedisplay(Display *disp) 318*7dd7cddfSDavid du Colombier { 319*7dd7cddfSDavid du Colombier int fd; 320*7dd7cddfSDavid du Colombier char buf[128]; 321*7dd7cddfSDavid du Colombier 322*7dd7cddfSDavid du Colombier if(disp == nil) 323*7dd7cddfSDavid du Colombier return; 324*7dd7cddfSDavid du Colombier if(disp == display) 325*7dd7cddfSDavid du Colombier display = nil; 326*7dd7cddfSDavid du Colombier if(disp->oldlabel[0]){ 327*7dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/label", disp->windir); 328*7dd7cddfSDavid du Colombier fd = open(buf, OWRITE); 329*7dd7cddfSDavid du Colombier if(fd >= 0){ 330*7dd7cddfSDavid du Colombier write(fd, disp->oldlabel, strlen(disp->oldlabel)); 331*7dd7cddfSDavid du Colombier close(fd); 332*7dd7cddfSDavid du Colombier } 333*7dd7cddfSDavid du Colombier } 334*7dd7cddfSDavid du Colombier 335*7dd7cddfSDavid du Colombier free(disp->devdir); 336*7dd7cddfSDavid du Colombier free(disp->windir); 337*7dd7cddfSDavid du Colombier freeimage(disp->white); 338*7dd7cddfSDavid du Colombier freeimage(disp->black); 339*7dd7cddfSDavid du Colombier free(disp->image); 340*7dd7cddfSDavid du Colombier close(disp->fd); 341*7dd7cddfSDavid du Colombier close(disp->ctlfd); 342*7dd7cddfSDavid du Colombier /* should cause refresh slave to shut down */ 343*7dd7cddfSDavid du Colombier close(disp->reffd); 344*7dd7cddfSDavid du Colombier qunlock(&disp->qlock); 345*7dd7cddfSDavid du Colombier free(disp); 346*7dd7cddfSDavid du Colombier } 347*7dd7cddfSDavid du Colombier 348*7dd7cddfSDavid du Colombier void 349*7dd7cddfSDavid du Colombier lockdisplay(Display *disp) 350*7dd7cddfSDavid du Colombier { 351*7dd7cddfSDavid du Colombier if(debuglockdisplay){ 352*7dd7cddfSDavid du Colombier /* avoid busy looping; it's rare we collide anyway */ 353*7dd7cddfSDavid du Colombier while(!canqlock(&disp->qlock)){ 354*7dd7cddfSDavid du Colombier _drawprint(1, "proc %d waiting for display lock...\n", getpid()); 355*7dd7cddfSDavid du Colombier sleep(1000); 356*7dd7cddfSDavid du Colombier } 357*7dd7cddfSDavid du Colombier }else 358*7dd7cddfSDavid du Colombier qlock(&disp->qlock); 359*7dd7cddfSDavid du Colombier } 360*7dd7cddfSDavid du Colombier 361*7dd7cddfSDavid du Colombier void 362*7dd7cddfSDavid du Colombier unlockdisplay(Display *disp) 363*7dd7cddfSDavid du Colombier { 364*7dd7cddfSDavid du Colombier qunlock(&disp->qlock); 365*7dd7cddfSDavid du Colombier } 366*7dd7cddfSDavid du Colombier 367*7dd7cddfSDavid du Colombier /* use static buffer to avoid stack bloat */ 368*7dd7cddfSDavid du Colombier int 369*7dd7cddfSDavid du Colombier _drawprint(int fd, char *fmt, ...) 370*7dd7cddfSDavid du Colombier { 371*7dd7cddfSDavid du Colombier int n; 372*7dd7cddfSDavid du Colombier va_list arg; 373*7dd7cddfSDavid du Colombier static char buf[1024]; 374*7dd7cddfSDavid du Colombier static QLock l; 375*7dd7cddfSDavid du Colombier 376*7dd7cddfSDavid du Colombier qlock(&l); 377*7dd7cddfSDavid du Colombier va_start(arg, fmt); 378*7dd7cddfSDavid du Colombier doprint(buf, buf+sizeof buf, fmt, arg); 379*7dd7cddfSDavid du Colombier va_end(arg); 380*7dd7cddfSDavid du Colombier n = write(fd, buf, strlen(buf)); 381*7dd7cddfSDavid du Colombier qunlock(&l); 382*7dd7cddfSDavid du Colombier return n; 383*7dd7cddfSDavid du Colombier } 384*7dd7cddfSDavid du Colombier 385*7dd7cddfSDavid du Colombier void 386*7dd7cddfSDavid du Colombier drawerror(Display *d, char *s) 387*7dd7cddfSDavid du Colombier { 388*7dd7cddfSDavid du Colombier char err[ERRLEN]; 389*7dd7cddfSDavid du Colombier 390*7dd7cddfSDavid du Colombier if(d->error) 391*7dd7cddfSDavid du Colombier d->error(d, s); 392*7dd7cddfSDavid du Colombier else{ 393*7dd7cddfSDavid du Colombier errstr(err); 394*7dd7cddfSDavid du Colombier _drawprint(2, "draw: %s: %s\n", s, err); 395*7dd7cddfSDavid du Colombier exits(s); 396*7dd7cddfSDavid du Colombier } 397*7dd7cddfSDavid du Colombier } 398*7dd7cddfSDavid du Colombier 399*7dd7cddfSDavid du Colombier static 400*7dd7cddfSDavid du Colombier int 401*7dd7cddfSDavid du Colombier doflush(Display *d) 402*7dd7cddfSDavid du Colombier { 403*7dd7cddfSDavid du Colombier int n; 404*7dd7cddfSDavid du Colombier 405*7dd7cddfSDavid du Colombier n = d->bufp-d->buf; 406*7dd7cddfSDavid du Colombier if(n <= 0) 407*7dd7cddfSDavid du Colombier return 1; 408*7dd7cddfSDavid du Colombier 409*7dd7cddfSDavid du Colombier if(write(d->fd, d->buf, n) != n){ 410*7dd7cddfSDavid du Colombier /* _drawprint(2, "flushimage fail: d=%lux: %r\n", d); /**/ 411*7dd7cddfSDavid du Colombier d->bufp = d->buf; /* might as well; chance of continuing */ 412*7dd7cddfSDavid du Colombier return -1; 413*7dd7cddfSDavid du Colombier } 414*7dd7cddfSDavid du Colombier d->bufp = d->buf; 415*7dd7cddfSDavid du Colombier return 1; 416*7dd7cddfSDavid du Colombier } 417*7dd7cddfSDavid du Colombier 418*7dd7cddfSDavid du Colombier int 419*7dd7cddfSDavid du Colombier flushimage(Display *d, int visible) 420*7dd7cddfSDavid du Colombier { 421*7dd7cddfSDavid du Colombier if(visible) 422*7dd7cddfSDavid du Colombier *d->bufp++ = 'v'; /* one byte always reserved for this */ 423*7dd7cddfSDavid du Colombier return doflush(d); 424*7dd7cddfSDavid du Colombier } 425*7dd7cddfSDavid du Colombier 426*7dd7cddfSDavid du Colombier uchar* 427*7dd7cddfSDavid du Colombier bufimage(Display *d, int n) 428*7dd7cddfSDavid du Colombier { 429*7dd7cddfSDavid du Colombier uchar *p; 430*7dd7cddfSDavid du Colombier 431*7dd7cddfSDavid du Colombier if(n<0 || n>Displaybufsize){ 432*7dd7cddfSDavid du Colombier werrstr("bad count in bufimage"); 433*7dd7cddfSDavid du Colombier return 0; 434*7dd7cddfSDavid du Colombier } 435*7dd7cddfSDavid du Colombier if(d->bufp+n > d->buf+Displaybufsize) 436*7dd7cddfSDavid du Colombier if(doflush(d) < 0) 437*7dd7cddfSDavid du Colombier return 0; 438*7dd7cddfSDavid du Colombier p = d->bufp; 439*7dd7cddfSDavid du Colombier d->bufp += n; 440*7dd7cddfSDavid du Colombier return p; 441*7dd7cddfSDavid du Colombier } 442*7dd7cddfSDavid du Colombier 443