n9.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  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 "ext.h"
  11. #include "fns.h"
  12. /*
  13. * troff9.c
  14. *
  15. * misc functions
  16. */
  17. Tchar setz(void)
  18. {
  19. Tchar i;
  20. if (!ismot(i = getch()))
  21. i |= ZBIT;
  22. return(i);
  23. }
  24. void setline(void)
  25. {
  26. Tchar *i;
  27. Tchar c;
  28. int length;
  29. int j, w, cnt, delim, rem, temp;
  30. Tchar linebuf[NC];
  31. if (ismot(c = getch()))
  32. return;
  33. delim = cbits(c);
  34. vflag = 0;
  35. dfact = EM;
  36. length = quant(atoi0(), HOR);
  37. dfact = 1;
  38. if (!length) {
  39. eat(delim);
  40. return;
  41. }
  42. s0:
  43. if ((j = cbits(c = getch())) == delim || j == '\n') {
  44. ch = c;
  45. c = RULE | chbits;
  46. } else if (cbits(c) == FILLER)
  47. goto s0;
  48. w = width(c);
  49. if (w <= 0) {
  50. ERROR "zero-width underline character ignored" WARN;
  51. c = RULE | chbits;
  52. w = width(c);
  53. }
  54. i = linebuf;
  55. if (length < 0) {
  56. *i++ = makem(length);
  57. length = -length;
  58. }
  59. if (!(cnt = length / w)) {
  60. *i++ = makem(-(temp = ((w - length) / 2)));
  61. *i++ = c;
  62. *i++ = makem(-(w - length - temp));
  63. goto s1;
  64. }
  65. if (rem = length % w) {
  66. if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c) == ROOTEN)
  67. *i++ = c | ZBIT;
  68. *i++ = makem(rem);
  69. }
  70. if (cnt) {
  71. *i++ = RPT;
  72. *i++ = cnt;
  73. *i++ = c;
  74. }
  75. s1:
  76. *i = 0;
  77. eat(delim);
  78. pushback(linebuf);
  79. }
  80. eat(int c)
  81. {
  82. int i;
  83. while ((i = cbits(getch())) != c && i != '\n')
  84. ;
  85. return(i);
  86. }
  87. void setov(void)
  88. {
  89. int j, k;
  90. Tchar i, o[NOV+1];
  91. int delim, w[NOV+1];
  92. if (ismot(i = getch()))
  93. return;
  94. delim = cbits(i);
  95. for (k = 0; k < NOV && (j = cbits(i = getch())) != delim && j != '\n'; k++) {
  96. o[k] = i;
  97. w[k] = width(i);
  98. }
  99. o[k] = w[k] = 0;
  100. if (o[0])
  101. for (j = 1; j; ) {
  102. j = 0;
  103. for (k = 1; o[k] ; k++) {
  104. if (w[k-1] < w[k]) {
  105. j++;
  106. i = w[k];
  107. w[k] = w[k-1];
  108. w[k-1] = i;
  109. i = o[k];
  110. o[k] = o[k-1];
  111. o[k-1] = i;
  112. }
  113. }
  114. }
  115. else
  116. return;
  117. *pbp++ = makem(w[0] / 2);
  118. for (k = 0; o[k]; k++)
  119. ;
  120. while (k>0) {
  121. k--;
  122. *pbp++ = makem(-((w[k] + w[k+1]) / 2));
  123. *pbp++ = o[k];
  124. }
  125. }
  126. void setbra(void)
  127. {
  128. int k;
  129. Tchar i, *j, dwn;
  130. int cnt, delim;
  131. Tchar brabuf[NC];
  132. if (ismot(i = getch()))
  133. return;
  134. delim = cbits(i);
  135. j = brabuf + 1;
  136. cnt = 0;
  137. if (NROFF)
  138. dwn = (2 * t.Halfline) | MOT | VMOT;
  139. else
  140. dwn = EM | MOT | VMOT;
  141. while ((k = cbits(i = getch())) != delim && k != '\n' && j <= brabuf + NC - 4) {
  142. *j++ = i | ZBIT;
  143. *j++ = dwn;
  144. cnt++;
  145. }
  146. if (--cnt < 0)
  147. return;
  148. else if (!cnt) {
  149. ch = *(j - 2);
  150. return;
  151. }
  152. *j = 0;
  153. if (NROFF)
  154. *--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT;
  155. else
  156. *--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT;
  157. *--j &= ~ZBIT;
  158. pushback(brabuf);
  159. }
  160. void setvline(void)
  161. {
  162. int i;
  163. Tchar c, rem, ver, neg;
  164. int cnt, delim, v;
  165. Tchar vlbuf[NC];
  166. Tchar *vlp;
  167. if (ismot(c = getch()))
  168. return;
  169. delim = cbits(c);
  170. dfact = lss;
  171. vflag++;
  172. i = quant(atoi0(), VERT);
  173. dfact = 1;
  174. if (!i) {
  175. eat(delim);
  176. vflag = 0;
  177. return;
  178. }
  179. if ((cbits(c = getch())) == delim) {
  180. c = BOXRULE | chbits; /*default box rule*/
  181. } else
  182. getch();
  183. c |= ZBIT;
  184. neg = 0;
  185. if (i < 0) {
  186. i = -i;
  187. neg = NMOT;
  188. }
  189. if (NROFF)
  190. v = 2 * t.Halfline;
  191. else {
  192. v = EM;
  193. if (v < VERT) /* ATT EVK hack: Erik van Konijnenburg, */
  194. v = VERT; /* hvlpb!evkonij, ATT NSI Hilversum, Holland */
  195. }
  196. cnt = i / v;
  197. rem = makem(i % v) | neg;
  198. ver = makem(v) | neg;
  199. vlp = vlbuf;
  200. if (!neg)
  201. *vlp++ = ver;
  202. if (absmot(rem) != 0) {
  203. *vlp++ = c;
  204. *vlp++ = rem;
  205. }
  206. while (vlp < vlbuf + NC - 3 && cnt--) {
  207. *vlp++ = c;
  208. *vlp++ = ver;
  209. }
  210. *(vlp - 2) &= ~ZBIT;
  211. if (!neg)
  212. vlp--;
  213. *vlp = 0;
  214. pushback(vlbuf);
  215. vflag = 0;
  216. }
  217. #define NPAIR (NC/2-6) /* max pairs in spline, etc. */
  218. void setdraw(void) /* generate internal cookies for a drawing function */
  219. {
  220. int i, j, k, dx[NPAIR], dy[NPAIR], delim, type;
  221. Tchar c, drawbuf[NC];
  222. int drawch = '.'; /* character to draw with */
  223. /* input is \D'f dx dy dx dy ... c' (or at least it had better be) */
  224. /* this does drawing function f with character c and the */
  225. /* specified dx,dy pairs interpreted as appropriate */
  226. /* pairs are deltas from last point, except for radii */
  227. /* l dx dy: line from here by dx,dy */
  228. /* c x: circle of diameter x, left side here */
  229. /* e x y: ellipse of diameters x,y, left side here */
  230. /* a dx1 dy1 dx2 dy2:
  231. ccw arc: ctr at dx1,dy1, then end at dx2,dy2 from there */
  232. /* ~ dx1 dy1 dx2 dy2...:
  233. spline to dx1,dy1 to dx2,dy2 ... */
  234. /* b x c:
  235. built-up character of type c, ht x */
  236. /* f dx dy ...: f is any other char: like spline */
  237. if (ismot(c = getch()))
  238. return;
  239. delim = cbits(c);
  240. numerr.escarg = type = cbits(getch());
  241. if (type == '~') /* head off the .tr ~ problem */
  242. type = 's';
  243. for (i = 0; i < NPAIR ; i++) {
  244. skip();
  245. vflag = 0;
  246. dfact = EM;
  247. dx[i] = quant(atoi0(), HOR);
  248. if (dx[i] > MAXMOT)
  249. dx[i] = MAXMOT;
  250. else if (dx[i] < -MAXMOT)
  251. dx[i] = -MAXMOT;
  252. skip();
  253. if (type == 'c') {
  254. dy[i] = 0;
  255. goto eat;
  256. }
  257. vflag = 1;
  258. dfact = lss;
  259. dy[i] = quant(atoi0(), VERT);
  260. if (dy[i] > MAXMOT)
  261. dy[i] = MAXMOT;
  262. else if (dy[i] < -MAXMOT)
  263. dy[i] = -MAXMOT;
  264. eat:
  265. if (cbits(c = getch()) != ' ') { /* must be the end */
  266. if (cbits(c) != delim) {
  267. drawch = cbits(c);
  268. getch();
  269. }
  270. i++;
  271. break;
  272. }
  273. }
  274. dfact = 1;
  275. vflag = 0;
  276. if (TROFF) {
  277. drawbuf[0] = DRAWFCN | chbits | ZBIT;
  278. drawbuf[1] = type | chbits | ZBIT;
  279. drawbuf[2] = drawch | chbits | ZBIT;
  280. for (k = 0, j = 3; k < i; k++) {
  281. drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NMOT | -dx[k]));
  282. drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k]));
  283. }
  284. if (type == DRAWELLIPSE) {
  285. drawbuf[5] = drawbuf[4] | NMOT; /* so the net vertical is zero */
  286. j = 6;
  287. } else if (type == DRAWBUILD) {
  288. drawbuf[4] = drawbuf[3] | NMOT; /* net horizontal motion is zero */
  289. drawbuf[2] &= ~ZBIT; /* width taken from drawing char */
  290. j = 5;
  291. }
  292. drawbuf[j++] = DRAWFCN | chbits | ZBIT; /* marks end for ptout */
  293. drawbuf[j] = 0;
  294. pushback(drawbuf);
  295. }
  296. }
  297. void casefc(void)
  298. {
  299. int i;
  300. Tchar j;
  301. gchtab[fc] &= ~FCBIT;
  302. fc = IMP;
  303. padc = ' ';
  304. if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n')
  305. return;
  306. fc = i;
  307. gchtab[fc] |= FCBIT;
  308. if (skip() || ismot(ch) || (ch = cbits(ch)) == fc)
  309. return;
  310. padc = ch;
  311. }
  312. Tchar setfield(int x)
  313. {
  314. Tchar rchar, ii, jj, *fp;
  315. Tchar **pp, *padptr[NPP];
  316. Tchar fbuf[FBUFSZ];
  317. int i, j, length, ws, npad, temp, type, savepos, savfc, savtc, savlc;
  318. static Tchar wbuf[] = { WORDSP, 0};
  319. if (x == tabch)
  320. rchar = tabc | chbits;
  321. else if (x == ldrch)
  322. rchar = dotc | chbits;
  323. else
  324. rchar = 0;
  325. temp = npad = ws = 0;
  326. savfc = fc;
  327. savtc = tabch;
  328. savlc = ldrch;
  329. tabch = ldrch = fc = IMP;
  330. savepos = numtabp[HP].val;
  331. gchtab[tabch] &= ~TABBIT;
  332. gchtab[ldrch] &= ~LDRBIT;
  333. gchtab[fc] &= ~FCBIT;
  334. gchtab[IMP] |= TABBIT|LDRBIT|FCBIT;
  335. for (j = 0; ; j++) {
  336. if ((tabtab[j] & TABMASK) == 0) {
  337. if (x == savfc)
  338. ERROR "zero field width." WARN;
  339. jj = 0;
  340. goto rtn;
  341. }
  342. if ((length = ((tabtab[j] & TABMASK) - numtabp[HP].val)) > 0 )
  343. break;
  344. }
  345. type = tabtab[j] & ~TABMASK;
  346. fp = fbuf;
  347. pp = padptr;
  348. if (x == savfc) {
  349. while (1) {
  350. j = cbits(ii = getch());
  351. jj = width(ii);
  352. widthp = jj;
  353. numtabp[HP].val += jj;
  354. if (j == padc) {
  355. npad++;
  356. *pp++ = fp;
  357. if (pp > padptr + NPP - 1)
  358. break;
  359. goto s1;
  360. } else if (j == savfc)
  361. break;
  362. else if (j == '\n') {
  363. temp = j;
  364. if (nlflg && ip == 0) {
  365. numtabp[CD].val--;
  366. nlflg = 0;
  367. }
  368. break;
  369. }
  370. ws += jj;
  371. s1:
  372. *fp++ = ii;
  373. if (fp > fbuf + FBUFSZ - 3)
  374. break;
  375. }
  376. if (ws)
  377. *fp++ = WORDSP;
  378. if (!npad) {
  379. npad++;
  380. *pp++ = fp;
  381. *fp++ = 0;
  382. }
  383. *fp++ = temp;
  384. *fp = 0;
  385. temp = i = (j = length - ws) / npad;
  386. i = (i / HOR) * HOR;
  387. if ((j -= i * npad) < 0)
  388. j = -j;
  389. ii = makem(i);
  390. if (temp < 0)
  391. ii |= NMOT;
  392. for (; npad > 0; npad--) {
  393. *(*--pp) = ii;
  394. if (j) {
  395. j -= HOR;
  396. (*(*pp)) += HOR;
  397. }
  398. }
  399. pushback(fbuf);
  400. jj = 0;
  401. } else if (type == 0) {
  402. /*plain tab or leader*/
  403. if ((j = width(rchar)) > 0) {
  404. int nchar = length / j;
  405. while (nchar-->0 && pbp < &pbbuf[NC-3]) {
  406. numtabp[HP].val += j;
  407. widthp = j;
  408. *pbp++ = rchar;
  409. }
  410. length %= j;
  411. }
  412. if (length)
  413. jj = length | MOT;
  414. else
  415. jj = getch0();
  416. if (savepos > 0)
  417. pushback(wbuf);
  418. } else {
  419. /*center tab*/
  420. /*right tab*/
  421. while ((j = cbits(ii = getch())) != savtc && j != '\n' && j != savlc) {
  422. jj = width(ii);
  423. ws += jj;
  424. numtabp[HP].val += jj;
  425. widthp = jj;
  426. *fp++ = ii;
  427. if (fp > fbuf + FBUFSZ - 3)
  428. break;
  429. }
  430. *fp++ = ii;
  431. *fp = 0;
  432. if (type == RTAB)
  433. length -= ws;
  434. else
  435. length -= ws / 2; /*CTAB*/
  436. pushback(fbuf);
  437. if ((j = width(rchar)) != 0 && length > 0) {
  438. int nchar = length / j;
  439. while (nchar-- > 0 && pbp < &pbbuf[NC-3])
  440. *pbp++ = rchar;
  441. length %= j;
  442. }
  443. if (savepos > 0)
  444. pushback(wbuf);
  445. length = (length / HOR) * HOR;
  446. jj = makem(length);
  447. if (nlflg) {
  448. if (ip == 0)
  449. numtabp[CD].val--;
  450. nlflg = 0;
  451. }
  452. }
  453. rtn:
  454. gchtab[fc] &= ~FCBIT;
  455. gchtab[tabch] &= ~TABBIT;
  456. gchtab[ldrch] &= ~LDRBIT;
  457. fc = savfc;
  458. tabch = savtc;
  459. ldrch = savlc;
  460. gchtab[fc] |= FCBIT;
  461. gchtab[tabch] = TABBIT;
  462. gchtab[ldrch] |= LDRBIT;
  463. numtabp[HP].val = savepos;
  464. return(jj);
  465. }