/* trf-table.c - table writing functions Ugly ugly ugly. */ # include # include # include "rtf.h" # include "rtf2troff.h" static int CellBorderLocIndex (); static int VCellBorderType (); static char *VCellBorderStr (); static char *HCellBorderStr (); /* Border type tokens *follow* cell border location specifiers. */ void TblAttr () { double inch = (double) rtfParam / (double) rtfTpi; int i, j, loc; switch (rtfMinor) { case rtfCellBordBottom: case rtfCellBordTop: case rtfCellBordLeft: case rtfCellBordRight: if (its->nCells >= maxCell) { fprintf (stderr, "Borders specified for too many cells\n"); break; } loc = CellBorderLocIndex (rtfMinor); /* Get border type tokens until non-type token seen, then route non-type token normally. */ for (;;) { (void) RTFGetToken (); if (!RTFCheckCM (rtfControl, rtfParAttr) || (rtfMinor != rtfBorderSingle && rtfMinor != rtfBorderThick && rtfMinor != rtfBorderShadow && rtfMinor != rtfBorderDouble && rtfMinor != rtfBorderDot && rtfMinor != rtfBorderHair)) break; if (its->nCells < maxCell) its->border[its->nCells][loc] = rtfMinor; } RTFRouteToken (); /* send non-border through router */ break; case rtfRowDef: its->tableHeader = 0; its->nCells = 0; its->curCell = 0; for (i = 0; i < maxCell; i++) { its->cellPos[i] = 0; for (j = 0; j < 4; j++) its->border[i][j] = rtfNoBorderType; } its->tableLeft = 0; its->cellGap = 0; break; case rtfRowLeft: break; case rtfRowRight: break; case rtfRowCenter: break; case rtfRowGapH: its->cellGap = inch; break; case rtfRowHt: break; case rtfRowLeftEdge: its->tableLeft = inch; break; case rtfCellPos: if (its->nCells >= maxCell) fprintf (f, "max. table row cell count (%d) exceeded\n", maxCell); else its->cellPos[its->nCells++] = inch; break; case rtfMergeRngFirst: break; case rtfMergePrevious: break; } } void BeginTbl () { int i, n; double cwid; char *p; Flush (); FlushState (); SaveTblFPV (); /* save current font, ps, vs */ fprintf (f, ".TS\n"); fprintf (f, "center tab(^);\n"); for (i = 0; i < its->nCells; i++) { if ((p = VCellBorderStr (VCellBorderType (i))) != NULL) fprintf (f, "%s ", p); cwid = its->cellPos[i]; if (i > 0) cwid -= its->cellPos[i-1]; cwid -= EnWidth (); fprintf (f, "l1w(%gi) ", cwid); } if ((p = VCellBorderStr (VCellBorderType (its->nCells))) != NULL) fprintf (f, "%s ", p); fprintf (f, ".\n"); ++its->tableHeader; /* print top borders */ n = 0; for (i = 0; i < its->nCells; i++) { if (its->border[i][topIndex] != rtfNoBorderType) ++n; } if (n > 0) { for (i = 0; i < its->nCells; i++) { if (i > 0) fprintf (f, "^"); if ((p = HCellBorderStr (its->border[i][topIndex])) != NULL) fprintf (f, "%s", p); } fprintf (f, "\n"); } } void EndTbl () { int i, n; char *p; /* print bottom borders */ n = 0; for (i = 0; i < its->nCells; i++) { if (its->border[i][bottomIndex] != rtfNoBorderType) ++n; } if (n > 0) { for (i = 0; i < its->nCells; i++) { if (i > 0) fprintf (f, "^"); if ((p = HCellBorderStr (its->border[i][bottomIndex])) != NULL) fprintf (f, "%s", p); } fprintf (f, "\n"); } fprintf (f, ".TE\n"); /* this undoes ps/vs... */ FlushTblFPV (); /* so redo it. ugh. */ FlushState (); its->tableHeader = 0; its->curCell = 0; } /* BeginCell() called when first \intbl in row is seen and after each \cell; EndCell() called whenever \cell or \row are seen. These do nothing if the cell number is greater than would be expected given the number of cell positions found in the table layout information. (It *is* possible to find information beyond the last cell; Word for Macintosh, at least, seems to put an empty cell at the end of each row.) */ void BeginCell () { /* accept cells 0..nCells-1 */ if (its->curCell < its->nCells) { Flush (); fprintf (f, "T{\n"); /*FlushState ();*/ FlushTblFPV (); /* set up correct font, ps, vs */ } inTable = 1; } void EndCell () { Flush (); /* accept cells 0..nCells-1 */ if (its->curCell < its->nCells) { fprintf (f, "T}"); } ++its->curCell; if (its->curCell < its->nCells) fprintf (f, "^"); /* more cells to go */ else if (its->curCell == its->nCells) fprintf (f, "\n"); /* no more cells to go */ inTable = 0; } static int CellBorderLocIndex (loc) int loc; { switch (loc) { case rtfCellBordLeft: return (leftIndex); case rtfCellBordRight: return (rightIndex); case rtfCellBordTop: return (topIndex); case rtfCellBordBottom: return (bottomIndex); } fprintf (stderr, "CellBorderLocIndex: bad argument (%d)\n", loc); exit (1); } /* Determine vertical border for left of cell i. Takes into account right border of i-1 and left border of i, with the latter taking precedence. Two special cases are handled implicitly in code below. When i = 0, return left border of cell 0. When i = nCells, return right border of cell nCells-1. */ static int VCellBorderType (i) int i; { int border = rtfNoBorderType; if (i >= 0 && i < its->nCells) border = its->border[i][leftIndex]; if (i > 0 && i <= its->nCells && border == rtfNoBorderType) border = its->border[i-1][rightIndex]; return (border); } static char *VCellBorderStr (type) int type; { switch (type) { case rtfBorderShadow: case rtfBorderThick: case rtfBorderDot: case rtfBorderHair: case rtfBorderSingle: return ("|"); case rtfBorderDouble: return ("||"); } return (NULL); } static char *HCellBorderStr (type) int type; { switch (type) { case rtfBorderShadow: case rtfBorderThick: case rtfBorderDot: case rtfBorderHair: case rtfBorderSingle: return ("_"); case rtfBorderDouble: return ("="); } return (NULL); }