rows.c 14 KB

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