rows.c 15 KB

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