home *** CD-ROM | disk | FTP | other *** search
- /*
- Trap positions should be flushed *before* the .ev, unfortunately,
- they might not be changed until after the .ev is already out! Agh.
-
- Allow these options:
- -h disable headers/footers
- +h enable headers/footers (default)
-
- Bottom position should be written in terms of page length, which
- should be stored in a register.
-
- Need -me, -mm, -ms specific stuff. Is there a way of detecting
- them from within troff?
-
- Allow header/footer suppression? (for cases where the code written
- is just completely wrong.)
-
- Need to handle \titlepg.
-
- rtf2troff - read rtf input, write troff output
-
- Syntax: rtf2troff options file
-
- Options:
- -e echo token information
- -me write -me specific output
- -mm write -mm specific output
- -ms write -ms specific output
- -s disable strikethrough
- +s enable strikethrough (default)
- -t troff specify troff version
- -u disable underlining
- +u enable underlining (default)
-
- This translator was written to be used with the Primate Center's
- troff-variant (xroff). xroff dependencies are bracketed within
- "if (xroff) { ... }" constructions.
-
- 29 Jan 91 Paul DuBois dubois@primate.wisc.edu
-
- 29 Jan 91 V1.0. Created.
- 31 Jan 91 Made to work. :-)
- 27 Feb 91 V1.01. Updated for distribution 1.05.
- 28 Feb 91 V1.02. Began updating for distribution 1.06.
-
- --
-
- troff puts paragraph markers at the beginning of paragraphs,
- RTF puts 'em at end; the difference is a pain.
-
- "Small caps" is done by \s-1 ... \s+1 and capitalizing everything
- in between.
-
- Good underlining is hard to do in troff; each character is
- underlined individually, which generates an abysmal amount of
- output. Strikethrough output is even worse.
-
- --
-
- Deficiencies are myriad. They include, but are by no means
- limited to:
-
- No formula support.
-
- Poor table support. Tabs within cells are botched. Tables are
- always centered. Tables often come out looking pretty ugly.
-
- space before, after and between don't appear to always work.
-
- troff has no decimal tabs; they are treated as (ugh) right justified
- tabs.
-
- Vertical lines ("bar tabs") are unsupported.
-
- Poor font support (only R, I, B, not even I+B). Font table ignored.
-
- Line numbering ignored, for no good reason.
-
- Only normal and continuous underlining are supported.
-
- No outline or shadow, since troff can't do that.
-
- All-caps, small-caps doesn't work for non-ASCII characters (> 127)
- or special (mapped) characters. (Of course, why should it?)
-
- Default space between lines should be "auto" - but how to do that?
-
- Mixing of leader characters within a paragraph is not supported.
-
- Is nTabs = 0 handled incorrectly?
-
- Mechanism for handling invisible text is inconsistent.
- It's hard to do correctly...particularly as not everything
- is ignored when \v is in effect, and I'm not sure exactly
- what governs whether something is ignored or not.
- */
-
- # include <stdio.h>
- # include <sys/types.h>
- # include <ctype.h>
- # include "rtf.h"
- # include "rtf2troff.h"
-
-
- int tvers = TROFF;
- int mvers = noMacros;
-
-
- State *is; /* current internal state */
- DocState *ids; /* internal document state */
- SectState *iss; /* internal section state */
- ParState *ips; /* internal paragraph state */
- CharState *ics; /* internal character state */
-
- State *ws; /* written state */
- DocState *wds; /* written document state */
- SectState *wss; /* written section state */
- ParState *wps; /* written paragraph state */
- CharState *wcs; /* written character state */
-
-
- /*
- Whether internal state has been changed since written state
- was last synchronized to it. Initially true so that internal
- state will be flushed when first content character is written.
- */
-
- int docStateChanged = 1; /* document properties have changed */
- int sectStateChanged = 1; /* section properties have changed */
- int parStateChanged = 1; /* paragraph properties have changed */
- int charStateChanged = 1; /* character properties have changed */
-
-
- /*
- Indirection level for escape (\) processing. Incremented
- during macro/diversion collection.
- */
-
- int indirectionLevel = 0;
-
-
- static int haveTables = 0; /* non-zero if any seen */
- static TblState tableState;
- TblState *its = &tableState;
- int inTable = 0; /* whether in table cell or not */
-
-
- /*
- Default output stream
- */
-
- FILE *f = stdout;
-
- static int allowUnderline = 1;
- static int allowStrikeThru = 1;
-
- static char *usage = "Usage: rtf2troff [-e] [-me|-mm|-ms] [-s|+s] [-t troff] [-u|+u] file";
-
-
- static void TokenEcho ();
-
- static void Unknown ();
- static void Text ();
- static void Group ();
- static void Control ();
- static void BeginDestination ();
- static void EndDestination ();
- static void Destination ();
- static void CharSet ();
- static void SpecialChar ();
- static void DocAttr ();
- static void SectAttr ();
- static void ParAttr ();
- static void CharAttr ();
-
-
- static void SetNextTabType ();
- static void SetNextTabPos ();
- static void SetTabChar ();
-
-
- int main (argc, argv)
- int argc;
- char **argv;
- {
- char *troff = "troff";
- char *macros = (char *) NULL;
-
- RTFInit ();
-
- /*
- Process arguments. The -t and -me|-mm|-ms arguments
- must be remembered and applied *in that order* after
- argument processing, or char maps may not be selected
- properly.
- */
- --argc;
- ++argv;
- while (argc > 0 && **argv == '-')
- {
- if (strcmp ("-e", *argv) == 0)
- RTFSetReadHook (TokenEcho);
- else if (strcmp ("-s", *argv) == 0)
- allowStrikeThru = 0;
- else if (strcmp ("+s", *argv) == 0)
- allowStrikeThru = 1;
- else if (strcmp ("-u", *argv) == 0)
- allowUnderline = 0;
- else if (strcmp ("+u", *argv) == 0)
- allowUnderline = 1;
- else if (strcmp ("-t", *argv) == 0)
- {
- if (argc < 2)
- {
- fprintf (stderr, "%s\n", usage);
- exit (1);
- }
- --argc;
- ++argv;
- troff = *argv;
- if (strcmp (troff, "troff") == 0)
- tvers = TROFF;
- else if (strcmp (troff, "xroff") == 0)
- tvers = XROFF;
- else if (strcmp (troff, "pstroff") == 0)
- tvers = PSTROFF;
- }
- else if (strcmp ("-me", *argv) == 0)
- {
- macros = *argv;
- mvers = meMacros;
- }
- else if (strcmp ("-mm", *argv) == 0)
- {
- macros = *argv;
- mvers = mmMacros;
- }
- else if (strcmp ("-ms", *argv) == 0)
- {
- macros = *argv;
- mvers = msMacros;
- }
- else
- {
- fprintf (stderr, "Unknown option: %s\n", *argv);
- fprintf (stderr, "%s\n", usage);
- exit (1);
- }
- --argc;
- ++argv;
- }
- SelectFormatterMaps (troff);
- if (macros != (char *) NULL)
- SelectMacPackMaps (macros);
-
- /* not clever; only allows stdin or one named file to be read */
-
- if (argc > 0)
- {
- if (freopen (argv[0], "r", stdin) == (FILE *) NULL)
- {
- fprintf (stderr, "Can't open \"%s\"\n", argv[0]);
- exit (1);
- }
- }
-
-
- /*
- Install writer callbacks into reader and initialize state
- (sets up pointers into internal state 0, and equates initial
- written state to internal state).
- */
-
- RTFSetClassCallback (rtfText, Text);
- RTFSetClassCallback (rtfGroup, Group);
- RTFSetClassCallback (rtfControl, Control);
- RTFSetClassCallback (rtfUnknown, Unknown);
-
- InitState ();
-
- /*
- If macro package needs to be told special characters
- might be used, do so.
- */
- if (mvers == meMacros)
- fprintf (f, ".sc\n");
- else if (mvers == msMacros)
- fprintf (f, ".AM\n");
-
- /*
- Process the input stream. Make sure the first intoken is
- a "{" so a state push will occur before anything else
- (need to preserve state 0 intact for section, paragraph,
- character default restoration).
- */
-
- (void) RTFGetToken ();
- if (!RTFCheckCM (rtfGroup, rtfBeginGroup))
- {
- fprintf (stderr, "malformed rtf file - ");
- fprintf (stderr, "does not begin with \"{\"\n");
- exit (1);
- }
- RTFRouteToken (); /* send "{" through router */
- RTFRead (); /* read everything else */
- Flush ();
-
- /* some diagnostic stuff */
- CheckFinalState ();
-
- if (haveTables)
- fprintf (stderr, "Output contains tables (run through tbl)\n");
-
- exit (0);
- }
-
-
- /*
- Token echo function to implement -e
- */
-
- static void TokenEcho ()
- {
- fprintf (f, "%d\t%d\t%d\t%d\t\"%s\"\n",
- rtfClass, rtfMajor, rtfMinor, rtfParam, rtfTextBuf);
- }
-
-
-
- /* ---------------------------------------------------------------------- */
-
- /*
- Token class handlers
- */
-
- /*
- Echo any unknown tokens. This helps know where translator
- needs to be extended.
- */
-
- static void Unknown ()
- {
- fprintf (stderr, "Unknown symbol %s\n", rtfTextBuf);
- }
-
-
- /*
- Group operator. Push or pop internal state level.
-
- Before a pop, check whether the destination needs any shutdown.
- */
-
- static void Group ()
- {
- switch (rtfMajor)
- {
- case rtfBeginGroup: /* push */
- PushIState ();
- break;
- case rtfEndGroup: /* pop */
- /* do end-of-destination procecssing, then pop state */
- if (is->destination != rtfNoDestination)
- EndDestination ();
- PopIState ();
- break;
- }
- }
-
-
- /*
- Have a text char, write it out. Perform special char mapping
- for chars > 127, do escapes for backslashes.
-
- For normal characters, perform to-upper processing.
- */
-
- static void Text ()
- {
- char buf[2], *p;
-
- if (rtfMajor > 127) /* non-ASCII, map to troff equiv. */
- p = CharMapping (rtfMajor);
- else if (rtfMajor == '\\') /* escape; escape it */
- p = "\\e";
- else /* regular unmapped, unescaped char */
- {
- if (ics->charStyle & (styleAllCaps | styleSmallCaps))
- {
- /*
- OK to use islower()/toupper() because char
- is known to be <= 127
- */
- if (islower (rtfMajor))
- rtfMajor = toupper (rtfMajor);
- }
- buf[0] = rtfMajor;
- buf[1] = '\0';
- p = buf;
- }
- PutString (p);
- }
-
- /*
- The char sets, special chars and destinations do not involve
- a state change; most other control things do.
- */
-
- static void Control ()
- {
- switch (rtfMajor)
- {
- case rtfCharSet:
- CharSet ();
- break;
- case rtfSpecialChar:
- SpecialChar ();
- break;
- case rtfDestination:
- BeginDestination ();
- break;
- case rtfDocAttr:
- DocAttr ();
- break;
- case rtfSectAttr:
- SectAttr ();
- break;
- case rtfParAttr:
- ParAttr ();
- break;
- case rtfCharAttr:
- CharAttr ();
- break;
- case rtfTblAttr:
- TblAttr ();
- break;
- }
- }
-
-
- static void CharSet ()
- {
- SelectCharSetMaps (rtfMinor);
- }
-
- /*
- The hyphen and dash control things are treated as though they
- were rtfText here.
-
- An extra level of indirection is added to the page number register.
- */
-
- static void SpecialChar ()
- {
- char buf[rtfBufSiz];
-
- switch (rtfMinor)
- {
- case rtfCurHeadPage:
- PutString ("\\\\n%"); /* reference page number register */
- break;
- case rtfCurHeadDate:
- /* unimplemented */
- break;
- case rtfCurHeadTime:
- /* unimplemented */
- break;
- case rtfNoBrkSpace:
- PutString ("\\ ");
- break;
- case rtfNoReqHyphen:
- PutString ("\\%");
- break;
- case rtfNoBrkHyphen:
- PutString ("\\-");
- break;
- case rtfSect:
- Sect ();
- break;
- case rtfRow: /* end of cell, and of row/table */
- EndCell ();
- EndTbl ();
- break;
- case rtfLine:
- Par ();
- break;
- case rtfPar:
- Par ();
- break;
- case rtfCell:
- EndCell (); /* end current cell */
- BeginCell (); /* begin next cell */
- break;
- case rtfTab:
- PutString ("\t");
- break;
- case rtfPage:
- Par ();
- fprintf (f, ".bp\n");
- break;
- }
- }
-
-
- /*
- Begin/End destination don't try to do anything except dump
- out comments delimiting the destination. Something "real"
- should be done, but at least the comment is better than nothing.
-
- The switch explicitly lists those destinations for which something
- intelligent should be done. (But nothing is, yet.) Everything
- else falls under the default case and is simply skipped anonymously.
-
- When a destination is skipped, the "}" is fed back into the router
- so the group state gets popped by Group().
- */
-
- static void BeginDestination ()
- {
- Destination (1);
- }
-
-
- static void EndDestination ()
- {
- Destination (0);
- }
-
-
- static void Destination (startDest)
- int startDest;
- {
- char *dp = (char *) NULL; /* destination name */
- char *mp = (char *) NULL; /* macro name */
- char *rp = (char *) NULL; /* register name */
- char *sp = (char *) NULL; /* skipped destination name */
- int reset = 0; /* need reset to defaults? */
-
- /* if beginning destination, set dest type */
- if (startDest)
- is->destination = rtfMinor;
- /* switch on destination type */
- switch (is->destination)
- {
- case rtfFootnote:
- /*
- Don't skip, but don't start diversion: effect is to
- leave footnote text in main document body. Incorrect,
- but better than losing it. Eventually, footnotes
- should be caught in diversions.
- */
- dp = "footnote";
- break;
- case rtfHeader:
- dp = "header";
- mp = mHeaderAll;
- rp = rHeaderAll;
- ++reset;
- break;
- case rtfHeaderLeft:
- dp = "left header";
- mp = mHeaderLeft;
- rp = rHeaderLeft;
- ++reset;
- break;
- case rtfHeaderRight:
- dp = "right header";
- mp = mHeaderRight;
- rp = rHeaderRight;
- ++reset;
- break;
- case rtfHeaderFirst:
- dp = "first page header";
- mp = mHeaderFirst;
- rp = rHeaderFirst;
- ++reset;
- break;
- case rtfFooter:
- dp = "footer";
- mp = mFooterAll;
- rp = rFooterAll;
- ++reset;
- break;
- case rtfFooterLeft:
- dp = "left footer";
- mp = mFooterLeft;
- rp = rFooterLeft;
- ++reset;
- break;
- case rtfFooterRight:
- dp = "right footer";
- mp = mFooterRight;
- rp = rFooterRight;
- ++reset;
- break;
- case rtfFooterFirst:
- dp = "first page footer";
- mp = mFooterFirst;
- rp = rFooterFirst;
- ++reset;
- break;
- case rtfFNSep:
- sp = "footnote separator";
- break;
- case rtfFNContSep:
- sp = "continued footnote separator";
- break;
- case rtfFNContNotice:
- sp = "continued footnote notice";
- break;
- case rtfField: /* don't ignore, but don't capture */
- dp = "field";
- break;
- case rtfFieldInst: /* ignore */
- sp = "field instruction";
- break;
- case rtfFieldResult: /* don't ignore, but don't capture */
- dp = "field result";
- break;
- default:
- sp = rtfTextBuf;
- break;
- }
-
- if (dp != (char *) NULL && startDest)
- Comment ("begin %s", dp);
- if (mp != (char *) NULL) /* begin a capture macro */
- {
- Flush ();
- if (startDest)
- {
- FlushInitialState (); /* make sure this is out */
- FlushSectState (); /* flush trap positions */
- if (rp != (char *) NULL)/* set a register */
- fprintf (f, ".nr %s 1\n", rp);
- BeginDiversion (mp);
- if (reset)
- {
- /* reset paragraph, char defaults */
- /* (fake a \pard and \plain) */
- RTFSetToken (rtfControl, rtfParAttr,
- rtfParDef, -1, "\\pard");
- RTFRouteToken ();
- RTFSetToken (rtfControl, rtfCharAttr,
- rtfPlain, -1, "\\plain");
- RTFRouteToken ();
- }
- }
- else
- {
- EndDiversion ();
- }
- }
- if (sp != (char *) NULL) /* skip a group */
- {
- if (startDest)
- {
- Comment ("SKIPPING %s group", sp);
- RTFSkipGroup ();
- RTFRouteToken (); /* feed "}" back into router */
- }
- else
- Comment ("end skipped group");
- }
- if (dp != (char *) NULL && startDest == 0)
- Comment ("end %s", dp);
- }
-
-
- static void DocAttr ()
- {
- double inch = (double) rtfParam / (double) rtfTpi;
-
- switch (rtfMinor)
- {
- case rtfPaperWidth:
- ids->pageWidth = inch;
- break;
- case rtfPaperHeight:
- ids->pageHeight = inch;
- break;
- case rtfLeftMargin:
- ids->leftMargin = inch;
- break;
- case rtfRightMargin:
- ids->rightMargin = inch;
- break;
- case rtfTopMargin:
- ids->topMargin = inch;
- /* pre-emptive strike */
- if (iss->headerPos >= ids->topMargin)
- iss->headerPos = ids->topMargin / 2;
- break;
- case rtfBottomMargin:
- ids->bottomMargin = inch;
- if (iss->footerPos >= ids->bottomMargin)
- iss->footerPos = ids->bottomMargin / 2;
- break;
- case rtfDefTab:
- ids->tabWidth = inch;
- break;
- case rtfLandscape:
- ids->landscape = 1;
- break;
- }
- ++docStateChanged;
- }
-
-
- static void SectAttr ()
- {
- double inch = (double) rtfParam / (double) rtfTpi;
-
- switch (rtfMinor)
- {
- case rtfSectDef:
- RestoreSectDefaults ();
- break;
- case rtfNoBreak:
- case rtfColBreak:
- case rtfPageBreak:
- case rtfEvenBreak:
- case rtfOddBreak:
- iss->breakType = rtfMinor;
- break;
- case rtfPageStarts:
- iss->pageStart = rtfParam;
- break;
- case rtfPageCont:
- iss->pageRestart = 0;
- break;
- case rtfPageRestart:
- iss->pageRestart = 1;
- break;
- case rtfPageDecimal:
- Flush ();
- fprintf (f, ".af %% 1\n");
- break;
- case rtfPageURoman:
- Flush ();
- fprintf (f, ".af %% I\n");
- break;
- case rtfPageLRoman:
- Flush ();
- fprintf (f, ".af %% i\n");
- break;
- case rtfPageULetter:
- Flush ();
- fprintf (f, ".af %% A\n");
- break;
- case rtfPageLLetter:
- Flush ();
- fprintf (f, ".af %% a\n");
- break;
- case rtfPageNumLeft:
- break;
- case rtfPageNumTop:
- break;
- case rtfHeaderY:
- iss->headerPos = inch;
- if (iss->headerPos >= ids->topMargin)
- iss->headerPos = ids->topMargin / 2;
- break;
- case rtfFooterY:
- iss->footerPos = inch;
- if (iss->footerPos >= ids->bottomMargin)
- iss->footerPos = ids->bottomMargin / 2;
- break;
- case rtfLineModulus:
- break;
- case rtfLineDist:
- break;
- case rtfLineStarts:
- break;
- case rtfLineRestart:
- break;
- case rtfLineRestartPg:
- break;
- case rtfLineCont:
- break;
- case rtfTopVAlign:
- break;
- case rtfBottomVAlign:
- break;
- case rtfCenterVAlign:
- break;
- case rtfJustVAlign:
- break;
- case rtfColumns:
- break;
- case rtfColumnSpace:
- break;
- case rtfColumnLine:
- break;
- case rtfENoteHere:
- break;
- case rtfTitleSpecial:
- iss->titleSpecial = 1;
- break;
- }
- ++sectStateChanged;
- }
-
-
- /*
- Paragraph defaults are restored by using the state 0 values,
- they applying the "Normal" style (style 0).
-
- For the rtfStyleNum, 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.
-
- The "unimplemented" cases below are those which are currently
- ignored, but for which something might be done someday, i.e.,
- they're reminders.
- */
-
- static void ParAttr ()
- {
- double inch = (double) rtfParam / (double) rtfTpi;
-
- switch (rtfMinor)
- {
- case rtfParDef:
- RestoreParDefaults ();
- break;
- case rtfStyleNum:
- ips->tabFlag = 0;
- RTFExpandStyle (rtfParam);
- ips->tabFlag = 0;
- break;
- case rtfQuadLeft:
- case rtfQuadRight:
- case rtfQuadJust:
- case rtfQuadCenter:
- ips->justification = rtfMinor;
- break;
- case rtfFirstIndent:
- ips->firstIndent = inch;
- break;
- case rtfLeftIndent:
- ips->leftIndent = inch;
- break;
- case rtfRightIndent:
- ips->rightIndent = inch;
- break;
- case rtfSpaceBefore:
- ips->spaceBefore = inch;
- break;
- case rtfSpaceAfter:
- ips->spaceAfter = inch;
- break;
- case rtfSpaceBetween:
- ips->spaceBetween = inch;
- break;
- case rtfInTable:
- haveTables = 1;
- /*
- If first cell of row, set temp indent to left edge
- of table. (Actually, this is done incorrectly; tables
- are always centered.)
- Subsequent cells are begun when \cell is seen.
- */
- if (its->tableHeader == 0) /* first cell; need */
- { /* table prolog */
- BeginTbl ();
- BeginCell ();
- }
- break;
- case rtfNoLineNum:
- /* unimplemented */
- break;
- case rtfTabPos:
- SetNextTabPos (inch);
- break;
- case rtfTabRight:
- case rtfTabCenter:
- case rtfTabDecimal:
- SetNextTabType (rtfMinor);
- break;
- case rtfTabBar:
- /* unimplemented */
- break;
- case rtfBorderTop:
- ips->borderFlags |= borderTop;
- break;
- case rtfBorderBottom:
- ips->borderFlags |= borderBottom;
- break;
- case rtfBorderLeft:
- /* unimplemented */
- break;
- case rtfBorderRight:
- /* unimplemented */
- break;
- case rtfBorderBar:
- /* unimplemented */
- break;
- case rtfBorderBox:
- /* unimplemented */
- break;
- case rtfBorderBetween:
- /* unimplemented */
- break;
- case rtfBorderSingle:
- case rtfBorderThick:
- case rtfBorderShadow:
- case rtfBorderDouble:
- case rtfBorderDot:
- case rtfBorderHair:
- ips->borderType = rtfMinor;
- break;
- case rtfBorderSpace:
- /* unimplemented */
- break;
- case rtfLeaderDot:
- case rtfLeaderHyphen:
- case rtfLeaderUnder:
- case rtfLeaderThick:
- SetTabChar (rtfMinor);
- break;
- }
- ++parStateChanged;
- }
-
-
- /*
- Several of the attributes can be turned off with param value
- of zero (e.g., \b vs. \b0), but since the value of rtfParam
- is 0 if no param is given, test the text of the token directly.
- to find out if there's a zero at the end of it.
-
- \plain is like \pard but for characters, i.e, it restores all
- character defaults.
- */
-
- static void CharAttr ()
- {
- int turnOn = (rtfTextBuf[rtfTextLen-1] != '0');
-
- switch (rtfMinor)
- {
- case rtfPlain:
- RestoreCharDefaults ();
- break;
- case rtfBold:
- if (turnOn)
- ics->charStyle |= styleBold;
- else
- ics->charStyle &= ~styleBold;
- break;
- case rtfItalic:
- if (turnOn)
- ics->charStyle |= styleItalic;
- else
- ics->charStyle &= ~styleItalic;
- break;
- case rtfStrikeThru:
- if (allowStrikeThru)
- {
- if (turnOn)
- ics->charStyle |= styleStrikeThru;
- else
- ics->charStyle &= ~styleStrikeThru;
- }
- break;
- case rtfOutline:
- if (turnOn)
- ics->charStyle |= styleOutline;
- else
- ics->charStyle &= ~styleOutline;
- break;
- case rtfShadow:
- if (turnOn)
- ics->charStyle |= styleShadow;
- else
- ics->charStyle &= ~styleShadow;
- break;
- case rtfSmallCaps:
- if (turnOn)
- ics->charStyle |= styleSmallCaps;
- else
- ics->charStyle &= ~styleSmallCaps;
- break;
- case rtfAllCaps:
- if (turnOn)
- ics->charStyle |= styleAllCaps;
- else
- ics->charStyle &= ~styleAllCaps;
- break;
- case rtfInvisible:
- if (turnOn)
- ics->charStyle |= styleInvisible;
- else
- ics->charStyle &= ~styleInvisible;
- break;
- case rtfFontNum:
- /* unimplemented */
- break;
- case rtfFontSize:
- /* sizes are in half-points, convert to whole points */
- ics->fontSize = (int) (rtfParam / 2);
- if (ics->fontSize <= 0)
- ++ics->fontSize; /* don't play with fire */
- break;
- case rtfExpand:
- /* unimplemented */
- break;
- case rtfUnderline:
- if (allowUnderline)
- {
- if (turnOn)
- ics->charStyle |= styleUnderline;
- else
- ics->charStyle &= ~styleUnderline;
- }
- break;
- case rtfWUnderline:
- if (allowUnderline)
- {
- if (turnOn)
- ics->charStyle |= styleWUnderline;
- else
- ics->charStyle &= ~styleWUnderline;
- }
- break;
- case rtfDUnderline:
- /* unimplemented */
- break;
- case rtfDbUnderline:
- /* unimplemented */
- break;
- case rtfNoUnderline:
- ics->charStyle &= ~styleUnderline;
- ics->charStyle &= ~styleWUnderline;
- break;
- case rtfSuperScript:
- /* superscripts are in half-points, convert to points */
- ics->superScript = rtfParam / 2;
- break;
- case rtfSubScript:
- /* subscripts are in half-points, convert to points */
- ics->subScript = rtfParam / 2;
- break;
- case rtfRevised:
- /* unimplemented */
- break;
- case rtfForeColor:
- /* unimplemented */
- break;
- case rtfBackColor:
- /* unimplemented */
- break;
- }
- ++charStateChanged;
- }
-
-
- /* ---------------------------------------------------------------------- */
-
- /*
- Tab handling routines
- */
-
- void InitTabSet ()
- {
- int i;
-
- ips->nTabs = 0;
- /*
- Set all tabs to be left-justified; that will then be used if
- no other tab type is specified. This is done because the
- position is specified *after* the type.
- */
- for (i = 0; i < maxTab; i++)
- ips->tabType[i] = rtfTabLeft;
- }
-
-
- static void SetNextTabPos (pos)
- double pos;
- {
- if (ips->tabFlag != 0 && ips->nTabs >= maxTab)
- fprintf (stderr, "maximum tabstop count (%d) exceeded\n",
- maxTab);
- else
- {
- /* if no tab info has been set for this state, reinit them */
- if (ips->tabFlag == 0)
- {
- InitTabSet ();
- ips->tabFlag = 1;
- }
- ips->tab[ips->nTabs++] = pos;
- }
- }
-
-
- /*
- Tab types are specified *before* the position to which they apply
- is given, so set the next available slot in anticipation of the
- position's being specified next.
- */
-
- static void SetNextTabType (type)
- int type;
- {
- if (ips->tabFlag != 0 && ips->nTabs >= maxTab)
- fprintf (stderr, "maximum tabstop count (%d) exceeded\n",
- maxTab);
- else
- {
- /* if no tab info has been set for this state, reinit them */
- if (ips->tabFlag == 0)
- {
- InitTabSet ();
- ips->tabFlag = 1;
- }
- ips->tabType[ips->nTabs] = type;
- }
- }
-
-
- static void SetTabChar (leader)
- int leader;
- {
- if (ips->tabFlag != 0 && ips->nTabs >= maxTab)
- fprintf (stderr, "maximum tabstop count (%d) exceeded\n",
- maxTab);
- else
- {
- /* if no tab info has been set for this state, reinit them */
- if (ips->tabFlag == 0)
- {
- InitTabSet ();
- ips->tabFlag = 1;
- }
- ips->tabChar = rtfMinor;
- }
- }
-