home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / alde_c / misc / zed / yearcal / yearcal.c next >
Encoding:
Text File  |  1988-03-04  |  57.1 KB  |  1,873 lines

  1. /********************************************************************
  2. **  YEARCAL.C   v0.01Td     Copyright (c) 1987, 1988 by Paul M. Sittler.
  3. **  All rights reserved.  The copyright owner hereby authorizes the
  4. **  no-charge, noncommercial making and/or distribution of copies of
  5. **  the entirety of this work unchanged and unincorporated in any
  6. **  other work (except "LiBRary" or "ARChive" disk files for the sole
  7. **  purpose of no-charge noncommercial distribution).  No other
  8. **  reproduction or use is authorized without the express prior
  9. **  written consent of the copyright owner.
  10. **
  11. **  Once upon a time, in a kingdom far away, people shared source
  12. **  code and many of us benefited from the sharing.  This silly
  13. **  little program is here presented with source in hopes that it may
  14. **  stimulate the renewed sharing of our efforts.
  15. **
  16. **  I am open to comment, suggestions for enhancements, and bug
  17. **  reports.
  18. **
  19. **  Paul M. Sittler
  20. **  1106 Berkeley Drive
  21. **  College Station, TX 77840
  22. **
  23. **  Modem (409) 764-0056 300/1200/2400 baud 24 hours/day
  24. **  My Word #2 Fido 117/1
  25. **  GENie User mail address P.M.SITTLER
  26. **
  27. **  Modified for Borland's Turbo-C
  28. **  26 August 1987 <pms>
  29. **
  30. **  Modified for Workaround for Borland's Turbo-C bug on % Operator
  31. **  Replaced calls to scanf with get_int routine.
  32. **  10 September 1987 <pms>
  33. **
  34. **  Modified to produce a "Programmer's" Calendar, which can
  35. **  display dates in Octal or Hexadecimal numbering.
  36. **  11 September 1987 <pms>
  37. **
  38. **  Modified to produce calendars in any of 14 different languages
  39. **  at user's option
  40. **  18 September 1987 <pms>
  41. **
  42. **  Modified to create a Julian date calendar.
  43. **  Modified to add support for Afrikaans language.
  44. **  29 September 1987 <pms>
  45. **
  46. **  Modified to add support for Korean language.
  47. **  Modified Julian date calendar to skip a line every five.
  48. **  Rewrote menu for language selection to save space.
  49. **  14 October 1987 <pms>
  50. **
  51. **  Added Daily and Weekly Scheduling sheets.  User may choose beginning
  52. **  hour for scheduling.
  53. **  16 October 1987 <pms>
  54. **
  55. **  Fixed Daily and Weekly scheduling sheets.
  56. **  Added ability to select number of hours to schedule, program
  57. **  adapts the page for it.
  58. **  25 October 1987 <pms>
  59. **
  60. **  Added Monthly Calendar.
  61. **  Added ability to specify number of lines and columns on a page for
  62. **  file and printer output.  Modified filename routines to shorten
  63. **  program slightly.
  64. **  31 October 1987 <pms>
  65. **
  66. **  Added title lines that include the last month and next month
  67. **  calendars and two user-defined title lines.  Rewrote the
  68. **  program to calculate three years worth of calendars for each
  69. **  year so that previous month's calendars can be displayed even
  70. **  when they are last years.  Added Programmers calendar option
  71. **  to the monthly, daily, and weekly schedule options.
  72. **  Made defaults firm or sticky, such that once user selects one,
  73. **  it stays the same while running program.
  74. **  1 November 1987 <pms>
  75. **
  76. **  Added Czechoslovakian Language Support thanks to Briggs Myrick.
  77. **  3 January 1988 <pms>
  78. **
  79. **  Default Page width changed to 80 cols from 85.
  80. **  Maximum Page width increased to 270 from 200 for 20 CPI on 13.5".
  81. **  5 January 1988 <pms>
  82. **  Added optional pause at end of each printed page defaulted off.
  83. **  Added a C/R after the FF at the end of a page so that dot matrix
  84. **  printers like Epson will process FF without buffering it.
  85. **  Added 3rd, 7th and 8th user-defined title lines.  Explained that Titles
  86. **  #4-#6 are used for dates.  Explained how to remove a title.
  87. **  8 January 1988 <pms>
  88. **  Changed "Marz" to "Maerz" per Brief von Ed Braaten, and "Rizen" to "Rijen"
  89. **  on recommendation of Dr. Skrabanek.
  90. **  22 January 1988 <pms>
  91. **  Allow user to specify "Left Margin indent (spaces) ?"
  92. **  Make customized defaults "permanent" by writing them at end of .EXE file.
  93. **  Tnx to Alan Holub in C-Chest, DDJ, Feb 1988 4 February 1988 <pms>
  94. **  Someday, the following additions. . .
  95. **  Optional IBM/Epson graphic character set for printers/IBM screens.
  96. **  ?? February 1988 <pms>
  97. **************************************************************/
  98.  
  99. #include <stdio.h>
  100. #include <stdarg.h>
  101. #include <stdlib.h>
  102. #include <conio.h>
  103. #include <ctype.h>
  104. #include <dos.h>    /* DOS-specific file from Borland */
  105. #include <fcntl.h>
  106. #include <io.h>
  107. #include <process.h>
  108. #include <string.h>
  109.  
  110. #define DEF_SIG "(c) 1988, Paul M. Sittler.  All rights reserved."
  111. #define ERROR (-1)
  112. #define TRUE 1
  113. #define FALSE 0
  114. #define BUF 200
  115. #define LIN 80
  116.  
  117. struct options
  118. {
  119.     char signature[ sizeof(DEF_SIG) ];
  120.     int chksum;
  121.     int bh,    /* Beginning hour for schedules */
  122.       copies,   /* Number of copies to print */
  123.       indent,    /* Left Margin Indent in spaces */
  124.       lang,    /* Language desired for calendar */
  125.       more_yrs, /* Number of successive periods to print */
  126.       nh,    /* Number of Hours to schedule */
  127.       pl,    /* Page Length in lines */
  128.       pw;    /* Page Width in characters or columns */
  129.     char aggie;    /* Aggie calendar flag */
  130.     char base;    /* Number base for Programmers Calendar, 0, H(ex), O(ctal) */
  131.     char fy;    /* Fiscal year flag */
  132.     char julian;/* Julian calendar flag */
  133.     char pause;    /* Page pause flag */
  134.     char sched_type;/* Schedule type M(onthly), W(eekly), D(aily) */
  135.     char title[8][LIN];
  136.     /* This structure also contains fields for every option that
  137.      * the user can change at runtime.  These are the default values
  138.      * that are used if no other values have been specified by the
  139.      * user during a run.
  140.      */
  141. }
  142. Opt;
  143.  
  144. /* extern int directvideo = 0;     * Gag me with a spoon! */
  145.                 /* An "enhancement" of Turbo-c v1.5 */
  146. /* Zero = use BIOS calls     One  = write to video ram for PC-Compats */
  147. /* For MSDOS generic, this must now be zero.  And it STILL doesn't work!! */
  148. /* The getch function generates wild interrupts on Z-100 */
  149.  
  150. /* Suppress some library functions to conserve space */
  151. /* void _setargv () {}
  152.  * void _setenvp () {}
  153.  */
  154.  
  155. struct month
  156. {
  157.     int  length;
  158.     int  first_day;
  159. };
  160.  
  161. /* put month's lengths into structure */
  162. static struct month mon[] =
  163.     {
  164.     { 31, 0}, { 28, 0}, { 31, 0},
  165.     { 30, 0}, { 31, 0}, { 30, 0},
  166.     { 31, 0}, { 31, 0}, { 30, 0},
  167.     { 31, 0}, { 30, 0}, { 31, 0}
  168.     };
  169.  
  170. int lingos = 17;    /* How many languages we gonna have available */
  171. char *lingo[] =
  172.        {
  173. "Afrikaans",    /*  0 */
  174. "Czech",    /*  1 */
  175. "Danish",    /*  2 */
  176. "Dutch",    /*  3 */
  177. "English",    /*  4 */
  178. "Finnish",    /*  5 */
  179. "French",    /*  6 */
  180. "German",    /*  7 */
  181. "Italian",    /*  8 */
  182. "Korean",    /*  9 */
  183. "Norwegian",    /* 10 */
  184. "Polish",    /* 11 */
  185. "Portugese",    /* 12 */
  186. "Serbo-Croatian",/* 13 */
  187. "Spanish",    /* 14 */
  188. "Swedish",    /* 15 */
  189. "Texan"        /* 16 */
  190.        } ;
  191.  
  192. char *mnam[][12] =
  193.        {
  194. /* Afrikaans    0 */  "JANUARI",   "FEBRUARI",   "MAART",     "APRIL",    "MEI",      "JUNI",     "JULI",     "AUGUSTUS", "SEPTEMBER",  "OKTOBER",     "NOVEMBER",  "DECEMBER",
  195. /* Czech    1 */  "LEDEN",     "UNOR",       "BREZEN",    "DUBEN",    "KVETEN",   "CERVEN",   "CERVENEC", "SRPEN",    "ZARI",       "RIJEN",       "LISTOPAD",  "PROSINEC",
  196. /* Danish    2 */  "JANUAR",    "FEBRUAR",    "MARTS",     "APRIL",    "MAJ",      "JUNI",     "JULI",     "AUGUST",   "SEPTEMBER",  "OKTOBER",     "NOVEMBER",  "DECEMBER",
  197. /* Dutch    3 */  "JANUARI",   "FEBRUARI",   "MAART",     "APRIL",    "MEI",      "JUNI",     "JULI",     "AUGUSTUS", "SEPTEMBER",  "OKTOBER",     "NOVEMBER",  "DECEMBER",
  198. /* English    4 */  "JANUARY",   "FEBRUARY",   "MARCH",     "APRIL",    "MAY",      "JUNE",     "JULY",     "AUGUST",   "SEPTEMBER",  "OCTOBER",     "NOVEMBER",  "DECEMBER",
  199. /* Finnish    5 */  "PRPRNUU",  "HELMIKUU",   "MAALISKUU", "HUHTIKUU", "TOUKOKUU", "KESAKUU",  "HEINAKUU", "ELOKUU",   "SYYSKUU",    "LOKAKUU",     "MARRASKUU", "JOULUKUU",
  200. /* French    6 */  "JANVIER",   "FEVRIER",    "MARS",      "AVRIL",    "MAI",      "JUIN",     "JUILLET",  "AOUT",     "SEPTEMBRE",  "OCTOBRE",     "NOVEMBRE",  "DECEMBRE",
  201. /* German    7 */  "JANUAR",    "FEBRUAR",    "MAERZ",     "APRIL",    "MAI",      "JUNI",     "JULI",     "AUGUST",   "SEPTEMBER",  "OKTOBER",     "NOVEMBER",  "DEZEMBER",
  202. /* Italian    8 */  "GENNAIO",   "FEBBRAIO",   "MARZO",     "APRILE",   "MAGGIO",   "GIUGNIO",  "LUGLIO",   "AGOSTO",   "SETTEMBRE",  "OTTOBRE",     "NOVEMBRE",  "DICEMBRE",
  203. /* Latin          "JANUARIUS", "FEBRUARIUS", "MARTIUS",   "APRILIS",  "MAIUS",    "JUNIUS",   "JULIUS",   "AUGUSTUS", "SEPTEMBER",  "OCTOBER",     "NOVEMBER",  "DECEMBER", */
  204. /* Korean    9 */  "IL-WOL",    "I-WOL",      "SAM-WOL",   "SA-WOL",   "O-WOL",    "YU-WOL",  "CH'IL-WOL", "P'AL-WOL", "KU-WOL",     "SI-WOL",      "SIP IL-WOL","SIP I-WOL",
  205. /* Norwegian    10 */  "JANUAR",    "FEBRUAR",    "MARS",      "APRIL",    "MAI",      "JUNI",     "JULI",     "AUGUST",   "SEPTEMBER",  "OKTOBER",     "NOVEMBER",  "DESEMBER",
  206. /* Polish    11 */  "STYCZEN",   "LUTY",       "MARZEC",    "KWIECIEN", "MAJ",      "CZERWIEC", "LIPIEC",   "SIERPIEN", "WRZESIEN",   "PAZDZIERNIK", "LISTOPAD",  "GRUDZIEN",
  207. /* Portugese    12 */  "JANEIRO",   "FEVEREIRO",  "MARCO",     "ABRIL",    "MAIO",     "JUNHO",    "JULHO",    "AGOSTO",   "SETEMBRO",   "OUTUBRO",     "NOVEMBRO",  "DEZEMBRO",
  208. /* Serbo-Croatian 13 */  "JANUAR",    "FEBRUAR",    "MART",      "APRIL",    "MAJ",      "JUN",      "JULI",     "AVGUST",   "SEPTEMBAR",  "OKTOBAR",     "NOVEMBAR",  "DECEMBAR",
  209. /* Spanish    14 */  "ENERO",     "FEBRERO",    "MARZO",     "ABRIL",    "MAYO",     "JUNIO",    "JULIO",    "AGOSTO",   "SEPTIEMBRE", "OCTUBRE",     "NOVIEMBRE", "DICIEMBRE",
  210. /* Swedish    15 */  "JANUARI",   "FEBRUARI",   "MARS",      "APRIL",    "MAJ",      "JUNI",     "JULI",     "AUGUSTI",  "SEPTEMBER",  "OKTOBER",     "NOVEMBER",  "DECEMBER",
  211. /* Texan    16 */  "JANYEWARY", "FEBYEWARY",  "MAHCH",     "AYEPRIL",  "MEYE",     "CHEWN",    "CHEW-LIE", "AWGUST",   "SEPTEMBUH",  "AWKTOBUH",    "NOVEMBUH",  "DEESEMBUH"
  212.       } ;
  213.  
  214. /* put names of days into array */
  215. char *wkday[][7] =
  216.        {
  217. /* Afrikaans    0 */  "SONDAG",    "MAANDAG",       "DINSDAG",     "WOENSDAG",     "DONDERDAG",    "VRYDAG",      "SATERDAG",
  218. /* Czech    1 */  "NEDELE",    "PONDELI",       "UTERY",       "STREDA",       "CTVRTEK",      "PATEK",       "SOBOTA",
  219. /* Danish    2 */  "SONDAG",    "MANDAG",    "TIRSDAG",     "ONSDAG",       "TORSDAG",      "FREDAG",      "LORDAG",
  220. /* Dutch    3 */  "ZONDAG",    "MAANDAG",       "DINSDAG",     "WOENSDAG",     "DONDERDAG",    "VRIJDAG",     "ZATERDAG",
  221. /* English    4 */  "SUNDAY",    "MONDAY",    "TUESDAY",     "WEDNESDAY",    "THURSDAY",     "FRIDAY",      "SATURDAY",
  222. /* Finnish    5 */  "SUNNUNTAI", "MAANANTAI",     "TIISTAI",     "KESKIVIIKKO",  "TORSTAI",      "PERJANTAI",   "LAUANTAI",
  223. /* French    6 */  "DIMANCHE",  "LUNDI",     "MARDI",       "MERCREDI",     "JEUDI",    "VENDREDI",    "SAMEDI",
  224. /* German    7 */  "SONNTAG",   "MONTAG",    "DIENSTAG",    "MITTWOCH",     "DONNERSTAG",   "FREITAG",     "SONNABEND",
  225. /* Italian    8 */  "DOMENICA",  "LUNEDI",    "MARTEDI",     "MERCOLEDI",    "GIOVEDI",      "VENERDI",     "SABATO",
  226. /* Latin          "DOMINICUS", "LUNES",     "MIUS",    "",         "",         "",        "", */
  227. /* Korean    9 */  "IL-YO-IL",  "WOL-YO-IL",     "HWA-YO-IL",   "SU-YO-IL",     "MOK-YO-IL",    "KUM-YO-IL",   "T'O-YO-IL",
  228. /* Norwegian    10 */  "SONDAG",    "MANDAG",    "TIRSDAG",     "ONSDAG",       "TORSDAG",      "FREDAG",      "LORDAG",
  229. /* Polish    11 */  "NIEDZIELA", "PONIEDZIALEK",  "WTOREK",      "SRODA",    "CZWARTEK",     "PIATEK",      "SOBOTA",
  230. /* Portugese    12 */  "DOMINGO",   "SEGUNDA-FEIRA", "TERCA-FIERA", "QUARTA-FIERA", "QUINTA-FIERA", "SEXTA-FIERA", "SABADO",
  231. /* Serbo-Croatian 13 */  "NEDELJA",   "PONEDELJAK",    "UTORAK",      "SREDA",    "CETVRTAK",     "PETAK",       "SUBOTA",
  232. /* Spanish    14 */  "DOMINGO",   "LUNES",     "MARTES",      "MIERCOLES",    "JUEVES",       "VIERNES",     "SABADO",
  233. /* Swedish    15 */  "SONDAG",    "MANDAG",    "TISDAG",      "ONSDAG",       "TORSDAG",      "FREDAG",      "LORDAG",
  234. /* Texan    16 */  "SUNNY",     "MONEY",    "TEWSDI",      "WEDDSDI",      "THIRSTY",      "FRAWDDI",     "SATTADI"
  235.       } ;
  236.  
  237. /* Hebrew - based on solar years and lunar months.
  238.    shelema - 355 days - complete year, with Heshvan & Keslev having 30 days.
  239.    sedur   - 354 days - normal year, Heshvan is defective (29 days).
  240.    hasera  - 353 days - Heshvan & Kislev both defective (29 days).
  241.    The 11 days by which the solar year (365 days) exceeds the lunar year
  242.    (354 days) are accounted for by having a 13th month (Veadar of 30 days)
  243.    on the 3rd, 6th, 8th, 11th, 14th, and 17th year of a 19 year cycle.
  244.  
  245.     "TISHRI", 30,    "HESHVAN", 29/30,    "KISLEV", 29/30,
  246.     "TEBET", 29,    "SHEBAT", 30,        "ADAR", 30,    "VEADAR", 30
  247.     "NISAN", 30,    "IYAR", 29,        "SIVIAN", 30,
  248.     "TAMMUZ", 29,    "AB", 30,        "ELUL", 29
  249. */
  250.  
  251. int yr[3][12][6][7];    /* Array for 3 yrs, 4-D, 3 years, */
  252.             /* 12 months/year, 6 weeks/month, 7 days/week */
  253.  
  254. char *new_file  = "DATAFILE.$$$";
  255. char *file      = "DATAFILE.CAL";
  256. FILE *fp;
  257.  
  258. void main(argc, argv)
  259. char **argv;
  260. int argc;
  261. {
  262.   int bd,    /* Beginning day passed to functions */
  263.       bm,       /* Beginning month passed to functions */
  264.       by,    /* Beginning year passed to functions */
  265.       fy_bm,    /* Fiscal year beginning month */
  266.       fy_bd,    /* Fiscal year beginning date */
  267.       i,
  268.       j,
  269.       year;
  270.   char c,
  271.        outp;
  272.  
  273.   int get_int(),
  274.       get_yn(),
  275.       leap();
  276.   void agg_printer(),
  277.        cal_printer(),
  278.        day_printer(),
  279.        get_opts(),
  280.        jul_printer(),
  281.        prep_cal(),
  282.        put_opts(),
  283.        sched_printer(),
  284.        setup_files(),
  285.        signon();
  286.   struct date today;    /* dos.h from Borland */
  287.   get_opts(argv[0]);
  288.   signon();
  289.  
  290.                 /* DOS specific. . . */
  291.     getdate(&today);        /* Get DOS's idea of date */
  292.     fy_bd = today.da_day;    /* Make it today */
  293.     fy_bm = today.da_mon;    /* Make it this month */
  294.     year  = today.da_year;    /* It was a very good year. . . */
  295.  
  296.   for ( ;; )
  297.   {
  298.     fprintf(stderr,
  299.     "\nSchedule period to be <A>nnual, <M>onthly, <W>eekly, or <D>aily (A/M/W/D)? %c\b",
  300.                Opt.sched_type ? Opt.sched_type : 'A' );
  301.     for ( ;; )
  302.     {
  303.     c = toupper(getch());
  304.     switch(c)
  305.     {
  306.         case  'M'  : break;
  307.         case  'W'  : break;
  308.         case  'D'  : break;
  309.         case  'A'  : break;
  310.         case '\033': exit(0);
  311.         case '\r'  :
  312.         case '\n'  : c = (Opt.sched_type == FALSE) ? 'A': Opt.sched_type;
  313.         default    : ;
  314.     }
  315.     if( (c == 'M') ||
  316.         (c == 'W') ||
  317.         (c == 'D') ||
  318.         (c == 'A')  )
  319.     {
  320.         Opt.sched_type = c;
  321.         putch(c);
  322.         if (Opt.sched_type == 'A')
  323.         Opt.sched_type = FALSE;
  324.         break;
  325.     }
  326.     continue;
  327.     }
  328.     fputs("\nType year desired for calendar (1901-4000): ", stderr);
  329.     year = get_int(year, 4, 1901, 4000);
  330.  
  331.     fprintf(stderr, "\nHow many successive %ss? (0-99): ",
  332.         (Opt.sched_type == 'M') ? "month" :
  333.         (Opt.sched_type == 'W') ? "week" :
  334.         (Opt.sched_type == 'D') ? "day" :
  335.                       "year");
  336.     Opt.more_yrs = get_int(Opt.more_yrs, 2, 0, 99);
  337.  
  338.     if (! (Opt.sched_type) )
  339.     {
  340.     fputs("\nDo you want an Aggie Calendar", stderr);
  341.     Opt.aggie = get_yn(Opt.aggie ? 'y' : 'n');
  342.     }
  343.  
  344.     if (!Opt.aggie)
  345.     {
  346.     if (! (Opt.sched_type) )
  347.     {
  348.         fputs("\nDo you want a 3-digit Julian Calendar", stderr);
  349.         Opt.julian = get_yn(Opt.julian ? 'y' : 'n');
  350.     }
  351.  
  352.     if (! (Opt.julian | Opt.sched_type) )
  353.     {
  354.         fputs("\nFiscal year calendar ", stderr);
  355.         Opt.fy = get_yn(Opt.fy ? 'y' : 'n');
  356.     }
  357.  
  358.     if (Opt.fy | Opt.sched_type)
  359.     {
  360.         fprintf(stderr, "\n%s beginning month (1-12): ",
  361.         (Opt.sched_type == 'M') ? "Monthly calendar" :
  362.         (Opt.sched_type == 'W') ? "Weekly schedule" :
  363.         (Opt.sched_type == 'D') ? "Daily schedule" :
  364.                       "Fiscal year");
  365.         fy_bm = get_int(fy_bm, 2, 1, 12);
  366.             /* make month J=0, F=1, . . . D=11 */
  367.  
  368.         if (Opt.sched_type != 'M')
  369.         {
  370.         fprintf(stderr, "\n%s beginning date  (1-31): ",
  371.             (Opt.sched_type == 'W') ? "Weekly schedule" :
  372.             (Opt.sched_type == 'D') ? "Daily schedule" :
  373.                       "Fiscal year");
  374.         fy_bd = get_int(fy_bd, 2, 1, 31);
  375.         }
  376.         else fy_bd = 1;    /* make months start on first */
  377.     }
  378.     }
  379.  
  380.     if ( (Opt.sched_type) &&
  381.      (Opt.sched_type != 'M') )
  382.     {
  383.     fprintf(stderr, "\n%s schedule beginning hour  (0-23): ",
  384.         (Opt.sched_type == 'W') ? "Weekly" :
  385.                   "Daily" );
  386.     Opt.bh = get_int(Opt.bh, 2, 0, 23);
  387.  
  388.     fprintf(stderr, "\n%s schedule number of hours (1-24): ",
  389.         (Opt.sched_type == 'W') ? "Weekly" :
  390.                   "Daily" );
  391.     Opt.nh = get_int(Opt.nh, 2, 1, 24);
  392.  
  393.     }
  394.  
  395.     if (Opt.sched_type)
  396.     {
  397. fputs("\nYou may enter up to five custom title lines for the schedules.", stderr);
  398. fputs("\nThe first three titles entered will be printed on the top three lines.", stderr);
  399. fputs("\nThe last two titles will be printed below the date titles.", stderr);
  400.     for (i = 0;
  401.          i < 8;
  402.          i++  )
  403.     {
  404.         if (i == 3)
  405.         {
  406.         fprintf(stderr, "\nTitles #4, #5, and #6 are used for dates");
  407.         i = 6;    /* So skip to Title #7 */
  408.         }
  409.         fprintf(stderr,
  410.       "\nTitle #%d currently is (RETURN to keep it the same, SPACE to erase):",
  411.                      i + 1);
  412.         fprintf(stderr, "\nTitle #%d: %s", i + 1,
  413.                       Opt.title[i][0] ?
  414.                       Opt.title[i]    :
  415.                       "\t(No title currently defined)" );
  416.         fprintf(stderr, "\nTitle #%d: ", i + 1);
  417.         gets(Opt.title[4]);
  418.         if (Opt.title[4][0] != '\0')
  419.         strcpy(Opt.title[i], Opt.title[4]);
  420.     }
  421.     }
  422.  
  423.     fputs("\nProgrammer's Calendar", stderr);
  424.     i = get_yn(Opt.base ? 'y' : 'n');
  425.     if (!i)            /* Decimal numbers used */
  426.     Opt.base = FALSE;
  427.     else            /* Hexadecimal or Octal numbers */
  428.     {
  429.     fprintf(stderr,
  430.     "\n<H>exadecimal or <O>ctal numbering (H/O)? %c\b",
  431.                    (Opt.base == FALSE) ? 'H' : Opt.base);
  432.     for ( ;; )
  433.     {
  434.         c = toupper(getch());
  435.         switch(c)
  436.         {
  437.         case  'O': break;
  438.         case  'H': break;
  439.         case '\r':
  440.         case '\n': c = (Opt.base == FALSE) ? 'H' : Opt.base ; break;
  441.         default  : c = '?';
  442.         }
  443.         if( (c == 'H') || (c == 'O') )
  444.         {
  445.         putch(c);
  446.         Opt.base = c;
  447.         break;
  448.         }
  449.         continue;
  450.     }
  451.     }
  452.  
  453.     fputs("\nThe calendar(s) may be composed in several languages:\n", stderr);
  454.     for (i = 0;
  455.      i < lingos;
  456.      i++)
  457.     {
  458.     if (!(i % 3))
  459.         fputs("\n", stderr);
  460.     fprintf(stderr, "%2d = %-15s",
  461.              i +1, lingo[i]);
  462.     }
  463.  
  464.  
  465.     fprintf(stderr, "\nWhich language for this calendar? (1-%d): ", lingos);
  466.     Opt.lang = get_int(Opt.lang, 2, 1, lingos);
  467.  
  468.     fputs("\n<V>iew, <P>rint, or write to <F>ile(s) (V/P/F)? V\b", stderr);
  469.     for ( ;; )
  470.     {
  471.     c = toupper(getch());
  472.     switch(c)
  473.     {
  474.         case  'F'  : outp = 'F'; break;
  475.         case  'P'  : outp = 'P'; break;
  476.         case '\033': exit(0);
  477.         case '\r'  :
  478.         case '\n'  :
  479.         case  'V'  : outp = 'V'; break;
  480.         default    : outp = '?';
  481.     }
  482.     if( (outp == 'F') || (outp == 'V') || (outp == 'P') )
  483.     {
  484.         putch(c);
  485.         break;
  486.     }
  487.     continue;
  488.     }
  489.  
  490.     if (Opt.sched_type)        /* Page width/length useful only */
  491.                 /* in M/W/D schedules at this time */
  492.  
  493.     if ( (outp == 'P') ||    /* We want hardcopy */
  494. /*       (outp == 'V') || */    /* He wants to look at it */
  495.      (outp == 'F')  )    /* He wants a file */
  496.     {
  497.     fputs("\nType # of lines for each page (51-132): ", stderr);
  498.     Opt.pl = get_int(Opt.pl, 3, 51, 132);
  499.  
  500.     fputs("\nType # of characters for each line (40-270): ", stderr);
  501.     Opt.pw = get_int(Opt.pw, 3, 40, 270);
  502.  
  503.     fputs("\nType # of spaces for left margin indent (0-40): ", stderr);
  504.     Opt.indent = get_int(Opt.indent, 2, 0, 40);
  505.     }
  506.  
  507.     if (outp == 'P')        /* We want hardcopy */
  508.     {
  509.     fprintf(stderr,
  510.     "\nType # of copies desired of each %s (1-999): ",
  511.              (Opt.sched_type == 'M') ? "month" :
  512.              (Opt.sched_type == 'W') ? "week"  :
  513.              (Opt.sched_type == 'D') ? "day"   :
  514.                        "year"  );
  515.     Opt.copies = get_int(Opt.copies, 3, 1, 999);
  516.  
  517.     fputs("\nPause after each page", stderr);
  518.     Opt.pause = get_yn(Opt.pause ? 'y' : 'n');
  519.     }
  520.  
  521.     setup_files(outp);
  522.  
  523.     by = year;
  524.     bm = fy_bm -1;
  525.     bd = fy_bd;
  526.  
  527.     for (i = 0;
  528.      i < Opt.more_yrs + 1;
  529.      i++, (Opt.sched_type == 'M') ? bm++:
  530.           (Opt.sched_type == 'W') ? bd += 7:
  531.           (Opt.sched_type == 'D') ? bd++:
  532.                     by++)
  533.     {
  534.     if (leap(by))        /* Tidy up month length array */
  535.         mon[1].length = 29; /* For this year by fixin' February. . . */
  536.     else
  537.         mon[1].length = 28;
  538.  
  539.     if (bd > mon[bm].length)/* Past this End Of Month */
  540.     {
  541.         bd -= mon[bm].length;
  542.                 /* So make it appropriate day. . . */
  543.         bm++;        /* Of following month. . . */
  544.     }
  545.  
  546.        if (bm > 11)        /* Egad! We are past December. . . */
  547.        {
  548.         bm = bm % 12;    /* Normalise it. . . */
  549.         if (bm == 0)    /* Now have January? J=0, F=1 D=11 */
  550.         by++;        /* Ratchet the year. . . */
  551.        }
  552.  
  553.     if (! (Opt.julian))        /* Prepare the calendar arrays */
  554.         prep_cal(by);
  555.  
  556.     for ( j = 0;
  557.           j < Opt.copies;
  558.           j++)
  559.         {
  560.            if (Opt.sched_type)
  561.            sched_printer(by, outp, bm, bd, Opt.bh, Opt.nh, Opt.pl, Opt.pw, Opt.sched_type, Opt.title, Opt.base, Opt.lang, Opt.pause, Opt.indent);
  562.            else
  563.            if (Opt.julian)
  564.            jul_printer(by, outp, Opt.base, Opt.lang, Opt.pause);
  565.            else
  566.            if (Opt.aggie)
  567.            agg_printer(by, outp, Opt.base, Opt.lang, Opt.pause);
  568.            else
  569.            if (Opt.fy)
  570.            cal_printer(by, outp, bm, Opt.fy, bd, Opt.base, Opt.lang, Opt.pause);
  571.            else
  572.            cal_printer(by, outp, 0,  Opt.fy,  1, Opt.base, Opt.lang, Opt.pause);
  573.         }
  574.     }
  575.     fputs("\nAnother calendar", stderr);
  576.     if (!get_yn('n'))
  577.     {
  578.     if(outp != 'F')
  579.         fclose(fp);
  580. /*      printf("\nClosed %s\n", file);*/
  581.         fputs("\nRetain present options as defaults", stderr);
  582.         if (get_yn('n'))
  583.             put_opts(argv[0]);
  584.     exit(0);
  585.     }
  586.   }
  587. }
  588.  
  589.  
  590.  
  591. void setup_files(out)
  592. char out;
  593. {
  594.     if (fp) fflush(fp);
  595.     if(out == 'V')
  596.     {
  597.     if(!strcmp(file, "PRN"))
  598.     {
  599.         fclose(fp);
  600. /*       printf("\nClosed %s\n", file);*/
  601.     }
  602.     if(strcmp(file, "CON"))
  603.     {
  604.         strcpy(file, "CON");
  605.         fp = fopen(file, "w");
  606. /*      printf("\nOpened %s for write\n", file);*/
  607.     }
  608.     }
  609.     else
  610.     if(out == 'P')
  611.     {
  612.     if(!strcmp(file, "CON"))
  613.     {
  614.         fclose(fp);
  615. /*      printf("\nClosed %s\n", file);*/
  616.     }
  617.     if(strcmp(file, "PRN"))
  618.     {
  619.         strcpy(file, "PRN");
  620.         fp = fopen(file, "w");
  621. /*      printf("\nOpened %s for write\n", file);*/
  622.     }
  623.     }
  624. }
  625.  
  626.  
  627.  
  628. void prep_cal(year)
  629. int year;
  630. {
  631.     int count,        /* Count of the days */
  632.     day,        /* Weekday Sun=0, Mon=2, ... Sat=6 */
  633.     month,        /* Month Jan=0, Feb=1, ... Dec=11 */
  634.     week,        /* Six weeks/month possible */
  635.     yeer,        /* Year for calendar */
  636.     y,        /* Year Last=0, This=1, Next=2 */
  637.         leap(),
  638.     weekday_month();
  639. /*printf("\nIn Prep_cal\n"); */
  640.     for (y = 0;        /* Start at last year y[0] */
  641.      y < 3;        /* Stop after next year y[2] */
  642.      y++)
  643.     {
  644. /*      printf("\nIn Prep_cal, y = [%d]\n", y); */
  645.     yeer = (year + y - 1);
  646.     if (leap(yeer))    /* Tidy up month length array */
  647.         mon[1].length = 29; /* For this year by fixin' February. . . */
  648.     else
  649.         mon[1].length = 28;
  650.  
  651.     /* get weekday of first day of each month, put into array mon */
  652.     /* Su = 0, Mo = 1, Tu = 2, We = 3, Th = 4, Fr = 5, Sa = 6   */
  653.     for (month = 0;
  654.          month < 12;    /* 12 months/year */
  655.          month++)
  656.     mon[month].first_day = weekday_month(month, yeer);
  657.  
  658.     /* form year array with 0 for unused dates, with dates */
  659.     /* in their relative positions by weekday */
  660.     for (month = 0;
  661.          month < 12;    /* 12 months/year */
  662.          month++)
  663.     {
  664.         count = 0;        /* set day counter to 0 */
  665.         for (week = 0;
  666.          week < 6;    /* 6 weeks/month */
  667.          week++)
  668.         {
  669.         for (day = 0;
  670.              day < 7;    /* 7 days/week */
  671.              day++)
  672.         {
  673.             if( (week == 0) &&  /* first week of month */
  674.             (day < mon[month].first_day))
  675.                     /* before first day */
  676.             yr[y][month][week][day] = 0;
  677.                     /* Zero it */
  678.             else
  679.             if (++count <= mon[month].length)
  680.                     /* Not past End of Month */
  681.             yr[y][month][week][day] = count;
  682.             else
  683.             yr[y][month][week][day] = 0;
  684.                     /* Zero it */
  685.         }
  686.         }
  687.     }
  688.     }
  689. }
  690.  
  691.  
  692.  
  693. /* Function to get first day index (day of week of 1st of month) */
  694. /* Jan = 0, Feb = 1, Mar = 2, Apr = 3, . . .  Dec = 11 */
  695. /* Su = 0, Mo = 1, Tu = 2, We = 3, Th = 4, Fr = 5, Sa = 6 */
  696. int weekday_month(Monat, Jahr) /* 1st day of any month after 1900 */
  697. int Monat;
  698. int Jahr;
  699. {
  700.     long int date,    /* date after 1901 */
  701.          numb_days; /* number of days to deal with */
  702.     int      mt[12] = {   0,  31,  59,  90, 120, 151,
  703.             181, 212, 243, 273, 304, 334  };
  704.     date       = Jahr - 1901;    /* subtract 1901 from year */
  705.     numb_days  = date * 365;    /* # of yrs times 365 days/year */
  706.     numb_days += ( ( date / 4)    /* add number of leap years */
  707.           - (date / 100)    /* subtract non-leap centuries */
  708.           + (date / 400 ))    /* add number of leap centuries */
  709.           + mt[Monat];    /* add days offset for this year */
  710.     if ( ( Jahr % 4) == 0 &&    /* if a conventional leap year */
  711.        Monat > 1 )        /* and after February */
  712.     numb_days++;        /* add a day for Feb 29th */
  713.     return((numb_days +2) %7);    /* divide the number of days by 7 */
  714.                 /* and return the remainder */
  715. }
  716.  
  717.  
  718.  
  719. /* Function to decide if a year is a leap year */
  720. int leap(years)
  721. int years;
  722. {            /* Leap year sieve */
  723.     if (years & 0x0003) /* Mask year to see if not leap year */
  724.        return FALSE;    /* If we look at the last two bits, and */
  725.             /* one of them is on, then the year can't */
  726.             /* be divisible by four.  Thus it is not */
  727.             /* a leap year, so function returns FALSE. */
  728.             /* Test for the leap century. */
  729.     else        /* Leap century:   years that are: */
  730.     if (!(years % 100) && /* evenly divisible by 100:  not leap */
  731.      (years % 400) )  /* years unless evenly divisible by 400 */
  732.     return FALSE;    /* Gruenberger and Jaffray, "Problems for */
  733.             /* Computer Solution", Wiley, 1965. */
  734.             /* We have filtered out all years that are */
  735.             /* not evenly divisible by four as well as */
  736.             /* those evenly divisible by 100 that are */
  737.             /* evenly divisible by 400. */
  738.             /* It seems that all the rest are */
  739.             /*   (a) evenly divisible by four */
  740.             /*   (b) evenly divisible by 400  */
  741.     return TRUE;    /*   (c) Thus, leap years. . . */
  742. }
  743.  
  744.  
  745.  
  746. void cal_printer(year, out, bm, fy, bd, base, lang, pause)
  747. int year;
  748. char out;
  749. int bm;
  750. char fy;
  751. int bd;
  752. char base;    /* Number base used, 0 = Decimal, H = Hex, O = Octal */
  753. int lang;    /* Language used 1=Danish, 2=Dutch, 3=English etc. */
  754. char pause;    /* Page pause True/False */
  755. {
  756.     char hdr1[] = {" Su Mo Tu We Th Fr Sa"},
  757.      hdr2[] = {" -- -- -- -- -- -- --"};
  758.  
  759.     int y, month, week, day, count, stat;
  760.     void hold();    /* Printing page pause function */
  761.     char  linbuf[BUF],
  762.       temp[BUF],
  763.      *char_str(),
  764.      *center(),
  765.      *trim();
  766.     char *off = (out == 'V') ? " " : "       ";
  767.     y = 1;        /* Make year this year */
  768.  
  769.     sprintf(hdr1, " %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s",
  770.        wkday[lang -1][0], wkday[lang -1][1], wkday[lang -1][2],
  771.        wkday[lang -1][3], wkday[lang -1][4], wkday[lang -1][5],
  772.        wkday[lang -1][6] );
  773.  
  774.     if(out == 'F')        /* setup for file output */
  775.     {
  776.     sprintf(file, fy ?
  777.           "%dFY%c" :
  778.           "%d%c",
  779.            year, base);
  780.     strcpy(new_file, file);
  781.     strcat(file, ".$$$");
  782.     sprintf(temp, ".%3.3s", lingo[lang -1]);
  783.     strcat(new_file, temp);
  784.     fp = fopen(file, "w");
  785. /*      printf("\nOpened %s for write\n", file);*/
  786.     }
  787.  
  788.     if ((pause)     &&        /* User wants time after each page */
  789.     (out == 'P') )        /* gets printed to add paper etc... */
  790.     hold();            /* Wait for keystroke */
  791.  
  792.     fputs("\n\n\n", fp);
  793.     sprintf(temp, fy ? "%s%s%s Calendar for Fiscal Year %d-%d":
  794.                "%s%s%s Calendar for %d",
  795. /*           ( (base == 'O') && (lang != 10) ) ? "Classical " : "" ,*/
  796.          base ? "Programmer's " : "" ,
  797.          base ? ( (base == 'O') ? "Octal " : "Hexadecimal ") : "",
  798.          lingo[lang -1],
  799.          year, year +1);
  800.  
  801.     fputs(center(temp, (out == 'V') ? 75 : 89), fp);
  802.     fputs("\n\n\n", fp);
  803.  
  804.     if (bd == 1)        /* If fy month starts on 1st, */
  805.     fy = FALSE;        /* treat like ordinary month */
  806.  
  807.     for (month = bm;        /* Start at beginning Month for FY */
  808.      month < (12 + bm + fy);
  809.      month += 3)
  810.     {                /* 4 sets of months  3 months across */
  811.     sprintf(linbuf,
  812.          "%s%s    ", off, center(mnam[lang -1][month %12], 21));
  813.  
  814.     if (month != (bm +12))    /* NOT FY and 13th month */
  815.     {
  816.         sprintf(temp,
  817.         "%s    ", center(mnam[lang -1][(month +1) %12], 21));
  818.         strcat(linbuf, temp);
  819.         sprintf(temp,
  820.         "%s"    , center(mnam[lang -1][(month +2) %12], 21));
  821.         strcat(linbuf, temp);
  822.     }
  823.  
  824.     strcat(linbuf, "\n");    /* add a newline */
  825.     fputs(linbuf, fp);    /* Names of three Months */
  826.     linbuf[0] = '\0';
  827.  
  828.     if(month != (bm +12))    /* NOT FY and 13th month */
  829.     {
  830.         fprintf(fp, "%s%s    %s    %s\n",
  831.             off, hdr1, hdr1, hdr1);
  832.         fprintf(fp, "%s%s    %s    %s\n",
  833.             off, hdr2, hdr2, hdr2);
  834.     }
  835.     else            /* FY and 13th month */
  836.     if (bd != 1)        /* beginning after the 1st */
  837.     {
  838.         fprintf(fp, "%s%s\n",    /* Names of weekdays */
  839.             off, hdr1);
  840.         fprintf(fp, "%s%s\n",    /* Lines of dashes */
  841.             off, hdr2);
  842.     }
  843.  
  844.     for (week = 0;        /* One line per week */
  845.          week < 6;        /* 6 wks/month possible */
  846.          week++)
  847.     {
  848.         sprintf(linbuf, off);
  849.  
  850.         for (count = 0;    /* 3 months/line ordinarily */
  851.          count < ((month == (bm +12)) ?
  852.                         1 : /* FY 13th month alone */
  853.                         3); /* Ordinary line */
  854.          count++)
  855.         {
  856.         for (day = 0;
  857.              day < 7;    /* 7 days/week */
  858.              day++)
  859.         {
  860.             if (((month + count) == bm) &&  /* FY 1st month */
  861.             (yr[y][month + count][week][day] < bd))
  862.              sprintf(temp, "   ");
  863.             else
  864.             if (((month + count) == (bm +12)) &&
  865.             (yr[y][month + count][week][day] >= bd))
  866.              sprintf(temp, "   ");
  867.             else
  868.             sprintf(temp,
  869.             yr[y][month + count][week][day] ?
  870.                 (base ?
  871.                 ((base == 'O') ? "%3o" : "%3X" ) :
  872.                          "%3d" ) :
  873.                          "   ",
  874.             yr[y][month + count][week][day]);
  875.             strcat(linbuf, temp);
  876.         }
  877.         strcat(linbuf,
  878.         count < ((month < (bm +12)) ? 2 : 0) ? "    ": "\n" );
  879.         }
  880.         fputs(linbuf, fp);
  881.         linbuf[0] = '\0';
  882.     }
  883.     fputs("\n\n", fp);
  884.     }
  885.     if (out != 'V') fputs("\f\r", fp);    /* no FF for screen */
  886.  
  887.     if (out == 'F')            /* setup for file output */
  888.     if ((stat = fclose(fp)) == ERROR)
  889.         printf("\nCan't close %s.\n", file);
  890. /*      else
  891.     printf("\nClosed %s\n", file);*/
  892.  
  893.     if (out == 'F')
  894.     {
  895.     if ((stat = rename(file, new_file)) == ERROR)
  896.     {
  897.         printf(
  898.         "\nCan't rename %s to %s.  %s may already exist.\n",
  899.                  file, new_file, new_file);
  900.     }
  901.     }
  902. }
  903.  
  904.  
  905.  
  906. void agg_printer(year, out, base, lang, pause)
  907. int year;
  908. char out;
  909. char base;    /* Number base used, 0 = Decimal, H = Hex, O = Octal */
  910. int lang;    /* Language used 1=Danish, 2=Dutch, 3=English etc. */
  911. char pause;    /* Page pause True/False */
  912. {
  913.     int mf[12][2];    /* mf flag for aggie calendar */
  914.  
  915.     char agg1[] = {" Ja Fe Ma Ap Ma Jn Jl Au Se Oc No De"},
  916.      agg2[] = {" -- -- -- -- -- -- -- -- -- -- -- --"};
  917.  
  918.     int y, month, week, day, count, stat, i, j;
  919.     void hold();    /* Printing page pause function */
  920.     char  linbuf[BUF],
  921.       temp[BUF],
  922.      *char_str(),
  923.      *center(),
  924.      *trim();
  925.     char *off = (out == 'V') ? " " : "    ";
  926.     y = 1;        /* Make year this year */
  927.     sprintf(agg1, " %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s %2.2s",
  928.        mnam[lang -1][0], mnam[lang -1][ 1], mnam[lang -1][ 2],
  929.        mnam[lang -1][3], mnam[lang -1][ 4], mnam[lang -1][ 5],
  930.        mnam[lang -1][6], mnam[lang -1][ 7], mnam[lang -1][ 8],
  931.        mnam[lang -1][9], mnam[lang -1][10], mnam[lang -1][11] );
  932.  
  933.     if (out == 'F')
  934.     {
  935.     sprintf(file, "%dAGG%c", year, base);
  936.     strcpy(new_file, file);
  937.     strcat(file, ".$$$");
  938.     sprintf(temp, ".%3.3s", lingo[lang -1]);
  939.     strcat(new_file, temp);
  940.     fp = fopen(file, "w");
  941. /*      printf("\nOpened %s for write\n", file);*/
  942.     }
  943.  
  944.     if ((pause)     &&        /* User wants time after each page */
  945.     (out == 'P') )        /* gets printed to add paper etc... */
  946.     hold();            /* Wait for keystroke */
  947.     fputs("\n\n\n", fp);
  948.     sprintf(temp, "%sAggie %s%sGig'Em %s Calander fer %d",
  949.          (base == 'O') ? "Olde " : "" ,
  950.          base ? "Hacker's " : "" ,
  951.          base ? ( (base == 'O') ? "Octal " : "Hexadecimal ") : "",
  952.          lingo[lang -1],
  953.          year);
  954.     fputs(center(temp, (out == 'V') ? 75 : 89), fp);
  955.     fputs("\n\n\n", fp);
  956.     for (day = 0;
  957.      day < 7;        /* 4 sets of days */
  958.      day += 2)        /* 2  days across */
  959.     {
  960.      for (i = 0;
  961.           i < 12;        /* 12 months in a day */
  962.           i++)
  963.          for (j = 0;
  964.           j < 2;    /* 2  days across */
  965.           j++)
  966.               mf[i][j] = 0;
  967.     if (day < 6)
  968.     {
  969.         sprintf(linbuf, "%s%s    ", off, center(wkday[lang -1][day], 36));
  970.         sprintf(temp,   "%s\n"  , center(wkday[lang -1][day +1], 36));
  971.         strcat(linbuf, temp);
  972.         fputs(linbuf, fp);
  973.         linbuf[0] = '\0';
  974.         fprintf(fp, "%s%s   %s\n", off, agg1, agg1);
  975.         fprintf(fp, "%s%s   %s\n", off, agg2, agg2);
  976.     }
  977.     else
  978.     {
  979.         fprintf(fp, "%s%s\n", off, trim(center(wkday[lang -1][day], 79) ) );
  980.         fprintf(fp, "%s%s\n", off, trim(center(agg1, 79) ) );
  981.         fprintf(fp, "%s%s\n", off, trim(center(agg2, 79) ) );
  982.     }
  983.     for (week = 0;
  984.          week < 5;        /* 5 weeks/day possible */
  985.          week++)
  986.     {
  987.         sprintf(linbuf, off);
  988.         for (count = 0;    /* 2 days across except Saturday */
  989.          count < ( (day == 6) ? 1 : 2) ;
  990.          count++)
  991.         {
  992.         if (day == 6)
  993.             strcat(linbuf, "              ");
  994.         for (month = 0;
  995.              month < 12;    /* 12 mnths/day */
  996.              month++)
  997.         {
  998.             if (!yr[y][month][week][day + count])
  999.             mf[month][count] = 1;
  1000.             sprintf(temp,
  1001.              yr[y][month][week +mf[month][count]][day +count] ?
  1002.                 (base ?
  1003.                 ((base == 'O') ? "%3o" : "%3X" ) :
  1004.                          "%3d" ) :
  1005.                          "   ",
  1006.              yr[y][month][week +mf[month][count]][day + count]);
  1007.             strcat(linbuf, temp);
  1008.         }
  1009.         strcat(linbuf, count < 1 ? "   ": "\n" );
  1010.         if (day == 6) strcat(linbuf, "\n");
  1011.         }
  1012.         fputs(linbuf, fp);
  1013.         linbuf[0] = '\0';
  1014.     }
  1015.     fputs("\n\n", fp);
  1016.     }
  1017.     if (out != 'V') fputs("\f\r", fp);    /* no FF for screen */
  1018.     if(out == 'F')            /* setup for file output */
  1019.     if ((stat = fclose(fp)) == ERROR)
  1020.         printf("\nCan't close %s.\n", file);
  1021. /*      else
  1022.     printf("\nClosed %s\n", file);*/
  1023.     if(out == 'F')
  1024.     {
  1025.     if ((stat = rename(file, new_file)) == ERROR)
  1026.     {
  1027.         printf(
  1028.         "\nCan't rename %s to %s.  %s may already exist.\n",
  1029.                  file, new_file, new_file);
  1030.     }
  1031.     }
  1032. }
  1033.  
  1034.  
  1035.  
  1036. void jul_printer(year, out, base, lang, pause)
  1037. int year;
  1038. char out;
  1039. char base;    /* Number base used, 0 = Decimal, H = Hex, O = Octal */
  1040. int lang;    /* Language used 1=Danish, 2=Dutch, 3=English etc. */
  1041. char pause;    /* Page pause True/False */
  1042. {
  1043.     int month, day, stat, count, leep;
  1044.     void hold();    /* Printing page pause function */
  1045.     char  temp[BUF],
  1046.      *char_str(),
  1047.      *center(),
  1048.      *trim();
  1049.     int jul[12][31];    /* Array for Julian yr, 12 months/year */
  1050.             /* 31 days/month */
  1051.     char *off = (out == 'V') ? " " : "    ";
  1052.     int month_length[12] =
  1053.     {
  1054.     0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
  1055.     };
  1056.     char jul1[] = {"Month:   Jan  Feb  Mar  Apr  May  Jun  Jul  Aug  Sep  Oct  Nov  Dec       "};
  1057.     char jul2[] = {"     ---  ---  ---  ---  ---  ---  ---  ---  ---  ---  ---  ---"};
  1058.  
  1059.     leep = leap(year);    /* Find out if leap year */
  1060.     sprintf(jul1, "     %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s  %3.3s",
  1061.        mnam[lang -1][0], mnam[lang -1][ 1], mnam[lang -1][ 2],
  1062.        mnam[lang -1][3], mnam[lang -1][ 4], mnam[lang -1][ 5],
  1063.        mnam[lang -1][6], mnam[lang -1][ 7], mnam[lang -1][ 8],
  1064.        mnam[lang -1][9], mnam[lang -1][10], mnam[lang -1][11] );
  1065.     if (out == 'F')
  1066.     {
  1067.     sprintf(file, "%dJUL%c", year, base);
  1068.     strcpy(new_file, file);
  1069.     strcat(file, ".$$$");
  1070.     sprintf(temp, ".%3.3s", lingo[lang -1]);
  1071.     strcat(new_file, temp);
  1072.     fp = fopen(file, "w");
  1073. /*      printf("\nOpened %s for write\n", file);*/
  1074.     }
  1075.  
  1076.     if ((pause)     &&    /* User wants time after each page */
  1077.     (out == 'P') )    /* gets printed to add paper etc... */
  1078.     hold();        /* Wait for keystroke */
  1079.     fputs("\n\n\n", fp);
  1080.     sprintf(temp, "%s%s%s%s 3-Digit Julian Calendar for %d",
  1081.          (base == 'O') ? "Olde " : "" ,
  1082.          base ? "Hacker's " : "" ,
  1083.          base ? ( (base == 'O') ? "Octal " : "Hexadecimal ") : "",
  1084.          lingo[lang -1],
  1085.          year);
  1086.     fputs(center(temp, (out == 'V') ? 75 : 89), fp);
  1087.     fputs("\n\n\n", fp);
  1088.     fprintf(fp, "%s%s\n", off, jul1);
  1089.     fprintf(fp, "%s%s\n", off, jul2);
  1090.  
  1091.     for (month = 0;
  1092.      month < 12;    /* 12 months */
  1093.      month++)
  1094.     for (day = 1;
  1095.          day < 32;    /* 31 days possible */
  1096.          day++)
  1097.     {
  1098.         count = (day + month_length[month] + ((month > 1) ? leep : 0) );
  1099.         if (count > (month_length[month +1] + ((month) ? leep : 0)) )
  1100.         count = 0;
  1101. /*      fprintf(stderr, "%6d", count); */
  1102.         jul[month][day -1] = count;
  1103.     }
  1104.  
  1105.     for (day = 0;
  1106.      day < 31;
  1107.      day++)
  1108.     {
  1109.     if ( (day)       &&
  1110.          (!(day % 2)) )
  1111.         fprintf(fp, "\n");
  1112.     fprintf(fp, "%sDay #%2d", off, day +1);
  1113.  
  1114.     for (month = 0;
  1115.          month < 12;
  1116.          month++)
  1117.     {
  1118.         if (jul[month][day])
  1119.         {
  1120.         fprintf(fp,
  1121.            (base ?
  1122.                ((base == 'O') ?
  1123.                "  %3o" :
  1124.                "  %3X" ) :
  1125.                "  %3d" ),
  1126.               jul[month][day]);
  1127.         }
  1128.         else
  1129.         fprintf(fp, "     ");
  1130.     }
  1131.     fprintf(fp, "   Day #%2d\n", day +1);
  1132.     }
  1133.  
  1134.     if (out != 'V') fputs("\f\r", fp);    /* no FF for screen */
  1135.     if (out == 'F')            /* setup for file output */
  1136.     if ((stat = fclose(fp)) == ERROR)
  1137.         printf("\nCan't close %s.\n", file);
  1138. /*      else
  1139.     printf("\nClosed %s\n", file);*/
  1140.     if (out == 'F')
  1141.     {
  1142.     if ((stat = rename(file, new_file)) == ERROR)
  1143.     {
  1144.         printf(
  1145.         "\nCan't rename %s to %s.  %s may already exist.\n",
  1146.                  file, new_file, new_file);
  1147.     }
  1148.     }
  1149. }
  1150.  
  1151.  
  1152.  
  1153. char *center(str, width)
  1154. char *str;
  1155. int width;
  1156. {
  1157.     static char buf[BUF];    /* location of finished string */
  1158.     static char copy[BUF];    /* copy of str to avoid side effects */
  1159.     char  filler,
  1160.      *char_str(),
  1161.      *strcpy(),
  1162.      *strcat();
  1163.     int i;
  1164.  
  1165.     filler = ' ';
  1166.     strcpy(copy, str);          /* copy str to copy */
  1167.     if (strlen(copy) >= width)    /* Test for str longer than width */
  1168.     copy[width] = '\0';    /* Terminate it at width */
  1169.     strcpy(buf, char_str( (width - strlen(copy) ) >> 1, filler));
  1170.     strcat(buf, copy);
  1171.     i = strlen(buf);
  1172.     while (width - i)
  1173.      buf[i++] = filler;
  1174.     buf[i] = '\0';
  1175.     return(buf);
  1176. }
  1177.  
  1178.  
  1179.  
  1180. char *trim(str)        /* trim spaces from end of string */
  1181. char *str;
  1182. {
  1183.     static char buf[BUF];    /* location of finished string */
  1184.     char  filler,
  1185.      *char_str(),
  1186.      *strcpy(),
  1187.      *strcat();
  1188.     int i;
  1189.     filler = ' ';
  1190.     strcpy(buf, str);
  1191.     i = strlen(buf);
  1192.     while (buf[--i] == filler)
  1193.     buf[i] = '\0';
  1194.     return(buf);
  1195. }
  1196.  
  1197.  
  1198.  
  1199. char *char_str(length, c)
  1200. int length;
  1201. char c;
  1202. {
  1203.     static char loc[BUF];
  1204.     char *ptr = loc;
  1205.  
  1206.     while (length--)
  1207.     *ptr++ = c;
  1208.     *ptr = '\0';
  1209.     return(loc);
  1210. }
  1211.  
  1212.  
  1213.  
  1214. int get_int(defalt, digits, lowest, highest)
  1215. int defalt,    /* default value when C/R alone is struck */
  1216.     digits,    /* maximum number of digits accepted */
  1217.     lowest,    /* lowest value accepted */
  1218.     highest;    /* highest value accepted */
  1219. {
  1220.     char buffer[80];    /* Buffer to store input string */
  1221.     int ch;        /* All purpose character ch */
  1222.     int index = 0;    /* Character array index */
  1223.     int value = 0;    /* value to return */
  1224.     int done = FALSE;    /* Done/Not Done Flag */
  1225.     char dfalt[10];    /* Buffer to store default value as string */
  1226.     int i, ii;        /* length of default value as a string */
  1227.  
  1228.     sprintf(dfalt, "%d", defalt); /* Convert default to string */
  1229.     i = ii = strlen(dfalt);    /* Calculate its length */
  1230.     printf("%s", dfalt);    /* Display default value */
  1231.     while (ii--)
  1232.     putch('\b');        /* Backspace to beginning */
  1233.  
  1234.     while (!done)
  1235.     {
  1236.     while (index < digits)  /* while not enough digits, grab 'em */
  1237.     {
  1238.         ch = getch();      /* Get a char from console, no echo */
  1239.  
  1240.         if (isdigit(ch))    /* Digit!! so . . .  */
  1241.         {
  1242.         putch(ch);    /* Echo it to console, and */
  1243.         buffer[index++] = ch;    /* Stuff it into buffer */
  1244.         if (index == 1)     /* Entered first digit, so. . . */
  1245.         {
  1246.             for (ii = digits; --ii; )
  1247.             putch(' ');    /* Blank it out */
  1248.             for (ii = digits; --ii; )
  1249.             putch('\b');    /* Backspace to beginning */
  1250.         }
  1251.         }
  1252.  
  1253.         else
  1254.         if ((ch == '\b') && /* Backspace? */
  1255.         (index) )    /* if index not zero */
  1256.         {
  1257.         --index;    /* Reduce index */
  1258.         putch(' ');    /* Blank it */
  1259.         putch('\b');    /* Backspace over blank */
  1260.         putch(ch);    /* Echo it to console */
  1261.         }
  1262.  
  1263.         else
  1264.         if (ch == '\033')    /* Escape */
  1265.         exit(0);    /* says he's through */
  1266.  
  1267.         else
  1268.         if (ch == '\r')    /* Return? */
  1269.         break;        /* says he's through */
  1270.     }    /* End while not enough digits, grab 'em */
  1271.  
  1272.     buffer[index] = '\0';    /* Terminate string */
  1273.  
  1274.     if (index == 0)        /* no digits entered before return */
  1275.     {
  1276.         value = defalt;    /* so use default */
  1277.         done  = TRUE;    /* We're through */
  1278.     }
  1279.  
  1280.     else            /* some digits were entered */
  1281.     {
  1282.         value = atoi(buffer);    /* Convert string to integer */
  1283.  
  1284.         if ((value < lowest) ||    /* Range test value returned */
  1285.         (value > highest) )
  1286.         {                /* Out of allowable range. . . */
  1287.         for (        ;
  1288.                index;
  1289.              --index )
  1290.             putch('\b');    /* Backspace to beginning */
  1291.         for (ii = digits;
  1292.              ii;
  1293.              --ii)
  1294.             putch(' ');        /* Blank it out */
  1295.         for (ii = digits;
  1296.              ii;
  1297.              --ii)
  1298.             putch('\b');    /* Backspace to beginning */
  1299.         printf("%s", dfalt);    /* Display default value */
  1300.         for (ii = i;
  1301.              ii;
  1302.               --ii)
  1303.             putch('\b');    /* Backspace to beginning */
  1304.         }
  1305.  
  1306.         else
  1307.         {
  1308.         done  = TRUE;        /* We're through */
  1309.         }
  1310.     }
  1311.     }        /* end while !done */
  1312.     return(value);
  1313. }
  1314.  
  1315.  
  1316.  
  1317. int get_yn(defalt)
  1318. char defalt;
  1319. {
  1320.     char c;            /* all purpose character */
  1321.     fputs(" (y/n) ? ", stderr); /* Prompt for Yes or No */
  1322.     putch(defalt);        /* Display default */
  1323.     putch('\b');        /* Backspace to it */
  1324.     do
  1325.     {
  1326.     c = tolower(getch());    /* Get a character, make it lowercase */
  1327.     }   while ( (c != 'y') &&    /* Until we get a y, n, ESC, or return */
  1328.         (c != 'n') &&
  1329.         (c != '\033') &&
  1330.         (c != '\r') );
  1331.  
  1332.     if (c == '\033')    /* Escape */
  1333.     exit(0);    /* says he's through */
  1334.     else
  1335.     if (c == '\r')    /* If a return, make it the default */
  1336.     c = defalt;
  1337.     putch(c);        /* Display choice to user */
  1338.     return (c == 'y') ? TRUE : FALSE ;
  1339. }
  1340.  
  1341.  
  1342.  
  1343. void hold()
  1344. {
  1345.     fputs("\nPrinter ready?  Any key to continue. . . ", stderr);
  1346.     getch();
  1347. }
  1348.  
  1349.  
  1350.  
  1351. void signon()
  1352. {
  1353.     fputs(
  1354.     "\t\t\tYEARCAL v0.07T 3 Mar 1988\n\n\t\tCopyright 1987, 1988 by Paul M. Sittler\n\n", stderr);
  1355.     fputs(
  1356.     "\tYEARCAL makes calendars (A/M) or schedules (W/D) for years after 1901.\n\n", stderr);
  1357.     fputs(
  1358.     "\tAt the user's option, Normal, Fiscal Year, AGGIE, or 3-Digit Julian\n", stderr);
  1359.     fputs(
  1360.     "\tDate Calendars can be produced, in multiple copies, for a number of\n", stderr);
  1361.     fputs(
  1362.     "\tconsecutive years, or both.  Fiscal Year calendars may be produced for\n", stderr);
  1363.     fputs(
  1364.     "\tany arbitrary 12 or 13 month fiscal year.  The user may select a\n", stderr);
  1365.     fputs(
  1366.     "\tProgrammer's calendar, numbered in Hexadecimal or Octal numbers rather\n", stderr);
  1367.     fputs(
  1368.     "\tthan decimal numbers, and may choose one of several languages.\n\n", stderr);
  1369.     fputs(
  1370.     "\tThe calendars may be displayed on the screen, printed, or written to\n", stderr);
  1371.     fputs(
  1372.     "\ta file as desired.  If written to disk, files are named like YYYY.ENG\n", stderr);
  1373.     fputs(
  1374.     "\t(Normal ENGlish), YYYYFY.DUT (Fiscal-Year DUTch), YYYYAGG.TEX (Aggie-\n", stderr);
  1375.     fputs(
  1376.     "\ttype TEXan), or YYYYJUL.POL (3-Digit Julian Date POLish) calendars,\n", stderr);
  1377.     fputs(
  1378.     "\tetc.  Hex or Octal calendar files will have an \"H\" or \"O\" added to\n", stderr);
  1379.     fputs(
  1380.     "\ttheir names, such as YYYYH.SPA, YYYYFYO.SER or YYYYAGGH.FRE.\n\n", stderr);
  1381.     fputs(
  1382.     "\tYEARCAL may be freely distributed, and used for non-commercial\n", stderr);
  1383.     fputs(
  1384.     "\tpurposes, as long as the unmodified program source code and\n", stderr);
  1385.     fputs(
  1386.     "\tdocumentation files are distributed with it.\n", stderr);
  1387. }
  1388.  
  1389.  
  1390.  
  1391. void sched_printer(year, out, bm, bd, bh, nh, pl, pw, sched_type, title, base, lang, pause, indent)
  1392. int year;    /* Year for calendar */
  1393. char out;    /* Output goes where? View, Printer, File */
  1394. int bm;        /* Month (beginning) for schedule */
  1395. int bd;        /* Day (beginning) for schedule */
  1396. int bh;        /* Hour (beginning) for schedule */
  1397. int nh;        /* number of hours to schedule (1-24) */
  1398. int pl;        /* Page Length in lines */
  1399. int pw;        /* Page Width in characters or columns */
  1400. char sched_type;/* Schedule type M(onthly), W(eekly), D(aily) */
  1401. char title[][LIN];
  1402. char base;    /* Number base used, 0 = Decimal, H = Hex, O = Octal */
  1403. int lang;    /* Language used 1=Danish, 2=Dutch, 3=English etc. */
  1404. char pause;    /* Page pause flag True/False */
  1405. int indent;    /* Left margin indent (# of spaces) */
  1406. {
  1407.     int bw,    /* Box width */
  1408.     day,
  1409.     first_day,
  1410.     i, j,
  1411.     month,
  1412.     stat,
  1413.     w,    /* Week number for printing top calendars */
  1414.     wk_day,
  1415.     y;
  1416.     void hold();    /* Printing page pause function */
  1417.     char  linbuf  [BUF],
  1418.       temp    [BUF],
  1419.       temp1   [BUF],
  1420.       temp2   [BUF],
  1421.       bnd     [BUF],
  1422.       sep     [BUF],
  1423.       hoursw  [BUF],
  1424.       spacerw [BUF],
  1425.       dates   [BUF],
  1426. /*    bc, */
  1427.      *char_str(),
  1428.      *center(),
  1429.      *trim();
  1430.     char *off = ( (out == 'V') ?
  1431.                " " :    /* Offset for screen */
  1432.     "                                        ");
  1433.     /* 40 spaces-----------------------------| Max Offset for printing */
  1434.     off[indent] = '\0';        /* clip offset to proper length */
  1435.     y = 1;            /* Make year this year */
  1436. /*  printf(
  1437. "\nArgs: year=[%d], out=[%c], bm=[%d], bd=[%d], bh=[%d], nh=[%d], pl=[%d]\n",
  1438.        year,      out,      bm,      bd,      bh,      nh,      pl);
  1439.     printf(
  1440. "Args: pw=[%d], sched_type=[%c], base=[%c], lang=[%d]\n",
  1441.        pw,      sched_type,      base,      lang);
  1442.  */
  1443.     if (out == 'V')        /* Gonna View it, so. . . */
  1444.       pw = 80  ;        /* pw is screen width */
  1445.  
  1446.     if (out == 'F')        /* setup for file output */
  1447.     {
  1448.     (sched_type == 'M') ?
  1449.         sprintf(file, "%d%3.3s%c", year, mnam[lang -1][bm], base):
  1450.         sprintf(file, "%d%02d%02d", year, bm + 1, bd);
  1451.     strcpy(new_file, file);
  1452.     strcat(file, ".$$$");
  1453.     sprintf(temp, ".%3.3s", lingo[lang -1]);
  1454.     strcat(new_file, temp);
  1455.     fp = fopen(file, "w");
  1456. /*      printf("\nOpened %s for write\n", file);*/
  1457.     }
  1458.  
  1459.     first_day = weekday_month(bm, year);    /* 1st day of month */
  1460.     if (sched_type == 'M')
  1461.     wk_day = 0;
  1462.     else
  1463.     wk_day = ( (first_day + bd -1) % 7);    /* Gives us weekday */
  1464.  
  1465.     sprintf(title[5], "%s",
  1466.            (sched_type == 'M')?        /* Monthly calendar */
  1467.            "Monthly Calendar" :
  1468.            (sched_type == 'W')? /* if weekly instead of daily */
  1469.             "Weekly Schedule" :
  1470.             "Daily Schedule");
  1471.  
  1472.     sprintf(title[4], (sched_type == 'W') ?
  1473.              "Week begins on %s" :
  1474.              (sched_type == 'D') ?
  1475.                     "%s" :
  1476.                       "" ,
  1477.                wkday[lang -1][wk_day]);
  1478.  
  1479.     if (sched_type == 'M')
  1480.     {
  1481.     sprintf(title[3], "%s %d",
  1482.            mnam[lang -1][bm], year );
  1483.     }
  1484.     else
  1485.     sprintf(title[3], "%d %s, %d",
  1486.            bd,
  1487.            mnam[lang -1][bm],
  1488.            year );
  1489.  
  1490.     strcpy(hoursw, off);        /* Put offset into hoursw */
  1491.     strcpy(spacerw, off);        /* Put offset into spacerw */
  1492.  
  1493.     if (sched_type != 'M')        /* If Daily or Weekly */
  1494.     {
  1495.     sprintf(temp, "| %s00 |",
  1496.                 (base ?
  1497.            ((base == 'O') ?
  1498.                 "%02o" :
  1499.               "%02X" ) :
  1500.               "%02d" ) );
  1501.     strcat(hoursw, temp);        /* Add header info to hoursw */
  1502.     strcat(spacerw, "|      |");    /* Add header info to spacerw */
  1503.     }
  1504.     else                /* Monthly Calendar, so. . . */
  1505.     {
  1506.     strcat(hoursw, "|");        /* Add header info to hoursw */
  1507.     strcat(spacerw, "|");        /* Add header info to spacerw */
  1508.     }
  1509.  
  1510.     bw = (((pw - strlen(hoursw) ) / 7) -1);  /* Calculate Box Width */
  1511.     for (i = 0;                /* Form strings for each day */
  1512.      i < bw;
  1513.      i++)
  1514.     {
  1515.     temp [i] = ' ';            /* Using spaces */
  1516.     }
  1517.     if (sched_type == 'M')        /* Monthly Calendar */
  1518.     {
  1519.     strcpy(dates, temp);        /* Copy temp to dates for length */
  1520.     dates[i -2] = '\0';        /* Cut dates to length */
  1521.     }
  1522.  
  1523.     temp[i++] =  (sched_type == 'D')?    /* If Daily */
  1524.                  ' ':    /* Add ' ' */
  1525.                  '|';    /* Otherwise add '|' */
  1526.     temp[i]   = '\0';            /* Terminate string */
  1527.  
  1528.     for (i = 0;                /* Adding multiple temps to */
  1529.      i < 7;
  1530.      i++)
  1531.     {
  1532.     if (sched_type != 'M')
  1533.         strcat(hoursw, temp);    /* Add temp to hoursw */
  1534.     strcat(spacerw, temp);        /* Add temp to spacerw */
  1535.     }
  1536.     if(sched_type == 'D')
  1537.     {
  1538.     hoursw [strlen(hoursw) -1] = '|';
  1539.     spacerw[strlen(spacerw)-1] = '|';
  1540.     }
  1541.  
  1542.     strcat(spacerw, "\n");    /* Add '\n' */
  1543.     strcat(hoursw, "\n");    /* Add '\n' */
  1544.  
  1545.     strcpy(bnd, off);        /* Put offset into boundary */
  1546.     strcpy(sep, off);        /* Put offset into separator */
  1547.  
  1548.     for (i = 0;            /* Draw them lines. . . */
  1549.      i < (strlen(spacerw) - strlen(off) -1);
  1550.      i++)
  1551.     {
  1552.     temp[i] = '-';        /* Using Hyphens */
  1553.     }
  1554.     temp[i]     = '\n';        /* Add Newline */
  1555.     temp[i +1]  = '\0';        /* Terminate string */
  1556.     strcat(bnd, temp);        /* Add temp to bnd */
  1557.     temp[0]     = '|';
  1558.     temp[i -1]  = '|';
  1559.     strcat(sep, temp);        /* Add temp to sep */
  1560.  
  1561.     pw = strlen(bnd) -1;    /* Adjust Page Width */
  1562.  
  1563.     if ((pause)     &&    /* User wants time after each page */
  1564.     (out == 'P') )    /* gets printed to add paper etc... */
  1565.     hold();        /* Wait for keystroke */
  1566.     fputs("\n\n", fp);        /* Print two blank lines */
  1567.     /* Line One: Last and Next Month's names */
  1568.     sprintf(temp, "%s %d",    /* Last month's name and year */
  1569.            mnam[lang -1]
  1570.               [(sched_type == 'M') ?
  1571.                (bm +11) % 12 :
  1572.                       bm ],
  1573.                (sched_type == 'M') ?
  1574.                  (bm == 0) ?
  1575.                  year -1 :
  1576.                     year :
  1577.                     year );
  1578.     sprintf(temp2,"%s %d",    /* Next month's name and year */
  1579.            mnam[lang -1][(bm +1) %12],
  1580.            (bm == 11) ? year +1 : year );
  1581.     strcpy(linbuf, off);
  1582.     strcat(linbuf, center(temp, 21) );
  1583.     strcat(linbuf, center(title[0], (pw -42 -strlen(off)) ) );
  1584.     strcat(linbuf, center(temp2, 21) );
  1585.     strcat(linbuf, "\n");
  1586.     fputs(linbuf, fp);
  1587.  
  1588.     /* Line Two: Weekday headers */
  1589.     temp[0] = '\0';
  1590.     for (i = 0;
  1591.      i < 7 ;
  1592.      i++)
  1593.     {
  1594.     sprintf(temp2, " %2.2s",
  1595.             wkday[lang -1][i] );
  1596.     strcat(temp, temp2);
  1597.     }
  1598.     strcpy(linbuf, off);
  1599.     strcat(linbuf, center(temp, 21) );
  1600.     strcat(linbuf, center(title[1], (pw -42 -strlen(off)) ) );
  1601.     strcat(linbuf, center(temp, 21) );
  1602.     strcat(linbuf, "\n");
  1603.     fputs(linbuf, fp);
  1604.  
  1605.     /* Lines 3-8: Last and Next Month's first weeks */
  1606.     for (w = 0;
  1607.      w < 6;
  1608.      w++)
  1609.     {
  1610.     temp[0] = '\0';
  1611.     temp2[0] = '\0';
  1612.     for (day = 0;
  1613.          day < 7;    /* 7 days/week */
  1614.          day++)
  1615.     {
  1616.         sprintf(linbuf,
  1617.          yr[(sched_type == 'M') ? (bm == 0) ? y -1 : y : y]
  1618.          [(sched_type == 'M') ? (bm +11) % 12 : bm][w][day] ?
  1619.                        (base ?
  1620.                   ((base == 'O') ?
  1621.                        "%3o" :
  1622.                      "%3X" ) :
  1623.                      "%3d" ) :
  1624.                     "   ",
  1625.          yr[(sched_type == 'M') ? (bm == 0) ? y -1 : y : y]
  1626.          [(sched_type == 'M') ? (bm +11) % 12 : bm][w][day]);
  1627.         sprintf(temp1,
  1628.          yr[((bm == 11) ? y +1 : y)][(bm +1) %12][w][day] ?
  1629.                        (base ?
  1630.                   ((base == 'O') ?
  1631.                        "%3o" :
  1632.                      "%3X" ) :
  1633.                      "%3d" ) :
  1634.                     "   ",
  1635.          yr[((bm == 11) ? y +1 : y)][(bm +1) %12][w][day]);
  1636.         strcat(temp, linbuf);
  1637.         strcat(temp2, temp1);
  1638.     }
  1639.     strcpy(linbuf, off);
  1640.     strcat(linbuf, center(temp, 21) );
  1641.     strcat(linbuf, center(title[w + 2], (pw -42 -strlen(off)) ) );
  1642.     strcat(linbuf, center(temp2, 21) );
  1643.     strcat(linbuf, "\n");
  1644.     fputs(linbuf, fp);
  1645.     }
  1646.  
  1647.     fputs(bnd, fp);        /* print boundary */
  1648.  
  1649.   if (sched_type != 'M')    /* NOT Monthly calendar */
  1650.   {
  1651.     sprintf(linbuf, "%s|      |", off);
  1652.     for (i = day = bd, month = bm;
  1653.      i < (bd + 7);
  1654.      i++, day++)
  1655.     {
  1656.     if (day >  mon[month].length)    /* Past this month */
  1657.     {
  1658.         day -= mon[month].length;
  1659.                 /* So make it appropriate day. . . */
  1660.         month++;        /* Of following month. . . */
  1661.         month = month % 12; /* And then normalise it. . . */
  1662.     }
  1663.     sprintf(temp1, "%d %3.3s", day, mnam[lang -1][month]);
  1664.     sprintf(temp, "%s|", center(temp1, bw) );
  1665.     strcat(linbuf, temp);
  1666.     }
  1667.     strcat(linbuf, "\n");
  1668.     fputs(linbuf, fp);
  1669.   }
  1670.  
  1671.     sprintf(linbuf, (sched_type != 'M')?
  1672.                "%s|      |":
  1673.                "%s|", off);
  1674.     for (i = wk_day;
  1675.      i < (wk_day + 7);
  1676.      i++)
  1677.     {
  1678.     sprintf(temp1, "%3.9s", wkday[lang -1][i % 7]);
  1679.     sprintf(temp, "%s|", center(temp1, bw) );
  1680.     strcat(linbuf, temp);
  1681.     }
  1682.     strcat(linbuf, "\n");
  1683.     fputs(linbuf, fp);
  1684.  
  1685.     if (sched_type == 'M')    /* Monthly calendar */
  1686.     {                /* Months have 5 or 6 weeks */
  1687.     bh = 0;
  1688.     nh = (yr[y][bm][5][0])?    /* Sixth week, Sunday? */
  1689.                6:    /* Six weeks/month */
  1690.                5;    /* Five weeks/month */
  1691.     }
  1692.  
  1693.     for (i = bh;
  1694.      i < (bh + nh);
  1695.      i++)    /* print the hourly lines */
  1696.     {
  1697.     fputs(sep, fp);        /* print separators */
  1698.     if (sched_type == 'M')
  1699.     {
  1700.         sprintf(hoursw, "%s|", off);/* Initialize hoursw */
  1701.         for (j = 0;
  1702.          j < 7;
  1703.          j++)
  1704.         {
  1705.         sprintf(temp,
  1706.             yr[y][bm][i][j] ?
  1707.                 (base ?
  1708.                 ((base == 'O') ? "%s%2o|" : "%s%2X|" ) :
  1709.                          "%s%2d|" ) :
  1710.                          "%s  |",
  1711.             dates,
  1712.             yr[y][bm][i][j]);
  1713.         strcat(hoursw, temp);
  1714.         }
  1715.         strcat(hoursw, "\n");
  1716.     }
  1717.  
  1718.     fprintf(fp, hoursw, (i % 24)); /* print hour/week line */
  1719.  
  1720.     for (j = 2;
  1721.          j < ((pl - 18) / nh);
  1722.          j++)
  1723.         fputs(spacerw, fp);        /* print spacer line(s) */
  1724.     }
  1725.     fputs(bnd, fp);            /* print boundary */
  1726.  
  1727.     if(out != 'V') fputs("\f\r", fp);    /* no FF for screen */
  1728.     if(out == 'F')            /* setup for file output */
  1729.     if((stat = fclose(fp)) == ERROR)
  1730.         printf("\nCan't close %s.\n", file);
  1731. /*  else
  1732.         printf("\nClosed %s\n", file);*/
  1733.     if(out == 'F')
  1734.     {
  1735.     if ((stat = rename(file, new_file)) == ERROR)
  1736.     {
  1737.         printf(
  1738.         "\nCan't rename %s to %s.  %s may already exist.\n",
  1739.                  file, new_file, new_file);
  1740.     }
  1741.     }
  1742. }
  1743.  
  1744.  
  1745.  
  1746. /************************************************************************/
  1747. void get_opts( name)
  1748. char *name;    /* filename from argv[0] */
  1749. {
  1750.     /* Various statistics (such as the last time the program was run)
  1751.     * are stored in a buffer at the end of the executable structure.
  1752.     * These stats and the settings for user selected options are all
  1753.     * stored in the "options" structure.  This function creates the
  1754.     * data area if it doesn't exist and initializes Opt as appropriate.
  1755.     * Alan Holub, C-Chest, DDJ Feb 1988.
  1756.     */
  1757.  
  1758.     int fd;        /* file descriptor handle */
  1759.     int i, *p;        /* used to create checksum */
  1760.     void ferr();    /* fatal error handler */
  1761.  
  1762.     if( (fd = open( name, O_RDWR | O_BINARY ) ) == ERROR)
  1763.     {
  1764.     perror( name);
  1765.     exit(1);
  1766.     }
  1767.  
  1768.     lseek(fd, 0L - sizeof(Opt), SEEK_END);
  1769.  
  1770.     /* Check to see if all of the options area is still there */
  1771.     if( read(fd, (char *) &Opt, sizeof(Opt) ) != sizeof(Opt) )
  1772.     ferr( "Internal error:  Can't read options\n");
  1773.  
  1774.     /* Check to see if the signature is still as it should be */
  1775.     if(strcmp( DEF_SIG, Opt.signature) != 0)
  1776.     {
  1777.     memset( &Opt, 0, sizeof(Opt));
  1778.     /* The memset is for debugging.  It shows us that the record has
  1779.      * been written correctly.
  1780.      */
  1781.  
  1782.         strcpy( Opt.signature, DEF_SIG);
  1783.         /* Initialize other fields in the Opt structure here. */
  1784.         Opt.aggie    = FALSE;    /* Not all are Aggies! */
  1785.     Opt.bh        =  6;        /* Hour defaults to 0600 */
  1786.     Opt.copies    =  1;        /* At least one copy. . . */
  1787.     Opt.fy        = FALSE;    /* Most are not Fiscal Year */
  1788.     Opt.indent      =  7;        /* Left Margin Indent in spaces */
  1789.     Opt.julian    = FALSE;    /* Regular calendar is default */
  1790.     Opt.lang    =  5;        /* Select English as default Language */
  1791.     Opt.more_yrs    =  0;        /* One period at a time. . . */
  1792.     Opt.nh        = 24;        /* Scheduled Hour defaults to 24 */
  1793.     Opt.pause    = FALSE;    /* No pause at end of each printed page */
  1794.     Opt.pl        = 66;        /* Page Length in lines */
  1795.     Opt.pw        = 80;        /* Page Width in characters or columns */
  1796.     Opt.base    = FALSE;    /* Decimal for most */
  1797.     Opt.sched_type     = FALSE;    /* Annual calendar is default */
  1798.     for (i = 0;            /* Initialize title array */
  1799.              i < 8;
  1800.              i++)
  1801.          Opt.title[i][0] = '\0';
  1802.  
  1803.         Opt.chksum = 0;
  1804.         for (p = (int *)(&Opt), i = sizeof(Opt) / 2;
  1805.              --i >= 0;
  1806.               )
  1807.             Opt.chksum -= *p++;
  1808.  
  1809.         lseek(fd, 0L, SEEK_END);
  1810.  
  1811.         if(write(fd, (char *) &Opt, sizeof(Opt)) != sizeof(Opt) )
  1812.         ferr("Internal error:  Can't initialize options\n");
  1813.     }
  1814.     close(fd);
  1815. }
  1816.  
  1817.  
  1818.  
  1819. void put_opts( name)
  1820. char *name;
  1821. {
  1822.     /* Update the options buffer at the end of the .EXE program (which
  1823.      * better exist).  If the options buffer doesn't exist, this function
  1824.      * will destroy the end of the file.  Alan Holub, C-Chest, DDJ Feb 1988.
  1825.      */
  1826.  
  1827.     int fd;            /* file descriptor handle */
  1828.     int i, *p, checksum;    /* used to create checksum */
  1829.     void ferr();        /* fatal error handler */
  1830.  
  1831.     if( (fd = open( name, O_RDWR | O_BINARY) ) == -1)
  1832.     {
  1833.     perror( name );
  1834.     exit(1);
  1835.     }
  1836.  
  1837.     /* Recompute the checksum */
  1838.  
  1839.     checksum = 0;
  1840.     for (p = (int *)(&Opt), i = sizeof(Opt) / 2;
  1841.        --i >= 0;
  1842.           )
  1843.     checksum -= *p++;
  1844.  
  1845.     if(checksum != Opt.chksum)
  1846.     printf("\tDefaults have been changed.");
  1847.  
  1848.     Opt.chksum = checksum;
  1849.  
  1850.     lseek(fd, 0L - sizeof(Opt), SEEK_END);
  1851.     if(write(fd, (char *) &Opt, sizeof(Opt)) != sizeof(Opt) )
  1852.     ferr("Can't do final options update\n");
  1853.     close(fd);
  1854. }
  1855.  
  1856.  
  1857.  
  1858. void ferr( fmt)
  1859. char *fmt;
  1860. {
  1861.     /* ferr() is used for fatal error processing.  It is used just like
  1862.      * printf().  However, it exits the program with a status of 1
  1863.      * immediately after printing the message.  I'm using ANSI, not UNIX
  1864.      * variable argument conventions here.  (Alan Holub, C-Chest Book, p. 299)
  1865.      */
  1866.  
  1867.     va_list args;
  1868.     va_start(args, fmt);
  1869.     vfprintf(stderr, fmt, args);
  1870.     exit(1);
  1871. }
  1872.  
  1873.