Subfont* _getsubfont(Display *d, char *name) { int fd; Subfont *f; fd = libopen(name, OREAD); if(fd < 0){ _drawprint(2, "getsubfont: can't open %s: %r\n", name); return 0; } /* * unlock display so i/o happens with display released, unless * user is doing his own locking, in which case this could break things. * _getsubfont is called only from string.c and stringwidth.c, * which are known to be safe to have this done. */ if(d->local == 0) unlockdisplay(d); f = readsubfont(d, name, fd, d->local == 0); if(d->local == 0) lockdisplay(d); if(f == 0) _drawprint(2, "getsubfont: can't read %s: %r\n", name); libclose(fd); return f; }
int tkcvstextsrch(TkCitem *i, int x, int y) { TkCtext *t; Font *font; Display *d; char *p, *next; int n, len, locked; t = TKobj(TkCtext, i); n = 0; font = i->env->font; d = i->env->top->display; p = t->text; if(p == nil) return 0; while(*p) { next = tkcvstextgetl(t, font, p, &len); if(y <= font->height) { locked = lockdisplay(d); for(n = 0; n < len && x > stringnwidth(font, p, n+1); n++) ; if(locked) unlockdisplay(d); break; } y -= font->height; p = next; } return p - t->text + n; }
void tkfreelabel(Tk *tk) { Image *i; int locked; Display *d; TkLabel *tkl; tkl = TKobj(TkLabel, tk); if(tkl->text != nil) free(tkl->text); if(tkl->command != nil) free(tkl->command); if(tkl->value != nil) free(tkl->value); if(tkl->variable != nil) { tkfreevar(tk->env->top, tkl->variable, tk->flag & Tkswept); free(tkl->variable); } if(tkl->img != nil) tkimgput(tkl->img); i = tkl->bitmap; if(i != nil) { d = i->display; locked = lockdisplay(d); freeimage(i); if(locked) unlockdisplay(d); } if(tkl->menu != nil) free(tkl->menu); }
static char* tkentryicursor(Tk *tk, char *arg, char **val) { TkEntry *tke = TKobj(TkEntry, tk); int index, locked; char *r, *buf; USED(val); buf = mallocz(Tkmaxitem, 0); if(buf == nil) return TkNomem; tkword(tk->env->top, arg, buf, buf+Tkmaxitem, nil); r = tkentryparseindex(tk, buf, &index); free(buf); if(r != nil) return r; tke->icursor = index; locked = lockdisplay(tk->env->top->display); tke->xicursor = entrytextwidth(tk, tke->icursor); if (locked) unlockdisplay(tk->env->top->display); blinkreset(tk); tk->dirty = tkrect(tk, 1); return nil; }
/* * return bounding box of character at index, in coords relative to * the top left position of the text. */ static Rectangle tkentrybbox(Tk *tk, int index) { TkEntry *tke; TkEnv *env; Display *d; int x, cw, locked; Rectangle r; tke = TKobj(TkEntry, tk); env = tk->env; d = env->top->display; locked = lockdisplay(d); x = entrytextwidth(tk, index); if (index < tke->textlen) cw = entrytextwidth(tk, index+1) - x; else cw = Inswidth; if(locked) unlockdisplay(d); r.min.x = x; r.min.y = 0; r.max.x = x + cw; r.max.y = env->font->height; return r; }
static char* tkentryb1p(Tk *tk, char* arg, char **ret) { TkEntry *tke = TKobj(TkEntry, tk); Point p; int i, locked, x; char buf[32], *e; USED(ret); x = atoi(arg); p = tkscrn2local(tk, Pt(x, 0)); sprint(buf, "@%d", p.x); e = tkentryparseindex(tk, buf, &i); if (e != nil) return e; tke->sel0 = 0; tke->sel1 = 0; tke->icursor = i; tke->anchor = i; tke->flag &= ~Ewordsel; locked = lockdisplay(tk->env->top->display); tke->xsel0 = 0; tke->xsel1 = 0; tke->xicursor = entrytextwidth(tk, tke->icursor); if (locked) unlockdisplay(tk->env->top->display); tke->oldx = x; blinkreset(tk); tkrepeat(tk, autoselect, nil, TkRptpause, TkRptinterval); tk->dirty = tkrect(tk, 0); return nil; }
char* tkupdate(TkTop *t) { Tk* tk; int locked; TkWin *tkw; Display *d; char *e; int dirty = 0; if(t->noupdate) return nil; d = t->display; locked = lockdisplay(d); tk = t->windows; while(tk) { tkw = TKobj(TkWin, tk); if((tk->flag & (Tkmapped|Tksuspended)) == Tkmapped) { if (tkupdatewinsize(tk) == 0){ e = tkdrawslaves(tk, ZP, &dirty); if(e != nil) return e; } } tk = tkw->next; } if (dirty || t->dirty) { flushimage(d, 1); t->dirty = 0; } if(locked) unlockdisplay(d); return nil; }
static void tkmkstipple(Image *stipple) { int locked; if (stipple != nil && !stipple->repl) { locked = lockdisplay(stipple->display); replclipr(stipple, 1, huger); if (locked) unlockdisplay(stipple->display); } }
void timeproc(void *dummy) { for(;;){ lockdisplay(display); drawtime(); updatetimes(); flushimage(display, 1); unlockdisplay(display); sleep(60000); setdate(); } }
void resizethread(void *v) { USED(v); while(recv(mc->resizec, 0) == 1){ lockdisplay(display); if(getwindow(display, Refnone) < 0) sysfatal("attach to window: %r"); resize(); unlockdisplay(display); } }
void timeproc(void) { for(;;){ lockdisplay(display); drawtime(); updatetimes(); flushimage(display, 1); unlockdisplay(display); now = time(nil); sleep(((60 - now%60) + 1)*1000); /* wait for minute to change */ setdate(); } }
void tkfreecanv(Tk *tk) { Display *d; int j, locked; TkCanvas *c; TkName *n, *nn; TkCtag *t, *tt; TkCitem *i, *next; c = TKobj(TkCanvas, tk); for(i = c->head; i; i = next) { next = i->next; tkcvsfreeitem(i); } if(c->xscroll != nil) free(c->xscroll); if(c->yscroll != nil) free(c->yscroll); for(j = 0; j < TkChash; j++) { for(n = c->thash[j]; n; n = nn) { nn = n->link; for(t = n->obj; t; t = tt) { tt = t->taglist; free(t); } tkfreebind(n->prop.binds); free(n); } } free(c->current); if((c->ialloc && c->image != nil) || c->mask != nil) { if (c->ialloc && c->image != nil) d = c->image->display; else d = c->mask->display; locked = lockdisplay(d); if (c->image != nil && c->ialloc) freeimage(c->image); if (c->mask != nil) freeimage(c->mask); if(locked) unlockdisplay(d); } }
void tkcvsfreeitem(TkCitem *i) { int locked; Display *d; d = i->env->top->display; locked = lockdisplay(d); tkcimethod[i->type].free(i); if(locked) unlockdisplay(d); tkfreepoint(&i->p); tkputenv(i->env); free(i); }
void addface(Face *f) /* always adds at 0 */ { Face **ofaces; Rectangle r0, r1, r; int y, nx, ny; if(f == nil) return; if(first != 0){ first = 0; eresized(0); } findbit(f); nx = nacross; ny = (nfaces+(nx-1)) / nx; lockdisplay(display); for(y=ny; y>=0; y--){ /* move them along */ r0 = facerect(y*nx+0); r1 = facerect(y*nx+1); r = r1; r.max.x = r.min.x + (nx - 1)*(Facesize+Facesep); draw(screen, r, screen, nil, r0.min); /* copy one down from row above */ if(y != 0){ r = facerect((y-1)*nx+nx-1); draw(screen, r0, screen, nil, r.min); } } ofaces = faces; faces = emalloc((nfaces+1)*sizeof(Face*)); memmove(faces+1, ofaces, nfaces*(sizeof(Face*))); free(ofaces); nfaces++; setlast(); drawarrows(); faces[0] = f; drawface(f, 0); flushimage(display, 1); unlockdisplay(display); }
Image* cachedpage(Document *doc, int angle, int page) { static int lastpage = -1; static int rabusy; Image *im; int ra; if(doc->npage < 1) return display->white; im = _cachedpage(doc, angle, page, ""); if(im == nil) return nil; /* readahead */ ra = -1; if(!rabusy){ if(page == lastpage+1) ra = page+1; else if(page == lastpage-1) ra = page-1; } lastpage = page; if(ra >= 0){ rabusy = 1; switch(rfork(RFPROC|RFMEM|RFNOWAIT)){ case -1: rabusy = 0; break; case 0: lockdisplay(display); _cachedpage(doc, angle, ra, "-ra"); rabusy = 0; unlockdisplay(display); _exits(nil); default: break; } } return im; }
void tkcvstextsize(TkCitem *i) { Point o; Font *font; TkCtext *t; Display *d; char *next, *p; int len, pixw, locked; t = TKobj(TkCtext, i); font = i->env->font; d = i->env->top->display; t->pixwidth = 0; t->pixheight = 0; p = t->text; if(p != nil) { locked = lockdisplay(d); while(*p) { next = tkcvstextgetl(t, font, p, &len); pixw = stringnwidth(font, p, len); if(pixw > t->pixwidth) t->pixwidth = pixw; t->pixheight += font->height; p = next; } if(locked) unlockdisplay(d); } o = tkcvsanchor(i->p.drawpt[0], t->pixwidth, t->pixheight, t->anchor); i->p.bb.min.x = o.x; i->p.bb.min.y = o.y - Cvsicursor; i->p.bb.max.x = o.x + t->pixwidth; i->p.bb.max.y = o.y + t->pixheight + Cvsicursor; i->p.bb = insetrect(i->p.bb, -2*t->sbw); t->anchorp = subpt(o, i->p.drawpt[0]); }
void tkfreectxt(TkCtxt *c) { int locked; Display *d; if(c == nil) return; tkextnfreectxt(c); d = c->display; locked = lockdisplay(d); tkfreecolcache(c); freeimage(c->i); freeimage(c->ia); if(locked) unlockdisplay(d); libqlfree(c->lock); free(c); }
void updateproc(void *v) { char *p, *f[2]; sleep(1000); while((p = Brdline(&b, '\n'))){ p[Blinelen(&b)-1] = '\0'; if(tokenize(p, f, 2) != 2) continue; n = strtoll(f[0], 0, 0); d = strtoll(f[1], 0, 0); if(!textmode){ lockdisplay(display); drawbar(); unlockdisplay(display); } else drawbar(); } threadexitsall("success"); }
/* * recalculate derived values */ static void recalcentry(Tk *tk) { TkEntry *tke = TKobj(TkEntry, tk); int x, avail, locked; locked = lockdisplay(tk->env->top->display); tke->xlen = entrytextwidth(tk, tke->textlen) + Inswidth; avail = tk->act.width - 2*xinset(tk); if (tke->xlen < avail) { switch(tke->flag & Ejustify) { default: tke->x0 = 0; break; case Eright: tke->x0 = -(avail - tke->xlen); break; case Ecenter: tke->x0 = -(avail - tke->xlen) / 2; break; } } tke->v0 = x2index(tk, tke->x0, &tke->xv0); tke->v1 = x2index(tk, tk->act.width + tke->x0, &x); /* perhaps include partial last character */ if (tke->v1 < tke->textlen && x < avail + tke->x0) tke->v1++; tke->xsel0 = entrytextwidth(tk, tke->sel0); tke->xsel1 = entrytextwidth(tk, tke->sel1); tke->xicursor = entrytextwidth(tk, tke->icursor); if (locked) unlockdisplay(tk->env->top->display); }
static void resize(Vnc *v, int first) { int fd; Point d; d = addpt(v->dim, Pt(2*Borderwidth, 2*Borderwidth)); lockdisplay(display); if(getwindow(display, Refnone) < 0) sysfatal("internal error: can't get the window image"); /* * limit the window to at most the vnc server's size */ if(first || d.x < Dx(screen->r) || d.y < Dy(screen->r)) { fd = open("/dev/wctl", OWRITE); if(fd >= 0) { fprint(fd, "resize -dx %d -dy %d", d.x, d.y); close(fd); } } unlockdisplay(display); }
int tktdispwidth(Tk *tk, TkTtabstop *tb, TkTitem *i, Font *f, int x, int pos, int nchars) { int w, del, locked; TkTtabstop *tbprev; Display *d; TkText *tkt; TkEnv env; tkt = TKobj(TkText, tk); d = tk->env->top->display; if (tb == nil) tb = tkt->tabs; switch(i->kind) { case TkTrune: pos = tktutfpos(i->istring, pos); /* FALLTHRU */ case TkTascii: if(f == nil) { if(!tktanytags(i)) f = tk->env->font; else { tkttagopts(tk, i, nil, &env, nil, 1); f = env.font; } } locked = 0; if(!(tkt->tflag&TkTdlocked)) locked = lockdisplay(d); if(nchars >= 0) w = stringnwidth(f, i->istring+pos, nchars); else w = stringwidth(f, i->istring+pos); if(locked) unlockdisplay(d); break; case TkTtab: if(tb == nil) w = 0; else { tbprev = nil; while(tb->pos <= x && tb->next != nil) { tbprev = tb; tb = tb->next; } w = tb->pos - x; if(w <= 0) { del = tb->pos; if(tbprev != nil) del -= tbprev->pos; while(w <= 0) w += del; } /* todo: other kinds of justification */ } break; case TkTwin: if(i->iwin->sub == 0) w = 0; else w = i->iwin->sub->act.width + 2*i->iwin->padx + 2*i->iwin->sub->borderwidth; break; default: w = 0; } return w; }
static char* tkentryparseindex(Tk *tk, char *buf, int *index) { TkEntry *tke = TKobj(TkEntry, tk); TkEnv *env; char *mod; int i, x, locked, modstart; modstart = 0; for(mod = buf; *mod != '\0'; mod++) if(*mod == '-' || *mod == '+') { modstart = *mod; *mod = '\0'; break; } if(strcmp(buf, "end") == 0) i = tke->textlen; else if(strcmp(buf, "anchor") == 0) i = tke->anchor; else if(strcmp(buf, "insert") == 0) i = tke->icursor; else if(strcmp(buf, "sel.first") == 0) i = tke->sel0; else if(strcmp(buf, "sel.last") == 0) i = tke->sel1; else if(buf[0] >= '0' && buf[0] <= '9') i = atoi(buf); else if(buf[0] == '@') { x = atoi(buf+1) - xinset(tk); if(tke->textlen == 0) { *index = 0; return nil; } env = tk->env; locked = lockdisplay(env->top->display); i = x2index(tk, x + tke->x0, nil); /* XXX could possibly select nearest character? */ if(locked) unlockdisplay(env->top->display); } else return TkBadix; if(i < 0 || i > tke->textlen) return TkBadix; if(modstart) { *mod = modstart; i += atoi(mod); if(i < 0) i = 0; if(i > tke->textlen) i = tke->textlen; } *index = i; return nil; }
static char* tkentryinsert(Tk *tk, char *arg, char **val) { TkTop *top; TkEntry *tke; int ins, i, n, locked; char *e, *t, *text, *buf; Rune *etext; USED(val); tke = TKobj(TkEntry, tk); top = tk->env->top; buf = mallocz(Tkmaxitem, 0); if(buf == nil) return TkNomem; arg = tkword(top, arg, buf, buf+Tkmaxitem, nil); e = tkentryparseindex(tk, buf, &ins); free(buf); if(e != nil) return e; if(*arg == '\0') return nil; n = strlen(arg) + 1; if(n < Tkmaxitem) n = Tkmaxitem; text = malloc(n); if(text == nil) return TkNomem; tkword(top, arg, text, text+n, nil); n = utflen(text); etext = realloc(tke->text, (tke->textlen+n+1)*sizeof(Rune)); if(etext == nil) { free(text); return TkNomem; } tke->text = etext; memmove(tke->text+ins+n, tke->text+ins, (tke->textlen-ins)*sizeof(Rune)); t = text; for(i=0; i<n; i++) t += chartorune(tke->text+ins+i, t); free(text); tke->textlen += n; tke->sel0 = adjustforins(ins, n, tke->sel0); tke->sel1 = adjustforins(ins, n, tke->sel1); tke->icursor = adjustforins(ins, n, tke->icursor); tke->anchor = adjustforins(ins, n, tke->anchor); locked = lockdisplay(tk->env->top->display); if (ins < tke->v0) tke->x0 += entrytextwidth(tk, tke->v0 + n) + (tke->x0 - tke->xv0); if (locked) unlockdisplay(tk->env->top->display); recalcentry(tk); e = tkentrysh(tk); blinkreset(tk); tk->dirty = tkrect(tk, 1); return e; }
static char* tkentrydelete(Tk *tk, char *arg, char **val) { TkTop *top; TkEntry *tke; int d0, d1, locked; char *e, *buf; Rune *text; USED(val); tke = TKobj(TkEntry, tk); top = tk->env->top; buf = mallocz(Tkmaxitem, 0); if(buf == nil) return TkNomem; arg = tkword(top, arg, buf, buf+Tkmaxitem, nil); e = tkentryparseindex(tk, buf, &d0); if(e != nil) { free(buf); return e; } d1 = d0+1; tkword(top, arg, buf, buf+Tkmaxitem, nil); if(buf[0] != '\0') { e = tkentryparseindex(tk, buf, &d1); if(e != nil) { free(buf); return e; } } free(buf); if(d1 <= d0 || tke->textlen == 0 || d0 >= tke->textlen) return nil; memmove(tke->text+d0, tke->text+d1, (tke->textlen-d1)*sizeof(Rune)); tke->textlen -= d1 - d0; text = realloc(tke->text, (tke->textlen+1) * sizeof(Rune)); if (text != nil) tke->text = text; tke->sel0 = adjustfordel(d0, d1, tke->sel0); tke->sel1 = adjustfordel(d0, d1, tke->sel1); tke->icursor = adjustfordel(d0, d1, tke->icursor); tke->anchor = adjustfordel(d0, d1, tke->anchor); locked = lockdisplay(tk->env->top->display); if (d1 < tke->v0) tke->x0 = entrytextwidth(tk, tke->v0 - (d1 - d0)) + (tke->x0 - tke->xv0); else if (d0 < tke->v0) tke->x0 = entrytextwidth(tk, d0); if (locked) unlockdisplay(tk->env->top->display); recalcentry(tk); e = tkentrysh(tk); blinkreset(tk); tk->dirty = tkrect(tk, 1); return e; }
char* tkentryselect(Tk *tk, char *arg, char **val) { TkTop *top; int start, from, to, locked; TkEntry *tke; char *e, *buf; buf = mallocz(Tkmaxitem, 0); if(buf == nil) return TkNomem; tke = TKobj(TkEntry, tk); top = tk->env->top; arg = tkword(top, arg, buf, buf+Tkmaxitem, nil); if(strcmp(buf, "clear") == 0) { tke->sel0 = 0; tke->sel1 = 0; } else if(strcmp(buf, "from") == 0) { tkword(top, arg, buf, buf+Tkmaxitem, nil); e = tkentryparseindex(tk, buf, &tke->anchor); tke->flag &= ~Ewordsel; free(buf); return e; } else if(strcmp(buf, "to") == 0) { tkword(top, arg, buf, buf+Tkmaxitem, nil); e = tkentryparseindex(tk, buf, &to); if(e != nil) { free(buf); return e; } if(to < tke->anchor) { if(tke->flag & Ewordsel) while(to > 0 && tkiswordchar(tke->text[to-1])) --to; tke->sel0 = to; tke->sel1 = tke->anchor; } else if(to >= tke->anchor) { if(tke->flag & Ewordsel) while(to < tke->textlen && tkiswordchar(tke->text[to])) to++; tke->sel0 = tke->anchor; tke->sel1 = to; } tkentrysee(tk, to, 0); recalcentry(tk); } else if(strcmp(buf, "word") == 0) { /* inferno invention */ tkword(top, arg, buf, buf+Tkmaxitem, nil); e = tkentryparseindex(tk, buf, &start); if(e != nil) { free(buf); return e; } from = start; while(from > 0 && tkiswordchar(tke->text[from-1])) --from; to = start; while(to < tke->textlen && tkiswordchar(tke->text[to])) to++; tke->sel0 = from; tke->sel1 = to; tke->anchor = from; tke->icursor = from; tke->flag |= Ewordsel; locked = lockdisplay(tk->env->top->display); tke->xicursor = entrytextwidth(tk, tke->icursor); if (locked) unlockdisplay(tk->env->top->display); } else if(strcmp(buf, "present") == 0) { e = tkvalue(val, "%d", tke->sel1 > tke->sel0); free(buf); return e; } else if(strcmp(buf, "range") == 0) { arg = tkword(top, arg, buf, buf+Tkmaxitem, nil); e = tkentryparseindex(tk, buf, &from); if(e != nil) { free(buf); return e; } tkword(top, arg, buf, buf+Tkmaxitem, nil); e = tkentryparseindex(tk, buf, &to); if(e != nil) { free(buf); return e; } tke->sel0 = from; tke->sel1 = to; if(to <= from) { tke->sel0 = 0; tke->sel1 = 0; } } else if(strcmp(buf, "adjust") == 0) { tkword(top, arg, buf, buf+Tkmaxitem, nil); e = tkentryparseindex(tk, buf, &to); if(e != nil) { free(buf); return e; } if(tke->sel0 == 0 && tke->sel1 == 0) { tke->sel0 = tke->anchor; tke->sel1 = to; } else { if(abs(tke->sel0-to) < abs(tke->sel1-to)) { tke->sel0 = to; tke->anchor = tke->sel1; } else { tke->sel1 = to; tke->anchor = tke->sel0; } } if(tke->sel0 > tke->sel1) { to = tke->sel0; tke->sel0 = tke->sel1; tke->sel1 = to; } } else { free(buf); return TkBadcm; } locked = lockdisplay(tk->env->top->display); tke->xsel0 = entrytextwidth(tk, tke->sel0); tke->xsel1 = entrytextwidth(tk, tke->sel1); if (locked) unlockdisplay(tk->env->top->display); tk->dirty = tkrect(tk, 1); free(buf); return nil; }
void viewer(Document *dd) { int i, fd, n, oldpage; int nxt; Menu menu, midmenu; Mouse m; Event e; Point dxy, oxy, xy0; Image *tmp; static char *fwditems[] = { "this page", "next page", "exit", 0 }; static char *miditems[] = { "orig size", "zoom in", "fit window", "rotate 90", "upside down", "", "next", "prev", "zerox", "", "reverse", "discard", "write", "", "quit", 0 }; char *s; enum { Eplumb = 4 }; Plumbmsg *pm; doc = dd; /* save global for menuhit */ ul = screen->r.min; einit(Emouse|Ekeyboard); if(doc->addpage != nil) eplumb(Eplumb, "image"); esetcursor(&reading); /* * im is a global pointer to the current image. * eventually, i think we will have a layer between * the display routines and the ps/pdf/whatever routines * to perhaps cache and handle images of different * sizes, etc. */ im = 0; page = reverse ? doc->npage-1 : 0; if(doc->fwdonly) { menu.item = fwditems; menu.gen = 0; menu.lasthit = 0; } else { menu.item = 0; menu.gen = menugen; menu.lasthit = 0; } midmenu.item = miditems; midmenu.gen = 0; midmenu.lasthit = Next; if(doc->docname != nil) setlabel(doc->docname); showpage(page, &menu); esetcursor(nil); nxt = 0; for(;;) { /* * throughout, if doc->fwdonly is set, we restrict the functionality * a fair amount. we don't care about doc->npage anymore, and * all that can be done is select the next page. */ unlockdisplay(display); i = eread(Emouse|Ekeyboard|Eplumb, &e); lockdisplay(display); switch(i){ case Ekeyboard: if(e.kbdc <= 0xFF && isdigit(e.kbdc)) { nxt = nxt*10+e.kbdc-'0'; break; } else if(e.kbdc != '\n') nxt = 0; switch(e.kbdc) { case 'r': /* reverse page order */ if(doc->fwdonly) break; reverse = !reverse; menu.lasthit = doc->npage-1-menu.lasthit; /* * the theory is that if we are reversing the * document order and are on the first or last * page then we're just starting and really want * to view the other end. maybe the if * should be dropped and this should happen always. */ if(page == 0 || page == doc->npage-1) { page = doc->npage-1-page; showpage(page, &menu); } break; case 'w': /* write bitmap of current screen */ esetcursor(&reading); s = writebitmap(); if(s) string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP, display->defaultfont, s); esetcursor(nil); flushimage(display, 1); break; case 'd': /* remove image from working set */ if(doc->rmpage && page < doc->npage) { if(doc->rmpage(doc, page) >= 0) { if(doc->npage < 0) wexits(0); if(page >= doc->npage) page = doc->npage-1; showpage(page, &menu); } } break; case 'q': case 0x04: /* ctrl-d */ wexits(0); case 'u': if(im==nil) break; angle = (angle+180) % 360; showpage(page, &menu); break; case '-': case '\b': case Kleft: if(page > 0 && !doc->fwdonly) { --page; showpage(page, &menu); } break; case '\n': if(nxt) { nxt--; if(nxt >= 0 && nxt < doc->npage && !doc->fwdonly) showpage(page=nxt, &menu); nxt = 0; break; } goto Gotonext; case Kright: case ' ': Gotonext: if(doc->npage && ++page >= doc->npage && !doc->fwdonly) wexits(0); showpage(page, &menu); break; /* * The upper y coordinate of the image is at ul.y in screen->r. * Panning up means moving the upper left corner down. If the * upper left corner is currently visible, we need to go back a page. */ case Kup: if(screen->r.min.y <= ul.y && ul.y < screen->r.max.y){ if(page > 0 && !doc->fwdonly){ --page; showbottom = 1; showpage(page, &menu); } } else { i = Dy(screen->r)/2; if(i > 10) i -= 10; if(i+ul.y > screen->r.min.y) i = screen->r.min.y - ul.y; translate(Pt(0, i)); } break; /* * If the lower y coordinate is on the screen, we go to the next page. * The lower y coordinate is at ul.y + Dy(im->r). */ case Kdown: i = ul.y + Dy(im->r); if(screen->r.min.y <= i && i <= screen->r.max.y){ ul.y = screen->r.min.y; goto Gotonext; } else { i = -Dy(screen->r)/2; if(i < -10) i += 10; if(i+ul.y+Dy(im->r) <= screen->r.max.y) i = screen->r.max.y - Dy(im->r) - ul.y - 1; translate(Pt(0, i)); } break; default: esetcursor(&query); sleep(1000); esetcursor(nil); break; } break; case Emouse: m = e.mouse; switch(m.buttons){ case Left: oxy = m.xy; xy0 = oxy; do { dxy = subpt(m.xy, oxy); oxy = m.xy; translate(dxy); unlockdisplay(display); m = emouse(); lockdisplay(display); } while(m.buttons == Left); if(m.buttons) { dxy = subpt(xy0, oxy); translate(dxy); } break; case Middle: if(doc->npage == 0) break; unlockdisplay(display); n = emenuhit(Middle, &m, &midmenu); lockdisplay(display); if(n == -1) break; switch(n){ case Next: /* next */ if(reverse) page--; else page++; if(page < 0) { if(reverse) return; else page = 0; } if((page >= doc->npage) && !doc->fwdonly) return; showpage(page, &menu); nxt = 0; break; case Prev: /* prev */ if(reverse) page++; else page--; if(page < 0) { if(reverse) return; else page = 0; } if((page >= doc->npage) && !doc->fwdonly && !reverse) return; showpage(page, &menu); nxt = 0; break; case Zerox: /* prev */ zerox(); break; case Zin: /* zoom in */ { double delta; Rectangle r; r = egetrect(Middle, &m); if((rectclip(&r, rectaddpt(im->r, ul)) == 0) || Dx(r) == 0 || Dy(r) == 0) break; /* use the smaller side to expand */ if(Dx(r) < Dy(r)) delta = (double)Dx(im->r)/(double)Dx(r); else delta = (double)Dy(im->r)/(double)Dy(r); esetcursor(&reading); tmp = xallocimage(display, Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)), im->chan, 0, DBlack); if(tmp == nil) { fprint(2, "out of memory during zoom: %r\n"); wexits("memory"); } resample(im, tmp); im = tmp; delayfreeimage(tmp); esetcursor(nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); break; } case Fit: /* fit */ { double delta; Rectangle r; delta = (double)Dx(screen->r)/(double)Dx(im->r); if((double)Dy(im->r)*delta > Dy(screen->r)) delta = (double)Dy(screen->r)/(double)Dy(im->r); r = Rect(0, 0, (int)((double)Dx(im->r)*delta), (int)((double)Dy(im->r)*delta)); esetcursor(&reading); tmp = xallocimage(display, r, im->chan, 0, DBlack); if(tmp == nil) { fprint(2, "out of memory during fit: %r\n"); wexits("memory"); } resample(im, tmp); im = tmp; delayfreeimage(tmp); esetcursor(nil); ul = screen->r.min; redraw(screen); flushimage(display, 1); break; } case Rot: /* rotate 90 */ angle = (angle+90) % 360; showpage(page, &menu); break; case Upside: /* upside-down */ angle = (angle+180) % 360; showpage(page, &menu); break; case Restore: /* restore */ showpage(page, &menu); break; case Reverse: /* reverse */ if(doc->fwdonly) break; reverse = !reverse; menu.lasthit = doc->npage-1-menu.lasthit; if(page == 0 || page == doc->npage-1) { page = doc->npage-1-page; showpage(page, &menu); } break; case Write: /* write */ esetcursor(&reading); s = writebitmap(); if(s) string(screen, addpt(screen->r.min, Pt(5,5)), display->black, ZP, display->defaultfont, s); esetcursor(nil); flushimage(display, 1); break; case Del: /* delete */ if(doc->rmpage && page < doc->npage) { if(doc->rmpage(doc, page) >= 0) { if(doc->npage < 0) wexits(0); if(page >= doc->npage) page = doc->npage-1; showpage(page, &menu); } } break; case Exit: /* exit */ return; case Empty1: case Empty2: case Empty3: break; }; case Right: if(doc->npage == 0) break; oldpage = page; unlockdisplay(display); n = emenuhit(RMenu, &m, &menu); lockdisplay(display); if(n == -1) break; if(doc->fwdonly) { switch(n){ case 0: /* this page */ break; case 1: /* next page */ showpage(++page, &menu); break; case 2: /* exit */ return; } break; } if(n == doc->npage) return; else page = reverse ? doc->npage-1-n : n; if(oldpage != page) showpage(page, &menu); nxt = 0; break; } break; case Eplumb: pm = e.v; if(pm->ndata <= 0){ plumbfree(pm); break; } if(plumbquit(pm)) exits(nil); if(showdata(pm)) { s = estrdup("/tmp/pageplumbXXXXXXX"); fd = opentemp(s); write(fd, pm->data, pm->ndata); /* lose fd reference on purpose; the file is open ORCLOSE */ } else if(pm->data[0] == '/') { s = estrdup(pm->data); } else { s = emalloc(strlen(pm->wdir)+1+pm->ndata+1); sprint(s, "%s/%s", pm->wdir, pm->data); cleanname(s); } if((i = doc->addpage(doc, s)) >= 0) { page = i; unhide(); showpage(page, &menu); } free(s); plumbfree(pm); break; } } }
static char* tkentryxview(Tk *tk, char *arg, char **val) { int locked; TkEnv *env; TkEntry *tke; char *buf, *v; int dx, top, bot, amount, ix, x; char *e; tke = TKobj(TkEntry, tk); env = tk->env; dx = tk->act.width - 2*xinset(tk); buf = mallocz(Tkmaxitem, 0); if(buf == nil) return TkNomem; if(*arg == '\0') { if (tke->textlen == 0 || tke->xlen < dx) { bot = TKI2F(0); top = TKI2F(1); } else { bot = TKI2F(tke->x0) / tke->xlen; top = TKI2F(tke->x0 + dx) / tke->xlen; } v = tkfprint(buf, bot); *v++ = ' '; tkfprint(v, top); e = tkvalue(val, "%s", buf); free(buf); return e; } arg = tkitem(buf, arg); if(strcmp(buf, "moveto") == 0) { e = tkfracword(env->top, &arg, &top, nil); if (e != nil) { free(buf); return e; } tke->x0 = TKF2I(top*tke->xlen); } else if(strcmp(buf, "scroll") == 0) { arg = tkitem(buf, arg); amount = atoi(buf); if(*arg == 'p') /* Pages */ amount *= (9*tke->xlen)/10; else if(*arg == 's') { /* Inferno-ism, "scr", must be used in the context of button2p */ x = amount; amount = x < tke->oldx ? env->wzero : (x > tke->oldx ? -env->wzero : 0); tke->oldx = x; } tke->x0 += amount; } else { e = tkentryparseindex(tk, buf, &ix); if(e != nil) { free(buf); return e; } locked = lockdisplay(env->top->display); tke->x0 = entrytextwidth(tk, ix); if (locked) unlockdisplay(env->top->display); } free(buf); if (tke->x0 > tke->xlen - dx) tke->x0 = tke->xlen - dx; if (tke->x0 < 0) tke->x0 = 0; recalcentry(tk); e = tkentrysh(tk); blinkreset(tk); tk->dirty = tkrect(tk, 1); return e; }