/* trf-stack.c - internal and written stack operations. */ # include # include # include "rtf.h" # include "rtf2troff.h" static int iTopState = 0; /* current internal state */ static State iState[maxIStack] = /* internal state stack */ { /* state 0 = initial state. */ rtfNoDestination, /* destination */ { 0, /* landscape (0 = no) */ 12240.0/rtfTpi, /* paper width = 8.5i*/ 15840.0/rtfTpi, /* paper height = 11i */ 1800.0/rtfTpi, /* left margin = 1.25i */ 1800.0/rtfTpi, /* right margin = 1.25i */ 1440.0/rtfTpi, /* top margin = 1i */ 1440.0/rtfTpi, /* bottom margin = 1i */ 720.0/rtfTpi /* tab width = .5i */ }, { rtfPageBreak, /* section break type */ 1, /* starting page number */ 0, /* continuous page numbering */ 1080.0/rtfTpi, /* header position */ 1080.0/rtfTpi, /* footer position */ 0 /* title page not special */ }, { 0, /* first indent */ 0, /* left indent */ 0, /* right indent */ 0, /* space before */ 0, /* space after */ .2, /* space between: 12p * 1.2 = 14.4p */ 0, /* no tabs set yet */ 0, /* number of tabs */ { 0 }, /* tab positions */ { 0 }, /* tab types */ rtfLeaderMotion, /* tab character */ rtfQuadLeft, /* justification */ rtfNoBorderType, /* no border */ 0 /* draw border nowhere */ }, { 12, /* font size */ 0, /* char style (plain, DON'T CHANGE) */ 0, /* superscript */ 0 /* subscript */ } }; static int wTopState = 0; /* current written state */ static State wState[maxWStack]; /* written state stack */ /* Set up pointers into internal state 0, and equate initial written state to internal state (although written state isn't actually written until FlushInitialState()). Initialize the tab type array to left tabs, so that any tab positions specified without a type will default to left-justified. */ void InitState () { is = &iState[0]; /* initialize state 0 */ ids = &is->docState; iss = &is->sectState; ips = &is->parState; ics = &is->charState; ips->tabFlag = 0; InitTabSet (); /* sync written state to internal state */ bcopy ((char *) &iState[0], (char *) &wState[0], (int) sizeof (State)); ws = &wState[0]; wds = &ws->docState; wss = &ws->sectState; wps = &ws->parState; wcs = &ws->charState; } void CheckFinalState () { if (iTopState != 0) fprintf (stderr, "Warning: unbalanced brace level\n"); if (wTopState != 0) fprintf (stderr, "Warning: unrestored environment\n"); if (indirectionLevel > 0) fprintf (stderr, "Warning: unrestored indirection\n"); } /* Push or pop internal state. On push, initial value of new state is same as current state, so no state *change* is involved. Indicate that no destination or tab stops have been specified. On pop, revert to previous state. It's just laziness to set the state change variables on a state pop, since some or all of them may well not have changed at all... but it's safest and easiest to do so. */ void PushIState () { if (iTopState >= maxIStack - 1) { fprintf (stderr, "Internal state stack limit exceeded"); fprintf (stderr, " maximum level (%d)\n", maxIStack); exit (1); } bcopy ((char *) &iState[iTopState], (char *) &iState[iTopState + 1], (int) sizeof (State)); is = &iState[++iTopState]; is->destination = rtfNoDestination; is->parState.tabFlag = 0; /* no tabs set in state yet */ ids = &is->docState; iss = &is->sectState; ips = &is->parState; ics = &is->charState; } void PopIState () { if (iTopState < 1) { fprintf (stderr, "Pop error: no internal state to pop"); fprintf (stderr, " maximum level (%d)\n", maxIStack); exit (1); } is = &iState[--iTopState]; ids = &is->docState; iss = &is->sectState; ips = &is->parState; ics = &is->charState; ++docStateChanged; ++sectStateChanged; ++parStateChanged; ++charStateChanged; } void PushWState () { if (wTopState >= maxWStack - 1) { fprintf (stderr, "Written state stack limit exceeded"); fprintf (stderr, " maximum level (%d)\n", maxWStack); exit (1); } bcopy ((char *) &wState[wTopState], (char *) &wState[wTopState + 1], (int) sizeof (State)); ws = &wState[++wTopState]; wds = &ws->docState; wss = &ws->sectState; wps = &ws->parState; wcs = &ws->charState; } void PopWState () { if (wTopState < 1) { fprintf (stderr, "Pop error: no written state to pop"); fprintf (stderr, " maximum level (%d)\n", maxWStack); exit (1); } ws = &wState[--wTopState]; wds = &ws->docState; wss = &ws->sectState; wps = &ws->parState; wcs = &ws->charState; ++docStateChanged; ++sectStateChanged; ++parStateChanged; ++charStateChanged; } /* Environment switching routines. When commands are written to switch environments, take snapshot of current written state. When environment switches back, restore to snapshot state to reflect the troff state switch. Environment switches are saved only when diversions are collected, not when they are written out. */ void BeginDiversion (name) char *name; { Flush (); fprintf (f, ".rm %s\n.di %s\n", name, name); ++indirectionLevel; fprintf (f, ".ev 1\n"); PushWState (); } void EndDiversion () { Flush (); fprintf (f, ".br\n"); fprintf (f, ".ev\n"); PopWState (); fprintf (f, ".di\n"); --indirectionLevel; } /* Restore section, paragraph or character defaults, using values stored in state 0. Paragraph defaults are restored by using the state 0 values, they applying the "Normal" style (style 0). The tab flag is reset before expanding the style so any inherited tabs will be overridden by tabs in the style, and reset after expansion so any tabs in the paragraph itself will override inherited or style tabs. */ void RestoreSectDefaults () { bcopy ((char *) &iState[0].sectState, (char *) iss, (int) sizeof (SectState)); } void RestoreParDefaults () { bcopy ((char *) &iState[0].parState, (char *) ips, (int) sizeof (ParState)); ips->tabFlag = 0; RTFExpandStyle (0); ips->tabFlag = 0; } void RestoreCharDefaults () { bcopy ((char *) &iState[0].charState, (char *) ics, (int) sizeof (CharState)); }