/* ========================================================================== * * DOCALYZE: generate tables to document the catalogs in a template. * * This program reads a MIF document from standard input. It locates the * various "catalog" lists, for example the , , * and . It extracts selected data * from a catalog and formats that data as Frame Table. All the tables are * written as a MIF file to standard output. * * This program assumes the use of a prepared template, MIFFEDTP.fm4. * * To use the program: * * 1. Create or select a template file that you need to document. * 2. Save it as MIF. * 3. Pipe the MIF to this program. * 4. Save the output in a new file of type ".mif" * 5. Under Frame, create a New document based on MIFFEDTP.fm4. * 6. Import this program's output into that new document. * * A number of tables will appear, showing the properties of the catalogs * in the input template file. You see and compare the different paragraph * tags, font tags, variables and so forth, all at once. * * NOTE: the table generation process is driven by static arrays which * determine the contents of the tables. For a discussion of these arrays * and simpler examples of how to code them, see "catable.c," an example * program in the MIFFEd package. (However, the arrays in this program * have been reorganized for easier coding.) * * ========================================================================= */ #include #include #include /* for nint() -- don't forget to compile with -lm */ /* NOTE: for SGI math.h, the function is double rint(double d) */ #ifndef __sgi #define NINT(x) nint(x) #else #define NINT(x) (int)rint(x) #endif #include "miffed.h" /* ========================================================================== * * Each cell in a table is based on the value of one MIF . That value * can be "treated" in different ways. This enum specifies the available * treatments, which are implemented in the treat() function. NOTE: This is * turning into a vicious collection of ugly hacks. * * ==========================================================================*/ enum Treatments { copyText /* just copy the textOf() the item */ , copyAllBut0 /* copy textOf()[1...] as in COverline -> Overline */ , copyInitial /* copy only the initial letter, like "Y"/"N" from Yes/No */ , copyQuote /* copy value within `' */ , copyPercent /* copy a percent value with trailing % e.g. min spacing */ , boolXDash /* item is Yes/No, but copy "X" for Yes and hyphen for No. */ , keywordXlate /* look the value up in a table and copy the translation */ , keyInContext /* look up the catenation of TagName_value */ , roundPct /* special for "Spread" where Frame messes up -- see treat() */ , measuredNum /* copy numeric value and unit text */ , measure2, measure3, measure4 /* copy numeric 2nd, 3rd, 4th value in list */ }; /* ========================================================================== * * When the "treatment" of a cell value is keywordXlate, the value of the * cell is translated by looking it up in this table and replacing it with * the value given. When a keyword is not found in this table, it is * replaced with "?keyword?" as shown in the last table entry. * * NOTE: keep these in ascii sequence by first column. Then if in time * it becomes necessary, we can use a binary search. After 50 or so rows, say. * ==========================================================================*/ struct wordPair { char * keyword; char * replacement; } lookupTable[] = { { "BodyPage", "Body Page"}, { "FAsTyped", "As typed" }, { "FDouble", "Double" }, { "FLowercase", "Lowercase" }, { "FNormal", "normal"}, { "FNoUnderlining","None"}, { "FNumeric", "Numeric" }, { "FSingle", "Single" }, { "FSmallCaps", "Small cap" }, { "FSubscript", "Sub" }, { "FSuperscript", "Super" }, { "FUppercase", "Uppercase" }, { "HiddenPage", "Hidden Text Page"}, { "LeftMasterPage", "Left Master Page"}, { "Normal", "Normal"}, { "OtherMasterPage", "Master Page"}, { "PgfCellBMarginFixed_No", "Table" }, { "PgfCellBMarginFixed_Yes", "Custom" }, { "PgfCellLMarginFixed_No", "Table" }, { "PgfCellLMarginFixed_Yes", "Custom" }, { "PgfCellRMarginFixed_No", "Table" }, { "PgfCellRMarginFixed_Yes", "Custom" }, { "PgfCellTMarginFixed_No", "Table" }, { "PgfCellTMarginFixed_Yes", "Custom" }, { "PgfNumAtEnd_No", "Left" }, /* para number position hack */ { "PgfNumAtEnd_Yes", "Right" }, { "ReferencePage", "Reference Page"}, { "RightMasterPage", "Right Master Page"}, { "SideheadFirstBaseline", "Sidehead (first baseline)" }, { "SideheadLastBaseline", "Sidehead (last baseline)" }, { "SideheadTop", "Sidehead (top)"}, { "Straddle", "Sidehead (straddle)"}, { "TblNumByColumn_No", "by row"}, { "TblNumByColumn_Yes", "by column"}, { NULL, "?keyword?" } /* list end delimiter */ }; /* ========================================================================== * * The characteristics of each column are specified in one of these structures. * An array of structures defines the columns of one table. * The fields are arranged so that the ones usually NULL are at the end, so * that default initialization will zero them. * * headText The text of the heading for this column * * sourceTag The name of the MIF list that supplies data, for example * PgfAlignment or FFamily * * colWidth The width of this column in points, usually 30, 36, 72 * * treatment Which of the "treatments" (enumerated above) to apply * * headAngle Heading rotation, usually 0, else 270 * * defaultText Text to be used when no is found, NULL=none * * wrapper The name of the MIF list that encloses sourceTag, as for * example PgfFont encloses FFamily in a Pgf. NULL when * the sourceTag is not enclosed, as is the usual case. * * bodyTag the of the one paragraph in the , by default * the one specified in the table definition bodyTag field. * * ==========================================================================*/ typedef struct { /* Column definition */ char * headText; /* text of column heading */ char * sourceTag; /* name of list supplying values, e.g. "PgfTag" */ short colWidth; /* column width in points */ short headAngle; /* heading rotation, 0/90/180/270 */ enum Treatments treatment; /* how to treat this value */ char * defaultText; /* value when sourceTag not found, NULL=none */ char * wrapper; /* list enclosing sourceTag, usually NULL */ char * bodyTag; /* paragraph tag, NULL==use TABLEDEF bodyTag */ } COLUMN_DEF; /* ========================================================================== * * This structure describes the global properties of a table. As with the * column definition, the structure is ordered so that the fields most * often NULL are at the end, for easy coding of the static initialization. * * titleText text of table title paragraph if any, NULL means no title * paragraph to be generated on the table. * * rowSourceTag the list that supplies one row of data, for example * or or . * * columns -->array of COLUMN_DEF structures for the columns in the table * * numColumns how many COLUMN_DEFs at *columns -- must be accurate * * styleTag name of table catalog style to use, NULL="MIFFEd" which is * defined in the MIFFEDTP.fm4 template. * * titleTag of the table title paragraph, NULL="TableTitle" * * headTag to use in all the heading cells, NULL="CellHeading" * * bodyTag to use in body cells when COLUMN_DEF does not * specify, NULL = "CellBody" * * ==========================================================================*/ typedef struct { /* Table definition */ char * titleText; /* text of table title */ char * rowSourceTag; /* list supplying 1 row */ COLUMN_DEF *columns; /* array of column definitions */ int numColumns; /* number of COLUMN_DEFs in array */ char * styleTag; /* name of table catalog tag */ char * titleTag; /* para tag of title para */ char * headTag; /* para tag of head/footers */ char * bodyTag; /* para tag of cells */ } TABLE_DEF; /* ========================================================================== * * Here are the table definitions. * * ==========================================================================*/ static char szasis[]="as-is"; /* "As-is" in Times 12 won't fit 36pt cols */ COLUMN_DEF VarColumns[] = { {"Variable Name", "VariableName", 144, 0, copyText }, {"Variable Definition", "VariableDef", 324, 0, copyText } }; TABLE_DEF Variables = { "Variable Definitions", "VariableFormat", &VarColumns[0], 2 }; COLUMN_DEF XRColumns[] = { {"Cross-Reference Name", "XRefName", 144, 0, copyText }, {"Cross-Reference Definition", "XRefDef", 324, 0, copyText } }; /* end of VarColumns */ TABLE_DEF XRefs = { "Cross-Reference Definitions", "XRefFormat", &XRColumns[0], 2 }; COLUMN_DEF CondColumns[] = { {"Condition", "CTag", 144,0, copyText }, {"State", "CState", 72, 0, copyAllBut0 }, {"Style", "CStyle", 72, 0, copyAllBut0 }, {"Color", "CColor", 72, 0, copyText, szasis }, {"Separation", "CSeparation", 72, 0, copyText } }; TABLE_DEF CondTab = { "Condition Tag Definitions", "Condition", &CondColumns[0], 5 }; COLUMN_DEF ColorCols[] = { {"Color Tag", "ColorTag", 90, 0, copyText }, {"Cyan", "ColorCyan", 60, 0, copyText }, {"Magenta", "ColorMagenta", 60, 0, copyText }, {"Yellow", "ColorYellow", 60, 0, copyText }, {"Black", "ColorBlack", 60, 0, copyText } }; TABLE_DEF ColorTab = { "Color Definitions", "Color", &ColorCols[0], 5 }; COLUMN_DEF FontsCols[] = { {"Font Tag", "FTag", 90, 0, copyText }, {"Family", "FFamily", 72, 0, copyText }, {"Size", "FSize", 36, 0, copyText, szasis }, {"Angle", "FAngle", 36, 0, copyText, szasis }, {"Weight", "FWeight", 42, 0, copyText, szasis }, {"Variation", "FVar", 42, 0, copyText, szasis }, {"Color", "FColor", 36, 0, copyText, szasis }, {"Spread", "FDW", 36, 0, roundPct, szasis }, {"Underline", "FUnderlining", 36, 270, keywordXlate, szasis }, {"Overline", "FOverline", 30, 270, copyInitial, szasis }, {"Strikethrough", "FStrike", 30, 270, copyInitial, szasis }, {"Change Bar", "FChangeBar", 30, 270, copyInitial, szasis }, {"Outline", "FOutline", 30, 270, copyInitial, szasis }, {"Shadow", "FShadow", 30, 270, copyInitial, szasis }, {"Superscript", "FSupScript", 30, 270, copyInitial, szasis }, {"Subscript", "FSubScript", 30, 270, copyInitial, szasis }, {"Letter Case", "FCase", 42, 270, keywordXlate, szasis }, {"Pair Kern", "FPairKern", 30, 270, copyInitial, szasis } }; /* end of FontsCols */ TABLE_DEF Fonts = { "Character Style Properties", "Font", &FontsCols[0], 18 }; COLUMN_DEF Para1Cols[] = { {"Paragraph Tag", "PgfTag", 90, 0, copyText }, {"First Indent", "PgfFIndent", 60, 0, measuredNum}, {"Left Indent", "PgfLIndent", 60, 0, measuredNum}, {"Right Indent", "PgfRIndent", 60, 0, measuredNum}, {"Alignment", "PgfAlignment", 60, 0, copyText }, {"Space Above", "PgfSpBefore", 60, 0, measuredNum}, {"Space Below", "PgfSpAfter", 60, 0, measuredNum}, {"Text Size", "FSize", 60, 0, measuredNum, NULL, "PgfFont"}, {"Leading", "PgfLeading", 60, 0, measuredNum}, {"Spacing Policy", "PgfLineSpacing", 60, 0, copyText }, {"#Tabstops", "PgfNumTabs", 60, 0, copyText, "0" } }; TABLE_DEF Para1Tab = { "Paragraph Basic Attributes", "Pgf", &Para1Cols[0], 10 }; COLUMN_DEF Para2Cols[] = { {"Paragraph Tag", "PgfTag", 90, 0, copyText }, {"Family", "FFamily", 72, 0, copyText, NULL, "PgfFont" }, {"Size", "FSize", 36, 0, copyText, szasis, "PgfFont" }, {"Angle", "FAngle", 36, 0, copyText, szasis, "PgfFont" }, {"Weight", "FWeight", 42, 0, copyText, szasis, "PgfFont" }, {"Variation", "FVar", 42, 0, copyText, szasis, "PgfFont" }, {"Color", "FColor", 36, 0, copyText, szasis, "PgfFont" }, {"Spread", "FDW", 36, 0, roundPct, szasis, "PgfFont" }, {"Underline", "FUnderlining", 36, 270, keywordXlate, szasis, "PgfFont" }, {"Overline", "FOverline", 30, 270, copyInitial, szasis, "PgfFont" }, {"Strikethrough", "FStrike", 30, 270, copyInitial, szasis, "PgfFont" }, {"Change Bar", "FChangeBar", 30, 270, copyInitial, szasis, "PgfFont" }, {"Outline", "FOutline", 30, 270, copyInitial, szasis, "PgfFont" }, {"Shadow", "FShadow", 30, 270, copyInitial, szasis, "PgfFont" }, {"Superscript", "FSupScript", 30, 270, copyInitial, szasis, "PgfFont" }, {"Subscript", "FSubScript", 30, 270, copyInitial, szasis, "PgfFont" }, {"Letter Case", "FCase", 42, 270, keywordXlate, szasis, "PgfFont" }, {"Pair Kern", "FPairKern", 30, 270, copyInitial, szasis, "PgfFont" } }; TABLE_DEF Para2Tab = { "Paragraph Default Font Attributes", "Pgf", &Para2Cols[0], 18 }; COLUMN_DEF Para3Cols[] = { {"Paragraph Tag", "PgfTag", 90, 0, copyText }, {"Start Position", "PgfPlacement", 72, 0, copyText }, {"Placement Style", "PgfPlacementStyle", 90, 0, keywordXlate }, {"Run-In Punct.", "PgfRunInDefaultPunct", 72, 0, copyQuote }, {"Keep With Prev.", "PgfWithPrev", 72, 0, boolXDash }, {"Keep With Next", "PgfWithNext", 72, 0, boolXDash }, {"Widows/Orphans", "PgfBlockSize", 72, 0, copyText } }; TABLE_DEF Para3Tab = { "Paragraph Pagination Attributes", "Pgf", &Para3Cols[0], 7 }; COLUMN_DEF Para4Cols[] = { {"Paragraph Tag", "PgfTag", 90, 0, copyText }, {"Numbering", "PgfAutoNum", 60, 0, copyInitial, "N" }, {"Position", "PgfNumAtEnd", 48, 0, keyInContext, }, {"Character style", "PgfNumberFont", 90, 0, copyText }, {"Number Format", "PgfNumFormat", 144, 0, copyQuote } }; TABLE_DEF Para4Tab = { "Paragraph Numbering Properties", "Pgf", &Para4Cols[0], 5 }; COLUMN_DEF Para5Cols[] = { {"Paragraph Tag", "PgfTag", 90, 0, copyText }, {"Auto Spacing", "PgfLetterSpace", 42, 0, copyInitial }, {"Max Space", "PgfMaxWordSpace", 42, 0, copyPercent }, {"Opt Space", "PgfOptWordSpace", 42, 0, copyPercent }, {"Min Space", "PgfMinWordSpace", 42, 0, copyPercent }, {"Auto Hyphens", "PgfHyphenate", 42, 0, copyInitial }, {"Max Adjacent", "HyphenMaxLines", 42, 0, copyText }, {"Shortest Word", "HyphenMinWord", 42, 0, copyText }, {"Shortest Prefix", "HyphenMinPrefix", 42, 0, copyText }, {"Shortest Suffix", "HyphenMinSuffix", 42, 0, copyText }, {"Language", "PgfLanguage", 60, 0, copyText }, {"Frame Above", "PgfTopSeparator", 72, 0, copyText }, {"Frame Below", "PgfBotSeparator", 72, 0, copyText } }; TABLE_DEF Para5Tab = { "Paragraph Advanced Properties", "Pgf", &Para5Cols[0], 13 }; COLUMN_DEF Para6Cols[] = { {"Paragraph Tag", "PgfTag", 90, 0, copyText }, {"Cell Alignment", "PgfCellAlignment", 90, 0, copyText }, {"Top Basis", "PgfCellTMarginFixed", 66, 0, keyInContext, }, {"Top Margin", "PgfCellMargins", 66, 0, measure2 }, {"Bottom Basis", "PgfCellBMarginFixed", 66, 0, keyInContext, }, {"Bottom Margin", "PgfCellMargins", 66, 0, measure4 }, {"Left Basis", "PgfCellLMarginFixed", 66, 0, keyInContext }, {"Left Margin", "PgfCellMargins", 66, 0, measuredNum }, {"Right Basis", "PgfCellRMarginFixed", 66, 0, keyInContext, }, {"Right Margin", "PgfCellMargins", 66, 0, measure3 } }; TABLE_DEF Para6Tab = { "Paragraph Table Cell Properties", "Pgf", &Para6Cols[0], 10 }; COLUMN_DEF Table1Cols[] = { {"Table Format Tag", "TblTag", 90, 0, copyText }, {"Left Indent", "TblLIndent", 42, 0, measuredNum }, {"Right Indent", "TblRIndent", 42, 0, measuredNum }, {"Space Above", "TblSpBefore", 42, 0, measuredNum }, {"Space Below", "TblSpAfter", 42, 0, measuredNum }, {"Alignment", "TblAlignment", 48, 0, copyText }, {"Start", "TblPlacement", 48, 0, copyText }, {"Numbering", "TblNumByColumn", 54, 0, keyInContext }, {"Title Position", "TblTitlePlacement", 48, 0, copyText }, {"Title Gap", "TblTitleGap", 42, 0, measuredNum }, {"Orphan Rows", "TblBlockSize", 42, 0, copyText }, {"Cell T. Margin", "TblCellMargins", 42, 0, measure2 }, {"Cell B. Margin", "TblCellMargins", 42, 0, measure4 }, {"Cell L. Margin", "TblCellMargins", 42, 0, measuredNum }, {"Cell R. Margin", "TblCellMargins", 42, 0, measure3 } }; TABLE_DEF Table1Table = { "Table Basic Properties", "TblFormat", &Table1Cols[0], 15 }; COLUMN_DEF PagesCols[] = { {"Page Type", "PageType", 72, 0, keywordXlate }, {"Page Tag", "PageTag", 72, 0, copyText }, {"Folio", "PageNum", 60, 0, copyText }, {"Page Width", "PageSize", 60, 0, measuredNum }, {"Page Height", "PageSize", 60, 0, measure2 }, {"Orientation", "PageOrientation", 60, 0, copyText } }; TABLE_DEF PagesTable = { "Pages In Document", "Page", &PagesCols[0], 6 }; /* ========================================================================== * * The following static table drives the main() function. Each top-level * list in the input file is looked up in this table, and used to generate * in the output each time it appears. Each table defined in the * preceding section should appear here once. * * ==========================================================================*/ struct tableCatPair { char * catname; TABLE_DEF *tblToDo; } masterWorkList[] = { {"FontCatalog", &Fonts}, {"VariableFormats",&Variables}, {"XRefFormats",&XRefs}, {"ConditionCatalog",&CondTab}, {"ColorCatalog",&ColorTab}, {"TblCatalog",&Table1Table}, {"PgfCatalog",&Para1Tab}, {"PgfCatalog",&Para2Tab}, {"PgfCatalog",&Para3Tab}, {"PgfCatalog",&Para4Tab}, {"PgfCatalog",&Para5Tab}, {"PgfCatalog",&Para6Tab}, { NULL, NULL } /* required end of list */ }; /* ========================================================================== * This function produces a one-string given a text string and a tag. * If the string is null, the Para contains > > * Note: there is a better (faster but more complicated) version of this * function in DOCCOUNT.C. * ==========================================================================*/ itemHandle oneLinePara(char *pgfTag, char *text) { if (!text) text = ""; /* don't pass null address to patToMIF */ return patToMIF(">",pgfTag,text); } /* ========================================================================== * This function takes a text string and a pgf tag and produces a * whose value is a one-string : * > > * ==========================================================================*/ itemHandle oneLineCell(char *pgfTag, char *text) { itemHandle hCell = newList("Cell"); itemHandle hCont = newList("CellContent"); append(hCont,oneLinePara(pgfTag,text)); append(hCell,hCont); return hCell; } /* ========================================================================== * This function initializes a from a TABLE_DEF and an ID number: * ...> * Note: for a different approach to this same operation, see tableStart() * in DOCCOUNT.C. * ==========================================================================*/ itemHandle tableStart(TABLE_DEF *TDef, int tblID) { int j; char *tbStyleTag = (TDef->styleTag)?TDef->styleTag:"MIFFEd"; itemHandle hTbl = patToMIF(">",tblID); append(hTbl,patToMIF("",tbStyleTag)); append(hTbl,patToMIF("",TDef->numColumns)); for(j = 0; j < TDef->numColumns; ++j) append(hTbl, patToMIF("",TDef->columns[j].colWidth) ); return hTbl; } /* ========================================================================== * This function generates the table title given the TABLE_DEF: * > * Uses oneLinePara(). Should not be called if titleText is null. * ==========================================================================*/ itemHandle tableTitle(TABLE_DEF *TDef) { itemHandle hTT = newList("TblTitleContent"); char * tTag = TDef->titleTag; if (NULL == tTag) tTag = "TableTitle"; /* default para tag */ append(hTT, oneLinePara(tTag, TDef->titleText) ); return hTT; } /* ========================================================================== * This function generates the heading row from the TABLE_DEF and COLUMN_DEFs: * ...> >. Uses oneLineCell(), but also has to insert * a when the heading is rotated. * ==========================================================================*/ itemHandle headRow(TABLE_DEF *TDef) { itemHandle hTH = newList("TblH"); itemHandle hRow = newList("Row"); char * cellTag = TDef->headTag; int j; if (NULL==cellTag) cellTag = "CellHeading"; /* default heading para tag */ for(j=0; jnumColumns; ++j) { itemHandle hCell = oneLineCell(cellTag, TDef->columns[j].headText); if (TDef->columns[j].headAngle) insert(hCell,patToMIF("",TDef->columns[j].headAngle)); append(hRow,hCell); } append(hTH,hRow); return hTH; } /* ========================================================================== * This function receives a one-item list -- like , * , or -- and an enum Treatments value * to be applied to the contents of the list. * * First locate the text value of the first item of the list -- like "Courier", * or "Center", or "No" -- then apply the requested treatment. The return * value is the address of the treated text. * ==========================================================================*/ static char treatedText[64]; /* output area for some treatments */ char * treat(itemHandle hAttribute, enum Treatments code) { itemHandle hValue = nextItem(hAttribute); char * pText = textOf(hValue); int iVal; struct wordPair * pWP; char tmp[128]; switch(code) { case copyAllBut0: /* copy all but the initial letter, which allows getting */ /* readable words out of keywords like Cstate */ ++pText; /* ***FALL INTO*** copyText */ case copyText: return pText; break; case copyInitial: /* copy only the initial letter (as a string) */ treatedText[0]=*pText; treatedText[1]=0; return treatedText; break; case copyQuote: /* copy the text but delimit it with ` and ' apostrophes. */ /* Since the returned text may then be output in MIF form */ /* (e.g. through oneLinePara()), it cannot contain actual */ /* `' characters, which are not valid in MIF Strings. So the */ /* MIF hex escapes for these characters are used. If you */ /* ever want literal `' output, a new treatment is needed. */ strcpy(treatedText,"\\xd4 "); strcat(treatedText,pText); strcat(treatedText,"\\xd5 "); return treatedText; break; case copyPercent: /* return the text (typically a number) followed by "%" */ strcpy(treatedText,pText); strcat(treatedText,"%"); return treatedText; break; case boolXDash: /* Return one-byte strings of "Y" or "-" */ treatedText[0]=('Y'==*pText)?'X':'-'; treatedText[1]=0; return treatedText; break; case roundPct: /* When Frame 4 stores a "spread" percentage it makes some kind */ /* of goof and stores a near-integer, -1.9989 instead of -2. */ /* Return the float value rounded to an integer. */ iVal = NINT(floatOf(hValue)); /* macro defined earlier */ sprintf(treatedText,"%d%%",iVal); return treatedText; break; /* The only place Frame-generated MIF ever has more than one */ /* value in a list is when it has 4 measurements as in the */ /* bounding box of a rectangle or a page. These treatments */ /* supply a way of getting at the 4th, 3rd, and 2nd numbers. */ case measure4: hValue = nextItem(hValue); case measure3: hValue = nextItem(hValue); case measure2: hValue = nextItem(hValue); case measuredNum: /* return the numeric text of a number followed by its unit */ /* of measure in a single string, as in "8.5 pt" However if */ /* the item has no measure, return just the text. */ strcpy(treatedText,textOf(hValue)); if (UM_NA != measureOf(hValue)) { strcat(treatedText," "); strcat(treatedText,unitTextOf(hValue)); } return treatedText; break; case keyInContext: /* concatenate the list name and the list value, and */ /* look up the combination. This permits giving different */ /* meanings to words such as "No" depending on their context. */ strcpy(tmp,textOf(hAttribute)); strcat(tmp,"_"); strcat(tmp,pText); pText = tmp; /* **FALL INTO** case "keywordXlate" */ case keywordXlate: /* search for *pText in the keyword lookupTable and return */ /* the replacement text, defaulting automatically to the */ /* in the terminating table entry, ?keyword? */ for(pWP = lookupTable; ((pWP->keyword)&&(strcmp(pText,pWP->keyword))); ++pWP) { /* nothing to do in loop */ } return pWP->replacement; break; default: return "?treatment?"; } } /* ========================================================================== * Here's the beef! This is the function that takes a catalog entry and a set * of COLUMN_DEFs, and generates one of data. In pseudocode: * * create a list * for each column: * Search the catalog entry for this column's source, e.g. look in * this for a . When the source is * enclosed in a wrapper, look for the first wrapper and look * within it for the first source tag. * If found, "treat" the first value in the source list as specified * to produce a string * If not found, select the default string if any * Use oneLineCell() to generate a cell and append it to the * end for * return the * * ==========================================================================*/ itemHandle bodyRow(TABLE_DEF *TDef, itemHandle catItem) { int j; itemHandle hRow = newList("Row"); char *dfltTag = (TDef->bodyTag)?TDef->bodyTag:"CellBody"; char *pgfTag; char *treatedValue; itemHandle hSrc; COLUMN_DEF *pCDef; for(j = 0; j < TDef->numColumns; ++j) { pCDef = &TDef->columns[j]; pgfTag = (pCDef->bodyTag)?pCDef->bodyTag:dfltTag; if (!(pCDef->wrapper)) { hSrc = firstOfName(catItem,pCDef->sourceTag); } else { hSrc = firstOfName(catItem,pCDef->wrapper); if ((hSrc)) hSrc = firstOfName(hSrc,pCDef->sourceTag); } if (hSrc) /* found it */ treatedValue = treat(hSrc, pCDef->treatment); else treatedValue = pCDef->defaultText; append(hRow,oneLineCell(pgfTag,treatedValue)); } return hRow; } /* ========================================================================== * This function takes a TABLE_DEF, a table ID number, and a Catalog list, * and produces an entire from it. It uses all the preceding funcs. * We are getting close to the main() action, now! * ==========================================================================*/ itemHandle oneTable(TABLE_DEF *TDef, int tblID, itemHandle catalog) { itemHandle catItem; itemHandle hBody; /* start with the basic */ itemHandle hTbl = tableStart(TDef,tblID); /* if a table title is wanted, generate it */ if (TDef->titleText) append(hTbl,tableTitle(TDef)); /* generate the > heading row */ append(hTbl,headRow(TDef)); /* generate the body consisting of one row for each rowSourceTag found */ hBody = newList("TblBody"); for(catItem = firstOfName(catalog,TDef->rowSourceTag); (catItem); catItem = nextSameName(catItem) ) { append(hBody, bodyRow(TDef, catItem) ); } /* add the body to the */ append(hTbl,hBody); return hTbl; } /* ========================================================================== * At long last, main(). * create the list into which each will be appended. * create the into which each will be appended. * loop over each top-level list in standard input: * test the list-name against the masterWorkList. * wherever it appears, * generate a table and append to * generate a para referencing the table and append to * write a MIF file consisting of ,, * ==========================================================================*/ int main () { struct tableCatPair *tcp; /* scans elements of masterWorkList */ int tblID = 1; /* table ID number, increments each */ itemHandle oneList; /* current input list */ itemHandle hTbls = newList("Tbls"); /* */ itemHandle hTFlow = newList("TextFlow"); /* */ itemHandle hPages = newList("Pages"); /* save Page lists here */ char *parapat = ">>"; for ( oneList = readOneItem(stdin,0); (oneList); oneList = readOneItem(stdin,0) ) { if (0 == textCmp(oneList,"Page")) { append(hPages,oneList); } else { for(tcp = masterWorkList; (tcp->catname); ++tcp) { if (0==strcmp(tcp->catname,textOf(oneList))) { append(hTbls,oneTable(tcp->tblToDo,tblID,oneList)); append(hTFlow, patToMIF(parapat,tblID)); ++tblID; } } trashSequence(oneList); } } append(hTbls,oneTable(&PagesTable,tblID,hPages)); append(hTFlow, patToMIF(parapat,tblID++)); printf("# from DOCALYZE\n"); writeMIF(stdout,hTbls,OUT_EOL+OUT_INDENT); writeMIF(stdout,hTFlow,OUT_EOL+OUT_INDENT); return 0; }