home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume16 / month8.7 / part03 < prev    next >
Text File  |  1988-11-08  |  56KB  |  2,685 lines

  1. Subject:  v16i056:  A visual calendar and appointment system, Part03/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 56
  8. Archive-name: month8.7/part03
  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. #    print.c        schedule.c    time.c        user.c        
  14. #    user2.c        
  15. LANG=""; export LANG
  16.  
  17. echo x - print.c
  18. cat >print.c <<'@EOF'
  19. #ifndef lint
  20. static char rcsid[] = "$Header: print.c,v 8.3 88/04/04 10:43:07 hull Exp $";
  21. #endif
  22.  
  23. #include <curses.h>
  24. #include <pwd.h>
  25. #include "month.h"
  26.  
  27. char *grids[] = {
  28. "mid .  .  .  1a .  .  .  2a .  .  .  3a .  .  .  4a .  .  .  5a .  .  . 6a",
  29. "6a  .  .  .  7a .  .  .  8a .  .  .  9a .  .  . 10a .  .  . 11a .  .  . noon",
  30. "noon.  .  .  1p .  .  .  2p .  .  .  3p .  .  .  4p .  .  .  5p .  .  . 6p",
  31. "6p  .  .  .  7p .  .  .  8p .  .  .  9p .  .  . 10p .  .  . 11p .  .  . mid"
  32. };
  33.  
  34. char *month_names[] = {
  35.     "JANUARY",
  36.     "FEBRUARY",
  37.     "MARCH",
  38.     "APRIL",
  39.     "MAY",
  40.     "JUNE",
  41.     "JULY",
  42.     "AUGUST",
  43.     "SEPTEMBER",
  44.     "OCTOBER",
  45.     "NOVEMBER",
  46.     "DECEMBER"
  47. };
  48.  
  49. char *smtwtfs_names[] = {
  50.     "Su",
  51.     "Mo",
  52.     "Tu",
  53.     "We",
  54.     "Th",
  55.     "Fr",
  56.     "Sa",
  57. };
  58.  
  59. extern short month_start, days;
  60. extern short all_flag, over_flag, date_flag, ins_mode, keep_old, read_only;
  61. extern short crow, ccol, area_ptr;
  62. extern struct event_rec current_event;
  63. extern struct date_rec current_date, todays_date;
  64. extern struct area_rec areas[];
  65. extern char time_mode, *month_dir, *user_name;
  66.  
  67. print_screen()
  68. {
  69.     print_day_headers();
  70.     show_all_events(current_date.month, current_date.year);
  71.     print_border();
  72.     print_all_months();
  73.     print_all_years();
  74.     print_user();
  75.     print_flags();
  76.     print_overview();
  77. }
  78.  
  79. print_day_headers()
  80. {
  81.     static char *days_of_week =
  82.     "Sunday    Monday   Tuesday  Wednesday  Thursday   Friday  Saturday";
  83.  
  84.     mvaddstr(DAY_ROW, DAY_COL, days_of_week);
  85. }
  86.  
  87. print_border()
  88. {
  89.     short row;
  90.     static char *border =
  91.     "+------------------------------------------------------------------+";
  92.  
  93.     mvaddstr(DAY_ROW + 1, CAL_COL - 2, border);
  94.  
  95.     for (row = DAY_ROW + 2; row < YEAR_ROW - 1; row++) {
  96.         mvaddch(row, CAL_COL - 2, '|');
  97.         mvaddch(row, CAL_COL + 65, '|');
  98.     }
  99.  
  100.     mvaddstr(YEAR_ROW - 1, CAL_COL - 2, border);
  101. }
  102.  
  103. print_cal(month, year, all_events_list)
  104. register month, year;
  105. char *all_events_list;
  106. {
  107.     short i, month_is_current, cday;
  108.     short row = CAL_ROW, col = CAL_COL;
  109.  
  110.     if (current_date.day > days)
  111.         current_date.day = days;
  112.     else if (current_date.day < 1)
  113.         current_date.day = 1;
  114.  
  115.     month_is_current = ((month == todays_date.month) &&
  116.         (year == todays_date.year));
  117.  
  118.     for (i = 1, cday = 1; i <= 42; i++) {
  119.         if ((cday <= days) && (i >= (month_start + 1))) {
  120.             if (month_is_current && (cday == todays_date.day))
  121.                 attron(A_UNDERLINE);
  122.  
  123.             if (all_events_list && all_events_list[cday])
  124.                 mvprintw(row, col, "(%2d)", cday);
  125.             else
  126.                 mvprintw(row, col, " %2d ", cday);
  127.  
  128.             attroff(A_UNDERLINE);
  129.             cday++;
  130.         } else
  131.             mvprintw(row, col, "    ");
  132.  
  133.         if ((i % 7) == 0) {
  134.             row += 2;
  135.             col = CAL_COL;
  136.         } else
  137.             col += 10;
  138.     }
  139.     hl_day(current_date.day, HL_ON);
  140. }
  141.  
  142. print_all_months()
  143. {
  144.     short i;
  145.  
  146.     for (i = 0; i <= 11; i++)
  147.         mvaddstr(MONTH_ROW + i, 0, month_names[i]);
  148.     hl_month(current_date.month, HL_ON);
  149. }
  150.  
  151. print_all_years()
  152. {
  153.     int ret = 1;
  154.     short first_year, i;
  155.  
  156.     if (current_date.year < FIRST_YEAR) {
  157.         current_date.month = 1;
  158.         current_date.day = 1;
  159.         current_date.year = FIRST_YEAR;
  160.         ret = 0;
  161.     } else if (current_date.year > LAST_YEAR) {
  162.         current_date.month = 12;
  163.         current_date.day = 31;
  164.         current_date.year = LAST_YEAR;
  165.         ret = 0;
  166.     }
  167.  
  168.     first_year = current_date.year - (current_date.year % 10);
  169.  
  170.     move(YEAR_ROW, YEAR_COL);
  171.     for (i = first_year; i < (first_year + 10); i++)
  172.         printw(" %4d ", i);
  173.     hl_year(current_date.year, HL_ON);
  174.     return(ret);
  175. }
  176.  
  177. print_flags()
  178. {
  179.     if (all_flag)
  180.         attron(A_BOLD);
  181.     mvaddstr(0, FLAG_COL, "A");
  182.     if (ins_mode)
  183.         attron(A_BOLD);
  184.     else
  185.         attroff(A_BOLD);
  186.     mvaddstr(0, FLAG_COL+2, "I");
  187.     if (keep_old)
  188.         attron(A_BOLD);
  189.     else
  190.         attroff(A_BOLD);
  191.     mvaddstr(0, FLAG_COL+4, "K");
  192.     if (over_flag)
  193.         attron(A_BOLD);
  194.     else
  195.         attroff(A_BOLD);
  196.     mvaddstr(0, FLAG_COL+6, "O");
  197. #if MULTIUSER
  198.     if (read_only)
  199.         attron(A_BOLD);
  200.     else
  201.         attroff(A_BOLD);
  202.     mvaddstr(0, FLAG_COL+8, "R");
  203. #endif MULTIUSER
  204.     attroff(A_BOLD);
  205. }
  206.  
  207. print_user()
  208. {
  209.     if (user_name != NULL) {
  210.         mvprintw(0, USER_COL, "%*s", FLAG_COL - USER_COL, " ");
  211.         mvaddstr(0, USER_COL, "User: ");
  212.         attron(A_UNDERLINE);
  213.         addstr(user_name);
  214.         attroff(A_UNDERLINE);
  215.     }
  216. }
  217.  
  218. print_version()
  219. {
  220.     char ver_string[BUFSIZE];
  221.     extern float get_version();
  222.  
  223.     sprintf(ver_string, "version %-3.3g", get_version());
  224.     print_message(ver_string, NO_BELL);
  225. }
  226.  
  227. print_event_regularity(event)
  228. struct event_rec *event;
  229. {
  230.     if (event->monthly)
  231.         attron(A_BOLD);
  232.     mvaddstr(SCHEDULE_ROW, MONTHLY_COL, "monthly");
  233.     attroff(A_BOLD);
  234.     if (event->yearly)
  235.         attron(A_BOLD);
  236.     mvaddstr(SCHEDULE_ROW, YEARLY_COL, "yearly");
  237.     attroff(A_BOLD);
  238.     if (event->every)
  239.         attron(A_BOLD);
  240.     mvaddstr(SCHEDULE_ROW, EVERY_COL, "every");
  241.     attroff(A_BOLD);
  242.     print_smtwtfs(event->smtwtfs);
  243.     print_nth(event);
  244.     if (event->last)
  245.         attron(A_BOLD);
  246.     mvaddstr(SCHEDULE_ROW, LAST_COL, "last");
  247.     attroff(A_BOLD);
  248.     print_until(event);
  249. }
  250.  
  251. print_smtwtfs(smtwtfs)
  252. char smtwtfs[];
  253. {
  254.     short i;
  255.  
  256.     move(SCHEDULE_ROW, SMTWTFS_COL);
  257.  
  258.     for (i = 0; i < 7; i++) {
  259.         if (smtwtfs[i])
  260.             attron(A_BOLD);
  261.         addstr(smtwtfs_names[i]);
  262.         if (smtwtfs[i])
  263.             attroff(A_BOLD);
  264.     }
  265. }
  266.  
  267. print_event(event)
  268. struct event_rec *event;
  269. {
  270.     clear_schedule_area();
  271.     print_date(event);
  272.     print_event_regularity(event);
  273.     print_event_private(event);
  274.     print_event_anti(event);
  275.     print_times(event);
  276.     print_warning(event);
  277.     print_event_description(event);
  278.     print_owner(event);
  279. }
  280.  
  281. print_event_private(event)
  282. struct event_rec *event;
  283. {
  284.     if (event->private)
  285.         attron(A_BOLD);
  286.     mvaddstr(SCHEDULE_ROW, PRIVATE_COL, "priv");
  287.     attroff(A_BOLD);
  288. }
  289.  
  290. print_event_anti(event)
  291. struct event_rec *event;
  292. {
  293.     if (event->anti)
  294.         attron(A_BOLD);
  295.     mvaddstr(SCHEDULE_ROW, ANTI_COL, "anti");
  296.     attroff(A_BOLD);
  297. }
  298.  
  299. print_times(event)
  300. struct event_rec *event;
  301. {
  302.     short hour;
  303.     char *apm;
  304.  
  305.     hour = event->start_time.hour;
  306.     apm = (hour < 12) ? "am" : "pm";
  307.     hour = ((hour + 11) % 12) + 1;
  308.  
  309.     mvaddstr(TIME_ROW-1, START_COL, "start time");
  310.     if (time_mode == START_MODE)
  311.         attron(A_UNDERLINE);
  312.     mvprintw(TIME_ROW, START_COL, "%2d:%02d %s", hour,
  313.         event->start_time.minute, apm);
  314.  
  315.     attroff(A_UNDERLINE);
  316.     mvaddstr(TIME_ROW-1, DURATION_COL, "duration");
  317.     if (time_mode == DURATION_MODE)
  318.         attron(A_UNDERLINE);
  319.     mvprintw(TIME_ROW, DURATION_COL, "%2d:%02d", event->duration.hour,
  320.         event->duration.minute);
  321.  
  322.     hour = event->end_time.hour;
  323.     apm = (hour < 12) ? "am" : "pm";
  324.     hour = ((hour + 11) % 12) + 1;
  325.  
  326.     attroff(A_UNDERLINE);
  327.     mvaddstr(TIME_ROW-1, END_COL, "end time");
  328.     if (time_mode == END_MODE)
  329.         attron(A_UNDERLINE);
  330.     mvprintw(TIME_ROW, END_COL, "%2d:%02d %s", hour,
  331.         event->end_time.minute, apm);
  332.     attroff(A_UNDERLINE);
  333. }
  334.  
  335. print_warning(event)
  336. struct event_rec *event;
  337. {
  338.     mvaddstr(TIME_ROW-1, WARNING_COL, "warning");
  339.     mvprintw(TIME_ROW, WARNING_COL, "%2d:%02d", event->warning.hour,
  340.         event->warning.minute);
  341. }
  342.  
  343. print_event_description(event)
  344. struct event_rec *event;
  345. {
  346.     mvprintw(DESCRIPTION_ROW, DESCRIPTION_COL-7, "event: %s",
  347.         event->event_string);
  348. }
  349.  
  350. print_owner(event)
  351. struct event_rec *event;
  352. {
  353.     struct passwd *pw, *getpwuid();
  354.  
  355.     mvaddstr(OWNER_ROW-1, OWNER_COL, "owner");
  356.     attron(A_UNDERLINE);
  357.  
  358.     if ((pw = getpwuid(event->event_owner)) != NULL)
  359.         mvprintw(OWNER_ROW, OWNER_COL, "%s", pw->pw_name);
  360.     else
  361.         mvprintw(OWNER_ROW, OWNER_COL, "%d", event->event_owner);
  362.  
  363.     attroff(A_UNDERLINE);
  364. }
  365.  
  366. print_until(event)
  367. struct event_rec *event;
  368. {
  369.     if (event->until) {
  370.         attron(A_BOLD);
  371.     }
  372.     mvprintw(SCHEDULE_ROW, UMONTH_COL, "%2d/%2d/%4d",
  373.         event->until_date.month, event->until_date.day,
  374.         event->until_date.year);
  375.     attroff(A_BOLD);
  376. }
  377.  
  378. print_date(event)
  379. struct event_rec *event;
  380. {
  381.     attron(A_BOLD);
  382.     mvprintw(SCHEDULE_ROW, SMONTH_COL, "%2d/%2d/%4d",
  383.         event->start_date.month, event->start_date.day,
  384.         event->start_date.year);
  385.     attroff(A_BOLD);
  386. }
  387.  
  388. print_message(str, sound)
  389. char *str;
  390. int sound;
  391. {
  392.     int strlen();
  393.  
  394.     clear_message_line();
  395.     standout();
  396.     mvaddstr(0, 0, str);
  397.     standend();
  398.     refresh();
  399.     if (sound) {
  400.         sound_bell();
  401.     }
  402.     return(strlen(str));
  403. }
  404.  
  405. print_nth(event)
  406. struct event_rec *event;
  407. {
  408.     char *ns;
  409.     short n;
  410.  
  411.     if (event->nth_is_on) {
  412.         attron(A_BOLD);
  413.     }
  414.     n = event->nth;
  415.     if (event->nth > 13) {
  416.         n %= 10;
  417.     }
  418.  
  419.     switch(n) {
  420.     case 0:
  421.     case 4:
  422.     case 5:
  423.     case 6:
  424.     case 7:
  425.     case 8:
  426.     case 9:
  427.     case 10:
  428.     case 11:
  429.     case 12:
  430.     case 13:
  431.         ns = "th";
  432.         break;
  433.     case 1:
  434.         ns = "st";
  435.         break;
  436.     case 2:
  437.         ns = "nd";
  438.         break;
  439.  
  440.     case 3:
  441.         ns = "rd";
  442.         break;
  443.     }
  444.     mvprintw(SCHEDULE_ROW, NTH_COL, "%02d%s", event->nth, ns);
  445.     attroff(A_BOLD);
  446. }
  447.  
  448. print_overview()
  449. {
  450.     short i, row, col, hour, minute, duration, n;
  451.     struct eptr_rec *ep, *events_today;
  452.     char *grid;
  453.  
  454.     clear_schedule_area();
  455.  
  456.     if (!over_flag) return;
  457.  
  458.     (void) get_daily_events(&events_today);
  459.  
  460.     for (i = 0; i < 4; i++)
  461.         mvaddstr((SCHEDULE_ROW + i + i), 0, grids[i]);
  462.  
  463.     attron(A_REVERSE);
  464.  
  465.     ep = events_today;
  466.     while (ep) {
  467.         hour = ep->event->start_time.hour;
  468.         minute = ep->event->start_time.minute;
  469.  
  470.         row = SCHEDULE_ROW + ((hour / 6) * 2);
  471.  
  472.         duration = (ep->event->duration.hour * 60) +
  473.             ep->event->duration.minute;
  474.         col = (12 * (hour % 6)) + (3 * (minute / 15));
  475.         n = hour / 6;
  476.         grid = grids[n];
  477.         duration /= 15;
  478.  
  479.         move(row, col);
  480.  
  481.         for (i = 0; i < duration; i++) {
  482.             addch(grid[col]);
  483.             addch(grid[col + 1]);
  484.             addch(grid[col + 2]);
  485.  
  486.             col += 3;
  487.             if (col > 71 && i < (duration - 1)) {
  488.                 while(grid[col])
  489.                     addch(grid[col++]);
  490.                 col = 0;
  491.                 row += 2;
  492.  
  493.                 if (row > (SCHEDULE_ROW + 6))
  494.                     break;
  495.                 move(row, col);
  496.                 grid = grids[++n];
  497.             }
  498.         }
  499.         ep = ep->next_event;
  500.     }
  501.     attroff(A_REVERSE);
  502. }
  503.  
  504. print_sched()
  505. {
  506.     short shour, sminute, ehour, eminute, n;
  507.     struct eptr_rec *ep, *events_today;
  508.  
  509.     if ((n = get_daily_events(&events_today)) <= 0) {
  510.         print_message("no events this day", BELL);
  511.         return;
  512.     }
  513.     sort_events(events_today, n);
  514.  
  515.     push_area(BOOK);
  516.     clear();
  517.     move(0,0);
  518.     printw("%s  %d/%d/%d\n",
  519.         smtwtfs_names[(current_date.day+month_start-1) % 7],
  520.         current_date.month, current_date.day, current_date.year);
  521.  
  522.     ep = events_today;
  523.     while (ep) {
  524.         shour = ep->event->start_time.hour;
  525.         sminute = ep->event->start_time.minute;
  526.         ehour = ep->event->end_time.hour;
  527.         eminute = ep->event->end_time.minute;
  528.  
  529.         if (shour == ehour && sminute == eminute)
  530.             printw("   %2d:%02d%2s         ",
  531.             ((shour + 11) % 12) + 1, sminute,
  532.             ((shour < 12) ? "am" : "pm"));
  533.         else
  534.             printw("   %2d:%02d%2s-%2d:%02d%2s ",
  535.             ((shour + 11) % 12) + 1, sminute,
  536.             ((shour < 12) ? "am" : "pm"),
  537.             ((ehour + 11) % 12) + 1, eminute,
  538.             ((ehour < 12) ? "am" : "pm"));
  539.         printw("%s\n", ep->event->event_string);
  540.  
  541.         ep = ep->next_event;
  542.     }
  543.     prompt_wait();
  544.     clear();
  545.     print_screen();
  546.     pop_area();
  547. }
  548.  
  549. print_book(ndays)
  550. int ndays;
  551. {
  552.     short shour, sminute, ehour, eminute, n;
  553.     struct eptr_rec *ep, *events_today;
  554.  
  555.     if (!date_flag) {
  556.         current_date.month = todays_date.month;
  557.         current_date.day = todays_date.day;
  558.         current_date.year = todays_date.year;
  559.     }
  560.  
  561.     if (ndays <= 0)
  562.         return(-1);
  563.     if (read_schedule(month_dir, READ_ONLY) != 0)
  564.         return(-1);
  565.  
  566.     for (; ndays; ndays--) {
  567.         month_start = get_month_start(current_date.month,
  568.         current_date.year);
  569.         days = days_in(current_date.month, current_date.year);
  570.         if ((n = get_daily_events(&events_today)) == 0) {
  571.         if (incr_date(1, ¤t_date))
  572.             continue;
  573.         else
  574.             break;
  575.         }
  576.  
  577.         sort_events(events_today, n);
  578.         printf("%s  %d/%d/%d\n",
  579.         smtwtfs_names[(current_date.day+month_start-1) % 7],
  580.         current_date.month, current_date.day, current_date.year);
  581.  
  582.         ep = events_today;
  583.         while (ep) {
  584.         shour = ep->event->start_time.hour;
  585.         sminute = ep->event->start_time.minute;
  586.         ehour = ep->event->end_time.hour;
  587.         eminute = ep->event->end_time.minute;
  588.  
  589.         if (shour == ehour && sminute == eminute)
  590.             printf("   %2d:%02d%2s         ",
  591.             ((shour + 11) % 12) + 1,sminute,
  592.             ((shour < 12) ? "am" : "pm"));
  593.         else
  594.             printf("   %2d:%02d%2s-%2d:%02d%2s ",
  595.             ((shour + 11) % 12) + 1,sminute,
  596.             ((shour < 12) ? "am" : "pm"),
  597.             ((ehour + 11) % 12) + 1,eminute,
  598.             ((ehour < 12) ? "am" : "pm"));
  599.         printf("%s\n", ep->event->event_string);
  600.  
  601.         ep = ep->next_event;
  602.         }
  603.         printf("\n");
  604.         if (!incr_date(1, ¤t_date))
  605.         break;
  606.     }
  607.     return(0);
  608. }
  609.  
  610. sound_bell()
  611. {
  612.     putchar(7);
  613.     fflush(stdout);
  614. }
  615.  
  616. clear_message_line()
  617. {
  618.     mvprintw(0, 0, "%*s", USER_COL, " ");
  619.     if (current_area == SCAN || current_area == SCHED_SCAN)
  620.         ccol = 0;
  621. }
  622.  
  623. clear_schedule_area()
  624. {
  625.     move(SCHEDULE_ROW, 0);
  626.     clrtobot();
  627. }
  628. @EOF
  629.  
  630. chmod 644 print.c
  631.  
  632. echo x - schedule.c
  633. cat >schedule.c <<'@EOF'
  634. #ifndef lint
  635. static char rcsid[] = "$Header: schedule.c,v 8.5 88/04/04 10:44:43 hull Exp $";
  636. #endif
  637.  
  638. #include <curses.h>
  639. #include <stdio.h>
  640. #include <string.h>
  641. #include <sys/types.h>
  642. #include <sys/stat.h>
  643. #if LOCKF
  644. #include <fcntl.h>
  645. #include <unistd.h>
  646. #endif LOCKF
  647. #if FLOCK
  648. #include <sys/file.h>
  649. #endif FLOCK
  650. #include "month.h"
  651.  
  652. struct event_rec current_event = {{0, 0, 0}, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0},
  653. 1, 0, 0, {10, 0}, {1, 0}, {0, 15}, {11, 0}, "", 0, 0, 0, 0, {0, 0, 0}, 0};
  654. short update_schedule = 0;
  655. short updating = 0, edit_flag = 0, parsed_correctly, alias_level;
  656. unsigned short file_owner;
  657. int fd;
  658. FILE *alias_file, *glob_alias_file;
  659.  
  660. extern short days, month_start, my_file;
  661. extern short all_flag, keep_old, read_only;
  662. extern short crow, ccol;
  663. extern struct date_rec current_date, todays_date;
  664. extern short area_ptr;
  665. extern struct area_rec areas[];
  666. extern struct event_rec events;
  667. extern int user_id;
  668. extern char *month_dir, *user_name;
  669.  
  670. group_post()
  671. {
  672.     char names[BUFSIZE];
  673.  
  674.     push_area(SCAN);
  675.     ccol = print_message("names: ", NO_BELL);
  676.  
  677.     if (get_string(names) == 0) {
  678.         clear_message_line();
  679.         pop_area();
  680.         return;
  681.     }
  682.  
  683.     post_event();        /* does push_area(SCHEDULE) */
  684.     edit_flag = 1;
  685.     parsed_correctly = 0;
  686.     while ((user() == ACCEPT) && !parsed_correctly)
  687.         ;
  688.     pop_area();
  689.     if (parsed_correctly)
  690.         post_it_to_em(names, ¤t_event);
  691.     edit_flag = 0;
  692.     show_all_events(current_date.month, current_date.year);
  693.     pop_area();
  694. }
  695.  
  696. post_it_to_em(names, event)
  697. char *names;
  698. struct event_rec *event;
  699. {
  700.     short i, save_keep;
  701.     struct name_rec *name_list = NULL, *cur_name;
  702.     char buf[BUFSIZE], *new_dir, *get_user_arg();
  703.     char *alias_file_name;
  704.     char ch, *name;
  705.  
  706.     glob_alias_file = fopen(ALIASFILE, "r");
  707.     alias_file_name = malloc((unsigned) strlen(month_dir)+10);
  708.     strcpy(alias_file_name, month_dir);
  709.     strcat(alias_file_name, "/.monthrc");
  710.     alias_file = fopen(alias_file_name, "r");
  711.     free(alias_file_name);
  712.  
  713.     clear_schedule_area();
  714.     refresh();
  715.     alias_level = 0;
  716.     if (expand_aliases(names, &name_list) == -1) {
  717.         print_message("too many alias levels", BELL);
  718.         fclose(alias_file);
  719.         fclose(glob_alias_file);
  720.         return;
  721.     }
  722. /*
  723.     cur_name = name_list;
  724.     printf("name_list:\n");
  725.     while (cur_name != NULL) {
  726.         printf("*%s*\n", cur_name->name);
  727.         cur_name = cur_name->next_name;
  728.     }
  729. */
  730.     fclose(alias_file);
  731.     fclose(glob_alias_file);
  732.     save_keep = keep_old;
  733.     keep_old = 1;
  734.  
  735.     /* write out current user's schedule */
  736.     if (!read_only && write_schedule() < 0) {
  737.         more();
  738.         sprintf(buf, "user %s: cannot write .month", user_name);
  739.         ccol = print_message(buf, BELL);
  740.     }
  741.  
  742.     cur_name = name_list;
  743.     while (cur_name != NULL) {
  744.         name = cur_name->name;
  745.         if ((new_dir = get_user_arg(name)) != NULL) {
  746.         while ((i = read_schedule(new_dir, READ_WRITE)) == -2) {
  747.             more();
  748.             sprintf(buf, "user %s: .month file locked", name);
  749.             ccol = print_message(buf, BELL);
  750.             more();
  751.             ccol = print_message("try again? ", NO_BELL);
  752.             ch = get_char();
  753.             clear_message_line();
  754.             if (ch != 'y')
  755.             break;        /* i is still -2 */
  756.         }
  757.  
  758.         if (i == -1) {
  759.             more();
  760.             sprintf(buf, "user %s: cannot open .month", name);
  761.             ccol = print_message(buf, BELL);
  762.         } else if (i > 0) {
  763.             more();
  764.             sprintf(buf, "user %s: cannot read .month version %d",
  765.             name, i);
  766.             ccol = print_message(buf, BELL);
  767.         } else if (i == 0) {    /* normal case */
  768.             link_event(event);
  769.             if (write_schedule() < 0) {
  770.             more();
  771.             sprintf(buf, "user %s: cannot write .month", name);
  772.             ccol = print_message(buf, BELL);
  773.             }
  774.         }
  775.         } else {
  776.         more();
  777.         sprintf(buf, "invalid user: %s", name);
  778.         ccol = print_message(buf, BELL);
  779.         }
  780.         cur_name = cur_name->next_name;
  781.     }
  782.  
  783.     free_names(name_list);
  784.  
  785.     /* read in original user's schedule */
  786.     if ((i = read_schedule(month_dir, read_only)) == -2) {
  787.         more();
  788.         ccol = print_message(".month file locked", BELL);
  789.         i = read_schedule(month_dir, READ_ONLY);
  790.         if (i == 0)
  791.         read_only = 1;
  792.     }
  793.  
  794.     if (i == -1) {
  795.         more();
  796.         ccol = print_message("cannot open .month", BELL);
  797.     } else if (i > 0) {
  798.         more();
  799.         sprintf(buf, "cannot read .month version %d", i);
  800.         ccol = print_message(buf, BELL);
  801.     }
  802.     show_all_events(current_date.month, current_date.year);
  803.     keep_old = save_keep;
  804. }
  805.  
  806. expand_aliases(names, list)
  807. char *names;
  808. struct name_rec **list;
  809.  {
  810.     struct name_rec *p, *q = NULL, *t;
  811.     char *name, *look_up_name();
  812.  
  813.     name = strtok(names, " ,\t\n");
  814.     while (name != NULL) {
  815.         p = (struct name_rec *) malloc(sizeof(struct name_rec));
  816.         p->name = strcpy(malloc((unsigned) strlen(name)+1), name);
  817.         p->next_name = NULL;
  818.         if (q == NULL)
  819.         t = p;
  820.         else
  821.         q->next_name = p;
  822.         q = p;
  823.         name = strtok((char *)NULL, " ,\t\n");
  824.     }
  825.  
  826.     p = t;
  827.     while (p != NULL) {
  828.         if ((names = look_up_name(p->name)) != NULL) {
  829.         if (alias_level++ == MAX_ALIAS_LEVEL ||    /* to prevent loops */
  830.           expand_aliases(names, list) == -1) {
  831.             free(names);
  832.             free_names(t);
  833.             return(-1);
  834.         }
  835.         free(names);
  836.         alias_level--;
  837.         } else
  838.         add_name(p->name, list);
  839.         p = p->next_name;
  840.     }
  841.  
  842.     free_names(t);
  843.     return(0);
  844. }
  845.  
  846. add_name(name, list)
  847. char *name;
  848. struct name_rec **list;
  849. {
  850.     struct name_rec *p, *q;
  851.  
  852.     p = *list;
  853.     while (p != NULL) {
  854.         if (strcmp(p->name, name) == 0)
  855.         return;
  856.         q = p;
  857.         p = p->next_name;
  858.     }
  859.  
  860.     p = (struct name_rec *) malloc(sizeof(struct name_rec));
  861.     p->name = strcpy(malloc((unsigned) strlen(name)+1), name);
  862.     p->next_name = NULL;
  863.  
  864.     if (*list == NULL) {
  865. /*        printf("add_name *%s* to empty list\n", p->name); */
  866.         *list = p;
  867.     } else {
  868. /*        printf("add_name *%s*\n", p->name); */
  869.         q->next_name = p;
  870.     }
  871. }
  872.  
  873. char *
  874. look_up_name(name)
  875. char *name;
  876. {
  877.     char line[MAXLINE], *word;
  878.  
  879.     if (alias_file != NULL) {
  880.         rewind(alias_file);
  881.         while (fgets(line, MAXLINE, alias_file) != NULL) {
  882.         line[strlen(line)-1] = '\0';
  883.         if ((strcmp(strtok(line, " \t\n"), "alias") == 0) &&
  884.             (strcmp(strtok((char *) NULL, " ,\t\n"), name) == 0) &&
  885.             ((word = strtok((char *) NULL, " ,\t\n")) != NULL)) {
  886.             *(word + strlen(word)) = ' ';
  887. /*            printf("look_up_name: %s -> *%s*\n", name, word); */
  888.             return(strcpy(malloc((unsigned) strlen(word)+1), word));
  889.         }
  890.         }
  891.     }
  892.  
  893.     if (glob_alias_file != NULL) {
  894.         rewind(glob_alias_file);
  895.         while (fgets(line, MAXLINE, glob_alias_file) != NULL) {
  896.         line[strlen(line)-1] = '\0';
  897.         if ((strcmp(strtok(line, " \t\n"), "alias") == 0) &&
  898.             (strcmp(strtok((char *) NULL, " ,\t\n"), name) == 0) &&
  899.             ((word = strtok((char *) NULL, " ,\t\n")) != NULL)) {
  900.             *(word + strlen(word)) = ' ';
  901. /*            printf("look_up_name: %s -> *%s*\n", name, word); */
  902.             return(strcpy(malloc((unsigned) strlen(word)+1), word));
  903.         }
  904.         }
  905.     }
  906.  
  907.     return(NULL);
  908. }
  909.  
  910. free_names(list)
  911. struct name_rec *list;
  912. {
  913.     struct name_rec *p;
  914.  
  915.     while (list != NULL) {
  916.         free(list->name);
  917.         p = list->next_name;
  918.         free((char *) list);
  919.         list = p;
  920.     }
  921. }
  922.  
  923. post_event()
  924. {
  925.     clear_message_line();
  926.     push_area(SCHEDULE);
  927.     current_event.start_date.month = current_date.month;
  928.     current_event.start_date.day = current_date.day;
  929.     current_event.start_date.year = current_date.year;
  930.     current_event.event_owner = user_id;
  931.     print_event(¤t_event);
  932. }
  933.  
  934. write_sched()
  935. {
  936.     int i;
  937.  
  938.     if (read_only) {
  939.         print_message("read-only mode", BELL);
  940.         return;
  941.     }
  942.  
  943.     push_area(SCAN);
  944.     if (update_schedule)
  945.         ccol = print_message("updating schedule", NO_BELL);
  946.     else
  947.         ccol = print_message("schedule unchanged", NO_BELL);
  948.  
  949.     if (write_schedule() < 0) {
  950.         more();
  951.         ccol = print_message("cannot write .month", BELL);
  952.         pop_area();
  953.         return;
  954.     }
  955.  
  956.     if ((i = read_schedule(month_dir, read_only)) == -2) {
  957.         more();
  958.         ccol = print_message(".month file locked", BELL);
  959.         i = read_schedule(month_dir, READ_ONLY);
  960.         if (i == 0)
  961.         read_only = 1;
  962.     }
  963.  
  964.     show_all_events(current_date.month, current_date.year);
  965.  
  966.     if (i != 0) {
  967.         more();
  968.         ccol = print_message("cannot open .month", BELL);
  969.     }
  970.     pop_area();
  971. }
  972.  
  973. select_regularity_col(col)
  974. register col;
  975. {
  976.     short i, hflag;
  977.  
  978.     switch(col) {
  979.     case PRIVATE_COL:
  980.         hl_all(¤t_event, (current_event.private ? 0 : 1),
  981.             -1, -1, -1, -1, -1, -1, -1, -1);
  982.         break;
  983.     case ANTI_COL:
  984.         hl_all(¤t_event, -1, (current_event.anti ? 0 : 1),
  985.             -1, -1, -1, -1, -1, -1, -1);
  986.         break;
  987.     case MONTHLY_COL:
  988.         hl_all(¤t_event, -1, -1,
  989.             (current_event.monthly ? 0 : 1), 0, -1, -1, -1, -1, -1);
  990.         break;
  991.     case YEARLY_COL:
  992.         hl_all(¤t_event, -1, -1, 0,
  993.             (current_event.yearly ? 0 : 1), -1, -1, -1, -1, -1);
  994.         break;
  995.     case EVERY_COL:
  996.         hl_all(¤t_event, -1, -1, -1, -1,
  997.            (current_event.every ? 0 : 1), -1, -1, -1, -1);
  998.         break;
  999.     case NTH_COL:
  1000.         hl_all(¤t_event, -1, -1, -1, -1, -1,
  1001.             (current_event.nth_is_on ? 0 : 1), -1, -1, -1);
  1002.         break;
  1003.     case LAST_COL:
  1004.         hl_all(¤t_event, -1, -1, -1, -1, -1, -1,
  1005.             (current_event.last ? 0 : 1), -1, -1);
  1006.         break;
  1007.     case SMTWTFS_COL:
  1008.     case SMTWTFS_COL + 2:
  1009.     case SMTWTFS_COL + 4:
  1010.     case SMTWTFS_COL + 6:
  1011.     case SMTWTFS_COL + 8:
  1012.     case SMTWTFS_COL + 10:
  1013.     case SMTWTFS_COL + 12:
  1014.         i = (col - SMTWTFS_COL) / 2;
  1015.         hflag = (current_event.smtwtfs[i] = !current_event.smtwtfs[i]);
  1016.         hl_schedule(col, hflag);
  1017.         hl_all(¤t_event, -1, -1, -1, -1, -1, -1, -1, -1, -1);
  1018.         break;
  1019.     case UMONTH_COL:
  1020.     case UDAY_COL:
  1021.     case UYEAR_COL:
  1022.         hl_all(¤t_event, -1, -1, -1, -1, -1, -1, -1,
  1023.             (current_event.until ? 0 : 1), -1);
  1024.         break;
  1025.     }
  1026. }
  1027.  
  1028. accept_current_event()
  1029. {
  1030.     if ((parse_event(¤t_event) != -1)) {
  1031.         if (!edit_flag) {
  1032.             pop_area();
  1033.         link_event(¤t_event);
  1034.             show_all_events(current_date.month, current_date.year);
  1035.         }
  1036.     }
  1037. }
  1038.  
  1039. cancel_current_event()
  1040. {
  1041.     if (!edit_flag)
  1042.         pop_area();
  1043.     print_overview();
  1044. }
  1045.  
  1046. link_event(event)
  1047. struct event_rec *event;
  1048. {
  1049.     struct event_rec *t, *ptr;
  1050.  
  1051.     if (!(ptr = (struct event_rec *)malloc(sizeof(struct event_rec))))
  1052.         return;
  1053.     *ptr = *event;
  1054.     t = events.next_event;
  1055.     events.next_event = ptr;
  1056.     ptr->next_event = t;
  1057.     update_schedule++;
  1058. }
  1059.  
  1060. parse_event(event)
  1061. struct event_rec *event;
  1062. {
  1063.     short hs;
  1064.  
  1065.     hs = has_smtwtfs(event->smtwtfs);
  1066.  
  1067.     if (!date_ok(&event->start_date)) {
  1068.         print_message("invalid start date", BELL);
  1069.         return(-1);
  1070.     }
  1071.     if (event->until && !date_ok(&event->until_date)) {
  1072.         print_message("invalid until date", BELL);
  1073.         return(-1);
  1074.     }
  1075.     if ((event->every || event->nth_is_on || event->last) && !hs) {
  1076.         print_message("missing day of week", BELL);
  1077.         return(-1);
  1078.     }
  1079.     if (hs && !event->every && !event->nth_is_on && !event->last) {
  1080. MQ:        print_message("missing qualifier", BELL);
  1081.         return(-1);
  1082.     }
  1083.     if (!event->every &&
  1084.         (event->monthly || event->yearly) &&
  1085.         (event->nth_is_on || event->last)) {
  1086.         print_message("need 'every'", BELL);
  1087.         return(-1);
  1088.     }
  1089.     if (event->last && !event->monthly && !event->yearly) {
  1090.         print_message("monthly or yearly?", BELL);
  1091.         return(-1);
  1092.     }
  1093.     if ((event->nth_is_on || event->last || event->until) &&
  1094.         (!event->monthly && !event->yearly && !event->every)) {
  1095.         goto MQ;
  1096.     }
  1097.     parsed_correctly = 1;
  1098.     return(0);
  1099. }
  1100.  
  1101. is_event_today()
  1102. /* are there any events today? */
  1103. {
  1104.     struct event_rec *eptr;
  1105.  
  1106.     eptr = events.next_event;
  1107.     while (eptr) {
  1108.         if (event_today(eptr))
  1109.         return(1);
  1110.         eptr = eptr->next_event;
  1111.     }
  1112.  
  1113.     return(0);
  1114. }
  1115.  
  1116. get_daily_events(ep)
  1117. struct eptr_rec **ep;
  1118. {
  1119.     short i = 0;
  1120.     struct event_rec *eptr;
  1121.     struct eptr_rec *p, *q, *first_event;
  1122.  
  1123.     first_event = (struct eptr_rec *)NULL;
  1124.     q = (struct eptr_rec *)NULL;
  1125.  
  1126.     eptr = events.next_event;
  1127.     while (eptr) {
  1128.         if (event_today(eptr)) {
  1129.         i++;
  1130.         p = (struct eptr_rec *)malloc(sizeof(struct eptr_rec));
  1131.         p->event = eptr;
  1132.         p->next_event = (struct eptr_rec *)NULL;
  1133.         p->prev_event = q;
  1134.         if (q)
  1135.             q->next_event = p;
  1136.         else
  1137.             first_event = p;
  1138.         q = p;
  1139.         }
  1140.         eptr = eptr->next_event;
  1141.     }
  1142.  
  1143.     *ep = first_event;
  1144.     return(i);
  1145. }
  1146.  
  1147. get_every_event(ep)
  1148. struct eptr_rec **ep;
  1149. {
  1150.     short i = 0;
  1151.     struct event_rec *eptr;
  1152.     struct eptr_rec *p, *q, *first_event;
  1153.  
  1154.     first_event = (struct eptr_rec *)NULL;
  1155.     q = (struct eptr_rec *)NULL;
  1156.  
  1157.     eptr = events.next_event;
  1158.     while (eptr) {
  1159.         if (event_visible(eptr)) {
  1160.         i++;
  1161.         p = (struct eptr_rec *)malloc(sizeof(struct eptr_rec));
  1162.         p->event = eptr;
  1163.         p->next_event = (struct eptr_rec *)NULL;
  1164.         p->prev_event = q;
  1165.         if (q)
  1166.             q->next_event = p;
  1167.         else
  1168.             first_event = p;
  1169.         q = p;
  1170.         }
  1171.         eptr = eptr->next_event;
  1172.     }
  1173.  
  1174.     *ep = first_event;
  1175.     return(i);
  1176. }
  1177.  
  1178. event_visible(event)
  1179. register struct event_rec *event;
  1180. {
  1181.     /* returns 1 if event is visible, 0 if not */
  1182.  
  1183.     return(my_file || !event->private || (user_id == event->event_owner));
  1184. }
  1185.  
  1186. scan_todays_events()
  1187. {
  1188.     struct eptr_rec *events_today;
  1189.     short n;
  1190.  
  1191.     if ((n = get_daily_events(&events_today)) <= 0) {
  1192.         print_message("no events this day", BELL);
  1193.         return;
  1194.     }
  1195.     sort_events(events_today, n);
  1196.  
  1197.     scan_events(&events_today);
  1198.     free_event_ptrs(events_today);
  1199.     print_overview();
  1200. }
  1201.  
  1202. scan_every_event()
  1203. {
  1204.     struct eptr_rec *first_event;
  1205.  
  1206.     if (get_every_event(&first_event) <= 0) {
  1207.         print_message("no events at all", BELL);
  1208.         return;
  1209.     }
  1210.  
  1211.     scan_events(&first_event);
  1212.     free_event_ptrs(first_event);
  1213.     print_overview();
  1214. }
  1215.  
  1216. scan_events(first_event_p)
  1217. struct eptr_rec **first_event_p;
  1218. {
  1219.     register short ch;
  1220.     struct event_rec *ptr;
  1221.     struct eptr_rec *p, *q;
  1222.  
  1223.     push_area(SCHED_SCAN);
  1224.     p = *first_event_p;
  1225.     while (p) {
  1226.         ptr = p->event;
  1227.         current_event = *ptr;
  1228.         print_event(ptr);
  1229.  
  1230.         ch = get_npdeq(p->next_event != NULL, p->prev_event != NULL,
  1231.           !read_only && (my_file || (ptr->event_owner == user_id)));
  1232.  
  1233.         switch(ch) {
  1234.         case 'n':
  1235.         p = p->next_event;
  1236.         break;
  1237.         case 'p':
  1238.         p = p->prev_event;
  1239.         break;
  1240.         case 'd':
  1241.         delete_event(ptr);
  1242.         show_all_events(current_date.month, current_date.year);
  1243.         if (p->prev_event)
  1244.             p->prev_event->next_event = p->next_event;
  1245.         else
  1246.             *first_event_p = p->next_event;
  1247.         if (p->next_event) {
  1248.             p->next_event->prev_event = p->prev_event;
  1249.             q = p->next_event;
  1250.         } else
  1251.             q = p->prev_event;
  1252.         free((char *)p);
  1253.         p = q;
  1254.         break;
  1255.         case 'e':
  1256.         edit_flag = 1;
  1257.         push_area(SCHEDULE);
  1258.         parsed_correctly = 0;
  1259.         while (!parsed_correctly)
  1260.             if (user() == ACCEPT) {
  1261.             if (parsed_correctly) {
  1262.                 *ptr = current_event;
  1263.                     show_all_events(current_date.month,
  1264.                 current_date.year);
  1265.                 update_schedule++;
  1266.             }
  1267.             } else {
  1268.             print_event(ptr);
  1269.             break;
  1270.             }
  1271.         pop_area();
  1272.         edit_flag = 0;
  1273.         break;
  1274.         case 'q':
  1275.         p = (struct eptr_rec *)NULL;
  1276.         break;
  1277.         }
  1278.     }
  1279.     pop_area();
  1280.     clear_message_line();
  1281. }
  1282.  
  1283. delete_event(event)
  1284. struct event_rec *event;
  1285. {
  1286.     struct event_rec *ptr;
  1287.  
  1288.     ptr = &events;
  1289.  
  1290.     while (ptr && (ptr->next_event != event)) {
  1291.         ptr = ptr->next_event;
  1292.     }
  1293.     if (ptr) {
  1294.         ptr->next_event = ptr->next_event->next_event;
  1295.         free((char *)event);
  1296.     }
  1297.     update_schedule++;
  1298. }
  1299.  
  1300. sort_events(e, n)
  1301. register struct eptr_rec *e;
  1302. int n;
  1303. {
  1304.     register struct event_rec *ev, *nev;
  1305.     register struct eptr_rec *ev_ptr;
  1306.     register i;
  1307.     short f;
  1308.  
  1309.     for (i = 0; i < n; i++) {
  1310.         f = 0;
  1311.         ev_ptr = e;
  1312.         while (ev_ptr->next_event) {
  1313.         ev = ev_ptr->event;
  1314.         nev = ev_ptr->next_event->event;
  1315.         if ((ev->start_time.hour > nev->start_time.hour) ||
  1316.             ((ev->start_time.hour == nev->start_time.hour) &&
  1317.             (ev->start_time.minute > nev->start_time.minute))) {
  1318.             ev_ptr->event = nev;
  1319.             ev_ptr->next_event->event = ev;
  1320.             f++;
  1321.         }
  1322.         ev_ptr = ev_ptr->next_event;
  1323.         }
  1324.         if (f == 0)
  1325.         break;
  1326.     }
  1327. }
  1328.  
  1329. free_event_ptrs(eptr)
  1330. struct eptr_rec *eptr;
  1331. {
  1332.     while (eptr) {
  1333.         free((char *)eptr);
  1334.         eptr = eptr->next_event;
  1335.     }
  1336. }
  1337.  
  1338. show_all_events(month, year)
  1339. register month, year;
  1340. {
  1341.     register struct event_rec *eptr;
  1342.     short i;
  1343.     char match_list[32];
  1344.     short tday;
  1345.  
  1346.     month_start = get_month_start(month, year);
  1347.     days = days_in(month, year);
  1348.  
  1349.     if (all_flag) {
  1350.         tday = current_date.day;
  1351.         for (i = 1; i <= days; i++) {
  1352.         eptr = events.next_event;
  1353.         match_list[i] = 0;
  1354.         current_date.day = i;
  1355.  
  1356.         while (eptr) {
  1357.             if (event_today(eptr)) {
  1358.             match_list[i] = 1;
  1359.             break;
  1360.             }
  1361.             eptr = eptr->next_event;
  1362.         }
  1363.         }
  1364.         current_date.day = tday;
  1365.         print_cal(month, year, match_list);
  1366.     } else
  1367.         print_cal(month, year, (char *)0);
  1368.  
  1369.     if (current_area != SCHEDULE && current_area != SCHED_SCAN)
  1370.         print_overview();
  1371. }
  1372.  
  1373. #if !SYS5
  1374. char *
  1375. strtok(s1, s2)
  1376. char *s1, *s2;
  1377. {
  1378.     static char *pos;
  1379.     char *p, *q;
  1380.  
  1381.     if (s1 != (char *)NULL)
  1382.     pos = s1;
  1383.  
  1384.     if (*pos == '\0')
  1385.     return((char *)NULL);
  1386.  
  1387.     for (p = pos; *p != '\0'; p++) {
  1388.     if (index(s2, (int) *p) == (char *)NULL)
  1389.         continue;
  1390.     *p = '\0';
  1391.     q = pos;
  1392.     for (pos = ++p; *pos != '\0' && index(s2, (int) *pos) != (char *)NULL;
  1393.         pos++);
  1394.     if (*pos == '\0')
  1395.         return((char *)NULL);
  1396.     return(q);
  1397.     }
  1398.     q = pos;
  1399.     pos = (char *)NULL;
  1400.     return(q);
  1401. }
  1402. #endif
  1403. @EOF
  1404.  
  1405. chmod 644 schedule.c
  1406.  
  1407. echo x - time.c
  1408. cat >time.c <<'@EOF'
  1409. #ifndef lint
  1410. static char rcsid[] = "$Header: time.c,v 8.2 87/11/13 21:47:20 hull Exp $";
  1411. #endif
  1412.  
  1413. #include "month.h"
  1414.  
  1415. extern struct date_rec current_date;
  1416.  
  1417. void
  1418. convert_year(base_year, year)
  1419. short base_year, *year;
  1420. {
  1421.     short delta;
  1422.  
  1423.     if (*year < 100) {
  1424.         *year += base_year - (base_year % 100);
  1425.         if ((delta = (*year - base_year)) >= 50)
  1426.         *year -= 100;
  1427.         else if (delta < -50)
  1428.         *year += 100;
  1429.     }
  1430. }
  1431.  
  1432. date_ok(date)
  1433. struct date_rec *date;
  1434. {
  1435.     if (date->day <= days_in(date->month, date->year))
  1436.         return(1);
  1437.     else
  1438.         return(0);
  1439. }
  1440.  
  1441. has_smtwtfs(smtwtfs)
  1442. register char *smtwtfs;
  1443. {
  1444.     register i;
  1445.  
  1446.     for (i = 0; i < 7; i++) {
  1447.         if (smtwtfs[i]) {
  1448.             return(1);
  1449.         }
  1450.     }
  1451.     return(0);
  1452. }
  1453.  
  1454. days_since_jan1(date)
  1455. struct date_rec *date;
  1456. {
  1457.     int dys = 0;
  1458.     short i;
  1459.  
  1460.     for (i = 1; i < date->month; i++) {
  1461.         dys += days_in(i, date->year);
  1462.     }
  1463.     dys += date->day;
  1464.     return(dys);
  1465. }
  1466.  
  1467. incr_date(inc, date)
  1468. short inc;
  1469. struct date_rec *date;
  1470. {
  1471.     /* return in date the increment (or decrement) of the current date */
  1472.     /* return 1 if incr successful, 0 if not */
  1473.  
  1474.     date->month = current_date.month;
  1475.     date->day = current_date.day;
  1476.     date->year = current_date.year;
  1477.  
  1478.     while (inc > 0) {
  1479.         if (date->day < days_in(date->month, date->year))
  1480.         date->day = date->day + 1;
  1481.         else {
  1482.         if (date->month < 12) {
  1483.             date->month = date->month + 1;
  1484.             date->day = 1;
  1485.         } else {
  1486.             if (date->year < LAST_YEAR) {
  1487.             date->month = 1;
  1488.             date->day = 1;
  1489.             date->year = date->year + 1;
  1490.             } else
  1491.             return(0);
  1492.         }
  1493.         }
  1494.         inc--;
  1495.     }
  1496.  
  1497.     while (inc < 0) {
  1498.         if (date->day > 1)
  1499.         date->day = date->day - 1;
  1500.         else {
  1501.         if (date->month > 1) {
  1502.             date->month = date->month - 1;
  1503.                 date->day = days_in(date->month, date->year);
  1504.         } else {
  1505.             if (date->year > FIRST_YEAR) {
  1506.             date->month = 12;
  1507.             date->year = date->year - 1;
  1508.                     date->day = days_in(date->month, date->year);
  1509.             } else
  1510.             return(0);
  1511.         }
  1512.         }
  1513.     inc++;
  1514.     }
  1515.     return(1);
  1516. }
  1517.  
  1518. compute_times(event, mode)
  1519. struct event_rec *event;
  1520. char mode;
  1521. {
  1522.     switch(mode) {
  1523.     case START_MODE:
  1524.         event->start_time.minute = 60 + event->end_time.minute -
  1525.             event->duration.minute;
  1526.         event->start_time.hour = (23 + event->end_time.hour -
  1527.             event->duration.hour + (event->start_time.minute / 60)) % 24;
  1528.         event->start_time.minute %= 60;
  1529.         break;
  1530.     case DURATION_MODE:
  1531.         event->duration.minute = 60 + event->end_time.minute -
  1532.             event->start_time.minute;
  1533.         event->duration.hour = (23 + event->end_time.hour -
  1534.             event->start_time.hour + (event->duration.minute / 60)) % 24;
  1535.         event->duration.minute %= 60;
  1536.         break;
  1537.     case END_MODE:
  1538.         event->end_time.minute = event->start_time.minute +
  1539.         event->duration.minute;
  1540.         event->end_time.hour = (event->start_time.hour +
  1541.         event->duration.hour + (event->end_time.minute / 60)) % 24;
  1542.         event->end_time.minute %= 60;
  1543.         break;
  1544.     }
  1545. }
  1546. @EOF
  1547.  
  1548. chmod 644 time.c
  1549.  
  1550. echo x - user.c
  1551. cat >user.c <<'@EOF'
  1552. #ifndef lint
  1553. static char rcsid[] = "$Header: user.c,v 8.2 87/11/13 21:47:22 hull Exp $";
  1554. #endif
  1555.  
  1556. #include <curses.h>
  1557. #if SYS5
  1558. #include <string.h>
  1559. #else
  1560. #include <strings.h>
  1561. #endif
  1562. #include "month.h"
  1563.  
  1564. extern short area_ptr, crow, ccol, edit_flag, read_only, over_flag;
  1565. extern short my_file, event_status;
  1566. extern struct area_rec areas[];
  1567. extern struct date_rec current_date, todays_date, mdates[];
  1568. extern struct event_rec current_event;
  1569.  
  1570. user()
  1571. {
  1572.     register short ch;
  1573.     short n, savecol;
  1574.     char *prompt, *incrp, iprompt[BUFSIZE];
  1575.  
  1576.     for (;;) {
  1577.         move(crow, ccol);
  1578.         refresh();
  1579.  
  1580. GETCH:
  1581.         ch = get_char();
  1582. /*
  1583.         mvprintw(0, 0, "ch = %c (0x%x)", ch, ch);
  1584.         move(crow, ccol);
  1585.         refresh();
  1586. */
  1587.  
  1588.         switch(ch) {
  1589.         case '\001':    /* ^A */
  1590.             if (current_area == SCHEDULE) {
  1591.                 accept_current_event();
  1592.                 if (edit_flag)
  1593.                 return(ACCEPT);
  1594.             } else
  1595.                 sound_bell();
  1596.             break;
  1597.         case '\033':    /* ^[ */
  1598.             if (current_area == SCHEDULE) {
  1599.                 cancel_current_event();
  1600.                 if (edit_flag)
  1601.                 return(CANCEL);
  1602.             } else
  1603.                 sound_bell();
  1604.             break;
  1605.         case '/':
  1606.             if (current_area != SCHEDULE) {
  1607.                 prompt = "date: ";
  1608.                 if (get_date(¤t_date, prompt))
  1609.                 goto_this_day(¤t_date);
  1610.             } else if (crow == SCHEDULE_ROW) {
  1611.                 savecol = ccol;
  1612.                 if (ccol <= SYEAR_COL) {
  1613.                 prompt = "start date: ";
  1614.                 if (get_date(¤t_event.start_date, prompt))
  1615.                     print_date(¤t_event);
  1616.                 } else if (ccol >= UMONTH_COL) {
  1617.                 prompt = "until date: ";
  1618.                 if (get_date(¤t_event.until_date,
  1619.                     prompt)) {
  1620.                     current_event.until = 1;
  1621.                     print_until(¤t_event);
  1622.                 }
  1623.                 } else
  1624.                 sound_bell();
  1625.                 ccol = savecol;
  1626.             } else
  1627.                 sound_bell();
  1628.             break;
  1629.         case ';':
  1630.             if (current_area != SCHEDULE)
  1631.                 goto_this_day(&mdates[SEMI_MARK]);
  1632.             else
  1633.                 sound_bell();
  1634.             break;
  1635.         case '?':
  1636.             if (current_area != SCHEDULE)
  1637.                 help();
  1638.             else
  1639.                 sound_bell();
  1640.             break;
  1641.         case '+':
  1642.         case '-':
  1643.             incrp = (ch == '+') ? "increment: " : "decrement: ";
  1644.             switch(current_area) {
  1645.             case MONTHS:
  1646.                 strcpy(iprompt, "month ");
  1647.                 strcat(iprompt, incrp);
  1648.                 break;
  1649.             case DAYS:
  1650.                 strcpy(iprompt, "day ");
  1651.                 strcat(iprompt, incrp);
  1652.                 break;
  1653.             case YEARS:
  1654.                 strcpy(iprompt, "year ");
  1655.                 strcat(iprompt, incrp);
  1656.                 break;
  1657.             case SCHEDULE:
  1658.                 if (crow == SCHEDULE_ROW) {
  1659.                     switch(ccol) {
  1660.                     case SMONTH_COL:
  1661.                     case UMONTH_COL:
  1662.                     strcpy(iprompt, "month ");
  1663.                     strcat(iprompt, incrp);
  1664.                     break;
  1665.                     case SDAY_COL:
  1666.                     case UDAY_COL:
  1667.                     strcpy(iprompt, "day ");
  1668.                     strcat(iprompt, incrp);
  1669.                     break;
  1670.                     case SYEAR_COL:
  1671.                     case UYEAR_COL:
  1672.                     strcpy(iprompt, "year ");
  1673.                     strcat(iprompt, incrp);
  1674.                     break;
  1675.                     case NTH_COL:
  1676.                     strcpy(iprompt, "nth ");
  1677.                     strcat(iprompt, incrp);
  1678.                     break;
  1679.                     default:
  1680.                     sound_bell();
  1681.                     goto GETCH;
  1682.                     }
  1683.                 } else {    /* must be on TIME_ROW */
  1684.                     switch(ccol) {
  1685.                     case START_COL:
  1686.                     case DURATION_COL:
  1687.                     case END_COL:
  1688.                     case WARNING_COL:
  1689.                     strcpy(iprompt, "hour ");
  1690.                     strcat(iprompt, incrp);
  1691.                     break;
  1692.                     case START_COL+3:
  1693.                     case DURATION_COL+3:
  1694.                     case END_COL+3:
  1695.                     case WARNING_COL+3:
  1696.                     strcpy(iprompt, "minute ");
  1697.                     strcat(iprompt, incrp);
  1698.                     break;
  1699.                     default:
  1700.                     sound_bell();
  1701.                     goto GETCH;
  1702.                     }
  1703.                 }
  1704.                 break;
  1705.             }
  1706.             if ((n = enter_number(ch, iprompt)) >= 0)
  1707.                 do_incr((ch == '+') ? n : -n);
  1708.             break;
  1709. #if SHELL_ESCAPE
  1710.         case '!':
  1711.             if (current_area != SCHEDULE)
  1712.                 shell_escape();
  1713.             else
  1714.                 sound_bell();
  1715.             break;
  1716. #endif
  1717.         case '\n':
  1718.             if ((n = selection()) != NOTHING)
  1719.                 return(n);
  1720.             break;
  1721.         case 'a':
  1722.             if (current_area != SCHEDULE)
  1723.                 print_aliases();
  1724.             else
  1725.                 sound_bell();
  1726.             break;
  1727.         case 'd':
  1728.         case 'm':
  1729.         case 'y':
  1730.             if (current_area != SCHEDULE) {
  1731.                 pop_area();
  1732.                 push_area(ch);
  1733.             } else
  1734.                 sound_bell();
  1735.             break;
  1736.         case 'h':
  1737.         case 'j':
  1738.         case 'k':
  1739.         case 'l':
  1740.             event_status = NOTHING;
  1741.             move_cursor(ch);
  1742.             switch(event_status) {
  1743.             case ACCEPT:
  1744.                 accept_current_event();
  1745.                 if (edit_flag)
  1746.                     return(event_status);
  1747.                 break;
  1748.             case CANCEL:
  1749.                 cancel_current_event();
  1750.                 if (edit_flag)
  1751.                     return(event_status);
  1752.                 break;
  1753.             }
  1754.             break;
  1755.         case 'n':
  1756.         case 'p':
  1757.         case ' ':
  1758.         case '\b':
  1759.             if (current_area == SCHEDULE)
  1760.                 do_incr_sched((ch == 'n' || ch == ' ') ? 1: -1);
  1761.             else
  1762.                 do_incr((ch == 'n' || ch == ' ') ? 1: -1);
  1763.             break;
  1764.         case 't':
  1765.             if (current_area == SCHEDULE)
  1766.                 change_time_mode();
  1767.             else
  1768.                 sound_bell();
  1769.             break;
  1770.         case '0':
  1771.         case '1':
  1772.         case '2':
  1773.         case '3':
  1774.         case '4':
  1775.         case '5':
  1776.         case '6':
  1777.         case '7':
  1778.         case '8':
  1779.         case '9':
  1780.             switch(current_area) {
  1781.             case DAYS:
  1782.                 prompt = "day: ";
  1783.                 break;
  1784.             case MONTHS:
  1785.                 prompt = "month: ";
  1786.                 break;
  1787.             case YEARS:
  1788.                 prompt = "year: ";
  1789.                 break;
  1790.             case SCHEDULE:
  1791.                 if (crow == SCHEDULE_ROW) {
  1792.                     switch(ccol) {
  1793.                     case SMONTH_COL:
  1794.                     case UMONTH_COL:
  1795.                     prompt = "month: ";
  1796.                     break;
  1797.                     case SDAY_COL:
  1798.                     case UDAY_COL:
  1799.                     prompt = "day: ";
  1800.                     break;
  1801.                     case SYEAR_COL:
  1802.                     case UYEAR_COL:
  1803.                     prompt = "year: ";
  1804.                     break;
  1805.                     case NTH_COL:
  1806.                     prompt = "nth: ";
  1807.                     break;
  1808.                     default:
  1809.                     goto GETCH;
  1810.                     }
  1811.                 } else {    /* must be on TIME_ROW */
  1812.                     switch(ccol) {
  1813.                     case START_COL:
  1814.                     case DURATION_COL:
  1815.                     case END_COL:
  1816.                     case WARNING_COL:
  1817.                     prompt = "hour: ";
  1818.                     break;
  1819.                     case START_COL+3:
  1820.                     case DURATION_COL+3:
  1821.                     case END_COL+3:
  1822.                     case WARNING_COL+3:
  1823.                     prompt = "minute: ";
  1824.                     break;
  1825.                     default:
  1826.                     sound_bell();
  1827.                     goto GETCH;
  1828.                     }
  1829.                 }
  1830.                 break;
  1831.             }
  1832.             if ((n = enter_number(ch, prompt)) >= 0)
  1833.                 do_number(n);
  1834.             break;
  1835.         case 'A':
  1836.             if (current_area != SCHEDULE) {
  1837.                 toggle_flag('A');
  1838.                 show_all_events(current_date.month,
  1839.                 current_date.year);
  1840.             } else
  1841.                 sound_bell();
  1842.             break;
  1843.         case 'B':
  1844.             if (current_area != SCHEDULE)
  1845.                 print_sched();
  1846.             else
  1847.                 sound_bell();
  1848.             break;
  1849.         case 'C':
  1850.             if (current_area != SCHEDULE) {
  1851.                 if (!over_flag)
  1852.                 clear_schedule_area();
  1853.                 clear_message_line();
  1854.             } else
  1855.                 sound_bell();
  1856.             break;
  1857.         case 'E':
  1858.             if (current_area != SCHEDULE)
  1859.                 scan_every_event();
  1860.             else
  1861.                 sound_bell();
  1862.             break;
  1863.         case 'G':
  1864.             if (current_area != SCHEDULE)
  1865.                 group_post();
  1866.             else
  1867.                 sound_bell();
  1868.             break;
  1869.         case 'K':
  1870.             if (current_area != SCHEDULE)
  1871.                 if (!my_file)
  1872.                 print_message("must keep old events", BELL);
  1873.                 else
  1874.                 toggle_flag('K');
  1875.             else
  1876.                 sound_bell();
  1877.             break;
  1878.         case 'L':
  1879.             if (current_area != SCHEDULE)
  1880.                 lunar();
  1881.             else
  1882.                 sound_bell();
  1883.             break;
  1884.         case 'M':
  1885.         case '\'':
  1886.             if (current_area != SCHEDULE)
  1887.                 mark_day((ch != 'M'));
  1888.             else
  1889.                 sound_bell();
  1890.             break;
  1891.         case 'O':
  1892.             if (current_area != SCHEDULE) {
  1893.                 toggle_flag('O');
  1894.                 print_overview();
  1895.             } else
  1896.                 sound_bell();
  1897.             break;
  1898.         case 'P':
  1899.             if (current_area != SCHEDULE)
  1900.                 if (read_only)
  1901.                     print_message("read-only mode", BELL);
  1902.                 else
  1903.                 post_event();
  1904.             else
  1905.                 sound_bell();
  1906.             break;
  1907.         case 'Q':
  1908.             if (current_area != SCHEDULE)
  1909.                 return(ACCEPT);
  1910.             else
  1911.                 sound_bell();
  1912.             break;
  1913. #if MULTIUSER
  1914.         case 'R':
  1915.             if (current_area != SCHEDULE)
  1916.                 do_read_mode();
  1917.             else
  1918.                 sound_bell();
  1919.             break;
  1920. #endif MULTIUSER
  1921.         case 'S':
  1922.             if (current_area != SCHEDULE)
  1923.                 scan_todays_events();
  1924.             else
  1925.                 sound_bell();
  1926.             break;
  1927.         case 'T':
  1928.             if (current_area != SCHEDULE)
  1929.                 goto_this_day(&todays_date);
  1930.             else
  1931.                 sound_bell();
  1932.             break;
  1933. #if MULTIUSER
  1934.         case 'U':
  1935.             if (current_area != SCHEDULE)
  1936.                 get_user();
  1937.             else
  1938.                 sound_bell();
  1939.             break;
  1940. #endif MULTIUSER
  1941.         case 'V':
  1942.             if (current_area != SCHEDULE)
  1943.                 print_version();
  1944.             else
  1945.                 sound_bell();
  1946.             break;
  1947.         case 'W':
  1948.             if (current_area != SCHEDULE)
  1949.                 write_sched();
  1950.             else
  1951.                 sound_bell();
  1952.             break;
  1953.         default:
  1954.             sound_bell();
  1955.             goto GETCH;
  1956.         }
  1957.  
  1958.         if ((current_date.month != mdates[CUR_MARK].month) ||
  1959.             (current_date.day != mdates[CUR_MARK].day) ||
  1960.             (current_date.year != mdates[CUR_MARK].year)) {
  1961.             mdates[SEMI_MARK] = mdates[CUR_MARK];
  1962.             mdates[CUR_MARK].month = current_date.month;
  1963.             mdates[CUR_MARK].day = current_date.day;
  1964.             mdates[CUR_MARK].year = current_date.year;
  1965.         }
  1966.     }
  1967.     /* NOTREACHED */
  1968. }
  1969. @EOF
  1970.  
  1971. chmod 644 user.c
  1972.  
  1973. echo x - user2.c
  1974. cat >user2.c <<'@EOF'
  1975. #ifndef lint
  1976. static char rcsid[] = "$Header: user2.c,v 8.4 88/04/04 10:13:30 hull Exp $";
  1977. #endif
  1978.  
  1979. #include <signal.h>
  1980. #include <curses.h>
  1981. #include "month.h"
  1982.  
  1983. extern short delchar, kilchar, update_schedule;
  1984. extern short all_flag, ins_mode, keep_old, over_flag, read_only;
  1985. extern short crow, ccol, days;
  1986. extern short area_ptr;
  1987. extern unsigned short getgid(), getegid();
  1988. extern int user_id;
  1989. extern char time_mode, *home_dir, *month_dir;
  1990. extern struct area_rec areas[];
  1991. extern struct date_rec current_date, todays_date, mdates[];
  1992. extern struct event_rec current_event;
  1993.  
  1994. selection()
  1995. {
  1996.     switch(current_area) {
  1997.         case MONTHS:
  1998.             if ((crow - MONTH_ROW) != current_date.month - 1) {
  1999.                 hl_month(current_date.month, HL_OFF);
  2000.                 current_date.month = crow - MONTH_ROW + 1;
  2001.                 show_all_events(current_date.month,
  2002.                 current_date.year);
  2003.                 hl_month(current_date.month, HL_ON);
  2004.             }
  2005.             break;
  2006.         case DAYS:
  2007.             hl_day(current_date.day, HL_OFF);
  2008.             current_date.day = get_day_from_row_col(crow, ccol);
  2009.             hl_day(current_date.day, HL_ON);
  2010.             print_overview();
  2011.             break;
  2012.         case YEARS:
  2013.             hl_year(current_date.year, HL_OFF);
  2014.             current_date.year = current_date.year -
  2015.                 (current_date.year % 10) +
  2016.                    ((ccol - (YEAR_COL + 4)) / 6);
  2017.             hl_year(current_date.year, HL_ON);
  2018.             show_all_events(current_date.month, current_date.year);
  2019.             break;
  2020.         case SCHEDULE:
  2021.             if (crow == SCHEDULE_ROW)
  2022.                 select_regularity_col(ccol);
  2023.             else
  2024.                 schedule_move_cursor('\n');
  2025.             break;
  2026.     }
  2027.     return(NOTHING);
  2028. }
  2029.  
  2030. enter_number(ch, prompt)
  2031. short ch;
  2032. char *prompt;
  2033. {
  2034.     char nbuf[BUFSIZE];
  2035.     short i = 0, max_digits = 2;
  2036.     int retval = -1;
  2037.  
  2038.     if (current_area == YEARS) {
  2039.         max_digits = 4;
  2040.         push_area(SCAN);
  2041.     } else if (current_area == SCHEDULE) {
  2042.         if (ccol == SYEAR_COL || ccol == UYEAR_COL)
  2043.         max_digits = 4;
  2044.         push_area(SCHED_SCAN);
  2045.     } else
  2046.         push_area(SCAN);
  2047.  
  2048.     ccol = print_message(prompt, NO_BELL);
  2049.  
  2050.     for (;;) {
  2051.         if ((ch >= '0') && (ch <= '9')) {
  2052.         if (i < max_digits) {
  2053.             nbuf[i++] = ch;
  2054.             mvaddch(0, ccol++, ch);
  2055.             refresh();
  2056.         }
  2057.         } else if (ch == '\n') {
  2058.         nbuf[i] = 0;
  2059.         retval = atoi(nbuf);
  2060.         break;
  2061.         } else if (ch == '\b') {
  2062.         if (i > 0) {
  2063.             i--; ccol--;
  2064.             mvaddch(0, ccol, ' ');
  2065.             move(0, ccol);
  2066.             refresh();
  2067.         }
  2068.         } else if (ch == '\033') {    /* ^[ */
  2069.         break;
  2070.         }
  2071.         ch = get_char();
  2072.     }
  2073.     clear_message_line();
  2074.     pop_area();
  2075.     return(retval);
  2076. }
  2077.  
  2078. do_number(n)
  2079. short n;
  2080. {
  2081.     void convert_year();
  2082.  
  2083.     switch(current_area) {
  2084.     case MONTHS:
  2085.         if (n <= 12 && n >= 1) {
  2086.         hl_month(current_date.month, HL_OFF);
  2087.         current_date.month = n;
  2088.         show_all_events(current_date.month, current_date.year);
  2089.         hl_month(current_date.month, HL_ON);
  2090.         goto_month();
  2091.         }
  2092.         break;
  2093.     case DAYS:
  2094.         if (n >= 1 && n <= days) {
  2095.         hl_day(current_date.day, HL_OFF);
  2096.         current_date.day = n;
  2097.         hl_day(current_date.day, HL_ON);
  2098.         print_overview();
  2099.         goto_day();
  2100.         }
  2101.         break;
  2102.     case YEARS:
  2103.         convert_year(current_date.year, &n);
  2104.         current_date.year = n;
  2105.         print_all_years();
  2106.         show_all_events(current_date.month, current_date.year);
  2107.         goto_year();
  2108.         break;
  2109.     case SCHEDULE:
  2110.         if (crow == SCHEDULE_ROW) {
  2111.         switch(ccol) {
  2112.         case SMONTH_COL:
  2113.             if (n >= 1 && n <= 12)
  2114.             current_event.start_date.month = n;
  2115.             print_date(¤t_event);
  2116.             break;
  2117.         case SDAY_COL:
  2118.             if (n >= 1 && n <= 31)
  2119.             current_event.start_date.day = n;
  2120.             print_date(¤t_event);
  2121.             break;
  2122.         case SYEAR_COL:
  2123.                 convert_year(current_date.year, &n);
  2124.             if (n >= FIRST_YEAR && n <= LAST_YEAR)
  2125.             current_event.start_date.year = n;
  2126.             print_date(¤t_event);
  2127.             break;
  2128.         case UMONTH_COL:
  2129.             if (n >= 1 && n <= 12) {
  2130.             current_event.until_date.month = n;
  2131.             current_event.until = 1;
  2132.             }
  2133.             print_until(¤t_event);
  2134.             break;
  2135.         case UDAY_COL:
  2136.             if (n >= 1 && n <= 31) {
  2137.             current_event.until_date.day = n;
  2138.             current_event.until = 1;
  2139.             }
  2140.             print_until(¤t_event);
  2141.             break;
  2142.         case UYEAR_COL:
  2143.                 convert_year(current_date.year, &n);
  2144.             if (n >= FIRST_YEAR && n <= LAST_YEAR) {
  2145.             current_event.until_date.year = n;
  2146.             current_event.until = 1;
  2147.             }
  2148.             print_until(¤t_event);
  2149.             break;
  2150.         case NTH_COL:
  2151.             if (n > 0 && n <= 53) {
  2152.             current_event.nth = n;
  2153.             current_event.nth_is_on = 1;
  2154.             print_nth(¤t_event);
  2155.             }
  2156.             break;
  2157.         default:
  2158.             sound_bell();
  2159.             break;
  2160.         }
  2161.         } else {    /* must be on TIME_ROW */
  2162.         switch(ccol) {
  2163.         case START_COL:
  2164.             if (n < 24) {
  2165.             current_event.start_time.hour = n;
  2166.             compute_times(¤t_event, time_mode);
  2167.             print_times(¤t_event);
  2168.             }
  2169.             break;
  2170.         case DURATION_COL:
  2171.             if (n < 24) {
  2172.             current_event.duration.hour = n;
  2173.             compute_times(¤t_event, time_mode);
  2174.             print_times(¤t_event);
  2175.             }
  2176.             break;
  2177.         case END_COL:
  2178.             if (n < 24) {
  2179.             current_event.end_time.hour = n;
  2180.             compute_times(¤t_event, time_mode);
  2181.             print_times(¤t_event);
  2182.             }
  2183.             break;
  2184.         case WARNING_COL:
  2185.             if (n < 24) {
  2186.             current_event.warning.hour = n;
  2187.             print_warning(¤t_event);
  2188.             }
  2189.             break;
  2190.         case START_COL+3:
  2191.             if (n < 60) {
  2192.             current_event.start_time.minute = n;
  2193.             compute_times(¤t_event, time_mode);
  2194.             print_times(¤t_event);
  2195.             }
  2196.             break;
  2197.         case DURATION_COL+3:
  2198.             if (n < 60) {
  2199.             current_event.duration.minute = n;
  2200.             compute_times(¤t_event, time_mode);
  2201.             print_times(¤t_event);
  2202.             }
  2203.             break;
  2204.         case END_COL+3:
  2205.             if (n < 60) {
  2206.             current_event.end_time.minute = n;
  2207.             compute_times(¤t_event, time_mode);
  2208.             print_times(¤t_event);
  2209.             }
  2210.             break;
  2211.         case WARNING_COL+3:
  2212.             if (n < 60) {
  2213.             current_event.warning.minute = n;
  2214.             print_warning(¤t_event);
  2215.             }
  2216.             break;
  2217.         default:
  2218.             sound_bell();
  2219.             break;
  2220.         }
  2221.         }
  2222.         break;
  2223.     }
  2224. }
  2225.  
  2226. do_incr_sched(dir)
  2227. register dir;
  2228. {
  2229.     if (crow == TIME_ROW) {
  2230.         switch(ccol) {
  2231.         case START_COL:
  2232.         case DURATION_COL:
  2233.         case END_COL:
  2234.         case WARNING_COL:
  2235.         do_incr(dir);
  2236.         break;
  2237.         case START_COL+3:
  2238.         case DURATION_COL+3:
  2239.         case END_COL+3:
  2240.         case WARNING_COL+3:
  2241.         do_incr(15 * dir);
  2242.         break;
  2243.         default:
  2244.         sound_bell();
  2245.         break;
  2246.         }
  2247.     } else    /* must be on SCHEDULE_ROW */
  2248.         do_incr(dir);
  2249. }
  2250.  
  2251. do_incr(n)
  2252. short n;
  2253. {
  2254.     short shift;
  2255.  
  2256.     switch(current_area) {
  2257.     case MONTHS:
  2258.         hl_month(current_date.month, HL_OFF);
  2259.         if (n < 0)
  2260.         shift = -((abs(n) / 12) +
  2261.             ((current_date.month - (abs(n) % 12) < 1) ? 1 : 0));
  2262.         else
  2263.         shift = (n / 12) +
  2264.             ((current_date.month + (n % 12) > 12) ? 1 : 0);
  2265.  
  2266.         current_date.year += shift;
  2267.         if (print_all_years())
  2268.             mod(¤t_date.month, 1, 12, n);
  2269.         show_all_events(current_date.month, current_date.year);
  2270.         hl_month(current_date.month, HL_ON);
  2271.         goto_month();
  2272.         break;
  2273.     case DAYS:
  2274.         hl_month(current_date.month, HL_OFF);
  2275.         (void) incr_date(n, ¤t_date);
  2276.         print_all_years();
  2277.         hl_month(current_date.month, HL_ON);
  2278.         show_all_events(current_date.month, current_date.year);
  2279.         goto_day();
  2280.         break;
  2281.     case YEARS:
  2282.         hl_month(current_date.month, HL_OFF);
  2283.         current_date.year += n;
  2284.         print_all_years();
  2285.         hl_month(current_date.month, HL_ON);
  2286.         show_all_events(current_date.month, current_date.year);
  2287.         goto_year();
  2288.         break;
  2289.     case SCHEDULE:
  2290.         if (crow == SCHEDULE_ROW) {
  2291.         switch(ccol) {
  2292.         case SMONTH_COL:
  2293.             mod(¤t_event.start_date.month, 1, 12, n);
  2294.             print_date(¤t_event);
  2295.             break;
  2296.         case SDAY_COL:
  2297.             mod(¤t_event.start_date.day, 1, 31, n);
  2298.             print_date(¤t_event);
  2299.             break;
  2300.         case SYEAR_COL:
  2301.             mod(¤t_event.start_date.year, FIRST_YEAR,
  2302.                 LAST_YEAR, n);
  2303.             print_date(¤t_event);
  2304.             break;
  2305.         case UMONTH_COL:
  2306.             mod(¤t_event.until_date.month, 1, 12, n);
  2307.             current_event.until = 1;
  2308.             print_until(¤t_event);
  2309.             break;
  2310.         case UDAY_COL:
  2311.             mod(¤t_event.until_date.day, 1, 31, n);
  2312.             current_event.until = 1;
  2313.             print_until(¤t_event);
  2314.             break;
  2315.         case UYEAR_COL:
  2316.             mod(¤t_event.until_date.year, FIRST_YEAR,
  2317.             LAST_YEAR, n);
  2318.             current_event.until = 1;
  2319.             print_until(¤t_event);
  2320.             break;
  2321.         case NTH_COL:
  2322.             modc(¤t_event.nth, 0, 53, n);
  2323.             current_event.nth_is_on = 1;
  2324.             print_nth(¤t_event);
  2325.             break;
  2326.         default:
  2327.             sound_bell();
  2328.             break;
  2329.         }
  2330.         } else {    /* must be on TIME_ROW */
  2331.         switch(ccol) {
  2332.         case START_COL:
  2333.             mod(¤t_event.start_time.hour, 0, 23, n);
  2334.             compute_times(¤t_event, time_mode);
  2335.             print_times(¤t_event);
  2336.             break;
  2337.         case DURATION_COL:
  2338.             mod(¤t_event.duration.hour, 0, 23, n);
  2339.             compute_times(¤t_event, time_mode);
  2340.             print_times(¤t_event);
  2341.             break;
  2342.         case END_COL:
  2343.             mod(¤t_event.end_time.hour, 0, 23, n);
  2344.             compute_times(¤t_event, time_mode);
  2345.             print_times(¤t_event);
  2346.             break;
  2347.         case WARNING_COL:
  2348.             mod(¤t_event.warning.hour, 0, 23, n);
  2349.             print_warning(¤t_event);
  2350.             break;
  2351.         case START_COL+3:
  2352.             mod(¤t_event.start_time.minute, 0, 59, n);
  2353.             compute_times(¤t_event, time_mode);
  2354.             print_times(¤t_event);
  2355.             break;
  2356.         case DURATION_COL+3:
  2357.             mod(¤t_event.duration.minute, 0, 59, n);
  2358.             compute_times(¤t_event, time_mode);
  2359.             print_times(¤t_event);
  2360.             break;
  2361.         case END_COL+3:
  2362.             mod(¤t_event.end_time.minute, 0, 59, n);
  2363.             compute_times(¤t_event, time_mode);
  2364.             print_times(¤t_event);
  2365.             break;
  2366.         case WARNING_COL+3:
  2367.             mod(¤t_event.warning.minute, 0, 59, n);
  2368.             print_warning(¤t_event);
  2369.             break;
  2370.         default:
  2371.             sound_bell();
  2372.             break;
  2373.         }
  2374.         }
  2375.         break;
  2376.     }
  2377. }
  2378.  
  2379. prompt_wait()
  2380. {
  2381.     move(LINES-1, 0);
  2382.     clrtoeol();
  2383.     standout();
  2384.     addstr("Press any key to return to calendar ");
  2385.     standend();
  2386.     refresh();
  2387.     (void) get_char();
  2388. }
  2389.  
  2390. more()
  2391. {
  2392.     if (ccol != 0) {
  2393.         standout();
  2394.         addstr(" -more-");
  2395.         standend();
  2396.         ccol += 7;
  2397.         refresh();
  2398.         (void) get_char();
  2399.     }
  2400. }
  2401.  
  2402. mark_day(goto_flag)
  2403. short goto_flag;
  2404. {
  2405.     short ch;
  2406.  
  2407.     print_message("mark: ", NO_BELL);
  2408.  
  2409.     for (;;) {
  2410.         ch = get_char();
  2411.  
  2412.         switch(ch) {
  2413.         case '0':
  2414.         case '1':
  2415.         case '2':
  2416.         case '3':
  2417.         case '4':
  2418.         case '5':
  2419.         case '6':
  2420.         case '7':
  2421.         case '8':
  2422.         case '9':
  2423.             mvaddch(0, 6, ch);
  2424.             refresh();
  2425.             ch -= '0';
  2426.  
  2427.             if (goto_flag)
  2428.                 goto_this_day(&mdates[ch]);
  2429.             else {
  2430.                 mdates[ch].month = current_date.month;
  2431.                 mdates[ch].day = current_date.day;
  2432.                 mdates[ch].year =  current_date.year;
  2433.             }
  2434.             return;
  2435.         case '\033':    /* ^[ */
  2436.         case '\n':
  2437.             clear_message_line();
  2438.             return;
  2439.         }
  2440.     }
  2441. }
  2442.  
  2443. toggle_flag(flag_char)
  2444. char flag_char;
  2445. {
  2446.     switch(flag_char) {
  2447.     case 'A':
  2448.         all_flag = !all_flag;
  2449.         break;
  2450.     case 'I':
  2451.         ins_mode = !ins_mode;
  2452.         break;
  2453.     case 'K':
  2454.         keep_old = !keep_old;
  2455.         break;
  2456.     case 'O':
  2457.         over_flag = !over_flag;
  2458.         break;
  2459.     case 'R':
  2460.         read_only = !read_only;
  2461.         break;
  2462.     }
  2463.  
  2464.     print_flags();
  2465. }
  2466.  
  2467. mod(var, min, max, inc)
  2468. short *var, min, max, inc;
  2469. {
  2470.     if (inc > 0)
  2471.         *var = ((*var - min + inc) % (max - min + 1)) + min;
  2472.     else
  2473.         *var = ((*var - min + (max - min + 1) -
  2474.         (abs(inc) % (max - min + 1))) % (max - min + 1)) + min;
  2475. }
  2476.  
  2477. modc(var, min, max, inc)
  2478. char *var;
  2479. short min, max, inc;
  2480. {
  2481.     if (inc > 0)
  2482.         *var = (char) ((*var - min + inc) % (max - min + 1)) + min;
  2483.     else
  2484.         *var = (char) ((*var - min + (max - min + 1) -
  2485.         (abs(inc) % (max - min + 1))) % (max - min + 1)) + min;
  2486. }
  2487.  
  2488. #if MULTIUSER
  2489. do_read_mode()
  2490. {
  2491.     int i;
  2492.     char buf[BUFSIZE];
  2493.  
  2494.     if (read_only) {
  2495.         if ((i = read_schedule(month_dir, READ_WRITE)) == 0)
  2496.         toggle_flag('R');
  2497.         else if (i == -2) {
  2498.         print_message(".month file locked", BELL);
  2499.         i = read_schedule(month_dir, READ_ONLY);
  2500.         }
  2501.  
  2502.         if (i != 0)
  2503.         if (i == -1)
  2504.             print_message("cannot open .month", BELL);
  2505.             else {
  2506.             sprintf(buf, "cannot read .month version %d", i);
  2507.             print_message(buf, BELL);
  2508.         }
  2509.     } else    /* read/write */ {
  2510.         push_area(SCAN);
  2511.         if (update_schedule)
  2512.         ccol = print_message("updating schedule", NO_BELL);
  2513.         else
  2514.         ccol = print_message("schedule unchanged", NO_BELL);
  2515.  
  2516.         if (write_schedule() < 0) {
  2517.         more();
  2518.         print_message("cannot write .month", BELL);
  2519.             pop_area();
  2520.         return;
  2521.         }
  2522.         toggle_flag('R');
  2523.         pop_area();
  2524.     }
  2525.  
  2526.     show_all_events(current_date.month, current_date.year);
  2527. }
  2528. #endif MULTIUSER
  2529.  
  2530. help()
  2531. {
  2532.     char *buf;
  2533.     int blast_out(), terminate();
  2534.  
  2535.     push_area(HELP);
  2536.     clear();
  2537.     refresh();
  2538.     buf = malloc((unsigned) (strlen(PG) + strlen(HELPFILE) + 2));
  2539.     sprintf(buf, "%s %s", PG, HELPFILE);
  2540.     do_system(buf);
  2541.     prompt_wait();
  2542.     clear();
  2543.     print_screen();
  2544.     pop_area();
  2545.     new_day();              /* may be new day now */
  2546. }
  2547.  
  2548. print_aliases()
  2549. {
  2550.     char *alias_file_name, *buf;
  2551.     extern char *strcat(), *strcpy();
  2552.  
  2553.     alias_file_name = malloc((unsigned) strlen(month_dir)+10);
  2554.     strcpy(alias_file_name, month_dir);
  2555.     strcat(alias_file_name, "/.monthrc");
  2556.  
  2557.     push_area(ALIAS);
  2558.     clear();
  2559.     refresh();
  2560.     buf = malloc((unsigned) (strlen(PG) + strlen(alias_file_name) +
  2561.         strlen(ALIASFILE) + 3));
  2562.     sprintf(buf, "%s %s %s", PG, alias_file_name, ALIASFILE);
  2563.     free(alias_file_name);
  2564.     do_system(buf);
  2565.     prompt_wait();
  2566.     clear();
  2567.     print_screen();
  2568.     pop_area();
  2569.     new_day();        /* may be new day now */
  2570. }
  2571.  
  2572. #if SHELL_ESCAPE
  2573. shell_escape()
  2574. {
  2575.     char *buf;
  2576.  
  2577.     buf = malloc((unsigned) (strlen(SH) + 1));
  2578.     sprintf(buf, "%s", SH);
  2579.     clear();
  2580.     mvprintw(0, 0, "!%s\n", buf);
  2581.     refresh();
  2582.     endwin();
  2583.     do_system(buf);
  2584.     initscr();
  2585.     crmode();
  2586.     noecho();
  2587. #if SYS5CURSES
  2588.     keypad(stdscr, TRUE);
  2589. #endif
  2590.     clear();
  2591.     print_screen();
  2592.     new_day();        /* may be new day now */
  2593. }
  2594. #endif
  2595.  
  2596. do_system(buf)
  2597. char *buf;
  2598. {
  2599.     int gid, egid;
  2600.     int blast_out(), terminate();
  2601.     alarm_t alarm();
  2602.  
  2603.     alarm((alarm_t) 0);
  2604.     signal(SIGINT, SIG_DFL);
  2605.     signal(SIGQUIT, SIG_DFL);
  2606.     signal(SIGHUP, SIG_DFL);
  2607.     signal(SIGALRM, SIG_DFL);
  2608.     gid = (int) getgid();    /* get original group */
  2609.     egid = (int) getegid();    /* get group month */
  2610.     setgid(gid);        /* change to original group */
  2611.     system(buf);
  2612.     setgid(egid);        /* restore group month */
  2613.     free(buf);
  2614.     signal(SIGINT, blast_out);
  2615.     signal(SIGQUIT, blast_out);
  2616.     signal(SIGHUP, terminate);
  2617. }
  2618.  
  2619. lunar()
  2620. {
  2621.     long yday, calculate();
  2622.  
  2623.     yday = (long) (days_since_jan1(¤t_date) + 1);
  2624.     (void) calculate(yday, ((long) (current_date.year - 1900)),
  2625.         11L, 0L);
  2626.     push_area(LUNAR);
  2627.     draw();
  2628.     prompt_wait();
  2629.     clear();
  2630.     print_screen();
  2631.     pop_area();
  2632. }
  2633.  
  2634. change_time_mode()
  2635. {
  2636.     short i, *cols;
  2637.  
  2638.     static short time_cols[] = {
  2639.         START_COL, START_COL+3, DURATION_COL, DURATION_COL+3,
  2640.         END_COL, END_COL+3, WARNING_COL, WARNING_COL+3
  2641.     };
  2642.     static short start_cols[] = {
  2643.         DURATION_COL, DURATION_COL+3, DURATION_COL, DURATION_COL+3,
  2644.         END_COL, END_COL+3, WARNING_COL, WARNING_COL+3
  2645.     };
  2646.     static short duration_cols[] = {
  2647.         START_COL, START_COL+3, END_COL, END_COL+3,
  2648.         END_COL, END_COL+3, WARNING_COL, WARNING_COL+3
  2649.     };
  2650.     static short end_cols[] = {
  2651.         START_COL, START_COL+3, DURATION_COL, DURATION_COL+3,
  2652.         START_COL, START_COL+3, WARNING_COL, WARNING_COL+3
  2653.     };
  2654.     
  2655.     switch(time_mode) {
  2656.     case START_MODE:
  2657.         cols = end_cols;
  2658.         time_mode = END_MODE;
  2659.         break;
  2660.     case DURATION_MODE:
  2661.         cols = start_cols;
  2662.         time_mode = START_MODE;
  2663.         break;
  2664.     case END_MODE:
  2665.         cols = duration_cols;
  2666.         time_mode = DURATION_MODE;
  2667.         break;
  2668.     }
  2669.  
  2670.     if (crow == TIME_ROW) {
  2671.         i = 0;
  2672.         while(time_cols[i] != ccol)
  2673.         i++;
  2674.         ccol = *(cols+i);
  2675.     }
  2676.  
  2677.     print_times(¤t_event);
  2678. }
  2679. @EOF
  2680.  
  2681. chmod 644 user2.c
  2682.  
  2683. exit 0
  2684.  
  2685.