17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <draw.h> 47dd7cddfSDavid du Colombier 57dd7cddfSDavid du Colombier Display *display; 67dd7cddfSDavid du Colombier Font *font; 77dd7cddfSDavid du Colombier Image *screen; 8*711d1557SDavid du Colombier int _drawdebug = 0; 97dd7cddfSDavid du Colombier 107dd7cddfSDavid du Colombier static char deffontname[] = "*default*"; 117dd7cddfSDavid du Colombier Screen *_screen; 127dd7cddfSDavid du Colombier 137dd7cddfSDavid du Colombier int debuglockdisplay = 0; 147dd7cddfSDavid du Colombier 157dd7cddfSDavid du Colombier static void 167dd7cddfSDavid du Colombier drawshutdown(void) 177dd7cddfSDavid du Colombier { 187dd7cddfSDavid du Colombier Display *d; 197dd7cddfSDavid du Colombier 207dd7cddfSDavid du Colombier d = display; 217dd7cddfSDavid du Colombier if(d){ 227dd7cddfSDavid du Colombier display = nil; 237dd7cddfSDavid du Colombier closedisplay(d); 247dd7cddfSDavid du Colombier } 257dd7cddfSDavid du Colombier } 267dd7cddfSDavid du Colombier 277dd7cddfSDavid du Colombier int 287dd7cddfSDavid du Colombier geninitdraw(char *devdir, void(*error)(Display*, char*), char *fontname, char *label, char *windir, int ref) 297dd7cddfSDavid du Colombier { 307dd7cddfSDavid du Colombier int fd, n; 317dd7cddfSDavid du Colombier Subfont *df; 327dd7cddfSDavid du Colombier char buf[128]; 337dd7cddfSDavid du Colombier 347dd7cddfSDavid du Colombier display = initdisplay(devdir, windir, error); 357dd7cddfSDavid du Colombier if(display == nil) 367dd7cddfSDavid du Colombier return -1; 377dd7cddfSDavid du Colombier 387dd7cddfSDavid du Colombier /* 397dd7cddfSDavid du Colombier * Set up default font 407dd7cddfSDavid du Colombier */ 417dd7cddfSDavid du Colombier df = getdefont(display); 427dd7cddfSDavid du Colombier display->defaultsubfont = df; 437dd7cddfSDavid du Colombier if(df == nil){ 449a747e4fSDavid du Colombier fprint(2, "imageinit: can't open default subfont: %r\n"); 457dd7cddfSDavid du Colombier Error: 467dd7cddfSDavid du Colombier closedisplay(display); 477dd7cddfSDavid du Colombier display = nil; 487dd7cddfSDavid du Colombier return -1; 497dd7cddfSDavid du Colombier } 507dd7cddfSDavid du Colombier if(fontname == nil){ 517dd7cddfSDavid du Colombier fd = open("/env/font", OREAD); 527dd7cddfSDavid du Colombier if(fd >= 0){ 537dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf)); 547dd7cddfSDavid du Colombier if(n>0 && n<sizeof buf-1){ 557dd7cddfSDavid du Colombier buf[n] = 0; 567dd7cddfSDavid du Colombier fontname = buf; 577dd7cddfSDavid du Colombier } 587dd7cddfSDavid du Colombier close(fd); 597dd7cddfSDavid du Colombier } 607dd7cddfSDavid du Colombier } 617dd7cddfSDavid du Colombier /* 627dd7cddfSDavid du Colombier * Build fonts with caches==depth of screen, for speed. 637dd7cddfSDavid du Colombier * If conversion were faster, we'd use 0 and save memory. 647dd7cddfSDavid du Colombier */ 657dd7cddfSDavid du Colombier if(fontname == nil){ 667dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%d %d\n0 %d\t%s\n", df->height, df->ascent, 677dd7cddfSDavid du Colombier df->n-1, deffontname); 687dd7cddfSDavid du Colombier //BUG: Need something better for this installsubfont("*default*", df); 697dd7cddfSDavid du Colombier font = buildfont(display, buf, deffontname); 707dd7cddfSDavid du Colombier if(font == nil){ 719a747e4fSDavid du Colombier fprint(2, "imageinit: can't open default font: %r\n"); 727dd7cddfSDavid du Colombier goto Error; 737dd7cddfSDavid du Colombier } 747dd7cddfSDavid du Colombier }else{ 757dd7cddfSDavid du Colombier font = openfont(display, fontname); /* BUG: grey fonts */ 767dd7cddfSDavid du Colombier if(font == nil){ 779a747e4fSDavid du Colombier fprint(2, "imageinit: can't open font %s: %r\n", fontname); 787dd7cddfSDavid du Colombier goto Error; 797dd7cddfSDavid du Colombier } 807dd7cddfSDavid du Colombier } 817dd7cddfSDavid du Colombier display->defaultfont = font; 827dd7cddfSDavid du Colombier 837dd7cddfSDavid du Colombier /* 847dd7cddfSDavid du Colombier * Write label; ignore errors (we might not be running under rio) 857dd7cddfSDavid du Colombier */ 867dd7cddfSDavid du Colombier if(label){ 877dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/label", display->windir); 887dd7cddfSDavid du Colombier fd = open(buf, OREAD); 897dd7cddfSDavid du Colombier if(fd >= 0){ 907dd7cddfSDavid du Colombier read(fd, display->oldlabel, (sizeof display->oldlabel)-1); 917dd7cddfSDavid du Colombier close(fd); 927dd7cddfSDavid du Colombier fd = create(buf, OWRITE, 0666); 937dd7cddfSDavid du Colombier if(fd >= 0){ 947dd7cddfSDavid du Colombier write(fd, label, strlen(label)); 957dd7cddfSDavid du Colombier close(fd); 967dd7cddfSDavid du Colombier } 977dd7cddfSDavid du Colombier } 987dd7cddfSDavid du Colombier } 997dd7cddfSDavid du Colombier 1009a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%s/winname", display->windir); 1019a747e4fSDavid du Colombier if(gengetwindow(display, buf, &screen, &_screen, ref) < 0) 1027dd7cddfSDavid du Colombier goto Error; 1037dd7cddfSDavid du Colombier 1047dd7cddfSDavid du Colombier atexit(drawshutdown); 1057dd7cddfSDavid du Colombier 1067dd7cddfSDavid du Colombier return 1; 1077dd7cddfSDavid du Colombier } 1087dd7cddfSDavid du Colombier 1097dd7cddfSDavid du Colombier int 1107dd7cddfSDavid du Colombier initdraw(void(*error)(Display*, char*), char *fontname , char *label) 1117dd7cddfSDavid du Colombier { 1127dd7cddfSDavid du Colombier char *dev = "/dev"; 1137dd7cddfSDavid du Colombier 1149a747e4fSDavid du Colombier if(access("/dev/draw/new", AEXIST)<0 && bind("#i", "/dev", MAFTER)<0){ 1159a747e4fSDavid du Colombier fprint(2, "imageinit: can't bind /dev/draw: %r"); 1167dd7cddfSDavid du Colombier return -1; 1177dd7cddfSDavid du Colombier } 1187dd7cddfSDavid du Colombier return geninitdraw(dev, error, fontname, label, dev, Refnone); 1197dd7cddfSDavid du Colombier } 1207dd7cddfSDavid du Colombier 1217dd7cddfSDavid du Colombier /* 1227dd7cddfSDavid du Colombier * Attach, or possibly reattach, to window. 1237dd7cddfSDavid du Colombier * If reattaching, maintain value of screen pointer. 1247dd7cddfSDavid du Colombier */ 1257dd7cddfSDavid du Colombier int 12680ee5cbfSDavid du Colombier gengetwindow(Display *d, char *winname, Image **winp, Screen **scrp, int ref) 1277dd7cddfSDavid du Colombier { 1287dd7cddfSDavid du Colombier int n, fd; 12980ee5cbfSDavid du Colombier char buf[64+1]; 1307dd7cddfSDavid du Colombier Image *image; 1319a747e4fSDavid du Colombier Rectangle r; 1327dd7cddfSDavid du Colombier 13380ee5cbfSDavid du Colombier fd = open(winname, OREAD); 13480ee5cbfSDavid du Colombier if(fd<0 || (n=read(fd, buf, sizeof buf-1))<=0){ 1359a747e4fSDavid du Colombier if((image=d->image) == nil){ 1369a747e4fSDavid du Colombier fprint(2, "gengetwindow: %r\n"); 1379a747e4fSDavid du Colombier *winp = nil; 1389a747e4fSDavid du Colombier d->screenimage = nil; 1399a747e4fSDavid du Colombier return -1; 1407dd7cddfSDavid du Colombier } 1419a747e4fSDavid du Colombier strcpy(buf, "noborder"); 1429a747e4fSDavid du Colombier }else{ 1437dd7cddfSDavid du Colombier close(fd); 14480ee5cbfSDavid du Colombier buf[n] = '\0'; 14580ee5cbfSDavid du Colombier if(*winp != nil){ 14680ee5cbfSDavid du Colombier _freeimage1(*winp); 14780ee5cbfSDavid du Colombier freeimage((*scrp)->image); 14880ee5cbfSDavid du Colombier freescreen(*scrp); 14980ee5cbfSDavid du Colombier *scrp = nil; 1507dd7cddfSDavid du Colombier } 15180ee5cbfSDavid du Colombier image = namedimage(d, buf); 1527dd7cddfSDavid du Colombier if(image == 0){ 1539a747e4fSDavid du Colombier fprint(2, "namedimage %s failed: %r\n", buf); 15480ee5cbfSDavid du Colombier *winp = nil; 1559a747e4fSDavid du Colombier d->screenimage = nil; 1567dd7cddfSDavid du Colombier return -1; 1577dd7cddfSDavid du Colombier } 1587dd7cddfSDavid du Colombier assert(image->chan != 0); 1599a747e4fSDavid du Colombier } 1607dd7cddfSDavid du Colombier 1619a747e4fSDavid du Colombier d->screenimage = image; 16280ee5cbfSDavid du Colombier *scrp = allocscreen(image, d->white, 0); 16380ee5cbfSDavid du Colombier if(*scrp == nil){ 1649a747e4fSDavid du Colombier freeimage(d->screenimage); 16580ee5cbfSDavid du Colombier *winp = nil; 1669a747e4fSDavid du Colombier d->screenimage = nil; 1677dd7cddfSDavid du Colombier return -1; 1687dd7cddfSDavid du Colombier } 1697dd7cddfSDavid du Colombier 1709a747e4fSDavid du Colombier r = image->r; 1719a747e4fSDavid du Colombier if(strncmp(buf, "noborder", 8) != 0) 1729a747e4fSDavid du Colombier r = insetrect(image->r, Borderwidth); 1739a747e4fSDavid du Colombier *winp = _allocwindow(*winp, *scrp, r, ref, DWhite); 1749a747e4fSDavid du Colombier if(*winp == nil){ 1759a747e4fSDavid du Colombier freescreen(*scrp); 1769a747e4fSDavid du Colombier *scrp = nil; 1779a747e4fSDavid du Colombier freeimage(image); 1789a747e4fSDavid du Colombier d->screenimage = nil; 1797dd7cddfSDavid du Colombier return -1; 1809a747e4fSDavid du Colombier } 1819a747e4fSDavid du Colombier d->screenimage = *winp; 18280ee5cbfSDavid du Colombier assert((*winp)->chan != 0); 1837dd7cddfSDavid du Colombier return 1; 1847dd7cddfSDavid du Colombier } 1857dd7cddfSDavid du Colombier 18680ee5cbfSDavid du Colombier int 18780ee5cbfSDavid du Colombier getwindow(Display *d, int ref) 18880ee5cbfSDavid du Colombier { 18980ee5cbfSDavid du Colombier char winname[128]; 19080ee5cbfSDavid du Colombier 19180ee5cbfSDavid du Colombier snprint(winname, sizeof winname, "%s/winname", d->windir); 19280ee5cbfSDavid du Colombier return gengetwindow(d, winname, &screen, &_screen, ref); 19380ee5cbfSDavid du Colombier } 19480ee5cbfSDavid du Colombier 1957dd7cddfSDavid du Colombier #define NINFO 12*12 1967dd7cddfSDavid du Colombier 1977dd7cddfSDavid du Colombier Display* 1987dd7cddfSDavid du Colombier initdisplay(char *dev, char *win, void(*error)(Display*, char*)) 1997dd7cddfSDavid du Colombier { 2009a747e4fSDavid du Colombier char buf[128], info[NINFO+1], *t, isnew; 2019a747e4fSDavid du Colombier int n, datafd, ctlfd, reffd; 2027dd7cddfSDavid du Colombier Display *disp; 2039a747e4fSDavid du Colombier Dir *dir; 2047dd7cddfSDavid du Colombier Image *image; 2057dd7cddfSDavid du Colombier 2069a747e4fSDavid du Colombier fmtinstall('P', Pfmt); 2079a747e4fSDavid du Colombier fmtinstall('R', Rfmt); 2087dd7cddfSDavid du Colombier if(dev == 0) 2097dd7cddfSDavid du Colombier dev = "/dev"; 2107dd7cddfSDavid du Colombier if(win == 0) 2117dd7cddfSDavid du Colombier win = "/dev"; 2127dd7cddfSDavid du Colombier if(strlen(dev)>sizeof buf-25 || strlen(win)>sizeof buf-25){ 2137dd7cddfSDavid du Colombier werrstr("initdisplay: directory name too long"); 2147dd7cddfSDavid du Colombier return nil; 2157dd7cddfSDavid du Colombier } 2167dd7cddfSDavid du Colombier t = strdup(win); 2177dd7cddfSDavid du Colombier if(t == nil) 2187dd7cddfSDavid du Colombier return nil; 2197dd7cddfSDavid du Colombier 2207dd7cddfSDavid du Colombier sprint(buf, "%s/draw/new", dev); 2217dd7cddfSDavid du Colombier ctlfd = open(buf, ORDWR|OCEXEC); 2227dd7cddfSDavid du Colombier if(ctlfd < 0){ 2237dd7cddfSDavid du Colombier if(bind("#i", dev, MAFTER) < 0){ 2247dd7cddfSDavid du Colombier Error1: 2257dd7cddfSDavid du Colombier free(t); 2267dd7cddfSDavid du Colombier werrstr("initdisplay: %s: %r", buf); 2277dd7cddfSDavid du Colombier return 0; 2287dd7cddfSDavid du Colombier } 2297dd7cddfSDavid du Colombier ctlfd = open(buf, ORDWR|OCEXEC); 2307dd7cddfSDavid du Colombier } 2317dd7cddfSDavid du Colombier if(ctlfd < 0) 2327dd7cddfSDavid du Colombier goto Error1; 2339a747e4fSDavid du Colombier if((n=read(ctlfd, info, sizeof info)) < 12){ 2347dd7cddfSDavid du Colombier Error2: 2357dd7cddfSDavid du Colombier close(ctlfd); 2367dd7cddfSDavid du Colombier goto Error1; 2377dd7cddfSDavid du Colombier } 2389a747e4fSDavid du Colombier if(n==NINFO+1) 2399a747e4fSDavid du Colombier n = NINFO; 2409a747e4fSDavid du Colombier buf[n] = '\0'; 2419a747e4fSDavid du Colombier isnew = 0; 2429a747e4fSDavid du Colombier if(n < NINFO) /* this will do for now, we need something better here */ 2439a747e4fSDavid du Colombier isnew = 1; 2447dd7cddfSDavid du Colombier sprint(buf, "%s/draw/%d/data", dev, atoi(info+0*12)); 2457dd7cddfSDavid du Colombier datafd = open(buf, ORDWR|OCEXEC); 2467dd7cddfSDavid du Colombier if(datafd < 0) 2477dd7cddfSDavid du Colombier goto Error2; 2487dd7cddfSDavid du Colombier sprint(buf, "%s/draw/%d/refresh", dev, atoi(info+0*12)); 2497dd7cddfSDavid du Colombier reffd = open(buf, OREAD|OCEXEC); 2507dd7cddfSDavid du Colombier if(reffd < 0){ 2517dd7cddfSDavid du Colombier Error3: 2527dd7cddfSDavid du Colombier close(datafd); 2537dd7cddfSDavid du Colombier goto Error2; 2547dd7cddfSDavid du Colombier } 2559a747e4fSDavid du Colombier disp = mallocz(sizeof(Display), 1); 2567dd7cddfSDavid du Colombier if(disp == 0){ 2577dd7cddfSDavid du Colombier Error4: 2587dd7cddfSDavid du Colombier close(reffd); 2597dd7cddfSDavid du Colombier goto Error3; 2607dd7cddfSDavid du Colombier } 2619a747e4fSDavid du Colombier image = nil; 2629a747e4fSDavid du Colombier if(0){ 2637dd7cddfSDavid du Colombier Error5: 2649a747e4fSDavid du Colombier free(image); 2657dd7cddfSDavid du Colombier free(disp); 2667dd7cddfSDavid du Colombier goto Error4; 2677dd7cddfSDavid du Colombier } 2689a747e4fSDavid du Colombier if(n >= NINFO){ 2699a747e4fSDavid du Colombier image = mallocz(sizeof(Image), 1); 2709a747e4fSDavid du Colombier if(image == nil) 2719a747e4fSDavid du Colombier goto Error5; 2727dd7cddfSDavid du Colombier image->display = disp; 2737dd7cddfSDavid du Colombier image->id = 0; 2749a747e4fSDavid du Colombier image->chan = strtochan(info+2*12); 2759a747e4fSDavid du Colombier image->depth = chantodepth(image->chan); 2767dd7cddfSDavid du Colombier image->repl = atoi(info+3*12); 2777dd7cddfSDavid du Colombier image->r.min.x = atoi(info+4*12); 2787dd7cddfSDavid du Colombier image->r.min.y = atoi(info+5*12); 2797dd7cddfSDavid du Colombier image->r.max.x = atoi(info+6*12); 2807dd7cddfSDavid du Colombier image->r.max.y = atoi(info+7*12); 2817dd7cddfSDavid du Colombier image->clipr.min.x = atoi(info+8*12); 2827dd7cddfSDavid du Colombier image->clipr.min.y = atoi(info+9*12); 2837dd7cddfSDavid du Colombier image->clipr.max.x = atoi(info+10*12); 2847dd7cddfSDavid du Colombier image->clipr.max.y = atoi(info+11*12); 2859a747e4fSDavid du Colombier } 2869a747e4fSDavid du Colombier 2879a747e4fSDavid du Colombier disp->_isnewdisplay = isnew; 2889a747e4fSDavid du Colombier disp->bufsize = iounit(datafd); 2899a747e4fSDavid du Colombier if(disp->bufsize <= 0) 2909a747e4fSDavid du Colombier disp->bufsize = 8000; 2919a747e4fSDavid du Colombier if(disp->bufsize < 512){ 2929a747e4fSDavid du Colombier werrstr("iounit %d too small", disp->bufsize); 2939a747e4fSDavid du Colombier goto Error5; 2949a747e4fSDavid du Colombier } 2959a747e4fSDavid du Colombier disp->buf = malloc(disp->bufsize+5); /* +5 for flush message */ 2969a747e4fSDavid du Colombier if(disp->buf == nil) 2979a747e4fSDavid du Colombier goto Error5; 2989a747e4fSDavid du Colombier 2999a747e4fSDavid du Colombier disp->image = image; 3007dd7cddfSDavid du Colombier disp->dirno = atoi(info+0*12); 3017dd7cddfSDavid du Colombier disp->fd = datafd; 3027dd7cddfSDavid du Colombier disp->ctlfd = ctlfd; 3037dd7cddfSDavid du Colombier disp->reffd = reffd; 3047dd7cddfSDavid du Colombier disp->bufp = disp->buf; 3057dd7cddfSDavid du Colombier disp->error = error; 3067dd7cddfSDavid du Colombier disp->windir = t; 3077dd7cddfSDavid du Colombier disp->devdir = strdup(dev); 3087dd7cddfSDavid du Colombier qlock(&disp->qlock); 3097dd7cddfSDavid du Colombier disp->white = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DWhite); 3107dd7cddfSDavid du Colombier disp->black = allocimage(disp, Rect(0, 0, 1, 1), GREY1, 1, DBlack); 3117dd7cddfSDavid du Colombier if(disp->white == nil || disp->black == nil){ 3127dd7cddfSDavid du Colombier free(disp->devdir); 3137dd7cddfSDavid du Colombier free(disp->white); 3147dd7cddfSDavid du Colombier free(disp->black); 3157dd7cddfSDavid du Colombier goto Error5; 3167dd7cddfSDavid du Colombier } 3177dd7cddfSDavid du Colombier disp->opaque = disp->white; 3187dd7cddfSDavid du Colombier disp->transparent = disp->black; 3199a747e4fSDavid du Colombier dir = dirfstat(ctlfd); 3209a747e4fSDavid du Colombier if(dir!=nil && dir->type=='i'){ 3217dd7cddfSDavid du Colombier disp->local = 1; 3229a747e4fSDavid du Colombier disp->dataqid = dir->qid.path; 3237dd7cddfSDavid du Colombier } 3249a747e4fSDavid du Colombier if(dir!=nil && dir->qid.vers==1) /* other way to tell */ 3259a747e4fSDavid du Colombier disp->_isnewdisplay = 1; 3269a747e4fSDavid du Colombier free(dir); 3277dd7cddfSDavid du Colombier 3287dd7cddfSDavid du Colombier return disp; 3297dd7cddfSDavid du Colombier } 3307dd7cddfSDavid du Colombier 3317dd7cddfSDavid du Colombier /* 3327dd7cddfSDavid du Colombier * Call with d unlocked. 3337dd7cddfSDavid du Colombier * Note that disp->defaultfont and defaultsubfont are not freed here. 3347dd7cddfSDavid du Colombier */ 3357dd7cddfSDavid du Colombier void 3367dd7cddfSDavid du Colombier closedisplay(Display *disp) 3377dd7cddfSDavid du Colombier { 3387dd7cddfSDavid du Colombier int fd; 3397dd7cddfSDavid du Colombier char buf[128]; 3407dd7cddfSDavid du Colombier 3417dd7cddfSDavid du Colombier if(disp == nil) 3427dd7cddfSDavid du Colombier return; 3437dd7cddfSDavid du Colombier if(disp == display) 3447dd7cddfSDavid du Colombier display = nil; 3457dd7cddfSDavid du Colombier if(disp->oldlabel[0]){ 3467dd7cddfSDavid du Colombier snprint(buf, sizeof buf, "%s/label", disp->windir); 3477dd7cddfSDavid du Colombier fd = open(buf, OWRITE); 3487dd7cddfSDavid du Colombier if(fd >= 0){ 3497dd7cddfSDavid du Colombier write(fd, disp->oldlabel, strlen(disp->oldlabel)); 3507dd7cddfSDavid du Colombier close(fd); 3517dd7cddfSDavid du Colombier } 3527dd7cddfSDavid du Colombier } 3537dd7cddfSDavid du Colombier 3547dd7cddfSDavid du Colombier free(disp->devdir); 3557dd7cddfSDavid du Colombier free(disp->windir); 3567dd7cddfSDavid du Colombier freeimage(disp->white); 3577dd7cddfSDavid du Colombier freeimage(disp->black); 3587dd7cddfSDavid du Colombier close(disp->fd); 3597dd7cddfSDavid du Colombier close(disp->ctlfd); 3607dd7cddfSDavid du Colombier /* should cause refresh slave to shut down */ 3617dd7cddfSDavid du Colombier close(disp->reffd); 3627dd7cddfSDavid du Colombier qunlock(&disp->qlock); 3637dd7cddfSDavid du Colombier free(disp); 3647dd7cddfSDavid du Colombier } 3657dd7cddfSDavid du Colombier 3667dd7cddfSDavid du Colombier void 3677dd7cddfSDavid du Colombier lockdisplay(Display *disp) 3687dd7cddfSDavid du Colombier { 3697dd7cddfSDavid du Colombier if(debuglockdisplay){ 3707dd7cddfSDavid du Colombier /* avoid busy looping; it's rare we collide anyway */ 3717dd7cddfSDavid du Colombier while(!canqlock(&disp->qlock)){ 3729a747e4fSDavid du Colombier fprint(1, "proc %d waiting for display lock...\n", getpid()); 3737dd7cddfSDavid du Colombier sleep(1000); 3747dd7cddfSDavid du Colombier } 3757dd7cddfSDavid du Colombier }else 3767dd7cddfSDavid du Colombier qlock(&disp->qlock); 3777dd7cddfSDavid du Colombier } 3787dd7cddfSDavid du Colombier 3797dd7cddfSDavid du Colombier void 3807dd7cddfSDavid du Colombier unlockdisplay(Display *disp) 3817dd7cddfSDavid du Colombier { 3827dd7cddfSDavid du Colombier qunlock(&disp->qlock); 3837dd7cddfSDavid du Colombier } 3847dd7cddfSDavid du Colombier 3857dd7cddfSDavid du Colombier void 3867dd7cddfSDavid du Colombier drawerror(Display *d, char *s) 3877dd7cddfSDavid du Colombier { 3889a747e4fSDavid du Colombier char err[ERRMAX]; 3897dd7cddfSDavid du Colombier 3907dd7cddfSDavid du Colombier if(d->error) 3917dd7cddfSDavid du Colombier d->error(d, s); 3927dd7cddfSDavid du Colombier else{ 3939a747e4fSDavid du Colombier errstr(err, sizeof err); 3949a747e4fSDavid du Colombier fprint(2, "draw: %s: %s\n", s, err); 3957dd7cddfSDavid du Colombier exits(s); 3967dd7cddfSDavid du Colombier } 3977dd7cddfSDavid du Colombier } 3987dd7cddfSDavid du Colombier 3997dd7cddfSDavid du Colombier static 4007dd7cddfSDavid du Colombier int 4017dd7cddfSDavid du Colombier doflush(Display *d) 4027dd7cddfSDavid du Colombier { 403*711d1557SDavid du Colombier int n, nn; 4047dd7cddfSDavid du Colombier 4057dd7cddfSDavid du Colombier n = d->bufp-d->buf; 4067dd7cddfSDavid du Colombier if(n <= 0) 4077dd7cddfSDavid du Colombier return 1; 4087dd7cddfSDavid du Colombier 409*711d1557SDavid du Colombier if((nn=write(d->fd, d->buf, n)) != n){ 41059cc4ca5SDavid du Colombier if(_drawdebug) 411*711d1557SDavid du Colombier fprint(2, "flushimage fail: d=%p: n=%d nn=%d %r\n", d, n, nn); /**/ 4127dd7cddfSDavid du Colombier d->bufp = d->buf; /* might as well; chance of continuing */ 4137dd7cddfSDavid du Colombier return -1; 4147dd7cddfSDavid du Colombier } 4157dd7cddfSDavid du Colombier d->bufp = d->buf; 4167dd7cddfSDavid du Colombier return 1; 4177dd7cddfSDavid du Colombier } 4187dd7cddfSDavid du Colombier 4197dd7cddfSDavid du Colombier int 4207dd7cddfSDavid du Colombier flushimage(Display *d, int visible) 4217dd7cddfSDavid du Colombier { 4229a747e4fSDavid du Colombier if(visible){ 4239a747e4fSDavid du Colombier *d->bufp++ = 'v'; /* five bytes always reserved for this */ 4249a747e4fSDavid du Colombier if(d->_isnewdisplay){ 4259a747e4fSDavid du Colombier BPLONG(d->bufp, d->screenimage->id); 4269a747e4fSDavid du Colombier d->bufp += 4; 4279a747e4fSDavid du Colombier } 4289a747e4fSDavid du Colombier } 4297dd7cddfSDavid du Colombier return doflush(d); 4307dd7cddfSDavid du Colombier } 4317dd7cddfSDavid du Colombier 4327dd7cddfSDavid du Colombier uchar* 4337dd7cddfSDavid du Colombier bufimage(Display *d, int n) 4347dd7cddfSDavid du Colombier { 4357dd7cddfSDavid du Colombier uchar *p; 4367dd7cddfSDavid du Colombier 4379a747e4fSDavid du Colombier if(n<0 || n>d->bufsize){ 4387dd7cddfSDavid du Colombier werrstr("bad count in bufimage"); 4397dd7cddfSDavid du Colombier return 0; 4407dd7cddfSDavid du Colombier } 4419a747e4fSDavid du Colombier if(d->bufp+n > d->buf+d->bufsize) 4427dd7cddfSDavid du Colombier if(doflush(d) < 0) 4437dd7cddfSDavid du Colombier return 0; 4447dd7cddfSDavid du Colombier p = d->bufp; 4457dd7cddfSDavid du Colombier d->bufp += n; 4467dd7cddfSDavid du Colombier return p; 4477dd7cddfSDavid du Colombier } 4487dd7cddfSDavid du Colombier 449