17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <draw.h> 47dd7cddfSDavid du Colombier 57dd7cddfSDavid du Colombier Point ZP; 67dd7cddfSDavid du Colombier Rectangle ZR; 77dd7cddfSDavid du Colombier Display *display; 87dd7cddfSDavid du Colombier Font *font; 97dd7cddfSDavid du Colombier Image *screen; 1059cc4ca5SDavid du Colombier int _drawdebug; 117dd7cddfSDavid du Colombier 127dd7cddfSDavid du Colombier static char deffontname[] = "*default*"; 137dd7cddfSDavid du Colombier Screen *_screen; 147dd7cddfSDavid du Colombier 157dd7cddfSDavid du Colombier int debuglockdisplay = 0; 167dd7cddfSDavid du Colombier 177dd7cddfSDavid du Colombier int 187dd7cddfSDavid du Colombier Rconv(va_list *arg, Fconv *f) 197dd7cddfSDavid du Colombier { 207dd7cddfSDavid du Colombier Rectangle r; 217dd7cddfSDavid du Colombier char buf[128]; 227dd7cddfSDavid du Colombier 237dd7cddfSDavid du Colombier r = va_arg(*arg, Rectangle); 247dd7cddfSDavid du Colombier sprint(buf, "%P %P", r.min, r.max); 257dd7cddfSDavid du Colombier strconv(buf, f); 267dd7cddfSDavid du Colombier return 0; 277dd7cddfSDavid du Colombier } 287dd7cddfSDavid du Colombier 297dd7cddfSDavid du Colombier int 307dd7cddfSDavid du Colombier Pconv(va_list *arg, Fconv *f) 317dd7cddfSDavid du Colombier { 327dd7cddfSDavid du Colombier Point p; 337dd7cddfSDavid du Colombier char buf[64]; 347dd7cddfSDavid du Colombier 357dd7cddfSDavid du Colombier p = va_arg(*arg, Point); 367dd7cddfSDavid du Colombier sprint(buf, "[%d %d]", p.x, p.y); 377dd7cddfSDavid du Colombier strconv(buf, f); 387dd7cddfSDavid du Colombier return 0; 397dd7cddfSDavid du Colombier } 407dd7cddfSDavid du Colombier 417dd7cddfSDavid du Colombier static void 427dd7cddfSDavid du Colombier drawshutdown(void) 437dd7cddfSDavid du Colombier { 447dd7cddfSDavid du Colombier Display *d; 457dd7cddfSDavid du Colombier 467dd7cddfSDavid du Colombier d = display; 477dd7cddfSDavid du Colombier if(d){ 487dd7cddfSDavid du Colombier display = nil; 497dd7cddfSDavid du Colombier closedisplay(d); 507dd7cddfSDavid du Colombier } 517dd7cddfSDavid du Colombier } 527dd7cddfSDavid du Colombier 537dd7cddfSDavid du Colombier int 547dd7cddfSDavid du Colombier geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref) 557dd7cddfSDavid du Colombier { 567dd7cddfSDavid du Colombier int fd, n; 577dd7cddfSDavid du Colombier Subfont *df; 587dd7cddfSDavid du Colombier char buf[128]; 597dd7cddfSDavid du Colombier 607dd7cddfSDavid du Colombier display = initdisplay(devdir, windir, error); 617dd7cddfSDavid du Colombier if(display == nil) 627dd7cddfSDavid du Colombier return -1; 637dd7cddfSDavid du Colombier 647dd7cddfSDavid du Colombier /* 657dd7cddfSDavid du Colombier * Set up default font 667dd7cddfSDavid du Colombier */ 677dd7cddfSDavid du Colombier df = getdefont(display); 687dd7cddfSDavid du Colombier display->defaultsubfont = df; 697dd7cddfSDavid du Colombier if(df == nil){ 707dd7cddfSDavid du Colombier _drawprint(2, "imageinit: can't open default subfont: %r\n"); 717dd7cddfSDavid du Colombier Error: 727dd7cddfSDavid du Colombier closedisplay(display); 737dd7cddfSDavid du Colombier display = nil; 747dd7cddfSDavid du Colombier return -1; 757dd7cddfSDavid du Colombier } 767dd7cddfSDavid du Colombier if(fontname == nil){ 777dd7cddfSDavid du Colombier fd = open("/env/font", OREAD); 787dd7cddfSDavid du Colombier if(fd >= 0){ 797dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf)); 807dd7cddfSDavid du Colombier if(n>0 && n<sizeof buf-1){ 817dd7cddfSDavid du Colombier buf[n] = 0; 827dd7cddfSDavid du Colombier fontname = buf; 837dd7cddfSDavid du Colombier } 847dd7cddfSDavid du Colombier close(fd); 857dd7cddfSDavid du Colombier } 867dd7cddfSDavid du Colombier } 877dd7cddfSDavid du Colombier /* 887dd7cddfSDavid du Colombier * Build fonts with caches==depth of screen, for speed. 897dd7cddfSDavid du Colombier * If conversion were faster, we'd use 0 and save memory. 907dd7cddfSDavid du Colombier */ 917dd7cddfSDavid du Colombier if(fontname == nil){ 927dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent, 937dd7cddfSDavid du Colombier df->n-1, deffontname); 947dd7cddfSDavid du Colombier //BUG: Need something better for this installsubfont("*default*", df); 957dd7cddfSDavid du Colombier font = buildfont(display, buf, deffontname); 967dd7cddfSDavid du Colombier if(font == nil){ 977dd7cddfSDavid du Colombier _drawprint(2, "imageinit: can't open default font: %r\n"); 987dd7cddfSDavid du Colombier goto Error; 997dd7cddfSDavid du Colombier } 1007dd7cddfSDavid du Colombier }else{ 1017dd7cddfSDavid du Colombier font = openfont(display, fontname); /* BUG: grey fonts */ 1027dd7cddfSDavid du Colombier if(font == nil){ 1037dd7cddfSDavid du Colombier _drawprint(2, "imageinit: can't open font %s: %r\n", fontname); 1047dd7cddfSDavid du Colombier goto Error; 1057dd7cddfSDavid du Colombier } 1067dd7cddfSDavid du Colombier } 1077dd7cddfSDavid du Colombier display->defaultfont = font; 1087dd7cddfSDavid du Colombier 1097dd7cddfSDavid du Colombier /* 1107dd7cddfSDavid du Colombier * Write label; ignore errors (we might not be running under rio) 1117dd7cddfSDavid du Colombier */ 1127dd7cddfSDavid du Colombier if(label){ 1137dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/label", display->windir); 1147dd7cddfSDavid du Colombier fd = open(buf, OREAD); 1157dd7cddfSDavid du Colombier if(fd >= 0){ 1167dd7cddfSDavid du Colombier read(fd, display->oldlabel, (sizeof display->oldlabel)-1); 1177dd7cddfSDavid du Colombier close(fd); 1187dd7cddfSDavid du Colombier fd = create(buf, OWRITE, 0666); 1197dd7cddfSDavid du Colombier if(fd >= 0){ 1207dd7cddfSDavid du Colombier write(fd, label, strlen(label)); 1217dd7cddfSDavid du Colombier close(fd); 1227dd7cddfSDavid du Colombier } 1237dd7cddfSDavid du Colombier } 1247dd7cddfSDavid du Colombier } 1257dd7cddfSDavid du Colombier 1267dd7cddfSDavid du Colombier if(getwindow(display, ref) < 0) 1277dd7cddfSDavid du Colombier goto Error; 1287dd7cddfSDavid du Colombier 1297dd7cddfSDavid du Colombier atexit(drawshutdown); 1307dd7cddfSDavid du Colombier 1317dd7cddfSDavid du Colombier return 1; 1327dd7cddfSDavid du Colombier } 1337dd7cddfSDavid du Colombier 1347dd7cddfSDavid du Colombier int 1357dd7cddfSDavid du Colombier initdraw(void(*error)(Display*, char*), char *fontname , char *label) 1367dd7cddfSDavid du Colombier { 1377dd7cddfSDavid du Colombier char *dev = "/dev"; 1387dd7cddfSDavid du Colombier char dir[DIRLEN]; 1397dd7cddfSDavid du Colombier 1407dd7cddfSDavid du Colombier if(stat("/dev/draw/new", dir)<0 && bind("#i", "/dev", MAFTER)<0){ 1417dd7cddfSDavid du Colombier _drawprint(2, "imageinit: can't bind /dev/draw: %r"); 1427dd7cddfSDavid du Colombier return -1; 1437dd7cddfSDavid du Colombier } 1447dd7cddfSDavid du Colombier return geninitdraw(dev, error, fontname, label, dev, Refnone); 1457dd7cddfSDavid du Colombier } 1467dd7cddfSDavid du Colombier 1477dd7cddfSDavid du Colombier /* 1487dd7cddfSDavid du Colombier * Attach, or possibly reattach, to window. 1497dd7cddfSDavid du Colombier * If reattaching, maintain value of screen pointer. 1507dd7cddfSDavid du Colombier */ 1517dd7cddfSDavid du Colombier int 152*80ee5cbfSDavid du Colombier gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref) 1537dd7cddfSDavid du Colombier { 1547dd7cddfSDavid du Colombier int n, fd; 155*80ee5cbfSDavid du Colombier char buf[64+1]; 1567dd7cddfSDavid du Colombier Image *image; 1577dd7cddfSDavid du Colombier 158*80ee5cbfSDavid du Colombier fd = open(winname, OREAD); 159*80ee5cbfSDavid du Colombier if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){ 160*80ee5cbfSDavid du Colombier *winp = d->image; 161*80ee5cbfSDavid du Colombier assert(*winp && (*winp)->chan != 0); 1627dd7cddfSDavid du Colombier return 1; 1637dd7cddfSDavid du Colombier } 1647dd7cddfSDavid du Colombier close(fd); 165*80ee5cbfSDavid du Colombier buf[n] = '\0'; 166*80ee5cbfSDavid du Colombier if(*winp != nil){ 167*80ee5cbfSDavid du Colombier _freeimage1(*winp); 168*80ee5cbfSDavid du Colombier freeimage((*scrp)->image); 169*80ee5cbfSDavid du Colombier freescreen(*scrp); 170*80ee5cbfSDavid du Colombier *scrp = nil; 1717dd7cddfSDavid du Colombier } 172*80ee5cbfSDavid du Colombier image = namedimage(d, buf); 1737dd7cddfSDavid du Colombier if(image == 0){ 174*80ee5cbfSDavid du Colombier *winp = nil; 1757dd7cddfSDavid du Colombier return -1; 1767dd7cddfSDavid du Colombier } 1777dd7cddfSDavid du Colombier assert(image->chan != 0); 1787dd7cddfSDavid du Colombier 179*80ee5cbfSDavid du Colombier *scrp = allocscreen(image, d->white, 0); 180*80ee5cbfSDavid du Colombier if(*scrp == nil){ 181*80ee5cbfSDavid du Colombier *winp = nil; 1827dd7cddfSDavid du Colombier return -1; 1837dd7cddfSDavid du Colombier } 1847dd7cddfSDavid du Colombier 185*80ee5cbfSDavid du Colombier *winp = _allocwindow(*winp, *scrp, insetrect(image->r, Borderwidth), ref, DWhite); 186*80ee5cbfSDavid du Colombier if(*winp == nil) 1877dd7cddfSDavid du Colombier return -1; 188*80ee5cbfSDavid du Colombier assert((*winp)->chan != 0); 1897dd7cddfSDavid du Colombier return 1; 1907dd7cddfSDavid du Colombier } 1917dd7cddfSDavid du Colombier 192*80ee5cbfSDavid du Colombier int 193*80ee5cbfSDavid du Colombier getwindow(Display *d, int ref) 194*80ee5cbfSDavid du Colombier { 195*80ee5cbfSDavid du Colombier char winname[128]; 196*80ee5cbfSDavid du Colombier 197*80ee5cbfSDavid du Colombier snprint(winname, sizeof winname, "%s/winname", d->windir); 198*80ee5cbfSDavid du Colombier return gengetwindow(d, winname, &screen, &_screen, ref); 199*80ee5cbfSDavid du Colombier } 200*80ee5cbfSDavid du Colombier 2017dd7cddfSDavid du Colombier #define NINFO 12*12 2027dd7cddfSDavid du Colombier 2037dd7cddfSDavid du Colombier Display* 2047dd7cddfSDavid du Colombier initdisplay(char *dev, char *win, void(*error)(Display*, char*)) 2057dd7cddfSDavid du Colombier { 2067dd7cddfSDavid du Colombier char buf[128], info[NINFO+1], *t; 2077dd7cddfSDavid du Colombier int datafd, ctlfd, reffd; 2087dd7cddfSDavid du Colombier Display *disp; 2097dd7cddfSDavid du Colombier Image *image; 2107dd7cddfSDavid du Colombier Dir dir; 2117dd7cddfSDavid du Colombier ulong chan; 2127dd7cddfSDavid du Colombier 2137dd7cddfSDavid du Colombier fmtinstall('P', Pconv); 2147dd7cddfSDavid du Colombier fmtinstall('R', Rconv); 2157dd7cddfSDavid du Colombier if(dev == 0) 2167dd7cddfSDavid du Colombier dev = "/dev"; 2177dd7cddfSDavid du Colombier if(win == 0) 2187dd7cddfSDavid du Colombier win = "/dev"; 2197dd7cddfSDavid du Colombier if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){ 2207dd7cddfSDavid du Colombier werrstr("initdisplay: directory name too long"); 2217dd7cddfSDavid du Colombier return nil; 2227dd7cddfSDavid du Colombier } 2237dd7cddfSDavid du Colombier t = strdup(win); 2247dd7cddfSDavid du Colombier if(t == nil) 2257dd7cddfSDavid du Colombier return nil; 2267dd7cddfSDavid du Colombier 2277dd7cddfSDavid du Colombier sprint(buf, "%s/draw/new", dev); 2287dd7cddfSDavid du Colombier ctlfd = open(buf, ORDWR|OCEXEC); 2297dd7cddfSDavid du Colombier if(ctlfd < 0){ 2307dd7cddfSDavid du Colombier if(bind("#i", dev, MAFTER) < 0){ 2317dd7cddfSDavid du Colombier Error1: 2327dd7cddfSDavid du Colombier free(t); 2337dd7cddfSDavid du Colombier werrstr("initdisplay: %s: %r", buf); 2347dd7cddfSDavid du Colombier return 0; 2357dd7cddfSDavid du Colombier } 2367dd7cddfSDavid du Colombier ctlfd = open(buf, ORDWR|OCEXEC); 2377dd7cddfSDavid du Colombier } 2387dd7cddfSDavid du Colombier if(ctlfd < 0) 2397dd7cddfSDavid du Colombier goto Error1; 2407dd7cddfSDavid du Colombier if(read(ctlfd, info, sizeof info) < NINFO){ 2417dd7cddfSDavid du Colombier Error2: 2427dd7cddfSDavid du Colombier close(ctlfd); 2437dd7cddfSDavid du Colombier goto Error1; 2447dd7cddfSDavid du Colombier } 2457dd7cddfSDavid du Colombier 2467dd7cddfSDavid du Colombier if((chan=strtochan(info+2*12)) == 0){ 2477dd7cddfSDavid du Colombier werrstr("bad channel in %s", buf); 2487dd7cddfSDavid du Colombier goto Error2; 2497dd7cddfSDavid du Colombier } 2507dd7cddfSDavid du Colombier 2517dd7cddfSDavid du Colombier sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12)); 2527dd7cddfSDavid du Colombier datafd = open(buf, ORDWR|OCEXEC); 2537dd7cddfSDavid du Colombier if(datafd < 0) 2547dd7cddfSDavid du Colombier goto Error2; 2557dd7cddfSDavid du Colombier sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12)); 2567dd7cddfSDavid du Colombier reffd = open(buf, OREAD|OCEXEC); 2577dd7cddfSDavid du Colombier if(reffd < 0){ 2587dd7cddfSDavid du Colombier Error3: 2597dd7cddfSDavid du Colombier close(datafd); 2607dd7cddfSDavid du Colombier goto Error2; 2617dd7cddfSDavid du Colombier } 2627dd7cddfSDavid du Colombier disp = malloc(sizeof(Display)); 2637dd7cddfSDavid du Colombier if(disp == 0){ 2647dd7cddfSDavid du Colombier Error4: 2657dd7cddfSDavid du Colombier close(reffd); 2667dd7cddfSDavid du Colombier goto Error3; 2677dd7cddfSDavid du Colombier } 2687dd7cddfSDavid du Colombier image = malloc(sizeof(Image)); 2697dd7cddfSDavid du Colombier if(image == 0){ 2707dd7cddfSDavid du Colombier Error5: 2717dd7cddfSDavid du Colombier free(disp); 2727dd7cddfSDavid du Colombier goto Error4; 2737dd7cddfSDavid du Colombier } 2747dd7cddfSDavid du Colombier memset(image, 0, sizeof(Image)); 2757dd7cddfSDavid du Colombier memset(disp, 0, sizeof(Display)); 2767dd7cddfSDavid du Colombier image->display = disp; 2777dd7cddfSDavid du Colombier image->id = 0; 2787dd7cddfSDavid du Colombier image->chan = chan; 2797dd7cddfSDavid du Colombier image->depth = chantodepth(chan); 2807dd7cddfSDavid du Colombier image->repl = atoi(info+3*12); 2817dd7cddfSDavid du Colombier image->r.min.x = atoi(info+4*12); 2827dd7cddfSDavid du Colombier image->r.min.y = atoi(info+5*12); 2837dd7cddfSDavid du Colombier image->r.max.x = atoi(info+6*12); 2847dd7cddfSDavid du Colombier image->r.max.y = atoi(info+7*12); 2857dd7cddfSDavid du Colombier image->clipr.min.x = atoi(info+8*12); 2867dd7cddfSDavid du Colombier image->clipr.min.y = atoi(info+9*12); 2877dd7cddfSDavid du Colombier image->clipr.max.x = atoi(info+10*12); 2887dd7cddfSDavid du Colombier image->clipr.max.y = atoi(info+11*12); 2897dd7cddfSDavid du Colombier disp->dirno = atoi(info+0*12); 2907dd7cddfSDavid du Colombier disp->fd = datafd; 2917dd7cddfSDavid du Colombier disp->ctlfd = ctlfd; 2927dd7cddfSDavid du Colombier disp->reffd = reffd; 2937dd7cddfSDavid du Colombier disp->image = image; 2947dd7cddfSDavid du Colombier disp->bufp = disp->buf; 2957dd7cddfSDavid du Colombier disp->error = error; 2967dd7cddfSDavid du Colombier disp->chan = image->chan; 2977dd7cddfSDavid du Colombier disp->depth = image->depth; 2987dd7cddfSDavid du Colombier disp->windir = t; 2997dd7cddfSDavid du Colombier disp->devdir = strdup(dev); 3007dd7cddfSDavid du Colombier qlock(&disp->qlock); 3017dd7cddfSDavid du Colombier disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite); 3027dd7cddfSDavid du Colombier disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack); 3037dd7cddfSDavid du Colombier if(disp->white == nil || disp->black == nil){ 3047dd7cddfSDavid du Colombier free(image); 3057dd7cddfSDavid du Colombier free(disp->devdir); 3067dd7cddfSDavid du Colombier free(disp->white); 3077dd7cddfSDavid du Colombier free(disp->black); 3087dd7cddfSDavid du Colombier goto Error5; 3097dd7cddfSDavid du Colombier } 3107dd7cddfSDavid du Colombier disp->opaque = disp->white; 3117dd7cddfSDavid du Colombier disp->transparent = disp->black; 3127dd7cddfSDavid du Colombier if(dirfstat(ctlfd, &dir)>=0 && dir.type=='i'){ 3137dd7cddfSDavid du Colombier disp->local = 1; 3147dd7cddfSDavid du Colombier disp->dataqid = dir.qid.path; 3157dd7cddfSDavid du Colombier } 3167dd7cddfSDavid du Colombier 3177dd7cddfSDavid du Colombier assert(disp->chan != 0 && image->chan != 0); 3187dd7cddfSDavid du Colombier return disp; 3197dd7cddfSDavid du Colombier } 3207dd7cddfSDavid du Colombier 3217dd7cddfSDavid du Colombier /* 3227dd7cddfSDavid du Colombier * Call with d unlocked. 3237dd7cddfSDavid du Colombier * Note that disp->defaultfont and defaultsubfont are not freed here. 3247dd7cddfSDavid du Colombier */ 3257dd7cddfSDavid du Colombier void 3267dd7cddfSDavid du Colombier closedisplay(Display *disp) 3277dd7cddfSDavid du Colombier { 3287dd7cddfSDavid du Colombier int fd; 3297dd7cddfSDavid du Colombier char buf[128]; 3307dd7cddfSDavid du Colombier 3317dd7cddfSDavid du Colombier if(disp == nil) 3327dd7cddfSDavid du Colombier return; 3337dd7cddfSDavid du Colombier if(disp == display) 3347dd7cddfSDavid du Colombier display = nil; 3357dd7cddfSDavid du Colombier if(disp->oldlabel[0]){ 3367dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/label", disp->windir); 3377dd7cddfSDavid du Colombier fd = open(buf, OWRITE); 3387dd7cddfSDavid du Colombier if(fd >= 0){ 3397dd7cddfSDavid du Colombier write(fd, disp->oldlabel, strlen(disp->oldlabel)); 3407dd7cddfSDavid du Colombier close(fd); 3417dd7cddfSDavid du Colombier } 3427dd7cddfSDavid du Colombier } 3437dd7cddfSDavid du Colombier 3447dd7cddfSDavid du Colombier free(disp->devdir); 3457dd7cddfSDavid du Colombier free(disp->windir); 3467dd7cddfSDavid du Colombier freeimage(disp->white); 3477dd7cddfSDavid du Colombier freeimage(disp->black); 3487dd7cddfSDavid du Colombier free(disp->image); 3497dd7cddfSDavid du Colombier close(disp->fd); 3507dd7cddfSDavid du Colombier close(disp->ctlfd); 3517dd7cddfSDavid du Colombier /* should cause refresh slave to shut down */ 3527dd7cddfSDavid du Colombier close(disp->reffd); 3537dd7cddfSDavid du Colombier qunlock(&disp->qlock); 3547dd7cddfSDavid du Colombier free(disp); 3557dd7cddfSDavid du Colombier } 3567dd7cddfSDavid du Colombier 3577dd7cddfSDavid du Colombier void 3587dd7cddfSDavid du Colombier lockdisplay(Display *disp) 3597dd7cddfSDavid du Colombier { 3607dd7cddfSDavid du Colombier if(debuglockdisplay){ 3617dd7cddfSDavid du Colombier /* avoid busy looping; it's rare we collide anyway */ 3627dd7cddfSDavid du Colombier while(!canqlock(&disp->qlock)){ 3637dd7cddfSDavid du Colombier _drawprint(1, "proc %d waiting for display lock...\n", getpid()); 3647dd7cddfSDavid du Colombier sleep(1000); 3657dd7cddfSDavid du Colombier } 3667dd7cddfSDavid du Colombier }else 3677dd7cddfSDavid du Colombier qlock(&disp->qlock); 3687dd7cddfSDavid du Colombier } 3697dd7cddfSDavid du Colombier 3707dd7cddfSDavid du Colombier void 3717dd7cddfSDavid du Colombier unlockdisplay(Display *disp) 3727dd7cddfSDavid du Colombier { 3737dd7cddfSDavid du Colombier qunlock(&disp->qlock); 3747dd7cddfSDavid du Colombier } 3757dd7cddfSDavid du Colombier 3767dd7cddfSDavid du Colombier /* use static buffer to avoid stack bloat */ 3777dd7cddfSDavid du Colombier int 3787dd7cddfSDavid du Colombier _drawprint(int fd, char *fmt, ...) 3797dd7cddfSDavid du Colombier { 3807dd7cddfSDavid du Colombier int n; 3817dd7cddfSDavid du Colombier va_list arg; 3827dd7cddfSDavid du Colombier static char buf[1024]; 3837dd7cddfSDavid du Colombier static QLock l; 3847dd7cddfSDavid du Colombier 3857dd7cddfSDavid du Colombier qlock(&l); 3867dd7cddfSDavid du Colombier va_start(arg, fmt); 3877dd7cddfSDavid du Colombier doprint(buf, buf+sizeof buf, fmt, arg); 3887dd7cddfSDavid du Colombier va_end(arg); 3897dd7cddfSDavid du Colombier n = write(fd, buf, strlen(buf)); 3907dd7cddfSDavid du Colombier qunlock(&l); 3917dd7cddfSDavid du Colombier return n; 3927dd7cddfSDavid du Colombier } 3937dd7cddfSDavid du Colombier 3947dd7cddfSDavid du Colombier void 3957dd7cddfSDavid du Colombier drawerror(Display *d, char *s) 3967dd7cddfSDavid du Colombier { 3977dd7cddfSDavid du Colombier char err[ERRLEN]; 3987dd7cddfSDavid du Colombier 3997dd7cddfSDavid du Colombier if(d->error) 4007dd7cddfSDavid du Colombier d->error(d, s); 4017dd7cddfSDavid du Colombier else{ 4027dd7cddfSDavid du Colombier errstr(err); 4037dd7cddfSDavid du Colombier _drawprint(2, "draw: %s: %s\n", s, err); 4047dd7cddfSDavid du Colombier exits(s); 4057dd7cddfSDavid du Colombier } 4067dd7cddfSDavid du Colombier } 4077dd7cddfSDavid du Colombier 4087dd7cddfSDavid du Colombier static 4097dd7cddfSDavid du Colombier int 4107dd7cddfSDavid du Colombier doflush(Display *d) 4117dd7cddfSDavid du Colombier { 4127dd7cddfSDavid du Colombier int n; 4137dd7cddfSDavid du Colombier 4147dd7cddfSDavid du Colombier n = d->bufp-d->buf; 4157dd7cddfSDavid du Colombier if(n <= 0) 4167dd7cddfSDavid du Colombier return 1; 4177dd7cddfSDavid du Colombier 4187dd7cddfSDavid du Colombier if(write(d->fd, d->buf, n) != n){ 41959cc4ca5SDavid du Colombier if(_drawdebug) 42059cc4ca5SDavid du Colombier _drawprint(2, "flushimage fail: d=%p: %r\n", d); /**/ 4217dd7cddfSDavid du Colombier d->bufp = d->buf; /* might as well; chance of continuing */ 4227dd7cddfSDavid du Colombier return -1; 4237dd7cddfSDavid du Colombier } 4247dd7cddfSDavid du Colombier d->bufp = d->buf; 4257dd7cddfSDavid du Colombier return 1; 4267dd7cddfSDavid du Colombier } 4277dd7cddfSDavid du Colombier 4287dd7cddfSDavid du Colombier int 4297dd7cddfSDavid du Colombier flushimage(Display *d, int visible) 4307dd7cddfSDavid du Colombier { 4317dd7cddfSDavid du Colombier if(visible) 4327dd7cddfSDavid du Colombier *d->bufp++ = 'v'; /* one byte always reserved for this */ 4337dd7cddfSDavid du Colombier return doflush(d); 4347dd7cddfSDavid du Colombier } 4357dd7cddfSDavid du Colombier 4367dd7cddfSDavid du Colombier uchar* 4377dd7cddfSDavid du Colombier bufimage(Display *d, int n) 4387dd7cddfSDavid du Colombier { 4397dd7cddfSDavid du Colombier uchar *p; 4407dd7cddfSDavid du Colombier 4417dd7cddfSDavid du Colombier if(n<0 || n>Displaybufsize){ 4427dd7cddfSDavid du Colombier werrstr("bad count in bufimage"); 4437dd7cddfSDavid du Colombier return 0; 4447dd7cddfSDavid du Colombier } 4457dd7cddfSDavid du Colombier if(d->bufp+n > d->buf+Displaybufsize) 4467dd7cddfSDavid du Colombier if(doflush(d) < 0) 4477dd7cddfSDavid du Colombier return 0; 4487dd7cddfSDavid du Colombier p = d->bufp; 4497dd7cddfSDavid du Colombier d->bufp += n; 4507dd7cddfSDavid du Colombier return p; 4517dd7cddfSDavid du Colombier } 4527dd7cddfSDavid du Colombier 453