n7.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  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 "tdef.h"
  10. #include "fns.h"
  11. #include "ext.h"
  12. #ifdef STRICT
  13. /* not in ANSI or POSIX */
  14. #undef isascii
  15. #define isascii(a) ((a) >= 0 && (a) <= 127)
  16. #endif
  17. #define GETCH gettch
  18. Tchar gettch(void);
  19. /*
  20. * troff7.c
  21. *
  22. * text
  23. */
  24. int brflg;
  25. void tbreak(void)
  26. {
  27. int pad, k;
  28. Tchar *i, j;
  29. int resol;
  30. int un0 = un;
  31. trap = 0;
  32. if (nb)
  33. return;
  34. if (dip == d && numtabp[NL].val == -1) {
  35. newline(1);
  36. return;
  37. }
  38. if (!nc) {
  39. setnel();
  40. if (!wch)
  41. return;
  42. if (pendw)
  43. getword(1);
  44. movword();
  45. } else if (pendw && !brflg) {
  46. getword(1);
  47. movword();
  48. }
  49. *linep = dip->nls = 0;
  50. if (NROFF && dip == d)
  51. horiz(po);
  52. if (lnmod)
  53. donum();
  54. lastl = ne;
  55. if (brflg != 1) {
  56. totout = 0;
  57. } else if (ad) {
  58. if ((lastl = ll - un) < ne)
  59. lastl = ne;
  60. }
  61. if (admod && ad && (brflg != 2)) {
  62. lastl = ne;
  63. adsp = adrem = 0;
  64. if (admod == 1)
  65. un += quant(nel / 2, HOR);
  66. else if (admod == 2)
  67. un += nel;
  68. }
  69. totout++;
  70. brflg = 0;
  71. if (lastl + un > dip->maxl)
  72. dip->maxl = lastl + un;
  73. horiz(un);
  74. if (NROFF) {
  75. if (adrem % t.Adj)
  76. resol = t.Hor;
  77. else
  78. resol = t.Adj;
  79. } else
  80. resol = HOR;
  81. lastl = ne + (nwd-1) * adsp + adrem;
  82. for (i = line; nc > 0; ) {
  83. if ((cbits(j = *i++)) == ' ') {
  84. pad = 0;
  85. do {
  86. pad += width(j);
  87. nc--;
  88. } while ((cbits(j = *i++)) == ' ');
  89. i--;
  90. pad += adsp;
  91. --nwd;
  92. if (adrem) {
  93. if (adrem < 0) {
  94. pad -= resol;
  95. adrem += resol;
  96. } else if ((totout & 01) || adrem / resol >= nwd) {
  97. pad += resol;
  98. adrem -= resol;
  99. }
  100. }
  101. pchar((Tchar) WORDSP);
  102. horiz(pad);
  103. } else {
  104. pchar(j);
  105. nc--;
  106. }
  107. }
  108. if (ic) {
  109. if ((k = ll - un0 - lastl + ics) > 0)
  110. horiz(k);
  111. pchar(ic);
  112. }
  113. if (icf)
  114. icf++;
  115. else
  116. ic = 0;
  117. ne = nwd = 0;
  118. un = in;
  119. setnel();
  120. newline(0);
  121. if (dip != d) {
  122. if (dip->dnl > dip->hnl)
  123. dip->hnl = dip->dnl;
  124. } else {
  125. if (numtabp[NL].val > dip->hnl)
  126. dip->hnl = numtabp[NL].val;
  127. }
  128. for (k = ls - 1; k > 0 && !trap; k--)
  129. newline(0);
  130. spread = 0;
  131. }
  132. void donum(void)
  133. {
  134. int i, nw;
  135. int lnv = numtabp[LN].val;
  136. nrbits = nmbits;
  137. nw = width('1' | nrbits);
  138. if (nn) {
  139. nn--;
  140. goto d1;
  141. }
  142. if (lnv % ndf) {
  143. numtabp[LN].val++;
  144. d1:
  145. un += nw * (nmwid + nms + ni);
  146. return;
  147. }
  148. i = 0;
  149. do { /* count digits in numtabp[LN].val */
  150. i++;
  151. } while ((lnv /= 10) > 0);
  152. horiz(nw * (ni + max(nmwid-i, 0)));
  153. nform = 0;
  154. fnumb(numtabp[LN].val, pchar);
  155. un += nw * nms;
  156. numtabp[LN].val++;
  157. }
  158. void text(void)
  159. {
  160. Tchar i;
  161. static int spcnt;
  162. nflush++;
  163. numtabp[HP].val = 0;
  164. if ((dip == d) && (numtabp[NL].val == -1)) {
  165. newline(1);
  166. return;
  167. }
  168. setnel();
  169. if (ce || !fi) {
  170. nofill();
  171. return;
  172. }
  173. if (pendw)
  174. goto t4;
  175. if (pendt)
  176. if (spcnt)
  177. goto t2;
  178. else
  179. goto t3;
  180. pendt++;
  181. if (spcnt)
  182. goto t2;
  183. while ((cbits(i = GETCH())) == ' ') {
  184. spcnt++;
  185. numtabp[HP].val += sps;
  186. widthp = sps;
  187. }
  188. if (nlflg) {
  189. t1:
  190. nflush = pendt = ch = spcnt = 0;
  191. callsp();
  192. return;
  193. }
  194. ch = i;
  195. if (spcnt) {
  196. t2:
  197. tbreak();
  198. if (nc || wch)
  199. goto rtn;
  200. un += spcnt * sps;
  201. spcnt = 0;
  202. setnel();
  203. if (trap)
  204. goto rtn;
  205. if (nlflg)
  206. goto t1;
  207. }
  208. t3:
  209. if (spread)
  210. goto t5;
  211. if (pendw || !wch)
  212. t4:
  213. if (getword(0))
  214. goto t6;
  215. if (!movword())
  216. goto t3;
  217. t5:
  218. if (nlflg)
  219. pendt = 0;
  220. adsp = adrem = 0;
  221. if (ad) {
  222. if (nwd == 1)
  223. adsp = nel;
  224. else
  225. adsp = nel / (nwd - 1);
  226. adsp = (adsp / HOR) * HOR;
  227. adrem = nel - adsp*(nwd-1);
  228. }
  229. brflg = 1;
  230. tbreak();
  231. spread = 0;
  232. if (!trap)
  233. goto t3;
  234. if (!nlflg)
  235. goto rtn;
  236. t6:
  237. pendt = 0;
  238. ckul();
  239. rtn:
  240. nflush = 0;
  241. }
  242. void nofill(void)
  243. {
  244. int j;
  245. Tchar i;
  246. if (!pendnf) {
  247. over = 0;
  248. tbreak();
  249. if (trap)
  250. goto rtn;
  251. if (nlflg) {
  252. ch = nflush = 0;
  253. callsp();
  254. return;
  255. }
  256. adsp = adrem = 0;
  257. nwd = 10000;
  258. }
  259. while ((j = (cbits(i = GETCH()))) != '\n') {
  260. if (j == ohc)
  261. continue;
  262. if (j == CONT) {
  263. pendnf++;
  264. nflush = 0;
  265. flushi();
  266. ckul();
  267. return;
  268. }
  269. j = width(i);
  270. widthp = j;
  271. numtabp[HP].val += j;
  272. storeline(i, j);
  273. }
  274. if (ce) {
  275. ce--;
  276. if ((i = quant(nel / 2, HOR)) > 0)
  277. un += i;
  278. }
  279. if (!nc)
  280. storeline((Tchar)FILLER, 0);
  281. brflg = 2;
  282. tbreak();
  283. ckul();
  284. rtn:
  285. pendnf = nflush = 0;
  286. }
  287. void callsp(void)
  288. {
  289. int i;
  290. if (flss)
  291. i = flss;
  292. else
  293. i = lss;
  294. flss = 0;
  295. casesp1(i);
  296. }
  297. void ckul(void)
  298. {
  299. if (ul && (--ul == 0)) {
  300. cu = 0;
  301. font = sfont;
  302. mchbits();
  303. }
  304. if (it && --it == 0 && itmac)
  305. control(itmac, 0);
  306. }
  307. void storeline(Tchar c, int w)
  308. {
  309. int diff;
  310. if (linep >= line + lnsize - 2) {
  311. lnsize += LNSIZE;
  312. diff = linep - line;
  313. if (( line = (Tchar *)realloc((char *)line, lnsize * sizeof(Tchar))) != NULL) {
  314. if (linep && diff)
  315. linep = line + diff;
  316. } else {
  317. if (over) {
  318. return;
  319. } else {
  320. flusho();
  321. ERROR "Line overflow." WARN;
  322. over++;
  323. *linep++ = LEFTHAND;
  324. w = width(LEFTHAND);
  325. nc++;
  326. c = '\n';
  327. }
  328. }
  329. }
  330. *linep++ = c;
  331. ne += w;
  332. nel -= w;
  333. nc++;
  334. }
  335. void newline(int a)
  336. {
  337. int i, j, nlss;
  338. int opn;
  339. nlss = 0;
  340. if (a)
  341. goto nl1;
  342. if (dip != d) {
  343. j = lss;
  344. pchar1((Tchar)FLSS);
  345. if (flss)
  346. lss = flss;
  347. i = lss + dip->blss;
  348. dip->dnl += i;
  349. pchar1((Tchar)i);
  350. pchar1((Tchar)'\n');
  351. lss = j;
  352. dip->blss = flss = 0;
  353. if (dip->alss) {
  354. pchar1((Tchar)FLSS);
  355. pchar1((Tchar)dip->alss);
  356. pchar1((Tchar)'\n');
  357. dip->dnl += dip->alss;
  358. dip->alss = 0;
  359. }
  360. if (dip->ditrap && !dip->ditf && dip->dnl >= dip->ditrap && dip->dimac)
  361. if (control(dip->dimac, 0)) {
  362. trap++;
  363. dip->ditf++;
  364. }
  365. return;
  366. }
  367. j = lss;
  368. if (flss)
  369. lss = flss;
  370. nlss = dip->alss + dip->blss + lss;
  371. numtabp[NL].val += nlss;
  372. if (TROFF && ascii) {
  373. dip->alss = dip->blss = 0;
  374. }
  375. pchar1((Tchar)'\n');
  376. flss = 0;
  377. lss = j;
  378. if (numtabp[NL].val < pl)
  379. goto nl2;
  380. nl1:
  381. ejf = dip->hnl = numtabp[NL].val = 0;
  382. ejl = frame;
  383. if (donef) {
  384. if ((!nc && !wch) || ndone)
  385. done1(0);
  386. ndone++;
  387. donef = 0;
  388. if (frame == stk)
  389. nflush++;
  390. }
  391. opn = numtabp[PN].val;
  392. numtabp[PN].val++;
  393. if (npnflg) {
  394. numtabp[PN].val = npn;
  395. npn = npnflg = 0;
  396. }
  397. nlpn:
  398. if (numtabp[PN].val == pfrom) {
  399. print++;
  400. pfrom = -1;
  401. } else if (opn == pto) {
  402. print = 0;
  403. opn = -1;
  404. chkpn();
  405. goto nlpn;
  406. }
  407. if (print)
  408. ptpage(numtabp[PN].val); /* supposedly in a clean state so can pause */
  409. if (stop && print) {
  410. dpn++;
  411. if (dpn >= stop) {
  412. dpn = 0;
  413. ptpause();
  414. }
  415. }
  416. nl2:
  417. trap = 0;
  418. if (numtabp[NL].val == 0) {
  419. if ((j = findn(0)) != NTRAP)
  420. trap = control(mlist[j], 0);
  421. } else if ((i = findt(numtabp[NL].val - nlss)) <= nlss) {
  422. if ((j = findn1(numtabp[NL].val - nlss + i)) == NTRAP) {
  423. flusho();
  424. ERROR "Trap botch." WARN;
  425. done2(-5);
  426. }
  427. trap = control(mlist[j], 0);
  428. }
  429. }
  430. findn1(int a)
  431. {
  432. int i, j;
  433. for (i = 0; i < NTRAP; i++) {
  434. if (mlist[i]) {
  435. if ((j = nlist[i]) < 0)
  436. j += pl;
  437. if (j == a)
  438. break;
  439. }
  440. }
  441. return(i);
  442. }
  443. void chkpn(void)
  444. {
  445. pto = *(pnp++);
  446. pfrom = pto>=0 ? pto : -pto;
  447. if (pto == -INT_MAX) {
  448. flusho();
  449. done1(0);
  450. }
  451. if (pto < 0) {
  452. pto = -pto;
  453. print++;
  454. pfrom = 0;
  455. }
  456. }
  457. findt(int a)
  458. {
  459. int i, j, k;
  460. k = INT_MAX;
  461. if (dip != d) {
  462. if (dip->dimac && (i = dip->ditrap - a) > 0)
  463. k = i;
  464. return(k);
  465. }
  466. for (i = 0; i < NTRAP; i++) {
  467. if (mlist[i]) {
  468. if ((j = nlist[i]) < 0)
  469. j += pl;
  470. if ((j -= a) <= 0)
  471. continue;
  472. if (j < k)
  473. k = j;
  474. }
  475. }
  476. i = pl - a;
  477. if (k > i)
  478. k = i;
  479. return(k);
  480. }
  481. findt1(void)
  482. {
  483. int i;
  484. if (dip != d)
  485. i = dip->dnl;
  486. else
  487. i = numtabp[NL].val;
  488. return(findt(i));
  489. }
  490. void eject(Stack *a)
  491. {
  492. int savlss;
  493. if (dip != d)
  494. return;
  495. ejf++;
  496. if (a)
  497. ejl = a;
  498. else
  499. ejl = frame;
  500. if (trap)
  501. return;
  502. e1:
  503. savlss = lss;
  504. lss = findt(numtabp[NL].val);
  505. newline(0);
  506. lss = savlss;
  507. if (numtabp[NL].val && !trap)
  508. goto e1;
  509. }
  510. movword(void)
  511. {
  512. int w;
  513. Tchar i, *wp;
  514. int savwch, hys;
  515. over = 0;
  516. wp = wordp;
  517. if (!nwd) {
  518. while (cbits(*wp++) == ' ') {
  519. wch--;
  520. wne -= sps;
  521. }
  522. wp--;
  523. }
  524. if (wne > nel && !hyoff && hyf && (!nwd || nel > 3 * sps) &&
  525. (!(hyf & 02) || (findt1() > lss)))
  526. hyphen(wp);
  527. savwch = wch;
  528. hyp = hyptr;
  529. nhyp = 0;
  530. while (*hyp && *hyp <= wp)
  531. hyp++;
  532. while (wch) {
  533. if (hyoff != 1 && *hyp == wp) {
  534. hyp++;
  535. if (!wdstart || (wp > wdstart + 1 && wp < wdend &&
  536. (!(hyf & 04) || wp < wdend - 1) && /* 04 => last 2 */
  537. (!(hyf & 010) || wp > wdstart + 2))) { /* 010 => 1st 2 */
  538. nhyp++;
  539. storeline((Tchar)IMP, 0);
  540. }
  541. }
  542. i = *wp++;
  543. w = width(i);
  544. wne -= w;
  545. wch--;
  546. storeline(i, w);
  547. }
  548. if (nel >= 0) {
  549. nwd++;
  550. return(0); /* line didn't fill up */
  551. }
  552. if (TROFF)
  553. xbits((Tchar)HYPHEN, 1);
  554. hys = width((Tchar)HYPHEN);
  555. m1:
  556. if (!nhyp) {
  557. if (!nwd)
  558. goto m3;
  559. if (wch == savwch)
  560. goto m4;
  561. }
  562. if (*--linep != IMP)
  563. goto m5;
  564. if (!(--nhyp))
  565. if (!nwd)
  566. goto m2;
  567. if (nel < hys) {
  568. nc--;
  569. goto m1;
  570. }
  571. m2:
  572. if ((i = cbits(*(linep - 1))) != '-' && i != EMDASH) {
  573. *linep = (*(linep - 1) & SFMASK) | HYPHEN;
  574. w = width(*linep);
  575. nel -= w;
  576. ne += w;
  577. linep++;
  578. }
  579. m3:
  580. nwd++;
  581. m4:
  582. wordp = wp;
  583. return(1); /* line filled up */
  584. m5:
  585. nc--;
  586. w = width(*linep);
  587. ne -= w;
  588. nel += w;
  589. wne += w;
  590. wch++;
  591. wp--;
  592. goto m1;
  593. }
  594. void horiz(int i)
  595. {
  596. vflag = 0;
  597. if (i)
  598. pchar(makem(i));
  599. }
  600. void setnel(void)
  601. {
  602. if (!nc) {
  603. linep = line;
  604. if (un1 >= 0) {
  605. un = un1;
  606. un1 = -1;
  607. }
  608. nel = ll - un;
  609. ne = adsp = adrem = 0;
  610. }
  611. }
  612. getword(int x)
  613. {
  614. int j, k;
  615. Tchar i, *wp;
  616. int noword;
  617. int obits;
  618. j = noword = 0;
  619. if (x)
  620. if (pendw) {
  621. *pendw = 0;
  622. goto rtn;
  623. }
  624. if (wordp = pendw)
  625. goto g1;
  626. hyp = hyptr;
  627. wordp = word;
  628. over = wne = wch = 0;
  629. hyoff = 0;
  630. obits = chbits;
  631. while (1) { /* picks up 1st char of word */
  632. j = cbits(i = GETCH());
  633. if (j == '\n') {
  634. wne = wch = 0;
  635. noword = 1;
  636. goto rtn;
  637. }
  638. if (j == ohc) {
  639. hyoff = 1; /* 1 => don't hyphenate */
  640. continue;
  641. }
  642. if (j == ' ') {
  643. numtabp[HP].val += sps;
  644. widthp = sps;
  645. storeword(i, sps);
  646. continue;
  647. }
  648. break;
  649. }
  650. storeword(' ' | obits, sps);
  651. if (spflg) {
  652. storeword(' ' | obits, sps);
  653. spflg = 0;
  654. }
  655. g0:
  656. if (j == CONT) {
  657. pendw = wordp;
  658. nflush = 0;
  659. flushi();
  660. return(1);
  661. }
  662. if (hyoff != 1) {
  663. if (j == ohc) {
  664. hyoff = 2;
  665. *hyp++ = wordp;
  666. if (hyp > hyptr + NHYP - 1)
  667. hyp = hyptr + NHYP - 1;
  668. goto g1;
  669. }
  670. if (((j == '-' || j == EMDASH)) && !(i & ZBIT)) /* zbit avoids \X */
  671. if (wordp > word + 1) {
  672. hyoff = 2;
  673. *hyp++ = wordp + 1;
  674. if (hyp > hyptr + NHYP - 1)
  675. hyp = hyptr + NHYP - 1;
  676. }
  677. }
  678. j = width(i);
  679. numtabp[HP].val += j;
  680. storeword(i, j);
  681. g1:
  682. j = cbits(i = GETCH());
  683. if (j != ' ') {
  684. static char *sentchar = ".?!"; /* sentence terminators */
  685. if (j != '\n')
  686. goto g0;
  687. wp = wordp-1; /* handle extra space at end of sentence */
  688. while (wp >= word) {
  689. j = cbits(*wp--);
  690. if (j=='"' || j=='\'' || j==')' || j==']' || j=='*' || j==DAGGER)
  691. continue;
  692. for (k = 0; sentchar[k]; k++)
  693. if (j == sentchar[k]) {
  694. spflg++;
  695. break;
  696. }
  697. break;
  698. }
  699. }
  700. *wordp = 0;
  701. numtabp[HP].val += sps;
  702. rtn:
  703. for (wp = word; *wp; wp++) {
  704. if (ismot(j))
  705. break; /* drechsler */
  706. j = cbits(*wp);
  707. if (j == ' ')
  708. continue;
  709. if (!(isascii(j) && isdigit(j)) && j != '-')
  710. break;
  711. }
  712. if (*wp == 0) /* all numbers, so don't hyphenate */
  713. hyoff = 1;
  714. wdstart = 0;
  715. wordp = word;
  716. pendw = 0;
  717. *hyp++ = 0;
  718. setnel();
  719. return(noword);
  720. }
  721. void storeword(Tchar c, int w)
  722. {
  723. Tchar *savp;
  724. int i;
  725. if (wordp >= word + wdsize - 2) {
  726. wdsize += WDSIZE;
  727. savp = word;
  728. if (( word = (Tchar *)realloc((char *)word, wdsize * sizeof(Tchar))) != NULL) {
  729. if (wordp)
  730. wordp = word + (wordp - savp);
  731. if (pendw)
  732. pendw = word + (pendw - savp);
  733. if (wdstart)
  734. wdstart = word + (wdstart - savp);
  735. if (wdend)
  736. wdend = word + (wdend - savp);
  737. for (i = 0; i < NHYP; i++)
  738. if (hyptr[i])
  739. hyptr[i] = word + (hyptr[i] - savp);
  740. } else {
  741. if (over) {
  742. return;
  743. } else {
  744. flusho();
  745. ERROR "Word overflow." WARN;
  746. over++;
  747. c = LEFTHAND;
  748. w = width(LEFTHAND);
  749. }
  750. }
  751. }
  752. widthp = w;
  753. wne += w;
  754. *wordp++ = c;
  755. wch++;
  756. }
  757. Tchar gettch(void)
  758. {
  759. extern int c_isalnum;
  760. Tchar i;
  761. int j;
  762. if (TROFF)
  763. return getch();
  764. i = getch();
  765. j = cbits(i);
  766. if (ismot(i) || fbits(i) != ulfont)
  767. return(i);
  768. if (cu) {
  769. if (trtab[j] == ' ') {
  770. setcbits(i, '_');
  771. setfbits(i, FT); /* default */
  772. }
  773. return(i);
  774. }
  775. /* should test here for characters that ought to be underlined */
  776. /* in the old nroff, that was the 200 bit on the width! */
  777. /* for now, just do letters, digits and certain special chars */
  778. if (j <= 127) {
  779. if (!isalnum(j))
  780. setfbits(i, FT);
  781. } else {
  782. if (j < c_isalnum)
  783. setfbits(i, FT);
  784. }
  785. return(i);
  786. }