home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume16 / month8.7 / part02 < prev    next >
Encoding:
Internet Message Format  |  1988-11-08  |  43.4 KB

  1. Subject:  v16i055:  A visual calendar and appointment system, Part02/06
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Michael Morrell <hplabs!hpda!morrell>
  7. Posting-number: Volume 16, Issue 55
  8. Archive-name: month8.7/part02
  9.  
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # This archive contains:
  13. #    month.h        month2.h    month3.h    month4.h    
  14. #    month5.h    month6.h    month7.h    month8.h    
  15. #    get.c        hl.c        lunar.c        month.c        
  16. #    move.c        
  17. LANG=""; export LANG
  18.  
  19. echo x - month.h
  20. cat >month.h <<'@EOF'
  21. /*
  22.  * @(#)$Header: month.h,v 8.4 88/04/04 10:46:35 hull Exp $
  23.  */
  24.  
  25. #define USER_COL    40        /* first column of "User:" */
  26. #define FLAG_COL    69        /* first column of flags */
  27. #define MONTH_ROW    3        /* top row of month area */
  28. #define CAL_ROW        3        /* top row of calendar area */
  29. #define CAL_COL        13        /* leftmost column of calendar area */
  30. #define DAY_ROW        1        /* row for list of days */
  31. #define DAY_COL        12        /* first column of list of days */
  32. #define YEAR_ROW    15        /* row for year list */
  33. #define YEAR_COL    15        /* first column of year list */
  34. #define SCHEDULE_ROW    17        /* top row of schedule area */
  35. #define SMONTH_COL    0        /* first column of start month */
  36. #define SDAY_COL    3        /* first column of start day */
  37. #define SYEAR_COL    6        /* first column of start year */
  38. #define PRIVATE_COL    12        /* first column of "priv" */
  39. #define ANTI_COL    17        /* first column of "anti" */
  40. #define MONTHLY_COL    22        /* first column of "monthly" */
  41. #define YEARLY_COL    30        /* first column of "yearly" */
  42. #define EVERY_COL    37        /* first column of "every" */
  43. #define NTH_COL        43        /* first column of "Nth" */
  44. #define LAST_COL    48        /* first column of "last" */
  45. #define SMTWTFS_COL    53        /* first column of "SuMoTuWeThFrSa" */
  46. #define UMONTH_COL    68        /* first column of until month */
  47. #define UDAY_COL    71        /* first column of until day */
  48. #define UYEAR_COL    74        /* first column of until year */
  49. #define TIME_ROW    20        /* row for event times */
  50. #define START_COL    3        /* first column of start time */
  51. #define DURATION_COL    21        /* first column of duration */
  52. #define END_COL        37        /* first column of end time */
  53. #define WARNING_COL    53        /* first column of warning time */
  54. #define OWNER_ROW    20        /* row for event owner */
  55. #define OWNER_COL    68        /* first column for event owner */
  56. #define DESCRIPTION_ROW    22        /* row for event description */
  57. #define DESCRIPTION_COL    7        /* first column of event description */
  58.  
  59. #define START_MODE    'S'        /* start time mode */
  60. #define DURATION_MODE    'D'        /* duration mode */
  61. #define END_MODE    'E'        /* end time mode */
  62.  
  63. #define ALIAS        'a'        /* alias area */
  64. #define MONTHS        'm'        /* months area */
  65. #define DAYS        'd'        /* days area */
  66. #define YEARS        'y'        /* years area */
  67. #define SCAN        'n'        /* scan area */
  68. #define SCHEDULE    's'        /* schedule area */
  69. #define SCHED_SCAN        'S'        /* scan and schedule area */
  70. #define BOOK        'B'        /* book area */
  71. #define HELP        'H'        /* help area */
  72. #define LUNAR        'L'        /* lunar area */
  73.  
  74. #define FIRST_YEAR    1760        /* 1/1/1760 is the beginning of time */
  75. #define LAST_YEAR    9999        /* 12/31/9999 is the end of time */
  76.  
  77. #define MAX_EVENT_STRING_LENGTH    70    /* maximum length of an event string */
  78. #define MAX_ALIAS_LEVEL    16        /* maximum number of alias levels */
  79.  
  80. #define NOTHING        0        /* no change in event status */
  81. #define ACCEPT        1        /* event was accepted */
  82. #define CANCEL        2        /* event change was cancelled */
  83.  
  84. #define NO_BELL        0        /* print message with no bell */
  85. #define BELL        1        /* print message with bell */
  86.  
  87. #define HL_OFF        0        /* print without highlighting */
  88. #define HL_ON        1        /* print with highlighting */
  89.  
  90. #define READ_WRITE    0        /* open .month with read/write access */
  91. #define READ_ONLY    1        /* open .month with read-only access */
  92.  
  93. #define NUM_MARKS    12        /* maximum number of marked dates */
  94. #define SEMI_MARK    (NUM_MARKS-2)    /* special marked date for ";" */
  95. #define CUR_MARK    (NUM_MARKS-1)    /* currently marked date */
  96.  
  97. #define BUFSIZE        40        /* size of temporary buffers */
  98. #define MAXLINE        1024        /* maximum line length in alias file */
  99.  
  100. #define MAXAREAS    5        /* size of area stack */
  101. #define current_area    areas[area_ptr-1].area    /* top of area stack */
  102.  
  103. /* shell used for shell escape */
  104. /* environment variable "SHELL" if defined, else "SHELLPROG" */
  105. extern char *getenv();
  106. #define SH    (getenv("SHELL") ? getenv("SHELL") : SHELLPROG)
  107.  
  108. /* pager used for printing help file */
  109. /* environment variable "PAGER" if defined, else "PAGERPROG" */
  110. #define PG    (getenv("PAGER") ? getenv("PAGER") : PAGERPROG)
  111.  
  112. #if !SYS5CURSES
  113. #define attron(arg)    standout()    /* use standout for all highlighting */
  114. #define attroff(arg)    standend()
  115. #define A_CHARTEXT    0177        /* mask to strip attributes */
  116. #endif
  117.  
  118. #if !CVOID
  119. #define void    int
  120. #endif
  121.  
  122. extern char *malloc();
  123. #if SYS5
  124. extern void exit(), free();
  125. #endif
  126. #ifdef hpux
  127. #define alarm_t unsigned long
  128. #else
  129. #define alarm_t unsigned
  130. #endif
  131.  
  132. /* structure of an area */
  133. struct area_rec {
  134.     short area;
  135.     short row;
  136.     short col;
  137. };
  138.  
  139. /* structure of a date */
  140. struct date_rec {
  141.     short month;
  142.     short day;
  143.     short year;
  144. };
  145.  
  146. /* structure of a time */
  147. struct time_rec {
  148.     short hour;
  149.     short minute;
  150. };
  151.  
  152. /* structure of an event pointer */
  153. struct eptr_rec {
  154.     struct event_rec *event;    /* event */
  155.     struct eptr_rec *prev_event;    /* previous event */
  156.     struct eptr_rec *next_event;    /* next event */
  157. };
  158.  
  159. /* structure of a name */
  160. struct name_rec {
  161.     char *name;            /* name */
  162.     struct name_rec *next_name    /* next name */
  163. };
  164.  
  165. #include "month8.h"
  166. @EOF
  167.  
  168. chmod 644 month.h
  169.  
  170. echo x - month2.h
  171. cat >month2.h <<'@EOF'
  172. /*
  173.  * @(#)$Header: month2.h,v 2.0 87/11/13 22:58:00 hull Exp $
  174.  */
  175.  
  176. struct event_rec2 {
  177.     char event_month;    /* month of the event */
  178.     char event_day;        /* day of the event */
  179.     short event_year;    /* year of the event */
  180.     char monthly;        /* does event occur monthly? */
  181.     char yearly;        /* does event occur yearly? */
  182.     char every;        /* does event occur on every something? */
  183.     char smtwtfs[7];    /* which days of the week are relevant? */
  184.     char nth, last;        /* does event occur on an nth or last something? */
  185.     char nth_is_on;        /* is 'nth' selected by user, n is nth above */
  186.     char hour;        /* hour of the event */
  187.     char minute;        /* minute of the event */
  188.     char duration_hours;    /* hours event lasts */
  189.     char duration_minutes;    /* minutes event lasts, multiple of 15 */
  190.     char event_string[MAX_EVENT_STRING_LENGTH];    /* short description of event */
  191.     char private;        /* is event private? */
  192.     struct event_rec2 *next_event;    /* next event */
  193. };
  194. @EOF
  195.  
  196. chmod 444 month2.h
  197.  
  198. echo x - month3.h
  199. cat >month3.h <<'@EOF'
  200. /*
  201.  * @(#)$Header: month3.h,v 3.0 87/11/13 22:58:40 hull Exp $
  202.  */
  203.  
  204. struct event_rec3 {
  205.     char event_month;    /* month of the event */
  206.     char event_day;        /* day of the event */
  207.     short event_year;    /* year of the event */
  208.     char monthly;        /* does event occur monthly? */
  209.     char yearly;        /* does event occur yearly? */
  210.     char every;        /* does event occur on every something? */
  211.     char smtwtfs[7];    /* which days of the week are relevant? */
  212.     char nth, last;        /* does event occur on an nth or last something? */
  213.     char nth_is_on;        /* is 'nth' selected by user, n is nth above */
  214.     char hour;        /* hour of the event */
  215.     char minute;        /* minute of the event */
  216.     char duration_hours;    /* hours event lasts */
  217.     char duration_minutes;    /* minutes event lasts, multiple of 15 */
  218.     char event_string[MAX_EVENT_STRING_LENGTH];    /* short description of event */
  219.     char private;        /* is event private? */
  220.     int event_owner;    /* owner of event */
  221.     struct event_rec3 *next_event;    /* next event */
  222. };
  223. @EOF
  224.  
  225. chmod 444 month3.h
  226.  
  227. echo x - month4.h
  228. cat >month4.h <<'@EOF'
  229. /*
  230.  * @(#)$Header: month4.h,v 4.0 87/11/13 22:59:20 hull Exp $
  231.  */
  232.  
  233. struct event_rec4 {
  234.     char start_month;    /* starting month of the event */
  235.     char start_day;        /* starting day of the event */
  236.     short start_year;    /* starting year of the event */
  237.     char monthly;        /* does event occur monthly? */
  238.     char yearly;        /* does event occur yearly? */
  239.     char every;        /* does event occur on every something? */
  240.     char smtwtfs[7];    /* which days of the week are relevant? */
  241.     char nth;        /* does event occur on an nth something? */
  242.     char last;        /* does event occur on a last something? */
  243.     char nth_is_on;        /* is 'nth' selected by user, n is nth above */
  244.     char hour;        /* hour of the event */
  245.     char minute;        /* minute of the event */
  246.     char duration_hours;    /* hours event lasts */
  247.     char duration_minutes;    /* minutes event lasts */
  248.     char event_string[MAX_EVENT_STRING_LENGTH];  /* description of event */
  249.     char private;        /* is event private? */
  250.     int event_owner;    /* owner of event */
  251.     char until;        /* does event occur until some date? */
  252.     char until_month;    /* month event goes until */
  253.     char until_day;        /* day event goes until */
  254.     short until_year;    /* year event goes until */
  255.     struct event_rec4 *next_event;    /* next event */
  256. };
  257. @EOF
  258.  
  259. chmod 444 month4.h
  260.  
  261. echo x - month5.h
  262. cat >month5.h <<'@EOF'
  263. /*
  264.  * @(#)$Header: month5.h,v 5.0 87/11/13 22:59:48 hull Exp $
  265.  */
  266.  
  267. struct event_rec5 {
  268.     char start_month;    /* starting month of the event */
  269.     char start_day;        /* starting day of the event */
  270.     short start_year;    /* starting year of the event */
  271.     char monthly;        /* does event occur monthly? */
  272.     char yearly;        /* does event occur yearly? */
  273.     char every;        /* does event occur on every something? */
  274.     char smtwtfs[7];    /* which days of the week are relevant? */
  275.     char nth;        /* does event occur on an nth something? */
  276.     char last;        /* does event occur on a last something? */
  277.     char nth_is_on;        /* is 'nth' selected by user, n is nth above */
  278.     char hour;        /* hour of the event */
  279.     char minute;        /* minute of the event */
  280.     char duration_hours;    /* hours event lasts */
  281.     char duration_minutes;    /* minutes event lasts */
  282.     char warning_hours;    /* hours of warning before event */
  283.     char warning_minutes;    /* minutes of warning before event */
  284.     char event_string[MAX_EVENT_STRING_LENGTH];  /* description of event */
  285.     char private;        /* is event private? */
  286.     int event_owner;    /* owner of event */
  287.     char until;        /* does event occur until some date? */
  288.     char until_month;    /* month event goes until */
  289.     char until_day;        /* day event goes until */
  290.     short until_year;    /* year event goes until */
  291.     struct event_rec5 *next_event;    /* next event */
  292. };
  293. @EOF
  294.  
  295. chmod 444 month5.h
  296.  
  297. echo x - month6.h
  298. cat >month6.h <<'@EOF'
  299. /*
  300.  * @(#)$Header: month6.h,v 6.0 87/11/13 23:00:18 hull Exp $
  301.  */
  302.  
  303. struct event_rec6 {
  304.     char start_month;    /* starting month of the event */
  305.     char start_day;        /* starting day of the event */
  306.     short start_year;    /* starting year of the event */
  307.     char monthly;        /* does event occur monthly? */
  308.     char yearly;        /* does event occur yearly? */
  309.     char every;        /* does event occur on every something? */
  310.     char smtwtfs[7];    /* which days of the week are relevant? */
  311.     char nth;        /* does event occur on an nth something? */
  312.     char last;        /* does event occur on a last something? */
  313.     char nth_is_on;        /* is 'nth' selected by user, n is nth above */
  314.     char hour;        /* hour of the event */
  315.     char minute;        /* minute of the event */
  316.     char duration_hours;    /* hours event lasts */
  317.     char duration_minutes;    /* minutes event lasts */
  318.     char warning_hours;    /* hours of warning before event */
  319.     char warning_minutes;    /* minutes of warning before event */
  320.     char event_string[MAX_EVENT_STRING_LENGTH];  /* description of event */
  321.     char private;        /* is event private? */
  322.     char anti;        /* is this an anti-event? */
  323.     int event_owner;    /* owner of event */
  324.     char until;        /* does event occur until some date? */
  325.     char until_month;    /* month event goes until */
  326.     char until_day;        /* day event goes until */
  327.     short until_year;    /* year event goes until */
  328.     struct event_rec6 *next_event;    /* next event */
  329. };
  330. @EOF
  331.  
  332. chmod 444 month6.h
  333.  
  334. echo x - month7.h
  335. cat >month7.h <<'@EOF'
  336. /*
  337.  * @(#)$Header: month7.h,v 7.0 87/11/13 23:01:04 hull Exp $
  338.  */
  339.  
  340. /* structure of an event */
  341. struct event_rec7 {
  342.     struct date_rec start_date;    /* starting date of the event */
  343.     char monthly;        /* does event occur monthly? */
  344.     char yearly;        /* does event occur yearly? */
  345.     char every;        /* does event occur on every something? */
  346.     char smtwtfs[7];    /* which days of the week are relevant? */
  347.     char nth;        /* does event occur on an nth something? */
  348.     char last;        /* does event occur on a last something? */
  349.     char nth_is_on;        /* is 'nth' selected by user, n is nth above */
  350.     char hour;        /* hour of the event */
  351.     char minute;        /* minute of the event */
  352.     char duration_hours;    /* hours event lasts */
  353.     char duration_minutes;    /* minutes event lasts */
  354.     char warning_hours;    /* hours of warning before event */
  355.     char warning_minutes;    /* minutes of warning before event */
  356.     char event_string[MAX_EVENT_STRING_LENGTH];  /* description of event */
  357.     char private;        /* is event private? */
  358.     char anti;        /* is this an anti-event? */
  359.     int event_owner;    /* owner of event */
  360.     char until;        /* does event occur until some date? */
  361.     struct date_rec until_date;    /* date event goes until */
  362.     struct event_rec7 *next_event;    /* next event */
  363. };
  364. @EOF
  365.  
  366. chmod 444 month7.h
  367.  
  368. echo x - month8.h
  369. cat >month8.h <<'@EOF'
  370. /*
  371.  * @(#)$Header: month8.h,v 8.0 87/11/13 22:50:14 hull Exp $
  372.  */
  373.  
  374. /* structure of an event */
  375. struct event_rec {
  376.     struct date_rec start_date;    /* starting date of the event */
  377.     char monthly;        /* does event occur monthly? */
  378.     char yearly;        /* does event occur yearly? */
  379.     char every;        /* does event occur on every something? */
  380.     char smtwtfs[7];    /* which days of the week are relevant? */
  381.     char nth;        /* does event occur on an nth something? */
  382.     char last;        /* does event occur on a last something? */
  383.     char nth_is_on;        /* is 'nth' selected by user, n is nth above */
  384.     struct time_rec start_time;    /* starting time of the event */
  385.     struct time_rec duration;    /* duration of the event */
  386.     struct time_rec warning;    /* warning of the event */
  387.     struct time_rec end_time;    /* ending time of the event */
  388.     char event_string[MAX_EVENT_STRING_LENGTH];  /* description of event */
  389.     char private;        /* is event private? */
  390.     char anti;        /* is this an anti-event? */
  391.     int event_owner;    /* owner of event */
  392.     char until;        /* does event occur until some date? */
  393.     struct date_rec until_date;    /* date event goes until */
  394.     struct event_rec *next_event;    /* next event */
  395. };
  396. @EOF
  397.  
  398. chmod 444 month8.h
  399.  
  400. echo x - get.c
  401. cat >get.c <<'@EOF'
  402. #ifndef lint
  403. static char rcsid[] = "$Header: get.c,v 8.5 88/04/04 10:41:04 hull Exp $";
  404. #endif
  405.  
  406. #include <curses.h>
  407. #if SYS5
  408. #include <string.h>
  409. #else
  410. #include <strings.h>
  411. #endif
  412. #include "month.h"
  413.  
  414. extern short crow, ccol, area_ptr;
  415. extern short ins_mode, keep_old, my_file, read_only, event_status;
  416. extern short delchar, kilchar, update_schedule;
  417. extern int user_id;
  418. extern char *home_dir, *month_dir, *user_name;
  419. extern struct date_rec current_date;
  420. extern struct event_rec current_event;
  421. extern struct area_rec areas[];
  422.  
  423. get_description()
  424. {
  425.     short i, pos, len, at_end;
  426.     int ch;
  427.  
  428.     pos = len = strlen(current_event.event_string);
  429.     crow = DESCRIPTION_ROW;
  430.  
  431.     for (;;) {
  432.         at_end = (pos == len);
  433.         ccol = DESCRIPTION_COL + pos;
  434.         move(crow, ccol);
  435.         refresh();
  436.         ch = get_char();
  437.  
  438.         if ((ch >= ' ') && (ch <= '~'))
  439.         if (ins_mode) {
  440.             if (len < MAX_EVENT_STRING_LENGTH - 2) {
  441. #if SYS5CURSES
  442.             insch((chtype) ch);
  443. #else
  444.             insch((char) ch);
  445. #endif
  446.             for (i = ++len; i > pos; i--)
  447.                 current_event.event_string[i] =
  448.                 current_event.event_string[i - 1];
  449.             current_event.event_string[pos++] = ch;
  450.             }
  451.         } else {
  452.             if (pos < MAX_EVENT_STRING_LENGTH - 2) {
  453.             addch(ch);
  454.             current_event.event_string[pos++] = ch;
  455.             if (at_end)
  456.                 current_event.event_string[++len] = '\0';
  457.             }
  458.         }
  459.         else
  460.         switch(ch) {
  461.         case '\001':  /* ^A */
  462.             event_status = ACCEPT;
  463.             return;
  464.         case '\033':  /* ^[ */
  465.             event_status = CANCEL;
  466.             return;
  467. #if SYS5CURSES
  468.         case KEY_UP:
  469.             schedule_move_cursor('k');
  470.             return;
  471.         case KEY_DOWN:
  472. #endif
  473.         case '\n':
  474.             schedule_move_cursor('\n');
  475.             return;
  476.         case '\b':
  477.             if (ins_mode) {
  478.             if (pos > 0) {
  479.                 for (i = pos--; i <= len; i++)
  480.                 current_event.event_string[i - 1] =
  481.                 current_event.event_string[i];
  482.                 len--;
  483.                 mvdelch(crow, ccol - 1);
  484.             }
  485.             } else
  486.             if (pos > 0) {
  487.                 mvaddch(crow, ccol - 1, ' ');
  488.                 current_event.event_string[--pos] = ' ';
  489.                 if (at_end)
  490.                 current_event.event_string[--len] = '\0';
  491.             }
  492.             break;
  493.         case '\025':    /* ^U */
  494.             current_event.event_string[pos = len = 0] = '\0';
  495.             move(crow, DESCRIPTION_COL);
  496.             clrtoeol();
  497.             break;
  498.         case '\027':    /* ^W */
  499.             while ((pos > 0) &&
  500.                (current_event.event_string[pos - 1] == ' '))
  501.             pos--;
  502.             while ((pos > 0) &&
  503.                (current_event.event_string[pos - 1] != ' ')) {
  504.             current_event.event_string[--pos] = ' ';
  505.             mvaddch(crow, DESCRIPTION_COL + pos, ' ');
  506.             }
  507.             if (at_end)
  508.             current_event.event_string[len = pos] = '\0';
  509.             break;
  510. #if SYS5CURSES
  511.         case KEY_IC:
  512.         case KEY_EIC:
  513. #endif
  514.         case '\t':    /* ^I */
  515.             toggle_flag('I');
  516.             break;
  517. #if SYS5CURSES
  518.         case KEY_LEFT:
  519. #endif
  520.         case '\002':    /* ^B */
  521.             if (pos > 0)
  522.             pos--;
  523.             break;
  524. #if SYS5CURSES
  525.         case KEY_DC:
  526. #endif
  527.         case '\004':    /* ^D */
  528.             if (!at_end) {
  529.             for (i = pos; i < len; i++)
  530.                 current_event.event_string[i] =
  531.                 current_event.event_string[i + 1];
  532.             len--;
  533.             delch();
  534.             }
  535.             break;
  536. #if SYS5CURSES
  537.         case KEY_RIGHT:
  538. #endif
  539.         case '\006':    /* ^F */
  540.             if (pos < len)
  541.             pos++;
  542.             break;
  543.         }
  544.     }
  545. }
  546.  
  547. get_npdeq(n_ok, p_ok, ed_ok)
  548. int n_ok, p_ok, ed_ok;
  549. {
  550.     register ch;
  551.     char buf[16];
  552.  
  553.     sprintf(buf, "[");
  554.  
  555.     if (n_ok)
  556.         strcat(buf, "n,");
  557.     if (p_ok)
  558.         strcat(buf, "p,");
  559.     if (ed_ok)
  560.         strcat(buf, "d,e,");
  561.     strcat(buf, "q] ");
  562.  
  563.     ccol = print_message(buf, NO_BELL);
  564.  
  565.     for (;;) {
  566.         ch = get_char();
  567.  
  568.         switch(ch) {
  569.         case '\n':
  570.         case 'n':
  571.             if (n_ok)
  572.                 return('n');
  573.             else
  574.                 sound_bell();
  575.             break;
  576.         case 'p':
  577.             if (p_ok)
  578.                 return('p');
  579.             else
  580.                 sound_bell();
  581.             break;
  582.         case 'd':
  583.             if (ed_ok) {
  584.                 ccol = print_message("really delete? ", NO_BELL);
  585.                 ch = get_char();
  586.                 if (ch == 'y')
  587.                 ccol = print_message("deleted", NO_BELL);
  588.                 else
  589.                 ccol = print_message("not deleted", NO_BELL);
  590.                 more();
  591.                 if (ch == 'y')
  592.                 return('d');
  593.                 else
  594.                 ccol = print_message(buf, NO_BELL);
  595.             } else
  596.                 sound_bell();
  597.             break;
  598.         case 'e':
  599.             if (ed_ok)
  600.                 return('e');
  601.             else
  602.                 sound_bell();
  603.             break;
  604.         case 'q':
  605.         case '\033':    /* ^[ */
  606.             return('q');
  607.         default:
  608.             sound_bell();
  609.         }
  610.     }
  611. }
  612.  
  613. get_char()
  614. {
  615.     register int ch;
  616.  
  617. GETCH:
  618.     ch = getch();
  619.  
  620.     if (ch == delchar)    /* convert user's delete char to \b */
  621.         ch = '\b';
  622.     else if (ch == kilchar)    /* convert user's kill char to ^U */
  623.         ch = '\025';
  624.  
  625.     switch(ch) {
  626.     case '\005':    /* ^E */
  627.         ch = '\033';    /* convert to ESC */
  628.         break;
  629.     case '\r':
  630.         ch = '\n';
  631.         break;
  632.     case '\014':    /* ^L */
  633.     case '\022':    /* ^R */
  634.         wrefresh(curscr);
  635.         goto GETCH;
  636.     }
  637.  
  638. #if SYS5CURSES
  639.     if (crow != DESCRIPTION_ROW)
  640.         switch(ch) {    /* convert curses chars to normal chars */
  641.         case KEY_PPAGE:
  642.         ch = 'p';
  643.         break;
  644.         case KEY_NPAGE:
  645.         ch = 'n';
  646.         break;
  647.         case KEY_LEFT:
  648.         ch = 'h';
  649.         break;
  650.         case KEY_RIGHT:
  651.         ch = 'l';
  652.         break;
  653.         case KEY_UP:
  654.         ch = 'k';
  655.         break;
  656.         case KEY_DOWN:
  657.         ch = 'j';
  658.         break;
  659.         }
  660. #endif
  661.     return(ch);
  662. }
  663.  
  664. get_date(date, prompt)
  665. struct date_rec *date;
  666. char *prompt;
  667. {
  668.     register short ch;
  669.     short col, slash_count, newm, newd, newy;
  670.     char buf[BUFSIZE];
  671.     int ret;
  672.     void convert_year();
  673.  
  674.     if (current_area == SCHEDULE)
  675.         push_area(SCHED_SCAN);
  676.     else
  677.         push_area(SCAN);
  678.  
  679.     ccol = print_message(prompt, NO_BELL);
  680.     col = 0;
  681.     slash_count = 0;
  682.  
  683.     for (;;) {
  684.         refresh();
  685.         ch = get_char();
  686.  
  687.         switch(ch) {
  688.         case '\b':
  689.             if (col > 0) {
  690.                 if (buf[col - 1] == '/') {
  691.                     slash_count--;
  692.                 }
  693.                 --col; ccol--;
  694.                 mvaddch(0, ccol, ' ');
  695.                 move(0, ccol);
  696.             }
  697.             break;
  698.         case '/':
  699.             if ((slash_count >= 2) || (col == 0) ||
  700.                (buf[col-1] == '/'))
  701.                 sound_bell();
  702.             else {
  703.                 addch(ch);
  704.                 buf[col++] = ch;
  705.                 slash_count++;
  706.                 ccol++;
  707.             }
  708.             break;
  709.         case '0':
  710.             if ((col == 0) ||
  711.                 (buf[col-1] == '/' && slash_count < 2))
  712.                 break;
  713.         case '1':
  714.         case '2':
  715.         case '3':
  716.         case '4':
  717.         case '5':
  718.         case '6':
  719.         case '7':
  720.         case '8':
  721.         case '9':
  722.             if (
  723.             ((col == 2) && (buf[col-1] != '/')) ||
  724.             ((slash_count == 1)&&(buf[col-1] != '/')&&(buf[col-2] != '/'))||
  725.             ((slash_count == 2) && (buf[col-1] != '/') && (buf[col-2] != '/') &&
  726.                 (buf[col-3] != '/') && (buf[col-4] != '/')) ||
  727.             ((col == 1) && ((ch > '2') || (buf[0] > '1')))
  728.             )
  729.                 sound_bell();
  730.             else {
  731.                 addch(ch);
  732.                 buf[col++] = ch;
  733.                 ccol++;
  734.             }
  735.             break;
  736.         case '\n':
  737.             if ((slash_count == 0) || (buf[col-1] == '/'))
  738.                 sound_bell();
  739.             else {
  740.                 buf[col] = 0;
  741.                 ret = sscanf(buf, "%hd/%hd/%hd",
  742.                     &newm, &newd, &newy);
  743.                 if (ret == 3)
  744.                     convert_year(current_date.year, &newy);
  745.                 else
  746.                     newy = current_date.year;
  747.                 if (newy < FIRST_YEAR)
  748.                     sound_bell();
  749.                 else {
  750.                     date->month = newm;
  751.                     date->day = newd;
  752.                     date->year = newy;
  753.                     clear_message_line();
  754.                     pop_area();
  755.                     return(1);
  756.                 }
  757.             }
  758.             break;
  759.         case '\033':    /* ^[ */
  760.             clear_message_line();
  761.             pop_area();
  762.             return(0);
  763.         case '\025':    /* ^U */
  764.             ccol = print_message(prompt, NO_BELL);
  765.             col = 0;
  766.             slash_count = 0;
  767.             break;
  768.         default:
  769.             break;
  770.         }
  771.     }
  772. }
  773.  
  774. #if MULTIUSER
  775. get_user()
  776. {
  777.     short i = 0;
  778.     char *new_dir, new_name[16], buf[BUFSIZE], *get_user_arg();
  779.     static char name[16];
  780.  
  781.     push_area(SCAN);
  782.     ccol = print_message("user: ", NO_BELL);
  783.     crow = 0;
  784.  
  785.     if (get_string(new_name) == 0) {
  786.         clear_message_line();
  787.         pop_area();
  788.         return;
  789.     }
  790.  
  791.     if ((new_dir = get_user_arg(new_name)) != NULL) {
  792.         if (update_schedule)
  793.         ccol = print_message("updating schedule", NO_BELL);
  794.         else
  795.         ccol = print_message("schedule unchanged", NO_BELL);
  796.  
  797.         if (!read_only && write_schedule() < 0) {
  798.         more();
  799.         ccol = print_message("cannot write .month", BELL);
  800.         }
  801.  
  802.         if ((i = read_schedule(new_dir, read_only)) == -2) {
  803.         more();
  804.         sprintf(buf, "%s's .month file locked", new_name);
  805.         ccol = print_message(buf, BELL);
  806.         i = read_schedule(new_dir, READ_ONLY);
  807.         if (i == 0)
  808.             read_only = 1;
  809.         }
  810.  
  811.         if (i != 0) {
  812.         more();
  813.         if (i == -1)
  814.             sprintf(buf, "cannot open %s's .month", new_name);
  815.         else
  816.             sprintf(buf, "cannot read %s's .month version %d",
  817.             new_name, i);
  818.         ccol = print_message(buf, BELL);
  819.         if ((i = read_schedule(month_dir, read_only)) == -2) {
  820.             more();
  821.             ccol = print_message(".month file locked", BELL);
  822.             i = read_schedule(month_dir, READ_ONLY);
  823.             if (i == 0)
  824.             read_only = 1;
  825.             }
  826.         if (i != 0) {
  827.             more();
  828.             if (i == -1)
  829.             ccol = print_message("cannot open .month", BELL);
  830.             else {
  831.             sprintf(buf, "cannot read .month version %d", i);
  832.             ccol = print_message(buf, BELL);
  833.             }
  834.         }
  835.         show_all_events(current_date.month, current_date.year);
  836.         pop_area();
  837.         return;
  838.         }
  839.  
  840.         keep_old = 1;
  841.         month_dir = new_dir;
  842.         my_file = (strcmp(home_dir, month_dir) == 0);
  843.         strcpy(name, new_name);
  844.         user_name = name;
  845.         print_screen();
  846.     } else
  847.         print_message("invalid user", BELL);
  848.     pop_area();
  849. }
  850.  
  851. get_string(name)
  852. char name[];
  853. {
  854.     short ch, first_col, i = 0;
  855.  
  856.     first_col = ccol;
  857.     crow = 0;
  858.     ch = get_char();
  859.  
  860.     for (;;) {
  861.         if (ch == '\n') {
  862.         name[i] = 0;
  863.         break;
  864.         } else if (ch > 0377) {
  865.         ;
  866.         } else if (ch == '\b') {
  867.         if (ccol > first_col) {
  868.             i--; ccol--;
  869.             mvaddch(0, ccol, ' ');
  870.             move(0, ccol);
  871.             refresh();
  872.         }
  873.         } else if (ch == '\025') {    /* ^U */
  874.         while (ccol > first_col) {
  875.             i--; ccol--;
  876.             mvaddch(0, ccol, ' ');
  877.             move(0, ccol);
  878.         }
  879.         refresh();
  880.         } else if (ch == '\033') {    /* ^[ */
  881.         return(0);
  882.         } else {
  883.         name[i++] = ch;
  884.         mvaddch(0, ccol++, ch);
  885.         refresh();
  886.         }
  887.         ch = get_char();
  888.     }
  889.     return(1);
  890. }
  891. #endif MULTIUSER
  892. @EOF
  893.  
  894. chmod 644 get.c
  895.  
  896. echo x - hl.c
  897. cat >hl.c <<'@EOF'
  898. #ifndef lint
  899. static char rcsid[] = "$Header: hl.c,v 8.2 87/11/13 21:46:46 hull Exp $";
  900. #endif
  901.  
  902. #include <curses.h>
  903. #include "month.h"
  904.  
  905. extern short all_flag;
  906. extern char *month_names[];
  907. extern struct date_rec current_date, todays_date;
  908.  
  909. hl_month(month, mflag)
  910. short month, mflag;
  911. {
  912.     if (mflag == HL_ON)
  913.         attron(A_REVERSE);
  914.     mvaddstr(MONTH_ROW + month - 1, 0, month_names[month - 1]);
  915.     if (mflag == HL_ON)
  916.         attroff(A_REVERSE);
  917. }
  918.  
  919. hl_day(day, dflag)
  920. short day, dflag;
  921. {
  922.     short row, col;
  923.  
  924.     get_row_col_from_day(&row, &col, day);
  925.  
  926.     if (dflag == HL_ON)
  927.         attron(A_REVERSE);
  928.  
  929.     if (current_date.month == todays_date.month &&
  930.         day == todays_date.day &&
  931.         current_date.year == todays_date.year)
  932.         attron(A_UNDERLINE);
  933.  
  934.     if (all_flag && is_event_today())
  935.         mvprintw(row, col, "(%2d)", day);
  936.     else
  937.         mvprintw(row, col, " %2d ", day);
  938.  
  939.     attroff(A_REVERSE | A_UNDERLINE);
  940. }
  941.  
  942. hl_year(year, yflag)
  943. short year, yflag;
  944. /* assumes year is currently displayed in year area */
  945. {
  946.     if (yflag == HL_ON)
  947.         attron(A_REVERSE);
  948.     move(YEAR_ROW, YEAR_COL + (6 * (year % 10)));
  949.     printw(" %4d ", year);
  950.     if (yflag == HL_ON)
  951.         attroff(A_REVERSE);
  952. }
  953.  
  954. hl_schedule(col, hflag)
  955. register col, hflag;
  956. {
  957.     register int ch;
  958.     short i;
  959.  
  960.     move(SCHEDULE_ROW, col);
  961.  
  962.     if (hflag)
  963.         attron(A_BOLD);
  964.  
  965.     if (col < SMTWTFS_COL) {
  966.         while((ch = (inch() & A_CHARTEXT)) != ' ') {
  967.             move(SCHEDULE_ROW, col);
  968.             addch(ch & A_CHARTEXT);
  969.             col++;
  970.         }
  971.     } else if (col > SMTWTFS_COL+12) {
  972.         move(SCHEDULE_ROW, col);
  973.  
  974.         for (i = 0; i < 10; i++) {
  975.             addch((char) (inch() & A_CHARTEXT));
  976.         }
  977.     } else {
  978.         move(SCHEDULE_ROW, col);
  979.  
  980.         for (i = 0; i < 2; i++) {
  981.             addch((char) (inch() & A_CHARTEXT));
  982.         }
  983.     }
  984.     attroff(A_BOLD);
  985. }
  986.  
  987. hl_all(event, pf, af, mf, yf, ef, nf, lf, uf, xf)
  988. struct event_rec *event;
  989. register pf, af, mf, yf, ef, nf, lf, uf, xf;
  990. {
  991.     short i;
  992.  
  993.     toggle_char(&(event->private), pf, PRIVATE_COL);
  994.     toggle_char(&(event->anti), af, ANTI_COL);
  995.     toggle_char(&(event->monthly), mf, MONTHLY_COL);
  996.     toggle_char(&(event->yearly), yf, YEARLY_COL);
  997.     toggle_char(&(event->every), ef, EVERY_COL);
  998.     toggle_char(&(event->nth_is_on), nf, NTH_COL);
  999.     toggle_char(&(event->last), lf, LAST_COL);
  1000.     toggle_char(&(event->until), uf, UMONTH_COL);
  1001.  
  1002.     if (xf != -1) {
  1003.         for (i = 0; i < 7; i++) {
  1004.             toggle_char(&(event->smtwtfs[i]), xf,
  1005.                 (SMTWTFS_COL+(2*i)));
  1006.         }
  1007.     }
  1008. }
  1009.  
  1010. toggle_char(c, f, col)
  1011. char *c;
  1012. register f, col;
  1013. {
  1014.     if (f == 1) {
  1015.         if (!(*c)) {
  1016.             *c = 1;
  1017.             hl_schedule(col, f);
  1018.         }
  1019.     } else if (f == 0) {
  1020.         if (*c) {
  1021.             *c = 0;
  1022.             hl_schedule(col, f);
  1023.         }
  1024.     }
  1025. }
  1026. @EOF
  1027.  
  1028. chmod 644 hl.c
  1029.  
  1030. echo x - lunar.c
  1031. cat >lunar.c <<'@EOF'
  1032. #ifndef lint
  1033. static char rcsid[] = "$Header: lunar.c,v 8.2 87/11/13 21:46:58 hull Exp $";
  1034. #endif
  1035.  
  1036. #include <curses.h>
  1037. #include <math.h>
  1038. #include <sys/types.h>
  1039.  
  1040. /* Globals. */
  1041. double         Fraction;
  1042.  
  1043. #define CENTER        ((COLS - 2 * LINES) / 2)
  1044. #define BRIGHT        '@'
  1045. #define LEDGE        '('
  1046. #define REDGE        ')'
  1047. #define FULL        0.5
  1048. #define TwoPi        (2 * 3.14159)
  1049. #define ZERO        0.03
  1050.  
  1051. long
  1052. calculate(julian, yr, hour, minute)
  1053. long julian, yr, hour, minute;
  1054. {
  1055.     register long     Length;
  1056.     register long     Phase;
  1057.     register long     Delta;
  1058.     register long     offset;
  1059.  
  1060.     yr -= 78;
  1061.     Length    = (double)2551 / 60 * 1000 + (double)443 / 60;
  1062.     offset    = ((yr * 365L + julian) * 24L + hour) * 60L + minute;
  1063.     Delta    = offset - (273L * 24L + 13L) * 60L + 23L;
  1064.     Phase    = Delta - (Delta / Length) * Length;
  1065.  
  1066.     Fraction    = (double)Phase / Length;
  1067.     return(Phase);
  1068. }
  1069.  
  1070. int
  1071. charpos(x)
  1072.     double        x;
  1073. {
  1074.     register int    i;
  1075.  
  1076.     i = x * LINES + 0.5;
  1077.     if ((i += LINES + CENTER) < 1)
  1078.     i = 1;
  1079.     return(i);
  1080. }
  1081.  
  1082.  
  1083. draw()
  1084. {
  1085.     register char    *p;
  1086.     register int     i;
  1087.     register int     end;
  1088.     register double     y;
  1089.     register double     cht;
  1090.     register double     squisher;
  1091.     register double     horizon;
  1092.     register double     terminator;
  1093.     char         Buffer[256];
  1094.     int line = 1;
  1095.  
  1096.     /* clear screen */
  1097.     clear();
  1098.  
  1099.     if (Fraction < FULL)
  1100.         squisher = cos(TwoPi * Fraction);
  1101.     else
  1102.         squisher = cos(TwoPi * (Fraction - FULL));
  1103.  
  1104.     cht = (double)2.0 / (LINES - 6.0);
  1105.     for (y = 0.93; y > -1.0; y -= cht) {
  1106.         for (i = sizeof Buffer, p = Buffer; --i >= 0; )
  1107.         *p++ = ' ';
  1108.         horizon = sqrt(1.0 - y * y);
  1109.         Buffer[    charpos(-horizon)]    = LEDGE;
  1110.         Buffer[i = charpos( horizon)]    = REDGE;
  1111.         Buffer[++i]            = '\0';
  1112.         terminator = horizon * squisher;
  1113.         if (Fraction > ZERO && Fraction < (1.0 - ZERO)) {
  1114.         if (Fraction < FULL) {
  1115.             i   = charpos( terminator);
  1116.             end = charpos( horizon);
  1117.         } else {
  1118.             i   = charpos(-horizon);
  1119.             end = charpos( terminator);
  1120.         }
  1121.         while (i <= end)
  1122.             Buffer[i++] = BRIGHT;
  1123.         }
  1124.         mvaddstr(line++, 1, Buffer);
  1125.     }
  1126. }
  1127. @EOF
  1128.  
  1129. chmod 644 lunar.c
  1130.  
  1131. echo x - month.c
  1132. cat >month.c <<'@EOF'
  1133. #ifndef lint
  1134. static char rcsid[] = "$Header: month.c,v 8.6 88/04/04 10:00:35 hull Exp $";
  1135. #endif
  1136.  
  1137. /***********************************************************
  1138.  *  Month - Visual Monthly Calendar and Time/Event Browser
  1139.  *
  1140.  *  Original Author: Tim Stoehn (zeus!tims)
  1141.  *  "Book code" originally written by Scott Turner (srt@ucla-cs.ARPA)
  1142.  *  Subsequent Modifications: Jim Hull (hull@hpda) and
  1143.  *                            Michael Morrell (morrell@hpda)
  1144.  *
  1145.  *
  1146.  ***********************************************************/
  1147.  
  1148. #include <curses.h>
  1149. #include <signal.h>
  1150. #if SYS5
  1151. #include <string.h>
  1152. #else
  1153. #include <strings.h>
  1154. #endif
  1155. #include <sys/types.h>
  1156. #if FCNTL
  1157. #include <fcntl.h>
  1158. #else
  1159. #include <sys/file.h>
  1160. #endif
  1161. #include <pwd.h>
  1162. #include <ctype.h>
  1163. #include "month.h"
  1164.  
  1165. short initialized = 0;
  1166. short date_flag = 0;
  1167. short my_file = 1;
  1168. short all_flag = 0;
  1169. short ins_mode = 0;
  1170. short keep_old = 0;
  1171. short over_flag = 0;
  1172. short read_only = READ_WRITE;
  1173. short ver_flag = 0;
  1174. short book = 0;
  1175. short daemon = 0;
  1176. short dint = 15;
  1177. short dhour, dminute, dsecond;
  1178. short delchar, kilchar;
  1179. short days;
  1180. short month_start;
  1181. short event_status = NOTHING;
  1182. short crow, ccol;
  1183. short area_ptr = 0;
  1184. char time_mode = END_MODE;
  1185. char *home_dir = NULL;
  1186. char *month_dir = NULL;
  1187. char *user_name = NULL;
  1188. char *prog_name;
  1189. int user_id;
  1190. struct date_rec current_date, todays_date;
  1191. struct date_rec mdates[NUM_MARKS];
  1192. struct area_rec areas[MAXAREAS];
  1193. struct event_rec events = {{0, 0, 0}, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0},
  1194. 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0, 0, 0, 0, 0, {0, 0, 0}, 0};
  1195.  
  1196. extern short update_schedule, updating;
  1197. extern struct event_rec events, current_event;
  1198. extern struct passwd *getpwnam();
  1199. extern char *get_home_dir();
  1200. extern alarm_t alarm();
  1201. extern unsigned short getuid();
  1202.  
  1203. main(argc, argv)
  1204. int argc;
  1205. char *argv[];
  1206. {
  1207.     prog_name = argv[0];
  1208.     user_id = (int) getuid();
  1209.     home_dir = get_home_dir(user_id);
  1210.     if (get_todays_date() != 0) {
  1211.         printf("%s: Cannot get today's date\n", prog_name);
  1212.         exit(1);
  1213.     }
  1214.     check_env();
  1215.     check_args(argc, argv);
  1216.     initialize();
  1217.     print_screen();
  1218.     (void) user();
  1219.     terminate();
  1220.     /* NOTREACHED */
  1221. }
  1222.  
  1223. initialize()
  1224. {
  1225.     int blast_out(), new_day(), /* stop(), */ i;
  1226. #ifndef killchar
  1227.     char killchar(), erasechar();
  1228. #endif
  1229.  
  1230.     signal(SIGINT, blast_out);
  1231.     signal(SIGQUIT, blast_out);
  1232.     signal(SIGHUP, terminate);
  1233.     signal(SIGALRM, new_day);
  1234. /*
  1235. #ifdef SIGTSTP
  1236.     signal(SIGTSTP, stop);
  1237. #endif
  1238. */
  1239.     if (!date_flag) {
  1240.         current_date.month = todays_date.month;
  1241.         current_date.day = todays_date.day;
  1242.         current_date.year = todays_date.year;
  1243.     }
  1244.  
  1245.     month_start = get_month_start(current_date.month, current_date.year);
  1246.     days = days_in(current_date.month, current_date.year);
  1247.     push_area(DAYS);
  1248.  
  1249.     for (i = 0; i < NUM_MARKS; i++) {
  1250.         mdates[i].month = current_date.month;
  1251.         mdates[i].day = current_date.day;
  1252.         mdates[i].year = current_date.year;
  1253.     }
  1254.  
  1255.     current_event.until_date.month = current_date.month;
  1256.     current_event.until_date.day = current_date.day;
  1257.     current_event.until_date.year = current_date.year;
  1258.  
  1259.     if ((i = read_schedule(month_dir, read_only)) == -2) {
  1260.         printf("%s: .month file locked\n", prog_name);
  1261.         sound_bell();
  1262.         read_only = READ_ONLY;
  1263.         i = read_schedule(month_dir, read_only);
  1264.     }
  1265.  
  1266.     if (i == -1) {
  1267.         printf("%s: Cannot open .month\n", prog_name);
  1268.         sound_bell();
  1269.         terminate();
  1270.     } else if (i > 0) {
  1271.         printf("%s: Cannot read .month version %d\n", prog_name, i);
  1272.         sound_bell();
  1273.         terminate();
  1274.     }
  1275.     
  1276.     initscr();
  1277.     crmode();
  1278.     noecho();
  1279. #if SYS5CURSES
  1280.     keypad(stdscr, TRUE);
  1281. #endif
  1282.     kilchar = (short) killchar();
  1283.     delchar = (short) erasechar();
  1284.     /* alarm call below should pop at midnight -- extra 2 seconds will
  1285.      * guarantee that it's really tomorrow.
  1286.      */
  1287.     alarm((alarm_t) 86402 - (dhour * 3600 + dminute * 60 + dsecond));
  1288.     /* for testing -- wake up every minute */
  1289.     /*
  1290.     alarm((alarm_t) 62 - dsecond);
  1291.     */
  1292.     initialized = 1;
  1293. }
  1294.  
  1295. new_day()
  1296. {
  1297.     if (get_todays_date() != 0) {
  1298.         printf("%s: Cannot get today's date\n", prog_name);
  1299.         exit(1);
  1300.     }
  1301.     /*
  1302.     fprintf(stderr, "new_day: %d/%d/%d %d:%02d:%02d current_area=%c\n",
  1303.         todays_date.month, todays_date.day, todays_date.year,
  1304.         dhour, dminute, dsecond, (char) current_area);
  1305.     */
  1306.     switch(current_area) {
  1307.     case MONTHS:
  1308.     case DAYS:
  1309.     case YEARS:
  1310.     case SCAN:
  1311.     case SCHED_SCAN:
  1312.     case SCHEDULE:
  1313.         show_all_events(current_date.month, current_date.year);
  1314.         move(crow, ccol);
  1315.         refresh();
  1316.         break;
  1317.     }
  1318.     /* reset alarm for midnight tomorrow (plus 2 seconds) */
  1319.     signal(SIGALRM, new_day);
  1320.     alarm((alarm_t) 86402 - (dhour * 3600 + dminute * 60 + dsecond));
  1321.     /* for testing -- wake up every minute */
  1322.     /*
  1323.     alarm((alarm_t) 62 - dsecond);
  1324.     */
  1325. }
  1326.  
  1327. terminate()
  1328. {
  1329.     if (updating)
  1330.         return;
  1331.  
  1332.     signal(SIGINT, SIG_IGN);
  1333. #ifdef SIGTSTP
  1334.     signal(SIGTSTP, SIG_IGN);
  1335. #endif
  1336. #ifdef SIGTTOU
  1337.     signal(SIGTTOU, SIG_IGN);
  1338. #endif
  1339.     signal(SIGQUIT, SIG_IGN);
  1340.     signal(SIGHUP, SIG_IGN);
  1341.     alarm((alarm_t) 0);
  1342.  
  1343.     if (initialized) {
  1344.         if (update_schedule)
  1345.         ccol = print_message("updating schedule", NO_BELL);
  1346.         else
  1347.         ccol = print_message("schedule unchanged", NO_BELL);
  1348.  
  1349.         if (!read_only && write_schedule() < 0) {
  1350.         more();
  1351.         ccol = print_message("cannot write .month", BELL);
  1352.         }
  1353.         move(LINES-1, 0);
  1354.         clrtoeol();
  1355.         refresh();
  1356.         endwin();
  1357.     }
  1358.  
  1359.     exit(0);
  1360.     /* NOTREACHED */
  1361. }
  1362.  
  1363. blast_out()
  1364. {
  1365.     update_schedule = 0;
  1366.     terminate();
  1367. }
  1368.  
  1369. /*
  1370. #ifdef SIGTSTP
  1371. stop()
  1372. {
  1373.     signal(SIGTSTP, SIG_DFL);
  1374.     signal(SIGINT, SIG_DFL);
  1375.     move(23,0);
  1376.     refresh();
  1377.     resetterm();
  1378.     kill(0, SIGTSTP);
  1379.     fixterm();
  1380.     signal(SIGINT, blast_out);
  1381.     signal(SIGTSTP, stop);
  1382.     clearok(curscr, TRUE);
  1383.     refresh();
  1384. }
  1385. #endif
  1386. */
  1387.  
  1388. get_date_arg(arg)
  1389. char *arg;
  1390. {
  1391.     short month, day, year;
  1392.     int ret;
  1393.     void convert_year();
  1394.  
  1395.     if (date_flag || daemon)
  1396.         return(1);
  1397.  
  1398.     if ((ret = sscanf(arg, "%hd/%hd/%hd", &month, &day, &year)) == 3)
  1399.         convert_year(todays_date.year, &year);
  1400.     else if (ret == 2)
  1401.         year = todays_date.year;
  1402.     else
  1403.         return(1);
  1404.  
  1405.     if (year < FIRST_YEAR || year > LAST_YEAR ||
  1406.         month < 1 || month > 12 ||
  1407.         day < 1 || day > days_in(month, year))
  1408.         return(1);
  1409.  
  1410.     current_date.month = month;
  1411.     current_date.day = day;
  1412.     current_date.year = year;
  1413.     return(0);
  1414. }
  1415.  
  1416. #if MULTIUSER
  1417. char *
  1418. get_user_arg(arg)
  1419. char *arg;
  1420. {
  1421.     struct passwd *pw;
  1422.  
  1423.     if ((pw = getpwnam(arg)) == NULL)
  1424.         return(NULL);
  1425.     else
  1426.         return(strcpy(malloc((unsigned)strlen(pw->pw_dir)+1), pw->pw_dir));
  1427. }
  1428. #endif MULTIUSER
  1429.  
  1430. check_env()
  1431. {
  1432.     char *month_env;
  1433.  
  1434.     if ((month_env = getenv("MONTH")) != NULL)
  1435.         while (*month_env) {
  1436.         switch(*month_env) {
  1437.         case 't':
  1438.             if (*(month_env+1) == 'S' || *(month_env+1) == 'D' ||
  1439.                 *(month_env+1) == 'E')
  1440.                 time_mode = *(++month_env);
  1441.             else {
  1442.                 printf("%s: Bad environment flag -- %c%c\n",
  1443.                 prog_name, *month_env, *(month_env+1));
  1444.                 exit(1);
  1445.             }
  1446.             break;
  1447.         case 'A':
  1448.             all_flag = 1;
  1449.             break;
  1450.         case 'I':
  1451.             ins_mode = 1;
  1452.             break;
  1453.         case 'K':
  1454.             keep_old = 1;
  1455.             break;
  1456.         case 'O':
  1457.             over_flag = 1;
  1458.             break;
  1459.         case 'R':
  1460.             read_only = READ_ONLY;
  1461.             break;
  1462.         default:
  1463.             printf("%s: Bad environment flag -- %c\n",
  1464.                 prog_name, *month_env);
  1465.             exit(1);
  1466.         }
  1467.         month_env++;
  1468.         }
  1469. }
  1470.  
  1471. check_args(argc, argv)
  1472. int argc;
  1473. char *argv[];
  1474. {
  1475.     short i, j;
  1476.     extern float get_version();
  1477.  
  1478.     for (i = 1; i < argc; i++) {
  1479.         if (argv[i][0] == '-') {
  1480.         for (j = 1; j < strlen(argv[i]); j++) {
  1481.             switch(argv[i][j]) {
  1482.             case 'a':
  1483.             all_flag = 0;
  1484.             break;
  1485.             case 'i':
  1486.             ins_mode = 0;
  1487.             break;
  1488.             case 'k':
  1489.             keep_old = 0;
  1490.             break;
  1491.             case 'o':
  1492.             over_flag = 0;
  1493.             break;
  1494.             case 'r':
  1495.             read_only = READ_WRITE;
  1496.             break;
  1497.             case 'A':
  1498.             all_flag = 1;
  1499.             break;
  1500.             case 'I':
  1501.             ins_mode = 1;
  1502.             break;
  1503.             case 'K':
  1504.             keep_old = 1;
  1505.             break;
  1506.             case 'O':
  1507.             over_flag = 1;
  1508.             break;
  1509.             case 'R':
  1510.             read_only = READ_ONLY;
  1511.             break;
  1512.             case 'B':
  1513.             book = i;
  1514.             break;
  1515.             case 'V':
  1516.             ver_flag = i;
  1517.             break;
  1518.             case 'd':
  1519.             if (date_flag)
  1520.                 goto BA;
  1521.             daemon = i;
  1522.             break;
  1523.             case 't':
  1524.             if (argv[i][j+1] == 'S' || argv[i][j+1] == 'D' ||
  1525.                 argv[i][j+1] == 'E')
  1526.                 time_mode = argv[i][++j];
  1527.             else
  1528.                 goto BA;
  1529.             break;
  1530.             default:
  1531.             goto BA;
  1532.             }
  1533.             if (argv[i][j] == 'B' || argv[i][j] == 'V' ||
  1534.                argv[i][j] == 'd')
  1535.             break;
  1536.         }
  1537.         } else if (get_date_arg(argv[i]) == 0) {
  1538.         date_flag = 1;
  1539. #if MULTIUSER
  1540.         } else if ((month_dir = get_user_arg(argv[i])) != NULL) {
  1541.         my_file = 0;
  1542.         keep_old = 1;
  1543.         user_name = argv[i];
  1544.         } else {
  1545. BA:        printf("%s: Bad argument -- %s\n", prog_name, argv[i]);
  1546.         printf("Usage: %s [-AaIiKkOoRr] [-{tS|tD|tE}] [-Bn] [-V] [-dn] [m/d/y] [user]\n", prog_name);
  1547. #else
  1548.         } else {
  1549. BA:        printf("%s: Bad argument -- %s\n", prog_name, argv[i]);
  1550.         printf("Usage: %s [-AaIiKkOo] [-{tS|tD|tE}] [-Bn] [-V] [-dn] [m/d/y]\n", prog_name);
  1551. #endif MULTIUSER
  1552.         exit(1);
  1553.         }
  1554.     }
  1555.     if (month_dir == NULL)
  1556.         month_dir = home_dir;
  1557.     
  1558.     if (ver_flag)
  1559.         printf("month version %-3.3g\n\n", get_version());
  1560.  
  1561.     if (book)
  1562.         if (argv[book][2] == '\0') {
  1563.         if (print_book(1))
  1564.             printf("%s: Cannot print schedule\n", prog_name);
  1565.         } else
  1566.         if (print_book(atoi(&argv[book][2])))
  1567.             printf("%s: Cannot print schedule\n", prog_name);
  1568.  
  1569.     if (daemon) {
  1570.         if (isdigit(argv[daemon][2]) && (argv[daemon][2] > '0'))
  1571.         dint = atoi(&argv[daemon][2]);
  1572.  
  1573.         if (!fork()) {
  1574.         signal(SIGINT, SIG_IGN);
  1575.         signal(SIGQUIT, SIG_IGN);
  1576. #ifdef SIGTSTP
  1577.         signal(SIGTSTP, SIG_IGN);
  1578. #endif
  1579. #ifdef SIGTTOU
  1580.         signal(SIGTTOU, SIG_IGN);
  1581. #endif
  1582.         daemonize();
  1583.         }
  1584.     }
  1585.  
  1586.     if (ver_flag || book || daemon)
  1587.         exit(0);
  1588. }
  1589.  
  1590. daemonize()
  1591. {
  1592.     char arg1[16];
  1593.  
  1594.     printf("WARNING: The -d option of month has been superseded by the\n");
  1595.     printf("monthd program.  For now, month -d will automatically invoke\n");
  1596.     printf("monthd, but future versions of month will not support -d.\n");
  1597.     if (dint == 15) {
  1598.     printf("Invoking: monthd\n");
  1599.     fflush(stdout);
  1600.     execlp("monthd", "monthd", 0);
  1601.     } else {
  1602.     sprintf(arg1, "-i%d", dint);
  1603.     printf("Invoking: monthd %s\n", arg1);
  1604.     fflush(stdout);
  1605.     execlp("monthd", "monthd", arg1, 0);
  1606.     }
  1607.     /* NOTREACHED */
  1608. }
  1609.  
  1610. #if !SYS5CURSES
  1611. #ifndef killchar
  1612. #include <sgtty.h>
  1613. char
  1614. killchar()
  1615. {
  1616.     struct sgttyb arg;
  1617.  
  1618.     ioctl(0, TIOCGETP, &arg);
  1619.     return(arg.sg_kill);
  1620. }
  1621.  
  1622. char
  1623. erasechar()
  1624. {
  1625.     struct sgttyb arg;
  1626.  
  1627.     ioctl(0, TIOCGETP, &arg);
  1628.     return(arg.sg_erase);
  1629. }
  1630. #endif
  1631. #endif
  1632. @EOF
  1633.  
  1634. chmod 644 month.c
  1635.  
  1636. echo x - move.c
  1637. cat >move.c <<'@EOF'
  1638. #ifndef lint
  1639. static char rcsid[] = "$Header: move.c,v 8.3 88/04/04 10:47:39 hull Exp $";
  1640. #endif
  1641.  
  1642. #include "month.h"
  1643.  
  1644. extern char time_mode;
  1645. extern short area_ptr;
  1646. extern short crow, ccol, month_start, days;
  1647. extern struct date_rec current_date;
  1648. extern struct area_rec areas[];
  1649.  
  1650. goto_this_day(date)
  1651. struct date_rec *date;
  1652. {
  1653.     /* current_area assumed to be MONTHS, DAYS, or YEARS */
  1654.     current_date.month = date->month;
  1655.     current_date.day = date->day;
  1656.     current_date.year = date->year;
  1657.  
  1658.     show_all_events(current_date.month, current_date.year);
  1659.     print_all_months();
  1660.     print_all_years();
  1661.     goto_area();
  1662. }
  1663.  
  1664. pop_area()
  1665. {
  1666.     if (area_ptr <= 0) {
  1667.         printf("area stack underflow\n");
  1668.         blast_out();
  1669.     }
  1670.     if (--area_ptr > 0) {
  1671.         crow = areas[area_ptr].row;
  1672.         ccol = areas[area_ptr].col;
  1673.     }
  1674. }
  1675.  
  1676. push_area(area)
  1677. short area;
  1678. {
  1679.     if (area_ptr >= MAXAREAS) {
  1680.         printf("area stack overflow\n");
  1681.         blast_out();
  1682.     }
  1683.     areas[area_ptr].row = crow;
  1684.     areas[area_ptr].col = ccol;
  1685.     areas[area_ptr++].area = area;
  1686.     goto_area();
  1687. }
  1688.  
  1689. goto_area()
  1690. {
  1691.     switch(current_area) {
  1692.     case MONTHS:
  1693.         goto_month();
  1694.         break;
  1695.     case DAYS:
  1696.         goto_day();
  1697.         break;
  1698.     case YEARS:
  1699.         goto_year();
  1700.         break;
  1701.     case SCHEDULE:
  1702.         goto_schedule();
  1703.         break;
  1704.     case SCAN:
  1705.     case SCHED_SCAN:
  1706.         goto_scan();
  1707.         break;
  1708.     }
  1709. }
  1710.  
  1711. goto_month()
  1712. {
  1713.     crow = MONTH_ROW + current_date.month - 1;
  1714.     ccol = 9;
  1715. }
  1716.  
  1717. goto_day()
  1718. {
  1719.     get_row_col_from_day(&crow, &ccol, current_date.day);
  1720.     ccol += 2;
  1721. }
  1722.  
  1723. goto_year()
  1724. {
  1725.     /* assumes the current year is displayed in YEARS area */
  1726.     crow = YEAR_ROW;
  1727.     ccol = YEAR_COL + 4 + (6 * (current_date.year % 10));
  1728. }
  1729.  
  1730. goto_schedule()
  1731. {
  1732.     crow = SCHEDULE_ROW;
  1733.     ccol = PRIVATE_COL;
  1734. }
  1735.  
  1736. goto_scan()
  1737. {
  1738.     crow = 0;
  1739.     ccol = 0;
  1740. }
  1741.  
  1742. move_cursor(dir)
  1743. register short dir;
  1744. {
  1745.     switch(current_area) {
  1746.     case MONTHS:
  1747.         switch(dir) {
  1748.         case 'j':
  1749.             if (crow < MONTH_ROW + 11)
  1750.                 crow++;
  1751.             else
  1752.                 crow = MONTH_ROW;
  1753.             break;
  1754.         case 'k':
  1755.             if (crow > MONTH_ROW)
  1756.                 crow--;
  1757.             else
  1758.                 crow = MONTH_ROW + 11;
  1759.             break;
  1760.         }
  1761.         break;
  1762.     case YEARS:
  1763.         switch(dir) {
  1764.         case 'h':
  1765.             if (ccol == YEAR_COL + 4)
  1766.                 ccol = YEAR_COL + 58;
  1767.             else
  1768.                 ccol -= 6;
  1769.             break;
  1770.         case 'l':
  1771.             if (ccol == YEAR_COL + 58)
  1772.                 ccol = YEAR_COL + 4;
  1773.             else
  1774.                 ccol += 6;
  1775.             break;
  1776.         }
  1777.         break;
  1778.     case DAYS:
  1779.         switch(dir) {
  1780.         case 'h':
  1781.             ccol -= 10;
  1782.             if (get_day_from_row_col(crow, ccol) == 0)
  1783.                 ccol = CAL_COL + 62;
  1784.             while (get_day_from_row_col(crow, ccol) == 0)
  1785.                 ccol -= 10;
  1786.             break;
  1787.         case 'j':
  1788.             crow += 2;
  1789.             if (get_day_from_row_col(crow, ccol) == 0)
  1790.                 crow = CAL_ROW;
  1791.             while (get_day_from_row_col(crow, ccol) == 0)
  1792.                 crow += 2;
  1793.             break;
  1794.         case 'k':
  1795.             crow -= 2;
  1796.             if (get_day_from_row_col(crow, ccol) == 0)
  1797.                 crow = CAL_ROW + 10;
  1798.             while (get_day_from_row_col(crow, ccol) == 0)
  1799.                 crow -= 2;
  1800.             break;
  1801.         case 'l':
  1802.             ccol += 10;
  1803.             if (get_day_from_row_col(crow, ccol) == 0)
  1804.                 ccol = CAL_COL + 2;
  1805.             while (get_day_from_row_col(crow, ccol) == 0)
  1806.                 ccol += 10;
  1807.             break;
  1808.         }
  1809.         break;
  1810.     case SCHEDULE:
  1811.         schedule_move_cursor(dir);
  1812.         break;
  1813.     }
  1814. }
  1815.  
  1816. schedule_move_cursor(dir)
  1817. short dir;
  1818. {
  1819.     short inc, *cols;
  1820.     static short schedule_cols[] = {
  1821.         UYEAR_COL, SMONTH_COL, SDAY_COL, SYEAR_COL, PRIVATE_COL,
  1822.         ANTI_COL, MONTHLY_COL, YEARLY_COL, EVERY_COL, NTH_COL, LAST_COL,
  1823.         SMTWTFS_COL, SMTWTFS_COL+2, SMTWTFS_COL+4, SMTWTFS_COL+6,
  1824.         SMTWTFS_COL+8, SMTWTFS_COL+10, SMTWTFS_COL+12,
  1825.         UMONTH_COL, UDAY_COL, UYEAR_COL, SMONTH_COL
  1826.     };
  1827.     static short start_mode_cols[] = {
  1828.         WARNING_COL+3, DURATION_COL, DURATION_COL+3, END_COL, END_COL+3,
  1829.         WARNING_COL, WARNING_COL+3, DURATION_COL
  1830.     };
  1831.     static short duration_mode_cols[] = {
  1832.         WARNING_COL+3, START_COL, START_COL+3, END_COL, END_COL+3,
  1833.         WARNING_COL, WARNING_COL+3, START_COL
  1834.     };
  1835.     static short end_mode_cols[] = {
  1836.         WARNING_COL+3, START_COL, START_COL+3, DURATION_COL, DURATION_COL+3,
  1837.         WARNING_COL, WARNING_COL+3, START_COL
  1838.     };
  1839.  
  1840.     switch(dir) {
  1841.     case 'h':
  1842.     case 'l':
  1843.         inc = (dir == 'h') ? -1 : 1;
  1844.         if (crow == SCHEDULE_ROW) {
  1845.             cols = schedule_cols;
  1846.             while (*(++cols) != ccol) ;
  1847.             ccol = *(cols+inc);
  1848.         } else if (crow == TIME_ROW) {
  1849.             switch(time_mode) {
  1850.             case START_MODE:
  1851.                 cols = start_mode_cols;
  1852.                 break;
  1853.             case DURATION_MODE:
  1854.                 cols = duration_mode_cols;
  1855.                 break;
  1856.             case END_MODE:
  1857.                 cols = end_mode_cols;
  1858.                 break;
  1859.             }
  1860.             while (*(++cols) != ccol) ;
  1861.             ccol = *(cols+inc);
  1862.         }
  1863.         break;
  1864.     case '\n':
  1865.     case 'j':
  1866.         switch(crow) {
  1867.         case SCHEDULE_ROW:
  1868.             crow = TIME_ROW;
  1869.             switch(time_mode) {
  1870.             case START_MODE:
  1871.                 ccol = DURATION_COL;
  1872.                 break;
  1873.             default:
  1874.                 ccol = START_COL;
  1875.                 break;
  1876.             }
  1877.             break;
  1878.         case TIME_ROW:
  1879.             get_description();
  1880.             break;
  1881.         case DESCRIPTION_ROW:
  1882.             crow = SCHEDULE_ROW;
  1883.             ccol = PRIVATE_COL;
  1884.             break;
  1885.         }
  1886.         break;
  1887.     case 'k':
  1888.         switch(crow) {
  1889.         case SCHEDULE_ROW:
  1890.             get_description();
  1891.             break;
  1892.         case TIME_ROW:
  1893.             crow = SCHEDULE_ROW;
  1894.             ccol = PRIVATE_COL;
  1895.             break;
  1896.         case DESCRIPTION_ROW:
  1897.             crow = TIME_ROW;
  1898.             switch(time_mode) {
  1899.             case START_MODE:
  1900.                 ccol = DURATION_COL;
  1901.                 break;
  1902.             default:
  1903.                 ccol = START_COL;
  1904.                 break;
  1905.             }
  1906.             break;
  1907.         default:
  1908.             crow--;
  1909.             break;
  1910.         }
  1911.         break;
  1912.     case '\033':    /* ^[ */
  1913.         pop_area();
  1914.         break;
  1915.     }
  1916. }
  1917.  
  1918. get_row_col_from_day(row, col, day)
  1919. short *row, *col, day;
  1920. {
  1921.     *row = CAL_ROW + (((month_start + day - 1) / 7) * 2);
  1922.     *col = CAL_COL + (((month_start + day - 1) % 7) * 10);
  1923. }
  1924.  
  1925. get_day_from_row_col(row, col)
  1926. short row, col;
  1927. {
  1928.     short mday;
  1929.  
  1930.     if (row < CAL_ROW || row > CAL_ROW + 10 ||
  1931.         col < CAL_COL + 2 || col > CAL_COL + 62)
  1932.         return(0);
  1933.  
  1934.     mday = (7 * ((row - CAL_ROW)) / 2) +
  1935.            ((col - CAL_COL) / 10) - month_start + 1;
  1936.  
  1937.     if ((mday <= days) && (mday > 0))
  1938.         return(mday);
  1939.  
  1940.     return(0);
  1941. }
  1942. @EOF
  1943.  
  1944. chmod 644 move.c
  1945.  
  1946. exit 0
  1947.  
  1948.