ref: f21361177f037d79ab8993818e49d474b0b97351
dir: /dirpanel.c/
#include "a.h" void datestr(char *buf, ulong bufsz, long dt) { char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; Tm *tm; tm = localtime(dt); snprint(buf, bufsz, "%s %02d %02d:%02d", months[tm->mon], tm->mday, tm->hour, tm->min); } Dirpanel* mkdirpanel(Dirmodel *dm) { Dirpanel *dp; dp = emalloc(sizeof *dp); dp->c = chancreate(sizeof(ulong), 1); dp->b = nil; dp->model = dm; dp->focused = 0; dp->offset = 0; dp->cursor = 0; return dp; } void dirpanelsetrect(Dirpanel *p, Rectangle r) { p->r = r; freeimage(p->b); p->b = nil; p->intr = insetrect(boundsrect(r), 2); p->titler = p->intr; p->titler.max.y = p->titler.min.y + 2 + font->height + 2; p->filesr = p->intr; p->filesr.min.y = p->titler.max.y; p->filesr.max.y -= 1; p->nlines = Dy(p->filesr) / (font->height + 2); } void drawfname(Dirpanel *p, Point pt, Image *f, char *t, int xmax) { char *s; Rune r; int i; s = t; for(i = 0; *s && i < 2; i++){ s += chartorune(&r, s); pt = runestringn(p->b, pt, f, ZP, font, &r, 1); } if(*s && (pt.x + stringwidth(font, s) > xmax)){ chartorune(&r, "~"); pt = runestringn(p->b, pt, f, ZP, font, &r, 1); while(*s && (pt.x + stringwidth(font, s) > xmax)) ++s; } while(*s){ s += chartorune(&r, s); pt = runestringn(p->b, pt, f, ZP, font, &r, 1); } } void drawline(Dirpanel *p, int index) { Rectangle r; Image *b, *f; Point pr, pt; char buf[32]; Dir d; d = dirmodelgetdir(p->model, p->offset + index); r = p->filesr; r.min.x += 2; r.min.y += index * (1 + font->height + 1); r.max.x -= 2; r.max.y = r.min.y + 1 + font->height + 1; b = cols[Cbg]; if(index == p->cursor && p->focused) b = cols[Csel]; f = cols[Cfg]; if(p->model->sel[p->offset + index]) f = cols[Ctitle]; else if(!p->focused) f = cols[Clfg]; draw(p->b, r, b, nil, ZP); pt = addpt(r.min, Pt(4, 1)); pt = string(p->b, pt, f, ZP, font, (d.qid.type&QTDIR) ? "/" : " "); drawfname(p, pt, f, d.name, p->colw[0] - 4); pt.x = p->filesr.min.x + p->colw[0] + 4; snprint(buf, sizeof buf, "%*lld", 6, d.length); string(p->b, pt, f, ZP, font, buf); pt.x = p->filesr.max.x - p->colw[2] + 4; datestr(buf, sizeof buf, d.mtime); string(p->b, pt, f, ZP, font, buf); pr = addpt(r.min, Pt(p->colw[0] - 2, 0)); pt = addpt(r.min, Pt(p->colw[0] - 2, Dy(r) + 1)); line(p->b, pr, pt, 0, 0, 0, cols[Cborder], ZP); pr = addpt(pr, Pt(p->colw[1], 0)); pt = addpt(pt, Pt(p->colw[1], 0)); line(p->b, pr, pt, 0, 0, 0, cols[Cborder], ZP); } int sizecolwidth(Dirpanel *p) { vlong m; int i, n; Dir d; m = 1; for(i = 0; i < dirmodelcount(p->model); i++){ d = dirmodelgetdir(p->model, i); if(d.length > m) m = d.length; } n = 6; if(m != 0) n = 1 + log(m)/log(10); if(n < 6) n = 6; return n * stringwidth(font, "0"); } void dirpanelredraw(Dirpanel *p) { Rectangle r, clipr, ir; Point pr, pt; Image *b; int i; p->colw[2] = 4 + stringwidth(font, "XXX 99 99:99") + 4; p->colw[1] = 4 + sizecolwidth(p) + 4; p->colw[0] = Dx(p->filesr) - (p->colw[1] + p->colw[2]); r = boundsrect(p->r); if(p->b == nil) p->b = allocimage(display, r, screen->chan, 0, DNofill); draw(p->b, r, cols[Cbg], nil, ZP); b = p->focused ? cols[Ctitle] : cols[Cborder]; ir = insetrect(r, 2); border(p->b, ir, 2, b, ZP); pt = string(p->b, addpt(ir.min, Pt(4, 2)), p->focused ? cols[Cfg] : cols[Clfg], ZP, font, p->model->path); if(p->model->filter != nil){ pt = string(p->b, pt, cols[Clfg], ZP, font, " ["); pt = string(p->b, pt, cols[Cfg], ZP, font, p->model->filter); pt = string(p->b, pt, cols[Clfg], ZP, font, "]"); } pr = Pt(0, ir.min.y + 2 + font->height + 2); line(p->b, addpt(pr, Pt(ir.min.x, 0)), addpt(pr, Pt(ir.max.x, 0)), 0, 0, 1, b, ZP); pt = addpt(p->filesr.min, Pt(4, 1)); clipr = p->b->clipr; replclipr(p->b, 0, p->filesr); for(i = 0; ; i++){ if(i >= p->nlines || (p->offset + i) >= dirmodelcount(p->model)) break; drawline(p, i); } replclipr(p->b, 0, clipr); pr = addpt(p->filesr.min, Pt(p->colw[0], 1)); pt = addpt(p->filesr.min, Pt(p->colw[0], Dy(p->filesr) - 1)); line(p->b, pr, pt, 0, 0, 0, cols[Cborder], ZP); pr = addpt(pr, Pt(p->colw[1], 0)); pt = addpt(pt, Pt(p->colw[1], 0)); line(p->b, pr, pt, 0, 0, 0, cols[Cborder], ZP); } void dirpanelredrawnotify(Dirpanel *p) { dirpanelredraw(p); sendul(p->c, 1); } void dirpanelemouse(Dirpanel *p, Mouse m) { Point pt; int n; pt = subpt(m.xy, screen->r.min); if(!ptinrect(pt, p->filesr)) return; if(m.buttons == 1){ n = (pt.y - p->filesr.min.y) / (font->height+2); if(n != p->cursor && n < p->nlines){ p->cursor = n; dirpanelredrawnotify(p); } }else if(m.buttons == 4){ n = (pt.y - p->filesr.min.y) / (font->height+2); if(n < p->nlines){ p->cursor = n; cmdview(); /* ugly hack */ } } } void dirpanelresetcursor(Dirpanel *p) { p->cursor = 0; p->offset = 0; } int dirpanelselectedindex(Dirpanel *p) { return p->offset + p->cursor; }