123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724 |
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <thread.h>
- #include <cursor.h>
- #include <mouse.h>
- #include <keyboard.h>
- #include <frame.h>
- #include <fcall.h>
- #include <bio.h>
- #include <plumb.h>
- #include "dat.h"
- #include "fns.h"
- void
- rowinit(Row *row, Rectangle r)
- {
- Rectangle r1;
- Text *t;
- draw(screen, r, display->white, nil, ZP);
- row->r = r;
- row->col = nil;
- row->ncol = 0;
- r1 = r;
- r1.max.y = r1.min.y + font->height;
- t = &row->tag;
- textinit(t, fileaddtext(nil, t), r1, rfget(FALSE, FALSE, FALSE, nil), tagcols);
- t->what = Rowtag;
- t->row = row;
- t->w = nil;
- t->col = nil;
- r1.min.y = r1.max.y;
- r1.max.y += Border;
- draw(screen, r1, display->black, nil, ZP);
- textinsert(t, 0, L"Newcol Kill Putall Dump Exit ", 29, TRUE);
- textsetselect(t, t->file->nc, t->file->nc);
- }
- Column*
- rowadd(Row *row, Column *c, int x)
- {
- Rectangle r, r1;
- Column *d;
- int i;
- d = nil;
- r = row->r;
- r.min.y = row->tag.r.max.y+Border;
- if(x<r.min.x && row->ncol>0){ /*steal 40% of last column by default */
- d = row->col[row->ncol-1];
- x = d->r.min.x + 3*Dx(d->r)/5;
- }
- /* look for column we'll land on */
- for(i=0; i<row->ncol; i++){
- d = row->col[i];
- if(x < d->r.max.x)
- break;
- }
- if(row->ncol > 0){
- if(i < row->ncol)
- i++; /* new column will go after d */
- r = d->r;
- if(Dx(r) < 100)
- return nil;
- draw(screen, r, display->white, nil, ZP);
- r1 = r;
- r1.max.x = min(x, r.max.x-50);
- if(Dx(r1) < 50)
- r1.max.x = r1.min.x+50;
- colresize(d, r1);
- r1.min.x = r1.max.x;
- r1.max.x = r1.min.x+Border;
- draw(screen, r1, display->black, nil, ZP);
- r.min.x = r1.max.x;
- }
- if(c == nil){
- c = emalloc(sizeof(Column));
- colinit(c, r);
- incref(&reffont);
- }else
- colresize(c, r);
- c->row = row;
- c->tag.row = row;
- row->col = realloc(row->col, (row->ncol+1)*sizeof(Column*));
- memmove(row->col+i+1, row->col+i, (row->ncol-i)*sizeof(Column*));
- row->col[i] = c;
- row->ncol++;
- clearmouse();
- return c;
- }
- void
- rowresize(Row *row, Rectangle r)
- {
- int i, dx, odx;
- Rectangle r1, r2;
- Column *c;
- dx = Dx(r);
- odx = Dx(row->r);
- row->r = r;
- r1 = r;
- r1.max.y = r1.min.y + font->height;
- textresize(&row->tag, r1);
- r1.min.y = r1.max.y;
- r1.max.y += Border;
- draw(screen, r1, display->black, nil, ZP);
- r.min.y = r1.max.y;
- r1 = r;
- r1.max.x = r1.min.x;
- for(i=0; i<row->ncol; i++){
- c = row->col[i];
- r1.min.x = r1.max.x;
- if(i == row->ncol-1)
- r1.max.x = r.max.x;
- else
- r1.max.x = r1.min.x+Dx(c->r)*dx/odx;
- if(i > 0){
- r2 = r1;
- r2.max.x = r2.min.x+Border;
- draw(screen, r2, display->black, nil, ZP);
- r1.min.x = r2.max.x;
- }
- colresize(c, r1);
- }
- }
- void
- rowdragcol(Row *row, Column *c, int)
- {
- Rectangle r;
- int i, b, x;
- Point p, op;
- Column *d;
- clearmouse();
- setcursor(mousectl, &boxcursor);
- b = mouse->buttons;
- op = mouse->xy;
- while(mouse->buttons == b)
- readmouse(mousectl);
- setcursor(mousectl, nil);
- if(mouse->buttons){
- while(mouse->buttons)
- readmouse(mousectl);
- return;
- }
- for(i=0; i<row->ncol; i++)
- if(row->col[i] == c)
- goto Found;
- error("can't find column");
- Found:
- if(i == 0)
- return;
- p = mouse->xy;
- if((abs(p.x-op.x)<5 && abs(p.y-op.y)<5))
- return;
- if((i>0 && p.x<row->col[i-1]->r.min.x) || (i<row->ncol-1 && p.x>c->r.max.x)){
- /* shuffle */
- x = c->r.min.x;
- rowclose(row, c, FALSE);
- if(rowadd(row, c, p.x) == nil) /* whoops! */
- if(rowadd(row, c, x) == nil) /* WHOOPS! */
- if(rowadd(row, c, -1)==nil){ /* shit! */
- rowclose(row, c, TRUE);
- return;
- }
- colmousebut(c);
- return;
- }
- d = row->col[i-1];
- if(p.x < d->r.min.x+80+Scrollwid)
- p.x = d->r.min.x+80+Scrollwid;
- if(p.x > c->r.max.x-80-Scrollwid)
- p.x = c->r.max.x-80-Scrollwid;
- r = d->r;
- r.max.x = c->r.max.x;
- draw(screen, r, display->white, nil, ZP);
- r.max.x = p.x;
- colresize(d, r);
- r = c->r;
- r.min.x = p.x;
- r.max.x = r.min.x;
- r.max.x += Border;
- draw(screen, r, display->black, nil, ZP);
- r.min.x = r.max.x;
- r.max.x = c->r.max.x;
- colresize(c, r);
- colmousebut(c);
- }
- void
- rowclose(Row *row, Column *c, int dofree)
- {
- Rectangle r;
- int i;
- for(i=0; i<row->ncol; i++)
- if(row->col[i] == c)
- goto Found;
- error("can't find column");
- Found:
- r = c->r;
- if(dofree)
- colcloseall(c);
- memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*));
- row->ncol--;
- row->col = realloc(row->col, row->ncol*sizeof(Column*));
- if(row->ncol == 0){
- draw(screen, r, display->white, nil, ZP);
- return;
- }
- if(i == row->ncol){ /* extend last column right */
- c = row->col[i-1];
- r.min.x = c->r.min.x;
- r.max.x = row->r.max.x;
- }else{ /* extend next window left */
- c = row->col[i];
- r.max.x = c->r.max.x;
- }
- draw(screen, r, display->white, nil, ZP);
- colresize(c, r);
- }
- Column*
- rowwhichcol(Row *row, Point p)
- {
- int i;
- Column *c;
- for(i=0; i<row->ncol; i++){
- c = row->col[i];
- if(ptinrect(p, c->r))
- return c;
- }
- return nil;
- }
- Text*
- rowwhich(Row *row, Point p)
- {
- Column *c;
- if(ptinrect(p, row->tag.all))
- return &row->tag;
- c = rowwhichcol(row, p);
- if(c)
- return colwhich(c, p);
- return nil;
- }
- Text*
- rowtype(Row *row, Rune r, Point p)
- {
- Window *w;
- Text *t;
- clearmouse();
- qlock(row);
- if(bartflag)
- t = barttext;
- else
- t = rowwhich(row, p);
- if(t!=nil && !(t->what==Tag && ptinrect(p, t->scrollr))){
- w = t->w;
- if(w == nil)
- texttype(t, r);
- else{
- winlock(w, 'K');
- wintype(w, t, r);
- winunlock(w);
- }
- }
- qunlock(row);
- return t;
- }
- int
- rowclean(Row *row)
- {
- int clean;
- int i;
- clean = TRUE;
- for(i=0; i<row->ncol; i++)
- clean &= colclean(row->col[i]);
- return clean;
- }
- void
- rowdump(Row *row, char *file)
- {
- int i, j, fd, m, n, dumped;
- uint q0, q1;
- Biobuf *b;
- char *buf, *a, *fontname;
- Rune *r;
- Column *c;
- Window *w, *w1;
- Text *t;
- if(row->ncol == 0)
- return;
- buf = fbufalloc();
- if(file == nil){
- if(home == nil){
- warning(nil, "can't find file for dump: $home not defined\n");
- goto Rescue;
- }
- sprint(buf, "%s/acme.dump", home);
- file = buf;
- }
- fd = create(file, OWRITE, 0600);
- if(fd < 0){
- warning(nil, "can't open %s: %r\n", file);
- goto Rescue;
- }
- b = emalloc(sizeof(Biobuf));
- Binit(b, fd, OWRITE);
- r = fbufalloc();
- Bprint(b, "%s\n", wdir);
- Bprint(b, "%s\n", fontnames[0]);
- Bprint(b, "%s\n", fontnames[1]);
- for(i=0; i<row->ncol; i++){
- c = row->col[i];
- Bprint(b, "%11d", 100*(c->r.min.x-row->r.min.x)/Dx(row->r));
- if(i == row->ncol-1)
- Bputc(b, '\n');
- else
- Bputc(b, ' ');
- }
- for(i=0; i<row->ncol; i++){
- c = row->col[i];
- for(j=0; j<c->nw; j++)
- c->w[j]->body.file->dumpid = 0;
- }
- for(i=0; i<row->ncol; i++){
- c = row->col[i];
- for(j=0; j<c->nw; j++){
- w = c->w[j];
- wincommit(w, &w->tag);
- t = &w->body;
- /* windows owned by others get special treatment */
- if(w->nopen[QWevent] > 0)
- if(w->dumpstr == nil)
- continue;
- /* zeroxes of external windows are tossed */
- if(t->file->ntext > 1)
- for(n=0; n<t->file->ntext; n++){
- w1 = t->file->text[n]->w;
- if(w == w1)
- continue;
- if(w1->nopen[QWevent])
- goto Continue2;
- }
- fontname = "";
- if(t->reffont->f != font)
- fontname = t->reffont->f->name;
- if(t->file->nname)
- a = runetobyte(t->file->name, t->file->nname);
- else
- a = emalloc(1);
- if(t->file->dumpid){
- dumped = FALSE;
- Bprint(b, "x%11d %11d %11d %11d %11d %s\n", i, t->file->dumpid,
- w->body.q0, w->body.q1,
- 100*(w->r.min.y-c->r.min.y)/Dy(c->r),
- fontname);
- }else if(w->dumpstr){
- dumped = FALSE;
- Bprint(b, "e%11d %11d %11d %11d %11d %s\n", i, t->file->dumpid,
- 0, 0,
- 100*(w->r.min.y-c->r.min.y)/Dy(c->r),
- fontname);
- }else if((w->dirty==FALSE && access(a, 0)==0) || w->isdir){
- dumped = FALSE;
- t->file->dumpid = w->id;
- Bprint(b, "f%11d %11d %11d %11d %11d %s\n", i, w->id,
- w->body.q0, w->body.q1,
- 100*(w->r.min.y-c->r.min.y)/Dy(c->r),
- fontname);
- }else{
- dumped = TRUE;
- t->file->dumpid = w->id;
- Bprint(b, "F%11d %11d %11d %11d %11d %11d %s\n", i, j,
- w->body.q0, w->body.q1,
- 100*(w->r.min.y-c->r.min.y)/Dy(c->r),
- w->body.file->nc, fontname);
- }
- free(a);
- winctlprint(w, buf, 0);
- Bwrite(b, buf, strlen(buf));
- m = min(RBUFSIZE, w->tag.file->nc);
- bufread(w->tag.file, 0, r, m);
- n = 0;
- while(n<m && r[n]!='\n')
- n++;
- r[n++] = '\n';
- Bprint(b, "%.*S", n, r);
- if(dumped){
- q0 = 0;
- q1 = t->file->nc;
- while(q0 < q1){
- n = q1 - q0;
- if(n > BUFSIZE/UTFmax)
- n = BUFSIZE/UTFmax;
- bufread(t->file, q0, r, n);
- Bprint(b, "%.*S", n, r);
- q0 += n;
- }
- }
- if(w->dumpstr){
- if(w->dumpdir)
- Bprint(b, "%s\n%s\n", w->dumpdir, w->dumpstr);
- else
- Bprint(b, "\n%s\n", w->dumpstr);
- }
- Continue2:;
- }
- }
- Bterm(b);
- close(fd);
- free(b);
- fbuffree(r);
- Rescue:
- fbuffree(buf);
- }
- static
- char*
- rdline(Biobuf *b, int *linep)
- {
- char *l;
- l = Brdline(b, '\n');
- if(l)
- (*linep)++;
- return l;
- }
- /*
- * Get font names from load file so we don't load fonts we won't use
- */
- void
- rowloadfonts(char *file)
- {
- int i;
- Biobuf *b;
- char *l;
- b = Bopen(file, OREAD);
- if(b == nil)
- return;
- /* current directory */
- l = Brdline(b, '\n');
- if(l == nil)
- goto Return;
- /* global fonts */
- for(i=0; i<2; i++){
- l = Brdline(b, '\n');
- if(l == nil)
- goto Return;
- l[Blinelen(b)-1] = 0;
- if(*l && strcmp(l, fontnames[i])!=0){
- free(fontnames[i]);
- fontnames[i] = estrdup(l);
- }
- }
- Return:
- Bterm(b);
- }
- int
- rowload(Row *row, char *file, int initing)
- {
- int i, j, line, percent, y, nr, nfontr, n, ns, ndumped, dumpid, x, fd;
- Biobuf *b, *bout;
- char *buf, *l, *t, *fontname;
- Rune *r, rune, *fontr;
- Column *c, *c1, *c2;
- uint q0, q1;
- Rectangle r1, r2;
- Window *w;
- buf = fbufalloc();
- if(file == nil){
- if(home == nil){
- warning(nil, "can't find file for load: $home not defined\n");
- goto Rescue1;
- }
- sprint(buf, "%s/acme.dump", home);
- file = buf;
- }
- b = Bopen(file, OREAD);
- if(b == nil){
- warning(nil, "can't open load file %s: %r\n", file);
- goto Rescue1;
- }
- /* current directory */
- line = 0;
- l = rdline(b, &line);
- if(l == nil)
- goto Rescue2;
- l[Blinelen(b)-1] = 0;
- if(chdir(l) < 0){
- warning(nil, "can't chdir %s\n", l);
- goto Rescue2;
- }
- /* global fonts */
- for(i=0; i<2; i++){
- l = rdline(b, &line);
- if(l == nil)
- goto Rescue2;
- l[Blinelen(b)-1] = 0;
- if(*l && strcmp(l, fontnames[i])!=0)
- rfget(i, TRUE, i==0 && initing, l);
- }
- if(initing && row->ncol==0)
- rowinit(row, screen->clipr);
- l = rdline(b, &line);
- if(l == nil)
- goto Rescue2;
- j = Blinelen(b)/12;
- if(j<=0 || j>10)
- goto Rescue2;
- for(i=0; i<j; i++){
- percent = atoi(l+i*12);
- if(percent<0 || percent>=100)
- goto Rescue2;
- x = row->r.min.x+percent*Dx(row->r)/100;
- if(i < row->ncol){
- if(i == 0)
- continue;
- c1 = row->col[i-1];
- c2 = row->col[i];
- r1 = c1->r;
- r2 = c2->r;
- r1.max.x = x;
- r2.min.x = x+Border;
- if(Dx(r1) < 50 || Dx(r2) < 50)
- continue;
- draw(screen, Rpt(r1.min, r2.max), display->white, nil, ZP);
- colresize(c1, r1);
- colresize(c2, r2);
- r2.min.x = x;
- r2.max.x = x+Border;
- draw(screen, r2, display->black, nil, ZP);
- }
- if(i >= row->ncol)
- rowadd(row, nil, x);
- }
- for(;;){
- l = rdline(b, &line);
- if(l == nil)
- break;
- dumpid = 0;
- switch(l[0]){
- case 'e':
- if(Blinelen(b) < 1+5*12+1)
- goto Rescue2;
- l = rdline(b, &line); /* ctl line; ignored */
- if(l == nil)
- goto Rescue2;
- l = rdline(b, &line); /* directory */
- if(l == nil)
- goto Rescue2;
- l[Blinelen(b)-1] = 0;
- if(*l == '\0'){
- if(home == nil)
- r = bytetorune("./", &nr);
- else{
- t = emalloc(strlen(home)+1+1);
- sprint(t, "%s/", home);
- r = bytetorune(t, &nr);
- free(t);
- }
- }else
- r = bytetorune(l, &nr);
- l = rdline(b, &line); /* command */
- if(l == nil)
- goto Rescue2;
- t = emalloc(Blinelen(b)+1);
- memmove(t, l, Blinelen(b));
- run(nil, t, r, nr, TRUE, nil, nil, FALSE);
- /* r is freed in run() */
- continue;
- case 'f':
- if(Blinelen(b) < 1+5*12+1)
- goto Rescue2;
- fontname = l+1+5*12;
- ndumped = -1;
- break;
- case 'F':
- if(Blinelen(b) < 1+6*12+1)
- goto Rescue2;
- fontname = l+1+6*12;
- ndumped = atoi(l+1+5*12+1);
- break;
- case 'x':
- if(Blinelen(b) < 1+5*12+1)
- goto Rescue2;
- fontname = l+1+5*12;
- ndumped = -1;
- dumpid = atoi(l+1+1*12);
- break;
- default:
- goto Rescue2;
- }
- l[Blinelen(b)-1] = 0;
- fontr = nil;
- nfontr = 0;
- if(*fontname)
- fontr = bytetorune(fontname, &nfontr);
- i = atoi(l+1+0*12);
- j = atoi(l+1+1*12);
- q0 = atoi(l+1+2*12);
- q1 = atoi(l+1+3*12);
- percent = atoi(l+1+4*12);
- if(i<0 || i>10)
- goto Rescue2;
- if(i > row->ncol)
- i = row->ncol;
- c = row->col[i];
- y = c->r.min.y+(percent*Dy(c->r))/100;
- if(y<c->r.min.y || y>=c->r.max.y)
- y = -1;
- if(dumpid == 0)
- w = coladd(c, nil, nil, y);
- else
- w = coladd(c, nil, lookid(dumpid, TRUE), y);
- if(w == nil)
- continue;
- w->dumpid = j;
- l = rdline(b, &line);
- if(l == nil)
- goto Rescue2;
- l[Blinelen(b)-1] = 0;
- r = bytetorune(l+5*12, &nr);
- ns = -1;
- for(n=0; n<nr; n++){
- if(r[n] == '/')
- ns = n;
- if(r[n] == ' ')
- break;
- }
- if(dumpid == 0)
- winsetname(w, r, n);
- for(; n<nr; n++)
- if(r[n] == '|')
- break;
- wincleartag(w);
- textinsert(&w->tag, w->tag.file->nc, r+n+1, nr-(n+1), TRUE);
- if(ndumped >= 0){
- /* simplest thing is to put it in a file and load that */
- sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser());
- fd = create(buf, OWRITE|ORCLOSE, 0600);
- if(fd < 0){
- free(r);
- warning(nil, "can't create temp file: %r\n");
- goto Rescue2;
- }
- bout = emalloc(sizeof(Biobuf));
- Binit(bout, fd, OWRITE);
- for(n=0; n<ndumped; n++){
- rune = Bgetrune(b);
- if(rune == '\n')
- line++;
- if(rune == Beof){
- free(r);
- Bterm(bout);
- free(bout);
- close(fd);
- goto Rescue2;
- }
- Bputrune(bout, rune);
- }
- Bterm(bout);
- free(bout);
- textload(&w->body, 0, buf, 1);
- close(fd);
- w->body.file->mod = TRUE;
- for(n=0; n<w->body.file->ntext; n++)
- w->body.file->text[n]->w->dirty = TRUE;
- winsettag(w);
- }else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-')
- get(&w->body, nil, nil, FALSE, XXX, nil, 0);
- if(fontr){
- fontx(&w->body, nil, nil, 0, 0, fontr, nfontr);
- free(fontr);
- }
- free(r);
- if(q0>w->body.file->nc || q1>w->body.file->nc || q0>q1)
- q0 = q1 = 0;
- textshow(&w->body, q0, q1, 1);
- w->maxlines = min(w->body.nlines, max(w->maxlines, w->body.maxlines));
- }
- Bterm(b);
- fbuffree(buf);
- return TRUE;
- Rescue2:
- warning(nil, "bad load file %s:%d\n", file, line);
- Bterm(b);
- Rescue1:
- fbuffree(buf);
- return FALSE;
- }
- void
- allwindows(void (*f)(Window*, void*), void *arg)
- {
- int i, j;
- Column *c;
- for(i=0; i<row.ncol; i++){
- c = row.col[i];
- for(j=0; j<c->nw; j++)
- (*f)(c->w[j], arg);
- }
- }
|