n9.c 8.9 KB

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