home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / remind / src / rem2ps.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-13  |  25.9 KB  |  927 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  REM2PS.C                                                   */
  4. /*                                                             */
  5. /*  Print a PostScript calendar.                               */
  6. /*                                                             */
  7. /*  This file is part of REMIND.                               */
  8. /*  Copyright (C) 1992, 1993 by David F. Skoll.                */
  9. /*                                                             */
  10. /***************************************************************/
  11. #include "config.h"
  12. #include "lang.h"
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #ifdef HAVE_UNISTD
  17. #include <unistd.h>
  18. #endif
  19. #include "rem2ps.h"
  20. #ifdef HAVE_MALLOC_H
  21. #include <malloc.h>
  22. #endif
  23. #ifdef HAVE_STDLIB_H
  24. #include <stdlib.h>
  25. #endif
  26.  
  27. #ifdef __TURBOC__
  28. #include <io.h>
  29. #endif
  30.  
  31. #ifdef HAVE_PROTOS
  32. #define ARGS(x) x
  33. #else
  34. #define ARGS(x) ()
  35. #endif
  36. #define NEW(type) ((type *) malloc(sizeof(type)))
  37.  
  38. typedef struct calentry {
  39.    struct calentry *next;
  40.    char *entry;
  41. } CalEntry;
  42.  
  43. typedef struct {
  44.    char *name;
  45.    int xsize, ysize;
  46. } PageType;
  47.  
  48. char Days[]=L_DAYINIT;
  49.  
  50. char *SmallCalLoc[] = {
  51.    "",
  52.    "bt",
  53.    "tb",
  54.    "sbt",
  55. };
  56.  
  57. #define NUMSMALL (sizeof(SmallCalLoc)/sizeof(SmallCalLoc[0]))
  58. char *SmallLocation;
  59. int SmallCol1, SmallCol2;
  60.  
  61. PageType Pages[] =
  62. {
  63.    {"Letter", 612, 792},     /* 8.5 x 11 in. */
  64.    {"Tabloid", 792, 1224},   /* 11 x 17 in. */
  65.    {"Ledger", 1224, 792},    /* 17 x 11 in. */
  66.    {"Legal", 612, 1008},     /* 8.5 x 14 in. */
  67.    {"Statement", 396, 612},  /* 5.5 x 8.5 in. */
  68.    {"Executive", 540, 720},  /* 7.5 x 10 in. */
  69.    {"A3", 842, 1190},
  70.    {"A4", 595, 842},
  71.    {"A5", 420, 595},
  72.    {"B4", 729, 1032},
  73.    {"B5", 519, 729},
  74.    {"Folio", 612, 936},
  75.    {"Quarto", 612, 780},
  76.    {"10x14", 720, 1008}
  77. };
  78.  
  79. PageType DefaultPage[1] =
  80. {
  81.    DEFAULT_PAGE
  82. };
  83.  
  84. #define NUMPAGES (sizeof(Pages)/sizeof(Pages[0]))
  85.  
  86. CalEntry *CurEntries = NULL;
  87. CalEntry *PsEntries[32];
  88. PageType *CurPage;
  89. char PortraitMode;
  90. char NoSmallCal;
  91. char UseISO;
  92.  
  93. char LineBuffer[LINELEN];
  94.  
  95. char *HeadFont="Helvetica";
  96. char *TitleFont="Helvetica";
  97. char *DayFont="Helvetica-BoldOblique";
  98. char *EntryFont="Helvetica";
  99. char *SmallFont="Helvetica";
  100. char *LineWidth = "1";
  101.  
  102. char *HeadSize="14";
  103. char *TitleSize="14";
  104. char *DaySize="14";
  105. char *EntrySize="8";
  106. char *BorderSize = "6";
  107.  
  108. char *UserProlog = NULL;
  109.  
  110. int validfile = 0;
  111.  
  112. int CurDay;
  113. int MaxDay;
  114. int DayNum;
  115. int WkDayNum;
  116. int FirstWkDay;
  117. int MondayFirst;
  118. int LeftMarg, RightMarg, TopMarg, BotMarg;
  119. int FillPage;
  120.  
  121. void Init ARGS ((int argc, char *argv[]));
  122. void Usage ARGS ((char *s));
  123. void DoPsCal ARGS ((void));
  124. int DoQueuedPs ARGS ((void));
  125. void DoSmallCal ARGS((char *m, int days, int first, int col, int which));
  126. void WriteProlog ARGS ((void));
  127. void WriteCalEntry ARGS ((void));
  128. void WriteOneEntry ARGS ((char *s));
  129. void GetSmallLocations ARGS ((void));
  130.  
  131. /***************************************************************/
  132. /*                                                             */
  133. /*   MAIN PROGRAM                                              */
  134. /*                                                             */
  135. /***************************************************************/
  136. #ifdef HAVE_PROTOS
  137. PUBLIC int main(int argc, char *argv[])
  138. #else
  139. int main(argc, argv)
  140. int argc;
  141. char argv[];
  142. #endif
  143. {
  144.    /* If stdin is a tty - probably wrong. */
  145.  
  146.    Init(argc, argv);
  147.  
  148.    if (isatty(0)) {
  149.       Usage("Input should not come from a terminal");
  150.    }
  151.  
  152.    /* Search for a valid input file */
  153.    while (!feof(stdin)) {
  154.       gets(LineBuffer);
  155.       if (!strcmp(LineBuffer, PSBEGIN)) {
  156.          if (!validfile) WriteProlog();
  157.          validfile++;
  158.          DoPsCal();
  159.       }
  160.    }
  161.    if (!validfile) {
  162.       fprintf(stderr, "rem2ps: Couldn't find any calendar data - are you\n");
  163.       fprintf(stderr, "        sure you fed me input produced by remind -p ...?\n");
  164.       exit(1);
  165.    }
  166.    printf("%%%%Trailer\n");
  167.    printf("%%%%Pages: %d\n", validfile);
  168.    return 0;
  169. }
  170.  
  171. /***************************************************************/
  172. /*                                                             */
  173. /*  DoPsCal - emit PostScript for the calendar.                */
  174. /*                                                             */
  175. /***************************************************************/
  176. #ifdef HAVE_PROTOS
  177. void DoPsCal(void)
  178. #else
  179. void DoPsCal()
  180. #endif
  181. {
  182.    char month[40], year[40];
  183.    char prevm[40], nextm[40];
  184.    int days, wkday, prevdays, nextdays;
  185.    int sfirst;
  186.    int i;
  187.    int is_ps;
  188.    CalEntry *c, *d;
  189.  
  190. /* Read the month and year name, followed by # days in month and 1st day of
  191.    month, followed by the MondayFirst flag */
  192.    gets(LineBuffer);
  193.    sscanf(LineBuffer, "%s %s %d %d", month, year, &days, &wkday);
  194.    gets(LineBuffer);
  195.    sscanf(LineBuffer, "%s %d", prevm, &prevdays);
  196.    gets(LineBuffer);
  197.    sscanf(LineBuffer, "%s %d", nextm, &nextdays);
  198.    MaxDay = days;
  199.    FirstWkDay = wkday;
  200.  
  201.    printf("%%%%Page: %c%c%c%c%c %d\n", month[0], month[1], month[2],
  202.              year[2], year[3], validfile);
  203.  
  204. /* Emit PostScript to do the heading */
  205.    if (!PortraitMode) printf("XSIZE 0 translate 90 rotate\n");
  206.    printf("/SAVESTATE save def (%s) (%s) PreCal SAVESTATE restore\n", month, year);
  207.    printf("(%s %s) doheading\n", month, year);
  208.  
  209. /* Calculate the minimum box size */
  210.    if (!FillPage) {
  211.       printf("/MinBoxSize ytop MinY sub 7 div def\n");
  212.    } else {
  213.       if ((days == 31 && wkday >= 5) || (days == 30 && wkday == 6))
  214.          printf("/MinBoxSize ytop MinY sub 6 div def\n");
  215.       else if (days == 28 && wkday == 0 && NoSmallCal)
  216.          printf("/MinBoxSize ytop MinY sub 4 div def\n");
  217.       else
  218.          printf("/MinBoxSize ytop MinY sub 5 div def\n");
  219.    }
  220.  
  221.    printf("/ysmalltop ytop def\n");
  222.  
  223. /* Do each entry */
  224.  
  225.    CurEntries = NULL;
  226.    CurDay = 1;
  227.    WkDayNum = wkday;
  228.  
  229.    while(1) {
  230.       if (feof(stdin)) {
  231.          fprintf(stderr, "Input from REMIND is corrupt!\n");
  232.      exit(1);
  233.       }
  234.      
  235.       gets(LineBuffer);
  236.       if (!strcmp(LineBuffer, PSEND)) break;
  237.  
  238. /* Read the day number - a bit of a hack! */
  239.       DayNum = (LineBuffer[8] - '0') * 10 + LineBuffer[9] - '0';
  240.       if (DayNum != CurDay) {
  241.          for(; CurDay<DayNum; CurDay++) {
  242.         WriteCalEntry();
  243.         WkDayNum = (WkDayNum + 1) % 7;
  244.          }
  245.       }
  246. /* Add the text */
  247.       c = NEW(CalEntry);
  248.       if (!c) {
  249.          fprintf(stderr, "malloc failed - aborting.\n");
  250.      exit(1);
  251.       }
  252.       is_ps = (*LineBuffer == 'F' || *LineBuffer == 'P');
  253.       c->next = NULL;
  254.       c->entry = malloc(strlen(LineBuffer+10) + 1 + is_ps);
  255.       if (!c->entry) {
  256.          fprintf(stderr, "malloc failed - aborting.\n");
  257.      exit(1);
  258.       }
  259.       strcpy(c->entry+is_ps, LineBuffer+10);
  260.  
  261.       if (is_ps) {
  262. /* Save the 'P' or 'F' flag */
  263.          *(c->entry) = *LineBuffer;
  264.          if (!PsEntries[DayNum]) PsEntries[DayNum] = c;
  265.      else {
  266.         d = PsEntries[DayNum];
  267.         while(d->next) d = d->next;
  268.         d->next = c;
  269.          }
  270.       } else {
  271. /* Put on linked list */
  272.          if (!CurEntries) CurEntries = c;
  273.          else {
  274.             d = CurEntries;
  275.            while(d->next) d = d->next;
  276.         d->next = c;
  277.      }
  278.       }
  279.    }
  280.    for(; CurDay<=days; CurDay++) {
  281.       WriteCalEntry();
  282.       WkDayNum = (WkDayNum + 1) % 7;
  283.    }
  284.  
  285. /* If wkday < 2, set ysmall.  If necessary (only for feb) increase cal size. */
  286.    printf("/ysmallbot ylast def\n");
  287.  
  288. /* Now draw the vertical lines */
  289.    GetSmallLocations();
  290.    for (i=0; i<=7; i++) {
  291.       printf("%d xincr mul MinX add ymin %d xincr mul MinX add topy L\n",
  292.               i, i);
  293.    }
  294.  
  295. /* print the small calendars */
  296.    if (!NoSmallCal) {
  297.       sfirst = wkday - (prevdays % 7);
  298.       if (sfirst < 0) sfirst += 7;
  299.       DoSmallCal(prevm, prevdays, sfirst, SmallCol1, 1);
  300.       sfirst = wkday + (days % 7);
  301.       if (sfirst >6) sfirst -= 7;
  302.       DoSmallCal(nextm, nextdays, sfirst, SmallCol2, 2);
  303.    }
  304. /* Do it! */
  305.    printf("showpage\n");
  306. }
  307.  
  308. /***************************************************************/
  309. /*                                                             */
  310. /*  WriteProlog - write the PostScript prologue                */
  311. /*                                                             */
  312. /***************************************************************/
  313. #ifdef HAVE_PROTOS
  314. void WriteProlog(void)
  315. #else
  316. void WriteProlog()
  317. #endif
  318. {
  319.    int i;
  320.    int x = CurPage->xsize;
  321.    int y = CurPage->ysize;
  322.    char *isostuff;
  323.    FILE *fp;
  324.    int nread;
  325.    char buffer[LINELEN];
  326.  
  327.    if (!PortraitMode) {
  328.       i = x; x = y; y = i;
  329.    }
  330.  
  331.    if (UseISO)
  332.       isostuff = "reencodeISO";
  333.    else
  334.       isostuff = "copyFont";
  335.  
  336. /* Write the document structuring stuff */
  337.    printf("%%!PS-Adobe-\n");
  338.    printf("%%%%DocumentFonts: %s", HeadFont);
  339.    if (strcmp(TitleFont, HeadFont)) printf(" %s", TitleFont);
  340.    if (strcmp(TitleFont, DayFont) &&
  341.        strcmp(HeadFont, DayFont)) printf(" %s", DayFont);
  342.    if (strcmp(EntryFont, HeadFont) &&
  343.        strcmp(TitleFont, EntryFont) &&
  344.        strcmp(EntryFont, DayFont)) printf(" %s", EntryFont);
  345.    if (!NoSmallCal && strcmp(SmallFont, HeadFont) &&
  346.        strcmp(SmallFont, DayFont)  &&
  347.        strcmp(TitleFont, SmallFont) &&
  348.        strcmp(SmallFont, EntryFont)) printf(" %s", SmallFont);
  349.    putchar('\n');
  350.    printf("%%%%Creator: Rem2PS\n");
  351.    printf("%%%%Pages: (atend)\n");
  352.    printf("%%%%Orientation: %s\n", PortraitMode ? "Portrait" : "Landscape");
  353.    printf("%%%%EndComments\n");
  354.  
  355.    for (i=0; PSProlog1[i]; i++) puts(PSProlog1[i]);
  356.    if (!MondayFirst)
  357.       printf("[(%s) (%s) (%s) (%s) (%s) (%s) (%s)]\n",
  358.          L_SUNDAY, L_MONDAY, L_TUESDAY, L_WEDNESDAY,
  359.          L_THURSDAY, L_FRIDAY, L_SATURDAY);
  360.    else
  361.       printf("[(%s) (%s) (%s) (%s) (%s) (%s) (%s)]\n",
  362.          L_MONDAY, L_TUESDAY, L_WEDNESDAY,
  363.          L_THURSDAY, L_FRIDAY, L_SATURDAY, L_SUNDAY);
  364.    for (i=0; PSProlog2[i]; i++) puts(PSProlog2[i]);
  365.  
  366.    printf("/HeadFont /%s %s\n", HeadFont, isostuff);
  367.    if (!NoSmallCal) printf("/SmallFont /%s %s\n", SmallFont, isostuff);
  368.    printf("/DayFont /%s %s\n", DayFont, isostuff);
  369.    printf("/EntryFont /%s %s\n", EntryFont, isostuff);
  370.    printf("/TitleFont /%s %s\n", TitleFont, isostuff);
  371.    printf("/HeadSize %s def\n", HeadSize);
  372.    printf("/DaySize %s def\n", DaySize);
  373.    printf("/EntrySize %s def\n", EntrySize);
  374.    printf("/TitleSize %s def\n", TitleSize);
  375.    printf("/XSIZE %d def\n", CurPage->xsize);
  376.    printf("/MinX %d def\n", LeftMarg);
  377.    printf("/MinY %d def\n", BotMarg);
  378.    printf("/MaxX %d def\n", x-RightMarg);
  379.    printf("/MaxY %d def\n", y-TopMarg);
  380.    printf("/Border %s def\n", BorderSize);
  381.    printf("/LineWidth %s def\n", LineWidth);
  382.    printf("%s setlinewidth\n", LineWidth);
  383.  
  384. /* Check if smallfont is fixed pitch */
  385.    if (!NoSmallCal) {
  386.       printf("/SmallFont findfont /FontInfo get /isFixedPitch get\n");
  387.  
  388. /* Define SmallString used to set smallfont size */
  389.       printf("{/SmallString (WW ) def}\n");
  390.       printf("{/SmallString (WW) def}\nifelse\n");
  391.    }
  392.  
  393. /* Do the user-supplied prolog file, if any */
  394.    if (UserProlog) {
  395.       fp = fopen(UserProlog, "r");
  396.       if (!fp) {
  397.          fprintf(stderr, "Could not open prologue file '%s'\n", UserProlog);
  398.       } else {
  399.          while(1) {
  400.         nread = fread(buffer, sizeof(char), LINELEN, fp);
  401.         if (!nread) break;
  402.         fwrite(buffer, sizeof(char), nread, stdout);
  403.          }
  404.          fclose(fp);
  405.       }
  406.    }
  407.  
  408.    printf("%%%%EndProlog\n");
  409.  
  410.  
  411. }
  412.  
  413. /***************************************************************/
  414. /*                                                             */
  415. /*  WriteCalEntry - write all entries for one day              */
  416. /*                                                             */
  417. /***************************************************************/
  418. #ifdef HAVE_PROTOS
  419. void WriteCalEntry(void)
  420. #else
  421. void WriteCalEntry()
  422. #endif
  423. {
  424.    CalEntry *c = CurEntries;
  425.    CalEntry *d;
  426.    int begin, end, i, HadQPS;
  427.  
  428. /* Move to appropriate location */
  429.    printf("/CAL%d {\n", CurDay);
  430.    if (!MondayFirst)
  431.       printf("Border ytop %d xincr mul MinX add xincr\n", WkDayNum);
  432.    else
  433.       printf("Border ytop %d xincr mul MinX add xincr\n", (WkDayNum ? WkDayNum-1 : 6));
  434.  
  435. /* Set up the text array */
  436.    printf("[\n");
  437.  
  438.    CurEntries = NULL;
  439.  
  440.    while(c) {
  441.       WriteOneEntry(c->entry);
  442.       free(c->entry);
  443.       d = c->next;
  444.       free(c);
  445.       c = d;
  446.    }
  447.    printf("]\n");
  448.  
  449. /* Print the day number */
  450.    printf("(%d)\n", CurDay);
  451. /* Do it! */
  452.    printf("DoCalBox\n");
  453.  
  454. /* Update ymin */
  455.    printf("/y exch def y ymin lt {/ymin y def} if\n");
  456.    printf("} def\n");
  457.  
  458. /* If WkDayNum is a Sunday or Monday, depending on MondayFirst,
  459.    move to next row.  Also handle the queued PS and PSFILE reminders */
  460.    if ((!MondayFirst && WkDayNum == 6) ||
  461.         (MondayFirst && WkDayNum == 0) || CurDay == MaxDay) {
  462.       HadQPS = 0;
  463.       if (MondayFirst) begin =  CurDay - (WkDayNum ? WkDayNum-1 : 6);
  464.       else             begin = CurDay - WkDayNum;
  465.       if (begin < 1) begin = 1;
  466.       end = CurDay;
  467.       for (i=begin; i<=end; i++) {
  468.      if (PsEntries[i]) {
  469.         HadQPS = 1;
  470.         break;
  471.          }
  472.       }
  473.       /* Avoid problems with blotching if PS printer has roundoff errors */
  474.       if (HadQPS) printf("1 setgray\n");
  475.       for (i=begin; i<=end; i++) {
  476.          printf("CAL%d\n", i);
  477.       }
  478.       if (HadQPS) printf("0 setgray\n");
  479.       printf("/y ytop MinBoxSize sub def y ymin lt {/ymin y def} if\n");
  480.  
  481. /* Draw the line at the bottom of the row */
  482.       printf("MinX ymin MaxX ymin L\n");
  483.  
  484. /* Update ytop */
  485.       printf("/ylast ytop def\n");
  486.       printf("/ytop ymin def\n");
  487.  
  488.       (void) DoQueuedPs();
  489.  
  490. /* Re-do the calendar stuff if there was any included PS code */
  491.       if (HadQPS) {
  492.          printf("/ytop ylast def\n");
  493.          for (i=begin; i<=end; i++) {
  494.             printf("CAL%d\n", i);
  495.          }
  496.          printf("/y ytop MinBoxSize sub def y ymin lt {/ymin y def} if\n");
  497.          printf("MinX ymin MaxX ymin L\n");
  498.          printf("/ylast ytop def\n");
  499.      printf("/ytop ymin def\n");
  500.       }
  501.    }
  502. }
  503.  
  504. /***************************************************************/
  505. /*                                                             */
  506. /*  WriteOneEntry - write an entry for one day                 */
  507. /*                                                             */
  508. /***************************************************************/
  509. #ifdef HAVE_PROTOS
  510. void WriteOneEntry(char *s)
  511. #else
  512. void WriteOneEntry(s)
  513. char *s;
  514. #endif
  515. {
  516.    int c;
  517.    printf("  [");
  518.  
  519. /* Chew up leading spaces */
  520.    while(isspace(*s)) s++;
  521.  
  522.    putchar('(');
  523.    while(*s) {
  524.       c = *s++;
  525.       if (c == '\\' || c == '(' || c == ')') putchar('\\');
  526.       if (!isspace(c)) putchar(c);
  527.       else {
  528.          putchar(')');
  529.          while(isspace(*s)) s++;
  530.      if (!*s) {
  531.             printf("]\n");
  532.         return;
  533.          }
  534.          putchar('(');
  535.       }
  536.    }
  537.    printf(")]\n");
  538. }
  539.  
  540. /***************************************************************/
  541. /*                                                             */
  542. /*  Init - set up parameters                                   */
  543. /*                                                             */
  544. /***************************************************************/
  545. #ifdef HAVE_PROTOS
  546. PUBLIC void Init(int argc, char *argv[])
  547. #else
  548. void Init(argc, argv)
  549. int argc;
  550. char *argv[];
  551. #endif
  552. {
  553.    char *s, *t;
  554.    int i=1;
  555.    int j;
  556.    int offset;
  557.  
  558.    PortraitMode = 1;
  559.    NoSmallCal = 0;
  560.    LeftMarg = 36;
  561.    RightMarg = 36;
  562.    TopMarg = 36;
  563.    BotMarg = 36;
  564.    UseISO = 0;
  565.    FillPage = 0;
  566.    MondayFirst = 0;
  567.    SmallLocation = "bt";
  568.  
  569.    for(j=0; j<32; j++) PsEntries[i] = NULL;
  570.  
  571.    CurPage = DefaultPage;  /* Letter size by default */
  572.  
  573.    while (i < argc) {
  574.       s = argv[i];
  575.       i++;
  576.  
  577.       if (*s++ != '-') Usage("Options must begin with '-'");
  578.  
  579.       switch(*s++) {
  580.  
  581.          case 'n':
  582.         MondayFirst = 1;
  583.         break;
  584.  
  585.          case 'p':
  586.         if (i == argc) Usage("Prologue filename must be supplied");
  587.         UserProlog = argv[i++];
  588.         break;
  589.  
  590.          case 's':
  591.         if (i == argc) Usage("Size must be supplied");
  592.         t = argv[i++];
  593.         while(*s) {
  594.            switch(*s++) {
  595.               case 'h': HeadSize = t; break;
  596.           case 'e': EntrySize = t; break;
  597.           case 'd': DaySize = t; break;
  598.           case 't': TitleSize = t; break;
  599.                   default: Usage("Size must specify h, t, e, or d");        
  600.            }
  601.             }
  602.         break;
  603.  
  604.          case 'f':
  605.         if (i == argc) Usage("Font must be supplied");
  606.         t = argv[i++];
  607.         while(*s) {
  608.            switch(*s++) {
  609.               case 'h': HeadFont = t; break;
  610.           case 'e': EntryFont = t; break;
  611.           case 'd': DayFont = t; break;
  612.           case 's': SmallFont = t; break;
  613.           case 't': TitleFont = t; break;
  614.                   default: Usage("Font must specify s, h, t, e, or d");        
  615.            }
  616.             }
  617.         break;
  618.  
  619.          case 'm':
  620.         if (i == argc) Usage("Media must be supplied");
  621.         t = argv[i++];
  622.         CurPage = NULL;
  623.         for (j=0; j<NUMPAGES; j++)
  624.            if (!strcmp(t, Pages[j].name)) {
  625.               CurPage = &Pages[j]; 
  626.           break;
  627.                }
  628.  
  629.         if (!CurPage) {
  630.            fprintf(stderr, "\nUnknown media specified.\n");
  631.                fprintf(stderr, "\nAvailable media types:\n");
  632.                for (j=0; j<NUMPAGES; j++)
  633.               fprintf(stderr, "   %s\n", Pages[j].name);
  634.                fprintf(stderr, "Default media type is %s\n", DefaultPage[0].name);
  635.            exit(1);
  636.             }
  637.         break;
  638.  
  639.      case 'o':
  640.         if (i == argc) Usage("Offset must be supplied");
  641.         offset = atoi(argv[i++]);
  642.         if (offset < 36) offset = 36;
  643.         if (!*s) Usage("Offset must specify l, r, t or b");
  644.         while(*s) {
  645.            switch(*s++) {
  646.               case 'l': LeftMarg = offset; break;
  647.           case 'r': RightMarg = offset ; break;
  648.           case 't': TopMarg = offset; break;
  649.           case 'b': BotMarg = offset; break;
  650.           default: Usage("Offset must specify l, r, t or b");
  651.            }
  652.         }
  653.         break;
  654.  
  655.          case 'b':
  656.         if (i == argc) Usage("Border must be supplied");
  657.         BorderSize = argv[i++];
  658.         break;
  659.  
  660.          case 't':
  661.         if (i == argc) Usage("Line thickness must be supplied");
  662.         LineWidth = argv[i++];
  663.         break;
  664.  
  665.      case 'l': PortraitMode = 0; break;
  666.  
  667.      case 'i': UseISO = 1; break;
  668.  
  669.      case 'c': j=(*s);
  670.                if (!j) {
  671.               SmallLocation = SmallCalLoc[0];
  672.                    } else {
  673.               j -= '0';
  674.               if (j>=0 && j<NUMSMALL) {
  675.                  SmallLocation = SmallCalLoc[j];
  676.               } else {
  677.                  SmallLocation = SmallCalLoc[0];
  678.                       }
  679.                    }
  680.            break;
  681.  
  682.      case 'e': FillPage = 1; break;
  683.  
  684.      default: Usage("Unrecognized option");
  685.       }
  686.    }
  687. }
  688.  
  689. /***************************************************************/
  690. /*                                                             */
  691. /*  Usage - print usage information                            */
  692. /*                                                             */
  693. /***************************************************************/
  694. #ifdef HAVE_PROTOS
  695. PUBLIC void Usage(char *s)
  696. #else
  697. void Usage(s)
  698. char *s;
  699. #endif
  700. {
  701.    if (s) fprintf(stderr, "\nrem2ps: %s\n\n", s);
  702.  
  703.    fprintf(stderr, "Rem2PS: Produce a PostScript calendar from output of Remind.\n\n");
  704.    fprintf(stderr, "Usage: rem2ps [options]\n\n");
  705.    fprintf(stderr, "Options:\n\n");
  706.    fprintf(stderr, "-p file       Include user-supplied PostScript code in prologue\n");
  707.    fprintf(stderr, "-l            Do calendar in landscape mode\n");
  708.    fprintf(stderr, "-c[n]         Control small calendars: 0=none; 1=bt; 2=tb; 3=sbt\n");
  709.    fprintf(stderr, "              and next month\n");
  710.    fprintf(stderr, "-i            Use ISO 8859-1 encoding in PostScript output\n");
  711.    fprintf(stderr, "-m media      Set page size (eg, Letter, Legal, A4.)  Case sensitive!\n");
  712.    fprintf(stderr, "              (Default page size is %s)\n", DefaultPage[0].name);
  713.    fprintf(stderr, "-f[shted] font Set font for small cal, hdr, title, cal entries, day numbers\n");
  714.    fprintf(stderr, "-s[hted] size Set size for header, title, calendar entries and/or day numbers\n");
  715.    fprintf(stderr, "-b size       Set border size for calendar entries\n");
  716.    fprintf(stderr, "-t size       Set line thickness\n");
  717.    fprintf(stderr, "-e            Make calendar fill entire page\n");
  718.    fprintf(stderr, "-o[lrtb] marg Specify left, right, top and bottom margins\n");
  719.    fprintf(stderr, "-n            Start calendar with Monday rather than Sunday\n");
  720.    exit(1);
  721. }
  722.  
  723. /***************************************************************/
  724. /*                                                             */
  725. /*  DoSmallCal - do the small calendar for previous or next    */
  726. /*  month.                                                     */
  727. /*                                                             */
  728. /***************************************************************/
  729. #ifdef HAVE_PROTOS
  730. void DoSmallCal(char *m, int days, int first, int col, int which)
  731. #else
  732. void DoSmallCal(m, days, first, col, which)
  733. char *m;
  734. int days, first, col;
  735. #endif
  736. {
  737.    /* Do the small calendar */
  738.    int i, j;
  739.    int row = 2;
  740.  
  741.    if (MondayFirst) {
  742.       first--;
  743.       if (first < 0) first = 6;
  744.    }
  745.    /* Figure out the font size */
  746.  
  747.    printf("/SmallFontSize MinBoxSize Border sub Border sub 8 div 2 sub def\n");
  748.    printf("/SmallFont findfont setfont\n");
  749.    printf("SmallString stringwidth pop /SmallWidth exch def\n");
  750.    printf("SmallWidth 7 mul xincr Border sub Border sub exch div /tmp exch def\n");
  751.    printf("tmp SmallFontSize lt {/SmallFontSize tmp def} if\n");
  752.    printf("/SmallFont findfont SmallFontSize scalefont setfont\n");
  753.  
  754.    /* Recalculate SmallWidth */
  755.    printf("SmallString stringwidth pop /SmallWidth exch def\n");
  756.  
  757.    /* Save graphics state */
  758.    printf("gsave\n");
  759.  
  760.    /* Move origin to upper-left hand corner of appropriate box */
  761.    printf("%d xincr mul MinX add ysmall%d translate\n", col, which);
  762.  
  763.    /* Print the month */   
  764.    printf("SmallWidth 7 mul (%s) stringwidth pop sub 2 div Border add Border neg SmallFontSize sub moveto (%s) show\n", m, m);
  765.  
  766.    /* Print the days of the week */
  767.    for (i=0; i<7; i++) {
  768.       if (MondayFirst) j=(i+1)%7;
  769.       else             j=i;
  770.       printf("Border %d SmallWidth mul add Border neg SmallFontSize sub SmallFontSize sub 2 sub moveto (%c) show\n", i, Days[j]);
  771.    }
  772.  
  773.    /* Now do the days of the month */
  774.    for (i=1; i<=days; i++) {
  775.       printf("Border %d SmallWidth mul add Border neg SmallFontSize sub SmallFontSize 2 add %d mul sub moveto (%d) show\n", first, row, i);
  776.       first++;
  777.       if (first == 7) { first = 0; row++; }
  778.    }
  779.  
  780.    /* restore graphics state */
  781.    printf("grestore\n");
  782. }
  783.  
  784. /***************************************************************/
  785. /*                                                             */
  786. /*  DoQueuedPs - do the queued PS and PSFILE reminders.        */
  787. /*                                                             */
  788. /***************************************************************/
  789. #ifdef HAVE_PROTOS
  790. PUBLIC int DoQueuedPs(void)
  791. #else
  792. int DoQueuedPs()
  793. #endif
  794. {
  795.    int i;
  796.    int HadPS = 0;
  797.    int wd;
  798.    int begin, end;
  799.    int nread;
  800.    CalEntry *e, *n;
  801.    FILE *fp;
  802.    int fnoff;
  803.    char buffer[LINELEN];
  804.  
  805.    if (!MondayFirst) begin = CurDay - WkDayNum;
  806.    else             begin = CurDay - (WkDayNum ? WkDayNum-1 : 6);
  807.    wd = 0;
  808.    while (begin < 1) begin++, wd++;
  809.    end = CurDay;
  810.    for (i=begin; i<=end; i++, wd++) {
  811.       e = PsEntries[i];
  812.  
  813.       if (e) {
  814.          HadPS = 1;
  815.          printf("/SAVESTATE save def\n");
  816.  
  817.          /* Translate coordinates to bottom of calendar box */
  818.          printf("%d xincr mul MinX add ytop translate\n", wd);
  819.  
  820.          /* Set up convenient variables */
  821.          printf("/BoxWidth xincr def\n/BoxHeight ylast ytop sub def\n");
  822.      printf("/InBoxHeight BoxHeight border sub DaySize sub DaySize sub 2 add EntrySize add def \n");
  823.       }
  824.  
  825.       while (e) {
  826.  
  827. /* Now do the user's PostScript code */
  828.          fnoff = 1;
  829.      while (isspace(*(e->entry+fnoff))) fnoff++;
  830.          if (*(e->entry) == 'P') {
  831.         printf("%s\n", e->entry+fnoff);
  832.          } else {
  833.         fp = fopen(e->entry+fnoff, "r");
  834.         if (!fp) {
  835.            fprintf(stderr, "Could not open PostScript file '%s'\n", e->entry+1);
  836.             } else {
  837.            while(1) {
  838.               nread = fread(buffer, sizeof(char), LINELEN, fp);
  839.           if (!nread) break;
  840.           fwrite(buffer, sizeof(char), nread, stdout);
  841.                }
  842.            fclose(fp);
  843.             }
  844.          }
  845.  
  846. /* Free the entry */
  847.          free(e->entry);
  848.      n = e->next;
  849.      free(e);
  850.      e = n;
  851.       }
  852.       if (PsEntries[i]) printf("\n SAVESTATE restore\n");
  853.       PsEntries[i] = NULL;
  854.    }
  855.    return HadPS;
  856. }
  857.  
  858. /***************************************************************/
  859. /*                                                             */
  860. /* GetSmallLocations                                           */
  861. /*                                                             */
  862. /* Set up the locations for the small calendars.               */
  863. /*                                                             */
  864. /***************************************************************/
  865. #ifdef HAVE_PROTOS
  866. PUBLIC void GetSmallLocations(void)
  867. #else
  868. void GetSmallLocations()
  869. #endif
  870. {
  871.    char c;
  872.    char *s = SmallLocation;
  873.    int colfirst, collast;
  874.  
  875. /* Figure out the first and last columns */
  876.    colfirst = FirstWkDay;
  877.    collast = (FirstWkDay+MaxDay-1) % 7;
  878.    if (MondayFirst) {
  879.       colfirst = colfirst ? colfirst - 1 : 6;
  880.       collast = collast ? collast - 1 : 6;
  881.    }
  882.    NoSmallCal = 0;
  883.  
  884.    while((c = *s++) != 0) {
  885.       switch(c) {
  886.          case 'b':
  887.         /* Adjust Feb. if we want it on the bottom */
  888.         if (MaxDay == 28 && colfirst == 0) { 
  889.            printf("/ysmallbot ymin def /ymin ysmallbot MinBoxSize sub def\n");
  890.            printf("MinX ymin MaxX ymin L\n");
  891.            printf("/ysmall1 ysmallbot def /ysmall2 ysmallbot def\n");
  892.            SmallCol1 = 5;
  893.            SmallCol2 = 6;
  894.            return;
  895.             }
  896.         if (collast <= 4) {
  897.            printf("/ysmall1 ysmallbot def /ysmall2 ysmallbot def\n");
  898.            SmallCol1 = 5;
  899.            SmallCol2 = 6;
  900.            return;
  901.         }
  902.         break;
  903.  
  904.      case 't':
  905.         if (colfirst >= 2) {
  906.            printf("/ysmall1 ysmalltop def /ysmall2 ysmalltop def\n");
  907.            SmallCol1 = 0;
  908.            SmallCol2 = 1;
  909.            return;
  910.         }
  911.         break;
  912.  
  913.      case 's':
  914.         if (colfirst >= 1 && collast<=5) {
  915.            printf("/ysmall1 ysmalltop def /ysmall2 ysmallbot def\n");
  916.            SmallCol1 = 0;
  917.            SmallCol2 = 6;
  918.            return;
  919.         }
  920.         break;
  921.       }
  922.    }
  923.    NoSmallCal = 1;
  924.    return;
  925. }
  926.            
  927.