📄 page.c
字号:
/* page.c -- functions and variables to compose and output pages *//* This is part of cdg - a C-source Documentation Generator. Copyright (C) 1995, 1996 Peter Knoppers. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include "cdg.h"#define ESC '\033'/* * Printer specific command strings. * Can be overridden with -Dxxx=yyy on the compiler command line (if you * figure out how to escape all those nasty escapes...) * * All printer specific stuff is contained in this file. * * There are three sets of codes: * PostScript * HP LaserJet * HP DeskJet 500 * The (default) codes are good for my HP deskjet 500 printer. * * The output is for A4 sized paper, PostScript output can also be * generated for US Letter. *//* * The PRINTERINITSTRING sets up the printer in landscape mode and prepares * things so that the next call to PRINTERSTARTLINE will position the "cursor" * on the first position of the first line of the page. */#ifndef PRINTERINITSTRING#ifdef POSTSCRIPT#ifdef USLETTER#define PRINTERINITSTRING printf ("%%!PS-Adobe-3.0\n\%%%%Pages: (atend)\ngsave\n\/R {/Courier findfont 7 scalefont setfont} def R \n\/B {/Courier-Bold findfont 7 scalefont setfont} def\n\/L {C 13 grestore moveto gsave 90 rotate C 9 add /C exch def} def\n\statusdict /setduplexmode known {statusdict begin true setduplexmode end} if\n\gsave\n%%%%Page: 1 1\n/C 28 def\n")#else#define PRINTERINITSTRING printf ("%%!PS-Adobe-3.0\n\%%%%Pages: (atend)\ngsave\n\/R {/Courier findfont 7 scalefont setfont} def R \n\/B {/Courier-Bold findfont 7 scalefont setfont} def\n\/L {C 44 grestore moveto gsave 90 rotate C 9 add /C exch def} def\n\statusdict /setduplexmode known {statusdict begin true setduplexmode end} if\n\gsave\n%%%%Page: 1 1\n/C 28 def\n")#endif#else#ifdef LASERJET#define PRINTERINITSTRING printf (\"%c&l1O%c&l26A%c(s16H%c&l8D%c(s9V%c&l1S%c&l0L%c&a5L%c&l2E%c&a0R", \ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC, ESC)#else#define PRINTERINITSTRING printf (\"%c&l1O%c&l26A%c(s16H%c&l8D%c&l1E%c&l60F%c(s9V", \ESC, ESC, ESC, ESC, ESC, ESC, ESC)#endif#endif#endif/* * The PRINTERSTARTLINE code positions the cursor on position 1 of the NEXT * line. */ #ifndef PRINTERSTARTLINE#ifdef POSTSCRIPT#define PRINTERSTARTLINE printf ("L (")#else#ifdef LASERJET#define PRINTERSTARTLINE /* No action required */#else#define PRINTERSTARTLINE /* No action required */#endif#endif#endif/* * The PRINTERENDLINE code terminates the current line. */#ifndef PRINTERENDLINE#ifdef POSTSCRIPT#define PRINTERENDLINE printf (") show\n")#else#ifdef LASERJET#define PRINTERENDLINE printf ("\r\n")#else#define PRINTERENDLINE printf ("\r\n")#endif#endif#endif/* * The PRINTERHIGHLIGHTON code set the printer into bold-face (or some other * highlighting) mode. * For some printers highlighting is done on a per-character basis. In these * cases the PRINTERHIGHLIGHTON and PRINTERHIGHLIGHTOFF macros may be empty. * It is guaranteed that PRINTERHIGHLIGHTON and PRINTERHIGHLIGHTOFF are called * in "pairs", and highlighting is never active accross lines. */#ifndef PRINTERHIGHLIGHTON#ifdef POSTSCRIPT#define PRINTERHIGHLIGHTON printf (") show\nB (")#else#ifdef LASERJET#define PRINTERHIGHLIGHTON /* No action required */#else#define PRINTERHIGHLIGHTON /* No action required */#endif#endif#endif/* * The PRINTERHIGHLIGHTOFF code resets the printer after it has been put into * bold-face (or some other highlighting) mode. */#ifndef PRINTERHIGHLIGHTOFF#ifdef POSTSCRIPT#define PRINTERHIGHLIGHTOFF printf (") show\nR (")#else#ifdef LASERJET#define PRINTERHIGHLIGHTOFF /* No action required */#else#define PRINTERHIGHLIGHTOFF /* No action required */#endif#endif#endif/* * The PRINTERHIGHLIGHTOUTCHAR code is a macro that outputs one char in * highlight-mode (the PRINTERHIGHLIGHTON code has been called before this * macro). * For printers that have a highlight-start and a highlight-end code, this * macro often can be identical to PRINTEROUTCHAR. */#ifndef PRINTERHIGHLIGHTOUTCHAR#ifdef POSTSCRIPT#define PRINTERHIGHLIGHTOUTCHAR(c) PRINTEROUTCHAR(c)#else#ifdef LASERJET/* These stupid HP laserprinters don't do boldface with scaled characters * (at least not in landscape mode). * My fix is to output the char twice at a slightly different position. * This makes the output file rather long... * The distance over which the character is shifted is in steps of 1/120 inch. * Luckily this even works with fractions of this step (here 0.7). * The space in this escape sequence causes the micro-shift. */#define PRINTERHIGHLIGHTOUTCHAR(c) printf (\"%c&f0S%c&k0.7H %c(s16H%c%c&f1S%c", ESC, ESC, ESC, c, ESC, c)#else/* * Highlighing by overstriking. This is a nondocumented feature of the * HP DeskJet 500 printer which also refuses to do boldface when controlled * according to the HP documentation... */#define PRINTERHIGHLIGHTOUTCHAR(c) PRINTEROUTCHAR(c), \PRINTEROUTCHAR('\b'), PRINTEROUTCHAR(c)#endif#endif#endif/* * The PRINTEROUTCHAR macro outputs one character while the printer is in * normal output mode. */#ifndef PRINTEROUTCHAR#ifdef POSTSCRIPT/* * In PostScript some printable characters must be escaped. Tabs have already * been expanded, so these can not cause problems here. */#define PRINTEROUTCHAR(c) if (strchr ("()\\", c))\{fputc ('\\', stdout); fputc (c, stdout);} else fputc (c, stdout)#else#ifdef LASERJET#define PRINTEROUTCHAR(c) fputc (c, stdout)#else#define PRINTEROUTCHAR(c) fputc (c, stdout)#endif#endif#endif/* * The PRINTERNEXTPAGESTRING macro ejects the current page and positions the * the "cursor" on position 1 of the top-most line of the next page. * The argument is the number of the next page. * This number does _not_ correspond to the page number printed on most pages. * (The difference is the number of pages occupied by the Table Of Contents.) * * On all pages all 60 lines are always output. */#ifndef PRINTERNEXTPAGESTRING#ifdef POSTSCRIPT#define PRINTERNEXTPAGESTRING(n) printf (\"showpage\n%%%%Page: %d %d\n/C 28 def\n", n, n)#else#ifdef LASERJET#define PRINTERNEXTPAGESTRING(n) printf ("\f")#else#define PRINTERNEXTPAGESTRING(n) /* No action required */#endif#endif#endif/* * The PRINTERRESETSTRING macro ejects the current page and resets the printer * to power-on state. * The argument is the total page count. */#ifndef PRINTERRESETSTRING#ifdef POSTSCRIPT#define PRINTERRESETSTRING(n) printf (\"showpage\n%%%%Trailer\ngrestore grestore\n%%%%Pages: %d\n", n)#else#ifdef LASERJET#define PRINTERRESETSTRING(n) printf ("%cE", ESC)#else#define PRINTERRESETSTRING(n) printf ("%cE", ESC)#endif#endif#endif#ifndef PRINTERSETTING#ifdef POSTSCRIPT#define PRINTERSETTING "PostScript"#else#ifdef LASERJET#define PRINTERSETTING "HP-LaserJet"#else#define PRINTERSETTING "HP-DeskJet"#endif#endif#endifchar printertype[] = PRINTERSETTING;/* * trim: Remove trailing newline(s), spaces and tabs from a * string. This function should've been part of stdlib... * arguments: * char * l: Pointer to string that is to be trimmed. * returns: Nothing. */void trim (char * l){ char * cp; for (cp = &l[strlen (l) - 1]; cp >= l; cp--) if ((*cp == '\n') || (*cp == '\r') || isspace (*cp)) *cp = '\0'; else break;}/* * The functions update_insertednewlines and copyout deal with writing the * source listings to a temporary file. *//* * Inserted newlines produced _during_ copyout of a token are added to the * lineno of all subsequent tokens (but not the the lineno of the current * token). * If a token is split over several lines, the line on which the token starts * must be used in the cross reference list. */static int insertednewlines = 0; /* incremented in copyout() */int totalinsertednewlines = 0; /* global visibility is intended */int column = 0; /* column in copyout file */int outputlineno = 0; /* line number in copyout file *//* * update_insertednewlines: Add the number of newlines inserted by copyout to * totalinsertednewlines and reset insertednewlines. * This function must be called _before_ a new token is * copied out so totalinsertednewlines reflects the total * number of newlines inserted _before_ the new token. * arguments: None. * returns: Nothing. */void update_insertednewlines (void){ totalinsertednewlines += insertednewlines; insertednewlines = 0;}/* * copyout: Copy one input character to the output listing, adding * linenumbers and breaking up lines as necessary. When a * line is broken, a \ is put in position MAXCOLUMN. * The variable "insertednewlines" is incremented each * time a line is broken. * arguments: * char c: Character to output. * returns: Nothing. */void copyout (char c){ if (column == 0) fprintf (listfile, "%6d ", outputlineno + 1);/* humans count from 1 */ if (c == '\n') { column = 0; outputlineno++; } else if (c == '\t') { /* expand tab */ do { column++; fputc (' ', listfile); } while (((column % 8) != 0) && (column < MAXCOLUMN)); /* Is this correct when MAXCOLUMN % 8 != 0 ?? */ return; } else column++; if (column > MAXCOLUMN) { /* break up line */ insertednewlines++; fputc ('\\', listfile); copyout ('\n'); copyout (c); /* must output line number first */ } else fputc (c, listfile);}/* * The remainder of this file contains functions and variables that are used * to compose and write the multi-column output pages. */static int pages = 0; /* count output pages (!= pagenumber) *//* * resetprinter: Output the printer reset string. This string should * reset the printer to power-on state. (Cancelling * landscape mode, scaled characters, etc. * Arguments: None. * returns: Nothing. */static void resetprinter (void){ PRINTERRESETSTRING (pages);}#define COLSTART (currentcol * (COLWIDTH + COLSEP))int pageno = 0; /* if 0, no page number on page */ /* else auto-incrementing pageno */static char page[MAXPAGELINE][MAXPAGECOL + MINCOLSEP + 2];/* construct page */static int currentline;static int currentcol;int cols; /* number of columns */char headerline [MAXPAGECOL + 1]; /* header for each column *//* * flushpage: Write out the contents of the constructed page. * If the page is empty, no output is generated. * Arguments: * int newcolcount: New value for cols per page. * returns: Nothing. * remark: If newcolcount == 0, the printer-reset string is * output after the page. */void flushpage (int newcolcount){ int line; while ((currentline > 0) && (currentline < LINESPERCOLUMN)) addline (""); /* will eventually recurse to flushpage */ if ((currentcol == 0) && (currentline == 0)) { /* page is (now) empty */ if (newcolcount == 0) resetprinter (); /* Done. */ cols = newcolcount; return; } if (pages++ == 0) /* initial page */ { PRINTERINITSTRING; } else /* subsequent page */ { /* These braces ({, }) prevent problems in case the macro is empty */ PRINTERNEXTPAGESTRING (pages); } for (line = 0; line < MAXPAGELINE; line++) { /* * Output one line from the buffer, switching highlighting on and * off as indicated. * * Highlighting can only be switched on for whole words. */ char * cp; int highlightison = 0; trim (page[line]); if ((line == COLUMNHEADLINE) && (pageno > 0)) sprintf (page[line] + strlen (page[line]), "%*sPage %4d", MAXPAGECOL - 9 - (int) strlen (page[line]), "", pageno++); PRINTERSTARTLINE; for (cp = page[line]; *cp; cp++) { if (*cp == HIGHLIGHTWORD) { PRINTEROUTCHAR (' '); highlightison = 1; PRINTERHIGHLIGHTON; continue; } else if (*cp == ' ') { if (highlightison != 0) { /* Don't delete these braces! */ PRINTERHIGHLIGHTOFF; } highlightison = 0; } if (highlightison != 0) PRINTERHIGHLIGHTOUTCHAR (*cp); else PRINTEROUTCHAR (*cp); } if (highlightison != 0) { /* Don't delete these braces! */ PRINTERHIGHLIGHTOFF; } highlightison = 0; PRINTERENDLINE; if (line < LINESPERCOLUMN + BODYHEADLINE) page[line][0] = '\0'; /* don't erase the footer */ } currentcol = 0; currentline = 0; if (newcolcount == 0) resetprinter (); cols = newcolcount;}/* * addline: Add one line to the "body" of the page under * construction. If the page is full, call flushpage to * output it. * Arguments: * char * l: Character pointer to string that is to be added. * returns: Nothing. */void addline (char * l){ sprintf (page[BODYHEADLINE + currentline++] + COLSTART, "%-*.*s", COLWIDTH + COLSEP, COLWIDTH + COLSEP, l);/* add and padd the line */ if (currentline >= LINESPERCOLUMN) /* currentcol is full */ { sprintf(page[COLUMNHEADLINE] + COLSTART, "%-*.*s", COLWIDTH + COLSEP, COLWIDTH + COLSEP, headerline); if (++currentcol >= cols) /* page is full */ flushpage(cols); currentline = 0; }}/* * addlinehard: Copy a string to a specified line in the page under * construction. * Arguments: * int where: Line number in the page. * char * l: Character pointer to string that is to be put at the * specified line.. * returns: Nothing. */void addlinehard (int where, char * l){ strcpy (page[where], l);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -