rows.c (17123B)
1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <thread.h> 5 #include <cursor.h> 6 #include <mouse.h> 7 #include <keyboard.h> 8 #include <frame.h> 9 #include <fcall.h> 10 #include <bio.h> 11 #include <plumb.h> 12 #include <libsec.h> 13 #include "dat.h" 14 #include "fns.h" 15 16 static Rune Lcolhdr[] = { 17 'N', 'e', 'w', 'c', 'o', 'l', ' ', 18 'K', 'i', 'l', 'l', ' ', 19 'P', 'u', 't', 'a', 'l', 'l', ' ', 20 'D', 'u', 'm', 'p', ' ', 21 'E', 'x', 'i', 't', ' ', 22 0 23 }; 24 25 void 26 rowinit(Row *row, Rectangle r) 27 { 28 Rectangle r1; 29 Text *t; 30 31 draw(screen, r, display->white, nil, ZP); 32 row->r = r; 33 row->col = nil; 34 row->ncol = 0; 35 r1 = r; 36 r1.max.y = r1.min.y + font->height; 37 t = &row->tag; 38 textinit(t, fileaddtext(nil, t), r1, rfget(FALSE, FALSE, FALSE, nil), tagcols); 39 t->what = Rowtag; 40 t->row = row; 41 t->w = nil; 42 t->col = nil; 43 r1.min.y = r1.max.y; 44 r1.max.y += Border; 45 draw(screen, r1, display->black, nil, ZP); 46 textinsert(t, 0, Lcolhdr, 29, TRUE); 47 textsetselect(t, t->file->b.nc, t->file->b.nc); 48 } 49 50 Column* 51 rowadd(Row *row, Column *c, int x) 52 { 53 Rectangle r, r1; 54 Column *d; 55 int i; 56 57 d = nil; 58 r = row->r; 59 r.min.y = row->tag.fr.r.max.y+Border; 60 if(x<r.min.x && row->ncol>0){ /*steal 40% of last column by default */ 61 d = row->col[row->ncol-1]; 62 x = d->r.min.x + 3*Dx(d->r)/5; 63 } 64 /* look for column we'll land on */ 65 for(i=0; i<row->ncol; i++){ 66 d = row->col[i]; 67 if(x < d->r.max.x) 68 break; 69 } 70 if(row->ncol > 0){ 71 if(i < row->ncol) 72 i++; /* new column will go after d */ 73 r = d->r; 74 if(Dx(r) < 100) 75 return nil; 76 draw(screen, r, display->white, nil, ZP); 77 r1 = r; 78 r1.max.x = min(x-Border, r.max.x-50); 79 if(Dx(r1) < 50) 80 r1.max.x = r1.min.x+50; 81 colresize(d, r1); 82 r1.min.x = r1.max.x; 83 r1.max.x = r1.min.x+Border; 84 draw(screen, r1, display->black, nil, ZP); 85 r.min.x = r1.max.x; 86 } 87 if(c == nil){ 88 c = emalloc(sizeof(Column)); 89 colinit(c, r); 90 incref(&reffont.ref); 91 }else 92 colresize(c, r); 93 c->row = row; 94 c->tag.row = row; 95 row->col = realloc(row->col, (row->ncol+1)*sizeof(Column*)); 96 memmove(row->col+i+1, row->col+i, (row->ncol-i)*sizeof(Column*)); 97 row->col[i] = c; 98 row->ncol++; 99 clearmouse(); 100 return c; 101 } 102 103 void 104 rowresize(Row *row, Rectangle r) 105 { 106 int i, deltax; 107 Rectangle or, r1, r2; 108 Column *c; 109 110 or = row->r; 111 deltax = r.min.x - or.min.x; 112 row->r = r; 113 r1 = r; 114 r1.max.y = r1.min.y + font->height; 115 textresize(&row->tag, r1, TRUE); 116 r1.min.y = r1.max.y; 117 r1.max.y += Border; 118 draw(screen, r1, display->black, nil, ZP); 119 r.min.y = r1.max.y; 120 r1 = r; 121 r1.max.x = r1.min.x; 122 for(i=0; i<row->ncol; i++){ 123 c = row->col[i]; 124 r1.min.x = r1.max.x; 125 /* the test should not be necessary, but guarantee we don't lose a pixel */ 126 if(i == row->ncol-1) 127 r1.max.x = r.max.x; 128 else 129 r1.max.x = (c->r.max.x-or.min.x)*Dx(r)/Dx(or) + deltax; 130 if(i > 0){ 131 r2 = r1; 132 r2.max.x = r2.min.x+Border; 133 draw(screen, r2, display->black, nil, ZP); 134 r1.min.x = r2.max.x; 135 } 136 colresize(c, r1); 137 } 138 } 139 140 void 141 rowdragcol(Row *row, Column *c, int _0) 142 { 143 Rectangle r; 144 int i, b, x; 145 Point p, op; 146 Column *d; 147 148 USED(_0); 149 150 clearmouse(); 151 setcursor2(mousectl, &boxcursor, &boxcursor2); 152 b = mouse->buttons; 153 op = mouse->xy; 154 while(mouse->buttons == b) 155 readmouse(mousectl); 156 setcursor(mousectl, nil); 157 if(mouse->buttons){ 158 while(mouse->buttons) 159 readmouse(mousectl); 160 return; 161 } 162 163 for(i=0; i<row->ncol; i++) 164 if(row->col[i] == c) 165 goto Found; 166 error("can't find column"); 167 168 Found: 169 p = mouse->xy; 170 if((abs(p.x-op.x)<5 && abs(p.y-op.y)<5)) 171 return; 172 if((i>0 && p.x<row->col[i-1]->r.min.x) || (i<row->ncol-1 && p.x>c->r.max.x)){ 173 /* shuffle */ 174 x = c->r.min.x; 175 rowclose(row, c, FALSE); 176 if(rowadd(row, c, p.x) == nil) /* whoops! */ 177 if(rowadd(row, c, x) == nil) /* WHOOPS! */ 178 if(rowadd(row, c, -1)==nil){ /* shit! */ 179 rowclose(row, c, TRUE); 180 return; 181 } 182 colmousebut(c); 183 return; 184 } 185 if(i == 0) 186 return; 187 d = row->col[i-1]; 188 if(p.x < d->r.min.x+80+Scrollwid) 189 p.x = d->r.min.x+80+Scrollwid; 190 if(p.x > c->r.max.x-80-Scrollwid) 191 p.x = c->r.max.x-80-Scrollwid; 192 r = d->r; 193 r.max.x = c->r.max.x; 194 draw(screen, r, display->white, nil, ZP); 195 r.max.x = p.x; 196 colresize(d, r); 197 r = c->r; 198 r.min.x = p.x; 199 r.max.x = r.min.x; 200 r.max.x += Border; 201 draw(screen, r, display->black, nil, ZP); 202 r.min.x = r.max.x; 203 r.max.x = c->r.max.x; 204 colresize(c, r); 205 colmousebut(c); 206 } 207 208 void 209 rowclose(Row *row, Column *c, int dofree) 210 { 211 Rectangle r; 212 int i; 213 214 for(i=0; i<row->ncol; i++) 215 if(row->col[i] == c) 216 goto Found; 217 error("can't find column"); 218 Found: 219 r = c->r; 220 if(dofree) 221 colcloseall(c); 222 row->ncol--; 223 memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*)); 224 row->col = realloc(row->col, row->ncol*sizeof(Column*)); 225 if(row->ncol == 0){ 226 draw(screen, r, display->white, nil, ZP); 227 return; 228 } 229 if(i == row->ncol){ /* extend last column right */ 230 c = row->col[i-1]; 231 r.min.x = c->r.min.x; 232 r.max.x = row->r.max.x; 233 }else{ /* extend next window left */ 234 c = row->col[i]; 235 r.max.x = c->r.max.x; 236 } 237 draw(screen, r, display->white, nil, ZP); 238 colresize(c, r); 239 } 240 241 Column* 242 rowwhichcol(Row *row, Point p) 243 { 244 int i; 245 Column *c; 246 247 for(i=0; i<row->ncol; i++){ 248 c = row->col[i]; 249 if(ptinrect(p, c->r)) 250 return c; 251 } 252 return nil; 253 } 254 255 Text* 256 rowwhich(Row *row, Point p) 257 { 258 Column *c; 259 260 if(ptinrect(p, row->tag.all)) 261 return &row->tag; 262 c = rowwhichcol(row, p); 263 if(c) 264 return colwhich(c, p); 265 return nil; 266 } 267 268 Text* 269 rowtype(Row *row, Rune r, Point p) 270 { 271 Window *w; 272 Text *t; 273 274 if(r == 0) 275 r = Runeerror; 276 277 clearmouse(); 278 qlock(&row->lk); 279 if(bartflag) 280 t = barttext; 281 else 282 t = rowwhich(row, p); 283 if(t!=nil && !(t->what==Tag && ptinrect(p, t->scrollr))){ 284 w = t->w; 285 if(w == nil) 286 texttype(t, r); 287 else{ 288 winlock(w, 'K'); 289 wintype(w, t, r); 290 /* Expand tag if necessary */ 291 if(t->what == Tag){ 292 t->w->tagsafe = FALSE; 293 if(r == '\n') 294 t->w->tagexpand = TRUE; 295 winresize(w, w->r, TRUE, TRUE); 296 } 297 winunlock(w); 298 } 299 } 300 qunlock(&row->lk); 301 return t; 302 } 303 304 int 305 rowclean(Row *row) 306 { 307 int clean; 308 int i; 309 310 clean = TRUE; 311 for(i=0; i<row->ncol; i++) 312 clean &= colclean(row->col[i]); 313 return clean; 314 } 315 316 void 317 rowdump(Row *row, char *file) 318 { 319 int i, j, fd, m, n, start, dumped; 320 uint q0, q1; 321 Biobuf *b; 322 char *buf, *a, *fontname, *fontfmt, *fontnamelo, *fontnamehi; 323 Rune *r; 324 Column *c; 325 Window *w, *w1; 326 Text *t; 327 328 if(row->ncol == 0) 329 return; 330 buf = fbufalloc(); 331 if(file == nil){ 332 if(home == nil){ 333 warning(nil, "can't find file for dump: $home not defined\n"); 334 goto Rescue; 335 } 336 sprint(buf, "%s/acme.dump", home); 337 file = buf; 338 } 339 fd = create(file, OWRITE, 0600); 340 if(fd < 0){ 341 warning(nil, "can't open %s: %r\n", file); 342 goto Rescue; 343 } 344 b = emalloc(sizeof(Biobuf)); 345 Binit(b, fd, OWRITE); 346 r = fbufalloc(); 347 Bprint(b, "%s\n", wdir); 348 Bprint(b, "%s\n", fontnames[0]); 349 Bprint(b, "%s\n", fontnames[1]); 350 for(i=0; i<row->ncol; i++){ 351 c = row->col[i]; 352 Bprint(b, "%11.7f", 100.0*(c->r.min.x-row->r.min.x)/Dx(row->r)); 353 if(i == row->ncol-1) 354 Bputc(b, '\n'); 355 else 356 Bputc(b, ' '); 357 } 358 for(i=0; i<row->ncol; i++){ 359 c = row->col[i]; 360 for(j=0; j<c->nw; j++) 361 c->w[j]->body.file->dumpid = 0; 362 } 363 m = min(RBUFSIZE, row->tag.file->b.nc); 364 bufread(&row->tag.file->b, 0, r, m); 365 n = 0; 366 while(n<m && r[n]!='\n') 367 n++; 368 Bprint(b, "w %.*S\n", n, r); 369 for(i=0; i<row->ncol; i++){ 370 c = row->col[i]; 371 m = min(RBUFSIZE, c->tag.file->b.nc); 372 bufread(&c->tag.file->b, 0, r, m); 373 n = 0; 374 while(n<m && r[n]!='\n') 375 n++; 376 Bprint(b, "c%11d %.*S\n", i, n, r); 377 } 378 for(i=0; i<row->ncol; i++){ 379 c = row->col[i]; 380 for(j=0; j<c->nw; j++){ 381 w = c->w[j]; 382 wincommit(w, &w->tag); 383 t = &w->body; 384 /* windows owned by others get special treatment */ 385 if(w->nopen[QWevent] > 0) 386 if(w->dumpstr == nil) 387 continue; 388 /* zeroxes of external windows are tossed */ 389 if(t->file->ntext > 1) 390 for(n=0; n<t->file->ntext; n++){ 391 w1 = t->file->text[n]->w; 392 if(w == w1) 393 continue; 394 if(w1->nopen[QWevent]) 395 goto Continue2; 396 } 397 fontfmt = "%s"; 398 fontnamelo = ""; 399 fontnamehi = nil; 400 if(t->reffont->f != font){ 401 fontnamelo = t->reffont->f->lodpi->name; 402 if(t->reffont->f->hidpi != nil){ 403 fontfmt = "%s,%s"; 404 fontnamehi = t->reffont->f->hidpi->name; 405 } 406 } 407 fontname = smprint(fontfmt, fontnamelo, fontnamehi); 408 if(t->file->nname) 409 a = runetobyte(t->file->name, t->file->nname); 410 else 411 a = emalloc(1); 412 if(t->file->dumpid){ 413 dumped = FALSE; 414 Bprint(b, "x%11d %11d %11d %11d %11.7f %s\n", i, t->file->dumpid, 415 w->body.q0, w->body.q1, 416 100.0*(w->r.min.y-c->r.min.y)/Dy(c->r), 417 fontname); 418 }else if(w->dumpstr){ 419 dumped = FALSE; 420 Bprint(b, "e%11d %11d %11d %11d %11.7f %s\n", i, t->file->dumpid, 421 0, 0, 422 100.0*(w->r.min.y-c->r.min.y)/Dy(c->r), 423 fontname); 424 }else if((w->dirty==FALSE && access(a, 0)==0) || w->isdir){ 425 dumped = FALSE; 426 t->file->dumpid = w->id; 427 Bprint(b, "f%11d %11d %11d %11d %11.7f %s\n", i, w->id, 428 w->body.q0, w->body.q1, 429 100.0*(w->r.min.y-c->r.min.y)/Dy(c->r), 430 fontname); 431 }else{ 432 dumped = TRUE; 433 t->file->dumpid = w->id; 434 Bprint(b, "F%11d %11d %11d %11d %11.7f %11d %s\n", i, j, 435 w->body.q0, w->body.q1, 436 100.0*(w->r.min.y-c->r.min.y)/Dy(c->r), 437 w->body.file->b.nc, fontname); 438 } 439 free(fontname); 440 free(a); 441 winctlprint(w, buf, 0); 442 Bwrite(b, buf, strlen(buf)); 443 m = min(RBUFSIZE, w->tag.file->b.nc); 444 bufread(&w->tag.file->b, 0, r, m); 445 n = 0; 446 while(n<m) { 447 start = n; 448 while(n<m && r[n]!='\n') 449 n++; 450 Bprint(b, "%.*S", n-start, r+start); 451 if(n<m) { 452 Bputc(b, 0xff); // \n in tag becomes 0xff byte (invalid UTF) 453 n++; 454 } 455 } 456 Bprint(b, "\n"); 457 if(dumped){ 458 q0 = 0; 459 q1 = t->file->b.nc; 460 while(q0 < q1){ 461 n = q1 - q0; 462 if(n > BUFSIZE/UTFmax) 463 n = BUFSIZE/UTFmax; 464 bufread(&t->file->b, q0, r, n); 465 Bprint(b, "%.*S", n, r); 466 q0 += n; 467 } 468 } 469 if(w->dumpstr){ 470 if(w->dumpdir) 471 Bprint(b, "%s\n%s\n", w->dumpdir, w->dumpstr); 472 else 473 Bprint(b, "\n%s\n", w->dumpstr); 474 } 475 Continue2:; 476 } 477 } 478 Bterm(b); 479 close(fd); 480 free(b); 481 fbuffree(r); 482 483 Rescue: 484 fbuffree(buf); 485 } 486 487 static 488 char* 489 rdline(Biobuf *b, int *linep) 490 { 491 char *l; 492 493 l = Brdline(b, '\n'); 494 if(l) 495 (*linep)++; 496 return l; 497 } 498 499 /* 500 * Get font names from load file so we don't load fonts we won't use 501 */ 502 void 503 rowloadfonts(char *file) 504 { 505 int i; 506 Biobuf *b; 507 char *l; 508 509 b = Bopen(file, OREAD); 510 if(b == nil) 511 return; 512 /* current directory */ 513 l = Brdline(b, '\n'); 514 if(l == nil) 515 goto Return; 516 /* global fonts */ 517 for(i=0; i<2; i++){ 518 l = Brdline(b, '\n'); 519 if(l == nil) 520 goto Return; 521 l[Blinelen(b)-1] = 0; 522 if(*l && strcmp(l, fontnames[i])!=0){ 523 free(fontnames[i]); 524 fontnames[i] = estrdup(l); 525 } 526 } 527 Return: 528 Bterm(b); 529 } 530 531 int 532 rowload(Row *row, char *file, int initing) 533 { 534 int i, j, line, y, nr, nfontr, n, ns, ndumped, dumpid, x, fd, done; 535 double percent; 536 Biobuf *b, *bout; 537 char *buf, *l, *t, *fontname; 538 Rune *r, *fontr; 539 int rune; 540 Column *c, *c1, *c2; 541 uint q0, q1; 542 Rectangle r1, r2; 543 Window *w; 544 545 buf = fbufalloc(); 546 if(file == nil){ 547 if(home == nil){ 548 warning(nil, "can't find file for load: $home not defined\n"); 549 goto Rescue1; 550 } 551 sprint(buf, "%s/acme.dump", home); 552 file = buf; 553 } 554 b = Bopen(file, OREAD); 555 if(b == nil){ 556 warning(nil, "can't open load file %s: %r\n", file); 557 goto Rescue1; 558 } 559 /* current directory */ 560 line = 0; 561 l = rdline(b, &line); 562 if(l == nil) 563 goto Rescue2; 564 l[Blinelen(b)-1] = 0; 565 if(chdir(l) < 0){ 566 warning(nil, "can't chdir %s\n", l); 567 goto Rescue2; 568 } 569 /* global fonts */ 570 for(i=0; i<2; i++){ 571 l = rdline(b, &line); 572 if(l == nil) 573 goto Rescue2; 574 l[Blinelen(b)-1] = 0; 575 if(*l && strcmp(l, fontnames[i])!=0) 576 rfget(i, TRUE, i==0 && initing, l); 577 } 578 if(initing && row->ncol==0) 579 rowinit(row, screen->clipr); 580 l = rdline(b, &line); 581 if(l == nil) 582 goto Rescue2; 583 j = Blinelen(b)/12; 584 if(j<=0 || j>10) 585 goto Rescue2; 586 for(i=0; i<j; i++){ 587 percent = atof(l+i*12); 588 if(percent<0 || percent>=100) 589 goto Rescue2; 590 x = row->r.min.x+percent*Dx(row->r)/100+0.5; 591 if(i < row->ncol){ 592 if(i == 0) 593 continue; 594 c1 = row->col[i-1]; 595 c2 = row->col[i]; 596 r1 = c1->r; 597 r2 = c2->r; 598 if(x<Border) 599 x = Border; 600 r1.max.x = x-Border; 601 r2.min.x = x; 602 if(Dx(r1) < 50 || Dx(r2) < 50) 603 continue; 604 draw(screen, Rpt(r1.min, r2.max), display->white, nil, ZP); 605 colresize(c1, r1); 606 colresize(c2, r2); 607 r2.min.x = x-Border; 608 r2.max.x = x; 609 draw(screen, r2, display->black, nil, ZP); 610 } 611 if(i >= row->ncol) 612 rowadd(row, nil, x); 613 } 614 done = 0; 615 while(!done){ 616 l = rdline(b, &line); 617 if(l == nil) 618 break; 619 switch(l[0]){ 620 case 'c': 621 l[Blinelen(b)-1] = 0; 622 i = atoi(l+1+0*12); 623 r = bytetorune(l+1*12, &nr); 624 ns = -1; 625 for(n=0; n<nr; n++){ 626 if(r[n] == '/') 627 ns = n; 628 if(r[n] == ' ') 629 break; 630 } 631 textdelete(&row->col[i]->tag, 0, row->col[i]->tag.file->b.nc, TRUE); 632 textinsert(&row->col[i]->tag, 0, r+n+1, nr-(n+1), TRUE); 633 free(r); 634 break; 635 case 'w': 636 l[Blinelen(b)-1] = 0; 637 r = bytetorune(l+2, &nr); 638 ns = -1; 639 for(n=0; n<nr; n++){ 640 if(r[n] == '/') 641 ns = n; 642 if(r[n] == ' ') 643 break; 644 } 645 textdelete(&row->tag, 0, row->tag.file->b.nc, TRUE); 646 textinsert(&row->tag, 0, r, nr, TRUE); 647 free(r); 648 break; 649 default: 650 done = 1; 651 break; 652 } 653 } 654 for(;;){ 655 if(l == nil) 656 break; 657 dumpid = 0; 658 switch(l[0]){ 659 case 'e': 660 if(Blinelen(b) < 1+5*12+1) 661 goto Rescue2; 662 l = rdline(b, &line); /* ctl line; ignored */ 663 if(l == nil) 664 goto Rescue2; 665 l = rdline(b, &line); /* directory */ 666 if(l == nil) 667 goto Rescue2; 668 l[Blinelen(b)-1] = 0; 669 if(*l == '\0'){ 670 if(home == nil) 671 r = bytetorune("./", &nr); 672 else{ 673 t = emalloc(strlen(home)+1+1); 674 sprint(t, "%s/", home); 675 r = bytetorune(t, &nr); 676 free(t); 677 } 678 }else 679 r = bytetorune(l, &nr); 680 l = rdline(b, &line); /* command */ 681 if(l == nil) 682 goto Rescue2; 683 t = emalloc(Blinelen(b)+1); 684 memmove(t, l, Blinelen(b)); 685 run(nil, t, r, nr, TRUE, nil, nil, FALSE); 686 /* r is freed in run() */ 687 goto Nextline; 688 case 'f': 689 if(Blinelen(b) < 1+5*12+1) 690 goto Rescue2; 691 fontname = l+1+5*12; 692 ndumped = -1; 693 break; 694 case 'F': 695 if(Blinelen(b) < 1+6*12+1) 696 goto Rescue2; 697 fontname = l+1+6*12; 698 ndumped = atoi(l+1+5*12+1); 699 break; 700 case 'x': 701 if(Blinelen(b) < 1+5*12+1) 702 goto Rescue2; 703 fontname = l+1+5*12; 704 ndumped = -1; 705 dumpid = atoi(l+1+1*12); 706 break; 707 default: 708 goto Rescue2; 709 } 710 l[Blinelen(b)-1] = 0; 711 fontr = nil; 712 nfontr = 0; 713 if(*fontname) 714 fontr = bytetorune(fontname, &nfontr); 715 i = atoi(l+1+0*12); 716 j = atoi(l+1+1*12); 717 q0 = atoi(l+1+2*12); 718 q1 = atoi(l+1+3*12); 719 percent = atof(l+1+4*12); 720 if(i<0 || i>10) 721 goto Rescue2; 722 if(i > row->ncol) 723 i = row->ncol; 724 c = row->col[i]; 725 y = c->r.min.y+(percent*Dy(c->r))/100+0.5; 726 if(y<c->r.min.y || y>=c->r.max.y) 727 y = -1; 728 if(dumpid == 0) 729 w = coladd(c, nil, nil, y); 730 else 731 w = coladd(c, nil, lookid(dumpid, TRUE), y); 732 if(w == nil) 733 goto Nextline; 734 w->dumpid = j; 735 l = rdline(b, &line); 736 if(l == nil) 737 goto Rescue2; 738 l[Blinelen(b)-1] = 0; 739 /* convert 0xff in multiline tag back to \n */ 740 for(i = 0; l[i] != 0; i++) 741 if((uchar)l[i] == 0xff) 742 l[i] = '\n'; 743 r = bytetorune(l+5*12, &nr); 744 ns = -1; 745 for(n=0; n<nr; n++){ 746 if(r[n] == '/') 747 ns = n; 748 if(r[n] == ' ') 749 break; 750 } 751 if(dumpid == 0) 752 winsetname(w, r, n); 753 for(; n<nr; n++) 754 if(r[n] == '|') 755 break; 756 wincleartag(w); 757 textinsert(&w->tag, w->tag.file->b.nc, r+n+1, nr-(n+1), TRUE); 758 if(ndumped >= 0){ 759 /* simplest thing is to put it in a file and load that */ 760 sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser()); 761 fd = create(buf, OWRITE, 0600); 762 if(fd < 0){ 763 free(r); 764 warning(nil, "can't create temp file: %r\n"); 765 goto Rescue2; 766 } 767 bout = emalloc(sizeof(Biobuf)); 768 Binit(bout, fd, OWRITE); 769 for(n=0; n<ndumped; n++){ 770 rune = Bgetrune(b); 771 if(rune == '\n') 772 line++; 773 if(rune == Beof){ 774 free(r); 775 Bterm(bout); 776 free(bout); 777 close(fd); 778 remove(buf); 779 goto Rescue2; 780 } 781 Bputrune(bout, rune); 782 } 783 Bterm(bout); 784 free(bout); 785 textload(&w->body, 0, buf, 1); 786 remove(buf); 787 close(fd); 788 w->body.file->mod = TRUE; 789 for(n=0; n<w->body.file->ntext; n++) 790 w->body.file->text[n]->w->dirty = TRUE; 791 winsettag(w); 792 }else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-') 793 get(&w->body, nil, nil, FALSE, XXX, nil, 0); 794 if(fontr){ 795 fontx(&w->body, nil, nil, 0, 0, fontr, nfontr); 796 free(fontr); 797 } 798 free(r); 799 if(q0>w->body.file->b.nc || q1>w->body.file->b.nc || q0>q1) 800 q0 = q1 = 0; 801 textshow(&w->body, q0, q1, 1); 802 w->maxlines = min(w->body.fr.nlines, max(w->maxlines, w->body.fr.maxlines)); 803 xfidlog(w, "new"); 804 Nextline: 805 l = rdline(b, &line); 806 } 807 Bterm(b); 808 fbuffree(buf); 809 return TRUE; 810 811 Rescue2: 812 warning(nil, "bad load file %s:%d\n", file, line); 813 Bterm(b); 814 Rescue1: 815 fbuffree(buf); 816 return FALSE; 817 } 818 819 void 820 allwindows(void (*f)(Window*, void*), void *arg) 821 { 822 int i, j; 823 Column *c; 824 825 for(i=0; i<row.ncol; i++){ 826 c = row.col[i]; 827 for(j=0; j<c->nw; j++) 828 (*f)(c->w[j], arg); 829 } 830 }