|
|
1.1 root 1: /*
2: * process.c
3: * nroff/Troff.
4: * Formatting.
5: * This source module does the serious work.
6: * Environmental variables:
7: * nlinptr points to next location in linebuf[]
8: * nlinsiz contains current horizontal size of linebuf[]
9: * nlindir contains non-space directive count
10: * llinsiz contains horizontal size to end of last word which fits
11: * tlinsiz contains horizontal size to previous tab (before expansion)
12: * Very confusing, the way the buffering works should be cleaned up eventually.
13: */
14:
15: #include <ctype.h>
16: #include "roff.h"
17:
18: #define CHYPHEN '-' /* hyphenation character */
19:
20: /*
21: * Make sure there is space to add another command.
22: */
23: chkcode()
24: {
25: if (nlinptr >= &linebuf[LINSIZE])
26: panic("line buffer overflow");
27: }
28:
29: /* Flush buffered data to avoid buffer overflow. */
30: flush(hpos) register int hpos;
31: {
32: if (hpos)
33: hormove(-hpos); /* reset output writer position to margin */
34: if (cdivp == mdivp)
35: flushl(linebuf, nlinptr);
36: else
37: flushd(linebuf, nlinptr);
38: setline(); /* reset buffer pointers */
39: if (hpos)
40: hormove(hpos); /* restore horizontal position */
41: }
42:
43: /*
44: * Add a character.
45: * Bump the directive count and nlinsiz.
46: */
47: addchar(f, w) int f; register int w;
48: {
49: chkcode();
50: nlinptr->c_arg.c_code = f & 0xFF;
51: nlinptr++->c_arg.c_move = w;
52: nlindir++;
53: nlinsiz += w;
54: spcnt = 0;
55: }
56:
57: /*
58: * Add a directive which takes an integer argument.
59: */
60: addidir(d, i)
61: {
62: chkcode();
63: nlinptr->l_arg.c_code = d;
64: nlinptr++->l_arg.c_iarg = i;
65: spcnt = 0;
66: }
67:
68: /*
69: * Add a transparent buffer directive.
70: */
71: addtrab(bp) char *bp;
72: {
73: chkcode();
74: nlinptr->b_arg.c_code = DTRAB;
75: nlinptr++->b_arg.c_bufp = bp;
76: }
77:
78: /*
79: * Process input, formatting text.
80: */
81: process()
82: {
83: register int c, w;
84: REG *rp;
85: int lastc, n;
86: char charbuf[CBFSIZE], name[2];
87: unsigned char *cp;
88:
89: c = '\n';
90: for (;;) {
91: lastc = c;
92: c = getf(1);
93: next:
94: switch (c) {
95: case EOF: /* End of file */
96: dprintd(DBGFILE|DBGPROC, ".end of file\n");
97: return;
98: case EBEG: /* Open brace \{ */
99: case EEND: /* Close brace \} */
100: continue; /* ignore braces in plain text */
101: case EESC: /* Printable version of escape */
102: dprintd(DBGPROC, ".printable escape\n");
103: character(esc);
104: continue;
105: case EACA: /* Acute accent */
106: dprintd(DBGPROC, ".acute accent\n");
107: character('\'');
108: continue;
109: case EGRA: /* Grave accent */
110: dprintd(DBGPROC, ".grave accent\n");
111: character('`');
112: continue;
113: case EMIN: /* Minus sign */
114: dprintd(DBGPROC, ".minus sign\n");
115: character('-');
116: continue;
117: case EUNP: /* Unpaddable space */
118: dprintd(DBGPROC, ".unpaddable space\n");
119: hormove(ssz);
120: continue;
121: case EM06: /* 1/6 em (narrow space) */
122: dprintd(DBGPROC, ".narrow space\n");
123: hormove(unit(SMNARS, SDNARS));
124: continue;
125: case EM12: /* 1/12 em (half narrow space) */
126: dprintd(DBGPROC, ".half narrow space\n");
127: hormove(unit(SMNARS, SDNARS*2));
128: continue;
129: case ENOP: /* Zero width character */
130: dprintd(DBGPROC, ".zero width character\n");
131: continue;
132: case ETLI: /* Transparent line indicator */
133: dprintd(DBGPROC, ".transparent line indicator\n");
134: for (cp = charbuf; ; c = *cp++ = getl(0)) {
135: if (c == '\n' || cp == &charbuf[CBFSIZE-1]) {
136: *cp = '\0';
137: addtrab(duplstr(charbuf));
138: if (c == '\n')
139: break;
140: cp = charbuf;
141: }
142: }
143: continue;
144: case EHYP: /* Potential hyphenation break */
145: dprintd(DBGPROC, ".hyphen break\n");
146: addidir(DHYPH, 0);
147: continue;
148: case EBRA: /* Bracket building function */
149: dprintd(DBGPROC, ".bracket building\n");
150: #if 1
151: printu("bracket building"); /* $$TO_DO$$ */
152: continue;
153: #else
154: /*
155: * The following does not work with special characters
156: * which include font escape sequences.
157: */
158: scandel(charbuf, CBFSIZE);
159: for (w = 0, cp = charbuf; *cp; cp++) {
160: n = width(trantab[*cp]);
161: if (n > w)
162: w = n; /* max width */
163: }
164: n = cp - charbuf; /* count */
165: vermove(unit(-SMVEMS * (n - 1), SDVEMS * 2));
166: for (cp = charbuf; *cp; cp++) {
167: addchar(trantab[*cp], 0);
168: vermove(unit(SMVEMS, SDVEMS));
169: }
170: vermove(unit(-SMVEMS * (n + 1), SDVEMS * 2));
171: hormove(w);
172: continue;
173: #endif
174: case EINT: /* Interrupt text processing */
175: dprintd(DBGPROC, ".interrupt proc\n");
176: if ((c=getf(0)) != '\n')
177: goto next;
178: continue;
179: case EVNF: /* 1/2 em vertical motion */
180: dprintd(DBGPROC, ".half vertical\n");
181: vermove(unit(SMVEMS, SDVEMS*2));
182: continue;
183: case EFON: /* Change font */
184: if ((c=getf(0)) != '(') {
185: name[0] = c;
186: name[1] = '\0';
187: } else {
188: name[0] = getf(0);
189: name[1] = getf(0);
190: }
191: dprint3(DBGPROC, ".font change to %c%c\n", name[0], name[1]);
192: setfont(name, 1);
193: continue;
194: case EHMT: /* Local horizontal motion */
195: n = scandel(charbuf, CBFSIZE) ? numb(charbuf, SMEMSP, SDEMSP) : 0;
196: dprint2(DBGPROC, ".local horiz motion = %d\n", n);
197: hormove(n);
198: continue;
199: case EMAR: /* Mark horizontal input place */
200: name[0] = c = getf(0);
201: name[1] = '\0';
202: dprint3(DBGPROC, ".mark horizontal input in %c at %d\n", c, nlinsiz);
203: rp = getnreg(name);
204: rp->n_reg.r_nval = nlinsiz;
205: continue;
206: case EHLF: /* Horizontal line drawing function */
207: n = scandel(charbuf, CBFSIZE) ? numb(charbuf, 1L, 1L) : 0;
208: dprint2(DBGPROC, ".horiz line %d\n", n);
209: draw_line(n, 1);
210: continue;
211: case EVLF: /* Vertical line drawing function */
212: n = scandel(charbuf, CBFSIZE) ? numb(charbuf, 1L, 1L) : 0;
213: dprint2(DBGPROC, ".vert line %d\n", n);
214: draw_line(n, 0);
215: continue;
216: case EOVS: /* Overstrike */
217: dprintd(DBGPROC, ".overstrike\n");
218: scandel(charbuf, CBFSIZE);
219: for (w = 0, cp = charbuf; *cp; cp++) {
220: n = width(trantab[*cp]);
221: if (n > w)
222: w = n; /* max width */
223: }
224: for (cp = charbuf; *cp; cp++) {
225: n = width(trantab[*cp]);
226: hormove((w-n)/2);
227: addchar(trantab[*cp], 0); /* centered */
228: hormove((n-w)/2);
229: }
230: hormove(w);
231: continue;
232: case ESPR: /* Break and spread output line */
233: dprintd(DBGPROC, ".break and spread\n");
234: wordbreak(DNULL);
235: linebreak(1);
236: continue;
237: case EVRM: /* Reverse 1 em vertically */
238: dprintd(DBGPROC, ".reverse vertical\n");
239: vermove(unit(-SMVEMS, SDVEMS));
240: continue;
241: case EPSZ: /* Change pointsize */
242: dprintd(DBGPROC, ".pointsize change\n");
243: if (scanoptdel(charbuf, CBFSIZE)) {
244: n = number(charbuf, SMPOIN, SDPOIN, psz, 0, oldpsz);
245: if (n == 0)
246: n = oldpsz;
247: newpsze(n);
248: }
249: continue;
250: case EVRN: /* Reverse 1 en vertically */
251: dprintd(DBGPROC, ".reverse 1 en vert\n");
252: vermove(unit(-SMVEMS, SDVEMS*2));
253: continue;
254: case EVMT: /* Local vertical motion */
255: n = scandel(charbuf, CBFSIZE) ? number(charbuf, SMUNIT, SDUNIT, 0, 1, 0) : 0;
256: dprint2(DBGPROC, ".local vert move %d\n", n);
257: vermove(n);
258: continue;
259: case EXLS: /* Extra line spacing */
260: n = scandel(charbuf, CBFSIZE) ? number(charbuf, SMUNIT, SDUNIT, 0, 1, 0) : 0;
261: dprint2(DBGPROC, ".extra line space %d\n", n);
262: if (n < 0) {
263: if (-n > preexls)
264: preexls = -n;
265: } else {
266: if (n > posexls)
267: posexls = n;
268: }
269: continue;
270: case EZWD: /* Print character with zero width */
271: dprintd(DBGPROC, ".print with zero width\n");
272: addchar(trantab[getf(0)], 0);
273: continue;
274: case ECOD: /* Processed text */
275: dprintd(DBGPROC, ".processed text\n");
276: c = diverse();
277: lastc = '\n';
278: goto next;
279: case '\001':
280: case ELDR:
281: dprintd(DBGPROC, ".leader character\n");
282: wordbreak(DHMOV);
283: movetab(ldc);
284: continue;
285: case '\t':
286: case ETAB:
287: dprintd(DBGPROC, ".tab\n");
288: wordbreak(DHMOV);
289: movetab(tbc);
290: continue;
291: case '\n':
292: dprintd(DBGPROC, ".newline\n");
293: wordbreak(DPADC);
294: switch (lastc) {
295: case '\n':
296: setbreak();
297: nlindir++;
298: setbreak();
299: break;
300: case '.':
301: case '!':
302: case '?':
303: pad(2 * ssz);
304: break;
305: default:
306: pad(ssz);
307: }
308: if (fill == 0 || cec != 0) {
309: linebreak(1);
310: if (cec != 0)
311: --cec;
312: }
313: if (ulc) {
314: if (--ulc == 0)
315: setfontnum(ufp, 1);
316: }
317: if (inpltrc) {
318: if (--inpltrc == 0)
319: execute(inptrap);
320: }
321: continue;
322: case ' ':
323: if (lastc == '\n')
324: setbreak();
325: else
326: wordbreak(DPADC);
327: if (fill || varsp) {
328: pad(ssz);
329: continue;
330: }
331: case EDWS: /* Digit width space */
332: dprintd(DBGPROC, ".digit width space\n");
333: hormove(width('0'));
334: continue;
335: default:
336: if (lastc == '\n') {
337: if (c == ccc) {
338: request();
339: c = '\n';
340: continue;
341: } else if (c == nbc) {
342: nbrflag = 1;
343: request();
344: nbrflag = 0;
345: c = '\n';
346: continue;
347: }
348: }
349: #if 0
350: /* Ignore non-ASCII characters. */
351: if (!isascii(c))
352: continue;
353: #endif
354: character(trantab[c]);
355: }
356: }
357: }
358:
359: /*
360: * Draw a horizontal (if hflag) or vertical (if !hflag) line of given length.
361: * This does not handle line drawing with characters other than '_' or '|';
362: * to make it do so, modify number() to store a pointer past the last used char.
363: * If len is positive, draw right or draw down.
364: * If len is negative, move horizontally and then draw right, or draw up.
365: */
366: draw_line(len, hflag) register int len; int hflag;
367: {
368: register int c, move, hmove, vmove, hpos, negflag, count, excess, savfont;
369:
370: if (len == 0)
371: return; /* no work */
372: hpos = nlinsiz; /* current horizontal position */
373: if (hflag && len > 0)
374: hpos += len; /* hpos after line drawn */
375:
376: #if 1
377: /*
378: * Implement PostScript lines with PostScript.
379: * If conditionalized out, troff -p uses character line drawing.
380: */
381: if (pflag) {
382: addidir((hflag) ? DHLIN : DVLIN, len);
383: flush(hpos);
384: return;
385: }
386: #endif
387: negflag = (len < 0); /* movement is negative */
388: if (negflag)
389: len = -len; /* absolute length */
390: savfont = curfont;
391: dev_font(ufn); /* use underline font */
392: if (hflag) {
393: /* Horizontal line. */
394: c = '_'; /* character */
395: move = hmove = width(c); /* horizontal movement */
396: vmove = 0; /* vertical movement */
397: } else {
398: /* Vertical line. */
399: c = '|'; /* character */
400: hmove = 0; /* effective width */
401: move = vmove = unit(SMVEMS, SDVEMS); /* movement */
402: hormove(-width(c)/2); /* center the '|' */
403: if (!negflag)
404: vermove(vmove); /* start below current pos */
405: }
406: count = len / move; /* number of full chars */
407: excess = len % move; /* remainder */
408: if (negflag) {
409: if (hflag)
410: hormove(-len); /* back up horizontally */
411: else {
412: vmove = -vmove; /* draw vertical line upward */
413: excess = -excess;
414: }
415: }
416:
417: /* Output single '_' or '|' characters, move appropriately. */
418: while (count--) {
419: addchar(c, hmove);
420: if (vmove)
421: vermove(vmove);
422: }
423:
424: /* Fudge last character position for remaining excess. */
425: if (excess != 0) {
426: if (hflag)
427: hormove(excess - hmove);
428: else
429: vermove(excess - vmove);
430: addchar(c, hmove);
431: if (vmove)
432: vermove(vmove);
433: }
434:
435: /* Adjust final position. */
436: if (!hflag) {
437: hormove(width(c)/2);
438: if (!negflag)
439: vermove(-vmove);
440: }
441:
442: /* Restore original font. */
443: dev_font(savfont);
444:
445: /* Flush to avoid buffer overflow. */
446: flush(hpos);
447: }
448:
449: /*
450: * Horizontal move code.
451: */
452: hormove(n)
453: int n;
454: {
455: addidir(DHMOV, n);
456: nlinsiz += n;
457: }
458:
459: /*
460: * Vertical move code.
461: */
462: vermove(n)
463: int n;
464: {
465: addidir(DVMOV, n);
466: cdivp->d_rpos += n;
467: }
468:
469: /*
470: * Character code.
471: */
472: character(f) register int f;
473: {
474: register int w;
475: CODE *cp;
476:
477: /* Should this complain about 0-width characters? Silent for now. */
478: w = width(f); /* scaled width */
479: dprint3(DBGCHAR, "** char ='%c', width = %d\n", f, w);
480: if (csz != 0 && csz != w) {
481: /*
482: * Constant width desired.
483: * Adjust previous character width so this character
484: * ends up centered in the constant width space.
485: */
486: w = (csz-w) / 2; /* previous char width adjust */
487: cp = llinptr - 1;
488: if (cp >= linebuf && is_char(cp->c_arg.c_code))
489: cp->c_arg.c_move += w;
490: else
491: hormove(w);
492: w = csz - w; /* current char width adjust */
493: }
494: addchar(f, w); /* output a character */
495: }
496:
497: /*
498: * Read text from a diversion.
499: * Whoever thought up the way diversions work in NROFF/TROFF
500: * should have done something else.
501: */
502: int
503: diverse()
504: {
505: register int code, arg;
506: int c, lastcode, cvls, clsp;
507: char *tp;
508:
509: lastcode = ' ';
510: for (c = ECOD; c == ECOD; c = getf(1)) {
511: code = codeval.l_arg.c_code;
512: arg = codeval.l_arg.c_iarg;
513: #if 0
514: fprintf(stderr, "diverse(): code=%d arg=%d\n", code, arg);
515: #endif
516: switch (code) {
517: case DSPAR:
518: if (arg==0) {
519: break; /* discard empty newline codes */
520: } else if (fill) {
521: wordbreak(DPADC);
522: padspace(lastcode);
523: } else {
524: wordbreak(DNULL);
525: cvls = vls;
526: clsp = lsp;
527: vls = 0;
528: lsp = 1;
529: linebreak(1);
530: vls = cvls;
531: lsp = clsp;
532: sspace(arg);
533: }
534: if (inpltrc && --inpltrc == 0)
535: execute(inptrap);
536: break;
537: case DPADC:
538: wordbreak(DPADC);
539: if (fill)
540: padspace(lastcode);
541: else
542: pad(arg);
543: break;
544: case DHYPC:
545: if (fill) {
546: register int c;
547:
548: addidir(DHYPH, 0);
549: while ((c=getf(0))==ECOD
550: && codeval.l_arg.c_code==DSPAR
551: && codeval.l_arg.c_iarg==0 )
552: ;
553: if (c!=ECOD || codeval.l_arg.c_code!=DSPAR)
554: panic("cannot dehyphenate");
555: } else {
556: nlindir++;
557: addidir(code, arg);
558: nlinsiz += arg;
559: }
560: break;
561: case DHMOV:
562: nlinsiz += arg;
563: /* fall through... */
564: case DNULL:
565: case DVMOV:
566: case DHYPH:
567: addidir(code, arg);
568: break;
569: case DFONT:
570: dev_font(arg);
571: break;
572: case DPSZE:
573: dev_ps(arg);
574: break;
575: case DTRAB:
576: tp = codeval.b_arg.c_bufp;
577: adscore(tp);
578: strp->x3.s_srel = tp;
579: break;
580: default:
581: addchar(code, codeval.c_arg.c_move);
582: break;
583: }
584: lastcode = code;
585: }
586: return c;
587: }
588:
589: pad(n) register int n;
590: {
591: llinptr->l_arg.c_iarg += n;
592: nlinsiz += n;
593: spcnt += n;
594: }
595:
596: padspace(lastcode) int lastcode;
597: {
598: switch (lastcode) {
599: case '!':
600: case '?':
601: case '.':
602: pad(2 * ssz);
603: break;
604: default:
605: pad(ssz);
606: break;
607: }
608: }
609:
610: /*
611: * End the current line and left justify it.
612: */
613: setbreak()
614: {
615: register int savfill;
616:
617: #if 0
618: fprintf(stderr, "setbreak()\n");
619: #endif
620: if (nbrflag)
621: return;
622: wordbreak(DNULL);
623: savfill = fill;
624: fill = 0;
625: linebreak(1);
626: fill = savfill;
627: }
628:
629: /*
630: * End the current word. The given directive type is added onto
631: * the end of the line.
632: */
633: wordbreak(dir) int dir;
634: {
635: int n, s, d;
636:
637: #if 0
638: fprintf(stderr, "wordbreak(%d)\n", dir);
639: #endif
640: if (nlindir == llindir)
641: return;
642: if (llinptr == linebuf)
643: setwork();
644: else if (fill != 0 && nlinsiz > lln) {
645: n = nlinptr - (llinptr+1);
646: s = nlinsiz - llinsiz - llinptr->l_arg.c_iarg;
647: d = nlindir - llindir;
648: if (hyp==0 || (hypf = fitword(&n, &s, &d))==0)
649: copystr(wordbuf, llinptr+1, sizeof (CODE), n);
650: if (n > WORSIZE)
651: panic("word buffer overflow");
652: linebreak(0);
653: hypf = 0;
654: copystr(nlinptr, wordbuf, sizeof (CODE), n);
655: nlinptr += n;
656: nlinsiz += s;
657: nlindir += d;
658: setwork();
659: }
660: if (mrc != '\0') /* Added by dag */
661: mrch = mrc;
662: llinptr = nlinptr;
663: llinsiz = nlinsiz;
664: llindir = nlindir;
665: addidir(dir, 0);
666: }
667:
668: /*
669: * Set up working parameters for the line.
670: */
671: setwork()
672: {
673: if (tif)
674: tif = 0;
675: else
676: tin = ind;
677: linebuf[0].l_arg.c_iarg += tin;
678: llinsiz += tin;
679: nlinsiz += tin;
680: tlinsiz += tin;
681: }
682:
683: /*
684: * Try to hyphenate and fit the last word in a line.
685: * This routine is really part of the routine 'wordbreak'.
686: * The arguments are pointers to variables in 'wordbreak'.
687: */
688: fitword(np, sp, dp) int *dp; int *sp; int *np;
689: {
690: CODE *wp;
691: int hflag, b1, b2, h, d, s, n, sav;
692: register CODE *cp;
693: register int c;
694: register char *hp;
695:
696: hyphen(wp=llinptr+1, nlinptr);
697: h = width(CHYPHEN);
698: b1 = nlinsiz - lln;
699: b2 = b1 + h;
700: d = 0;
701: s = 0;
702: n = 0;
703: cp = nlinptr;
704: hp = &hyphbuf[nlinptr-wp];
705: for (;;) {
706: if (--cp < wp)
707: return 0;
708: c = cp->l_arg.c_code;
709: if (cp>wp && c==CHYPHEN && s>=b1) {
710: hflag = 0;
711: break;
712: }
713: if (*--hp) {
714: if (s >= b2) {
715: hflag = 1;
716: break;
717: }
718: }
719: if (is_char(c)) {
720: d++;
721: s += cp->c_arg.c_move;
722: continue;
723: }
724: if (c==DHMOV || c==DPADC) {
725: s += cp->l_arg.c_iarg;
726: continue;
727: }
728: }
729: n = nlinptr - ++cp;
730: copystr(wordbuf, cp, sizeof (CODE), n);
731: llinptr = cp;
732: llinsiz = nlinsiz - s;
733: llindir = nlindir - d;
734: if (hflag) {
735: nlinptr = llinptr;
736: sav = nlinsiz;
737: addchar(CHYPHEN, h);
738: nlinsiz = sav;
739: llinptr = nlinptr;
740: llinsiz += h;
741: llindir = nlindir;
742: }
743: *dp = d;
744: *sp = s;
745: *np = n;
746: return 1;
747: }
748:
749: /*
750: * End the current line.
751: * This must be called after calling wordbreak.
752: */
753: linebreak(flag) int flag;
754: {
755: int slsiz, sldir;
756: CODE *slptr;
757:
758: #if 0
759: fprintf(stderr, "linebreak() llindir=%d\n", llindir);
760: #endif
761: if (llindir == 0) {
762: if (nlinptr != llinptr)
763: lineflush();
764: return;
765: }
766: movetab(EOF);
767: justify();
768: if (mrch != '\0' && llinsiz != 0) {
769:
770: /* Output margin character at mar from right margin. */
771: slsiz = nlinsiz;
772: sldir = nlindir;
773: slptr = nlinptr;
774: nlinsiz = llinsiz;
775: nlinptr = llinptr;
776: nlindir = llindir;
777: #if 0
778: /* Debug print-out to stderr */
779: fprintf(stderr, "margin char %c %d %d %d %d\n",
780: mrch, mar, lln, llinsiz, (lln-llinsiz) + mar);
781: #endif
782: hormove((lln - llinsiz) + mar);
783: character(mrch);
784: llinsiz = nlinsiz;
785: llindir = nlindir;
786: llinptr = nlinptr;
787: nlinsiz = slsiz;
788: nlindir = sldir;
789: nlinptr = slptr;
790: mrch = '\0';
791: }
792: if (llinsiz > cdivp->d_maxw)
793: cdivp->d_maxw = llinsiz;
794: sspace(preexls);
795: if (cdivp == mdivp) {
796: n_reg = llinsiz - linebuf[0].l_arg.c_iarg;
797: /* Kludge nroff output page offset; for troff, cf. output.c. */
798: if (ntroff == NROFF)
799: linebuf[0].l_arg.c_iarg += pof;
800: flushl(linebuf, llinptr);
801: nsm = 0;
802: } else
803: flushd(linebuf, llinptr);
804: if (flag && nlinptr != llinptr)
805: lineflush();
806: a_reg = posexls;
807: setline();
808: lspace(vls+posexls);
809: nrnlreg->n_reg.r_nval = mdivp->d_rpos;
810: sspace((lsp-1)*vls);
811: }
812:
813: /*
814: * The unflushed part of a buffered line can contain significant directives,
815: * notably pointsize and font changes.
816: * This flushes directives which would otherwise get ignored.
817: * There must be a better way...
818: */
819: lineflush()
820: {
821: register CODE *cp;
822:
823: for (cp = llinptr; cp < nlinptr; cp++) {
824: switch(cp->l_arg.c_code) {
825: case DFONT: break;
826: case DPSZE: break;
827: default: continue;
828: }
829: if (cdivp == mdivp)
830: flushl(cp, cp+1);
831: else
832: flushd(cp, cp+1);
833: }
834: setline();
835: }
836:
837: /*
838: * Justify the current line.
839: */
840: justify()
841: {
842: register CODE *cp, *cp0;
843: int t;
844: register int n, r;
845:
846: n = cec ? CJUS : (fill==0||adm==0) ? LJUS : adj;
847: switch (n) {
848: case LJUS:
849: n = 0;
850: break;
851: case CJUS:
852: n = (lln-llinsiz) / 2;
853: break;
854: case RJUS:
855: n = lln - llinsiz;
856: break;
857: case FJUS:
858: r = 0;
859: /*
860: * Walk backward through the line looking for horizontal move.
861: * If found, do not pad characters to its left.
862: */
863: for (cp0 = llinptr-1; cp0 > linebuf; cp0--)
864: if (cp0->l_arg.c_code == DHMOV)
865: break;
866: for (cp = cp0; cp < llinptr; cp++)
867: if (cp->l_arg.c_code == DPADC)
868: r++; /* paddable character count */
869: if (r == 0)
870: return; /* no paddable characters */
871: n = lln - llinsiz; /* padding required */
872:
873: /*
874: * Because tabs get expanded ex post facto,
875: * a tab in fill mode can make the line grow too large.
876: * If the line requires negative padding, tough matzohs.
877: * Avoid tabs in fill mode!
878: */
879: if (n < 0)
880: return;
881: t = n%r; /* padding remainder */
882: n = 1 + n/r; /* starting pad amount */
883: r = t; /* to do before decrementing */
884: for (cp = cp0; cp < llinptr; cp++) {
885: if (cp->l_arg.c_code != DPADC)
886: continue;
887: if (r-- == 0)
888: --n; /* decrement padding amount */
889: cp->l_arg.c_iarg += n; /* pad by n */
890: }
891: llinsiz = lln; /* dag for mrc/mrch */
892: return;
893: }
894: llinsiz += n; /* dag for mrc/mrch */
895: linebuf[0].l_arg.c_iarg += n;
896: }
897:
898: /*
899: * Tab to the next tab stop, filling intermediate space with character c.
900: * Because center and right justified tab spacing is determined by the
901: * text following the tab, the code determines the spacing for
902: * the tab before the one entered; arg c==EOF is passed
903: * at the end of a line to finish up the final tab stop.
904: * This must be called right after calling wordbreak().
905: */
906: movetab(c) int c;
907: {
908: register TAB *tp;
909: int n, w, d2, savfont, ls;
910: register int d, d1;
911: register int pos;
912:
913: ls = (nlinsiz != llinsiz) ? nlinsiz : llinsiz;
914: if (spcnt) {
915: /* Adjust for space padding following tab. */
916: llinsiz -= spcnt;
917: ls -= spcnt;
918: }
919: tp = tabptr;
920: pos = tp->t_pos;
921: if (cdivp == mdivp)
922: pos += tin; /* relative to indent */
923: #if 0
924: fprintf(stderr, "movetab(%d) tab#%d ltabchr=%d pos=%d tlinsiz=%d ls=%d\n",
925: c, tabptr-tab, ltabchr, pos, tlinsiz, ls);
926: #endif
927: switch (tp->t_jus) {
928: case LJUS:
929: d = pos - tlinsiz;
930: break;
931: case CJUS:
932: d = pos - (ls+tlinsiz)/2;
933: break;
934: case RJUS:
935: d = pos - ls;
936: break;
937: case NJUS:
938: llinptr->l_arg.c_iarg += ssz;
939: return;
940: }
941: if (ltabchr == 0) {
942: /* Blank tabs. */
943: tlinptr->l_arg.c_iarg += d;
944: } else {
945: /* Leader dots or nonblank tabs. */
946: if ((n = nlinptr - (tlinptr+1)) > WORSIZE)
947: panic("word buffer overflow");
948: copystr(wordbuf, tlinptr+1, sizeof (CODE), n); /* save */
949: nlinptr = tlinptr + 1;
950: savfont = curfont;
951: dev_font(tfn); /* tab font */
952: if ((w = tbs) == 0)
953: w = width(ltabchr); /* tab char width */
954: if ((d2 = (d1 = tlinsiz) % w) != 0) {
955: /* Futz start position to tab char width multiple. */
956: d1 += w-d2;
957: tlinptr->l_arg.c_iarg += w-d2;
958: }
959: d2 = tlinsiz + d; /* end position */
960: while ((d1 += w) <= d2)
961: addchar(ltabchr, w); /* write a tab char */
962: addidir(DHMOV, d2-(d1-w)); /* skip remaining space */
963: dev_font(savfont); /* restore font */
964: if (nlinptr+n >= &linebuf[LINSIZE])
965: panic("line buffer overflow");
966: copystr(nlinptr, wordbuf, sizeof (CODE), n); /* restore */
967: llinptr = nlinptr += n;
968: --llinptr;
969: }
970: tlinsiz = nlinsiz = llinsiz += d;
971: tlinptr = llinptr;
972: if (c == EOF)
973: return;
974: ls = (cdivp == mdivp) ? llinsiz-tin : llinsiz;
975: while ((++tp)->t_jus != NJUS && tp->t_pos <= ls)
976: ;
977: tabptr = tp;
978: ltabchr = c;
979: }
980:
981: /*
982: * Initialize line data for a new line.
983: */
984: setline()
985: {
986: #if 0
987: fprintf(stderr, "setline()\n");
988: #endif
989: llinptr = nlinptr = tlinptr = linebuf;
990: llinsiz = nlinsiz = tlinsiz = 0;
991: llindir = nlindir = 0;
992: tabptr = tab;
993: ltabchr = '\0';
994: preexls = posexls = 0;
995: addidir(DHMOV, 0);
996: }
997:
998: /* end of process.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.