static char* tkcvstextgetl(TkCtext *t, Font *font, char *start, int *len) { int w, n; char *lspc, *posn; w = t->width; if(w <= 0) w = 1000000; n = 0; lspc = nil; posn = start; while(*posn && *posn != '\n') { if(*posn == ' ') lspc = posn; n += stringnwidth(font, posn, 1); if(n >= w && posn != start) { if(lspc != nil) posn = lspc; *len = posn - start; if(lspc != nil) posn++; return posn; } posn++; } *len = posn - start; if(*posn == '\n') posn++; return posn; }
int _frcanfit(Frame *f, Point pt, Frbox *b) { int left, w, nr; uchar *p; Rune r; left = f->r.max.x-pt.x; if(b->nrune < 0) return b->minwid <= left; if(left >= b->wid) return b->nrune; for(nr=0,p=b->ptr; *p; p+=w,nr++){ r = *p; if(r < Runeself) w = 1; else w = chartorune(&r, (char*)p); left -= stringnwidth(f->font, (char*)p, 1); if(left < 0) return nr; } drawerror(f->display, "_frcanfit can't"); return 0; }
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; }
Point frdrawsel0(Frame *f, Point pt, ulong p0, ulong p1, Image *back, Image *text) { Frbox *b; int nb, nr, w, x, trim; Point qt; uint p; char *ptr; p = 0; b = f->box; trim = 0; for(nb=0; nb<f->nbox && p<p1; nb++){ nr = b->nrune; if(nr < 0) nr = 1; if(p+nr <= p0) goto Continue; if(p >= p0){ qt = pt; _frcklinewrap(f, &pt, b); /* fill in the end of a wrapped line */ if(pt.y > qt.y) draw(f->b, Rect(qt.x, qt.y, f->r.max.x, pt.y), back, nil, qt); } ptr = (char*)b->ptr; if(p < p0){ /* beginning of region: advance into box */ ptr += nbytes(ptr, p0-p); nr -= (p0-p); p = p0; } trim = 0; if(p+nr > p1){ /* end of region: trim box */ nr -= (p+nr)-p1; trim = 1; } if(b->nrune<0 || nr==b->nrune) w = b->wid; else w = stringnwidth(f->font, ptr, nr); x = pt.x+w; if(x > f->r.max.x) x = f->r.max.x; draw(f->b, Rect(pt.x, pt.y, x, pt.y+f->font->height), back, nil, pt); if(b->nrune >= 0) stringnbg(f->b, pt, text, ZP, f->font, ptr, nr, back, ZP); pt.x += w; Continue: b++; p += nr; } /* if this is end of last plain text box on wrapped line, fill to end of line */ if(p1>p0 && b>f->box && b<f->box+f->nbox && b[-1].nrune>0 && !trim){ qt = pt; _frcklinewrap(f, &pt, b); if(pt.y > qt.y) draw(f->b, Rect(qt.x, qt.y, f->r.max.x, pt.y), back, nil, qt); } return pt; }
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 tkcvstextdraw(Image *img, TkCitem *i, TkEnv *pe) { TkEnv *e; TkCtext *t; Point o, dp; Rectangle r; char *p, *next; Image *pen; int len, lw, end, start; t = TKobj(TkCtext, i); e = i->env; pen = t->pen; if(pen == nil) { if (e->set & (1<<TkCfill)) pen = tkgc(e, TkCfill); else pen = img->display->black; } o = addpt(t->anchorp, i->p.drawpt[0]); p = t->text; while(p && *p) { next = tkcvstextgetl(t, e->font, p, &len); dp = o; if(t->justify != Tkleft) { lw = stringnwidth(e->font, p, len); if(t->justify == Tkcenter) dp.x += (t->pixwidth - lw)/2; else if(t->justify == Tkright) dp.x += t->pixwidth - lw; } lw = p - t->text; if(t->self != -1 && lw+len > t->self) { if(t->sell >= t->self) { start = t->self - lw; end = t->sell - lw; } else { start = t->sell - lw; end = t->self - lw; } if(start < 0) r.min.x = o.x; else r.min.x = dp.x + stringnwidth(e->font, p, start); r.min.y = dp.y; if(end > len) r.max.x = o.x + t->pixwidth; else r.max.x = dp.x + stringnwidth(e->font, p, end); r.max.y = dp.y + e->font->height; tktextsdraw(img, r, pe, t->sbw); r.max.y = dp.y; if(start > 0) stringn(img, dp, pen, dp, e->font, p, start); if(end > start) stringn(img, r.min, tkgc(pe, TkCselectfgnd), r.min, e->font, p+start, end-start); if(len > end) stringn(img, r.max, pen, r.max, e->font, p+end, len-end); } else stringn(img, dp, pen, dp, e->font, p, len); if(t->focus) { lw = p - t->text; if(t->icursor >= lw && t->icursor <= lw+len) { lw = t->icursor - lw; if(lw > 0) lw = stringnwidth(e->font, p, lw); r.min.x = dp.x + lw; r.min.y = dp.y - 1; r.max.x = r.min.x + 2; r.max.y = r.min.y + e->font->height + 1; draw(img, r, pen, nil, ZP); } } o.y += e->font->height; p = next; } }
int eenter(char *ask, char *buf, int len, Mouse *m) { int done, down, tick, n, h, w, l, i; Image *b, *save, *backcol, *bordcol; Point p, o, t; Rectangle r, sc; Event ev; Rune k; o = screen->r.min; backcol = allocimagemix(display, DPurpleblue, DWhite); bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); if(backcol == nil || bordcol == nil) return -1; while(ecankbd()) ekbd(); if(m) o = m->xy; if(buf && len > 0) n = strlen(buf); else { buf = nil; len = 0; n = 0; } k = -1; tick = n; save = nil; done = down = 0; p = stringsize(font, " "); h = p.y; w = p.x; b = screen; sc = b->clipr; replclipr(b, 0, b->r); while(!done){ p = stringsize(font, buf ? buf : ""); if(ask && ask[0]){ if(buf) p.x += w; p.x += stringwidth(font, ask); } r = rectaddpt(insetrect(Rpt(ZP, p), -4), o); p.x = 0; r = rectsubpt(r, p); p = ZP; if(r.min.x < screen->r.min.x) p.x = screen->r.min.x - r.min.x; if(r.min.y < screen->r.min.y) p.y = screen->r.min.y - r.min.y; r = rectaddpt(r, p); p = ZP; if(r.max.x > screen->r.max.x) p.x = r.max.x - screen->r.max.x; if(r.max.y > screen->r.max.y) p.y = r.max.y - screen->r.max.y; r = rectsubpt(r, p); r = insetrect(r, -2); if(save == nil){ save = allocimage(display, r, b->chan, 0, DNofill); if(save == nil){ n = -1; break; } draw(save, r, b, nil, r.min); } draw(b, r, backcol, nil, ZP); border(b, r, 2, bordcol, ZP); p = addpt(r.min, Pt(6, 6)); if(ask && ask[0]){ p = string(b, p, bordcol, ZP, font, ask); if(buf) p.x += w; } if(buf){ t = p; p = stringn(b, p, display->black, ZP, font, buf, utfnlen(buf, tick)); draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), display->black, nil, ZP); draw(b, Rect(p.x, p.y, p.x+1, p.y+h), display->black, nil, ZP); draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), display->black, nil, ZP); p = string(b, p, display->black, ZP, font, buf+tick); } flushimage(display, 1); nodraw: i = Ekeyboard; if(m != nil) i |= Emouse; replclipr(b, 0, sc); i = eread(i, &ev); /* screen might have been resized */ if(b != screen || !eqrect(screen->clipr, sc)){ freeimage(save); save = nil; } b = screen; sc = b->clipr; replclipr(b, 0, b->r); switch(i){ default: done = 1; n = -1; break; case Ekeyboard: k = ev.kbdc; if(buf == nil || k == Keof || k == '\n'){ done = 1; break; } if(k == Knack || k == Kesc){ done = !n; buf[n = tick = 0] = 0; break; } if(k == Ksoh || k == Khome){ tick = 0; continue; } if(k == Kenq || k == Kend){ tick = n; continue; } if(k == Kright){ if(tick < n) tick += chartorune(&k, buf+tick); continue; } if(k == Kleft){ for(i = 0; i < n; i += l){ l = chartorune(&k, buf+tick); if(i+l >= tick){ tick = i; break; } } continue; } if(k == Ketb){ while(tick > 0){ tick--; if(tick == 0 || strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1])) break; } buf[n = tick] = 0; break; } if(k == Kbs){ if(tick <= 0) continue; for(i = 0; i < n; i += l){ l = chartorune(&k, buf+i); if(i+l >= tick){ memmove(buf+i, buf+i+l, n - (i+l)); buf[n -= l] = 0; tick -= l; break; } } break; } if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec) continue; if((len-n) <= (l = runelen(k))) continue; memmove(buf+tick+l, buf+tick, n - tick); runetochar(buf+tick, &k); buf[n += l] = 0; tick += l; break; case Emouse: *m = ev.mouse; if(!ptinrect(m->xy, r)){ down = 0; goto nodraw; } if(m->buttons & 7){ down = 1; if(buf && m->xy.x >= (t.x - w)){ down = 0; for(i = 0; i < n; i += l){ l = chartorune(&k, buf+i); t.x += stringnwidth(font, buf+i, 1); if(t.x > m->xy.x) break; } tick = i; } continue; } done = down; break; } if(save){ draw(b, save->r, save, nil, save->r.min); freeimage(save); save = nil; } } replclipr(b, 0, sc); freeimage(backcol); freeimage(bordcol); flushimage(display, 1); return n; }
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; }