home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / sun / volume1 / calentool / part02 / calentool.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-27  |  21.6 KB  |  794 lines

  1. /*
  2.  * $Header: calentool.c,v 2.1 89/05/09 15:28:43 billr Exp $
  3.  */
  4. /*
  5.  * calentool.c
  6.  *
  7.  * calentool - a year/month/week/day-at-a-glance calendar for Sun workstations.
  8.  *
  9.  * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
  10.  *
  11.  * Original source Copyright (C) 1987, Sun Microsystems, Inc.
  12.  *    All Rights Reserved
  13.  * Permission is hereby granted to use and modify this program in source
  14.  * or binary form as long as it is not sold for profit and this copyright
  15.  * notice remains intact.
  16.  *
  17.  *
  18.  * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
  19.  *
  20.  * Changes and additions Copyright (C) 1988, 1989 Tektronix, Inc.
  21.  *    All Rights Reserved
  22.  * Permission is hereby granted to use and modify the modifications in source
  23.  * or binary form as long as they are not sold for profit and this copyright
  24.  * notice remains intact.
  25.  */
  26. #include <stdio.h>
  27. #include <suntool/sunview.h>
  28. #include <suntool/panel.h>
  29. #include <sys/time.h>
  30. #include <sys/file.h>
  31. #include <signal.h>
  32. #include "ct.h"
  33.  
  34. extern Pixfont *font, *sfont;
  35. extern char apts_pathname[], tmpapts_pathname[];
  36. extern char todays_date[];
  37. extern char version[];
  38. extern Panel_item clock_pi;
  39. extern Frame fframe;
  40. extern Panel panel;
  41. #ifndef NO_SUN_MOON
  42. extern Frame sframe;
  43. #endif
  44.  
  45. Frame frame = 0;
  46. Pixwin *main_pixwin;
  47. int day_is_open;
  48. struct tm today, current;
  49. struct tm First, Last;
  50. struct tm olddate;
  51. int mainsw_state, selected_type;
  52. int x_coord, y_coord, startx, starty;
  53. int read_only;
  54. int nr_weekdays, dayslot_width, day_message_size, n_tslots;
  55. int week_message_size, weekslot_width, weekslot_height, dayslot_height;
  56. int ybox_height, ybox_width;
  57. struct dayslot slots[N_SLOTS];
  58. struct rect_limits boxlims[31];
  59. struct rect_limits mboxlims[12];
  60. struct week_arrow week_arrows[6];
  61. struct weekrect week_boxes[7];
  62. Pixrect *daybox_pr, *timeslot_pr, *gray_pr;
  63. Pixrect *weekslot_pr, *weekarrow_pr, *smallarrow_pr;
  64. Pixrect *arrowhead_pr, *arrowshaft_pr;
  65. Pixrect *weekarrowhead_pr, *weekarrowshaft_pr;
  66. Pixrect *triangle_pr;
  67. Pixrect *ydaybox_pr, *ymonthbox_pr;
  68. Pixrect *ic_pr, *rev_ic_pr, *na_ic_pr;
  69. Rect ilabel_rect = {1, 67, 62, 9}; /* location of timestring under icon */
  70. char *mailto = NULL;
  71. int one_based = 0, new_entry = 0, version2 = 0;
  72. int otherfile = 0;
  73. char *othername;
  74. int beep = 0, show_time = 0;
  75. int include_old = 0, save_old = 0;
  76. #ifndef NO_HOLIDAYS
  77. int holiday_a = 0, holiday_c = 0, holiday_i = 0;
  78. int holiday_j = 0, holiday_s = 0;
  79. #endif
  80. char *progname;
  81. struct itimerval cal_timer;
  82. int update_interval = 0;
  83. int show_future = 1;
  84. Icon icon, rev_icon, na_icon;
  85. Cursor year_cursor, month_cursor, week_cursor, day_cursor;
  86. Cursor wait_cursor;
  87. char orig_apts_pathname[160];
  88. int orig_ro;
  89. char timestr[16], datestr_day[3], datestr_mon[4];
  90. struct pr_prpos where;
  91. int working_msg;
  92.  
  93. static short icon_data[] = {
  94. #include "std.icon"
  95. };
  96. static short rev_icon_data[] = {
  97. #include "rev.icon"
  98. };
  99. static short na_icon_data[] = {
  100. #include "nap.icon"
  101. };
  102. mpr_static(ic_mpr, 64, 64, 1, icon_data);
  103. mpr_static(rev_ic_mpr, 64, 64, 1, rev_icon_data);
  104. mpr_static(na_ic_mpr, 64, 64, 1, na_icon_data);
  105.  
  106. static short year_cursor_data[] = {
  107. #include "year.cursor"
  108. };
  109. static short month_cursor_data[] = {
  110. #include "month.cursor"
  111. };
  112. static short week_cursor_data[] = {
  113. #include "week.cursor"
  114. };
  115. static short day_cursor_data[] = { 
  116. #include "day.cursor"
  117. };
  118. static short wait_cursor_data[] = {
  119. #include <images/hglass.cursor>
  120. };
  121. mpr_static(year_cursor_pr, 16, 16, 1, year_cursor_data);
  122. mpr_static(month_cursor_pr, 16, 16, 1, month_cursor_data);
  123. mpr_static(week_cursor_pr, 16, 16, 1, week_cursor_data);
  124. mpr_static(day_cursor_pr, 16, 16, 1, day_cursor_data);
  125. mpr_static(wait_cursor_pr, 16, 16, 1, wait_cursor_data);
  126.  
  127. #ifndef NO_SUN_MOON
  128. static short moon_icon_data[] = {
  129. #include "moony.icon"
  130. };
  131. static short sun_icon_data[] = {
  132. #include "sunny.icon"
  133. };
  134. mpr_static(moon_icon_pr, 64, 64, 1, moon_icon_data);
  135. mpr_static(sun_icon_pr, 64, 64, 1, sun_icon_data);
  136. #endif
  137.  
  138. static short tri_up_data[] = {
  139. #include <images/tri_up.pr>
  140. };
  141. mpr_static(tri_up_pr, 16, 16, 1, tri_up_data);
  142.  
  143. static short tri_right_data[] = {
  144. #include <images/tri_right.pr>
  145. };
  146. mpr_static(tri_right_pr, 16, 16, 1, tri_right_data);
  147.  
  148. char *strcpy(), *strcat(), *rindex();
  149. static Notify_value cleanup(), itimer_handler();
  150. Notify_value myframe_interposer();
  151.  
  152. main(argc,argv)
  153. int argc;
  154. char *argv[];
  155. {
  156.     int   flag, i;
  157.     int   printit = 0, toolrunning = 1, user_pos = 0;
  158.     extern char *optarg;
  159.     
  160.     if (progname = rindex(*argv, '/'))
  161.         progname++;
  162.     else
  163.         progname = *argv;
  164.  
  165.     nr_weekdays = NR_WEEKDAYS;
  166.     n_tslots = (N_TSLOTS > N_SLOTS ? N_SLOTS : N_TSLOTS);
  167.  
  168.     get_today();    /* initial day is today */
  169.     current = today;
  170.     read_only = 0;
  171.     working_msg = 1;
  172.  
  173.     /*
  174.      * Check for -p or -m option, which means we don't want
  175.      * to create the tool. Also check for -Wp so we can supply
  176.      * a resonable default if the user doesn't supply one.
  177.      */
  178.     i = argc;
  179.     while (--i > 0) {
  180.         if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "-m")
  181.             || !strcmp(argv[i], "-P"))
  182.             toolrunning = 0;
  183.         if (!strcmp(argv[i], "-Wp"))
  184.             user_pos = 1;
  185.     }
  186.     if (toolrunning) {
  187.         /* 
  188.         ** Parse args: window_create must be called before getopt, so
  189.         ** it can interpret and extract -W flags for SunView.
  190.         */
  191.         frame = window_create(NULL, FRAME,
  192.                 FRAME_ARGC_PTR_ARGV, &argc, argv,
  193.                 WIN_ERROR_MSG,
  194.                 "Can't create base frame. Are you in Suntools?",
  195.                 0);
  196.     }
  197.  
  198.     while ((flag = getopt(argc, argv, "57bd:f:im:opPrtu:zH:h:w")) != EOF)
  199.         switch (flag) {   
  200.             case 'f':    /* use this file */
  201.             otherfile = 1;
  202.             othername = optarg;
  203.             break;
  204.             
  205.             case 'd':    /* starting date */
  206.             (void)parse_date(optarg, TRUE);
  207.             break;
  208.  
  209.             case 'r':    /* read only file */
  210.             read_only = 1;
  211.             break;
  212.             
  213.             case 'p':    /* print and exit */
  214.             read_only = 1;
  215.             printit = 1;
  216.             break;
  217.  
  218.             case 'P':    /* print and exit (ignore some notes) */
  219.             read_only = 1;
  220.             printit = 3;
  221.             break;
  222.  
  223.             case 'm':    /* mail today's appts and exit */
  224.             read_only = 1;
  225.             printit = 2;
  226.             mailto = optarg;
  227.             break;
  228.  
  229.             case 'b':    /* beep to console for pending appt */
  230.             beep = 1;
  231.             break;
  232.  
  233.             case 'i':    /* include old appt files */
  234.             include_old = 1;
  235.             break;
  236.  
  237.             case 'o':    /* save outdate appts to another file */
  238.             save_old = 1;
  239.             break;
  240.  
  241.             case 't':    /* display current time under icon */
  242.             show_time = 1;
  243.             break;
  244.  
  245.             case '5':    /* Mon - Fri week display */
  246.             nr_weekdays = 5;
  247.             break;
  248.  
  249.             case '7':    /* Sun - Sat week display */
  250.             nr_weekdays = 7;
  251.             break;
  252.  
  253.             case 'u':    /* update interval (in seconds) */
  254.             update_interval = atoi(optarg);
  255.             break;
  256.  
  257.             case 'w':    /* don't display Working! message */
  258.             working_msg = 0;
  259.             break;
  260.  
  261.             case 'z':    /* zero offset -- new style appts file */
  262.             one_based = 1;
  263.             break;
  264.  
  265. #ifndef NO_HOLIDAYS
  266.             case 'h':
  267.             /* show certain holidays */
  268.             switch (*optarg) {
  269.                 case 'A':
  270.                     /* all holidays */
  271.                     holiday_a = holiday_c = holiday_i = 1;
  272.                     holiday_j = holiday_s = 1;
  273.                     break;
  274.                 case 'a':
  275.                     /* astronomical events */
  276.                     holiday_a = 1;
  277.                     break;
  278.                 case 'c':
  279.                     /* Christian holidays */
  280.                     holiday_c = 1;
  281.                     break;
  282.                 case 'i':
  283.                     /* Islamic holidays */
  284.                     holiday_i = 1;
  285.                     break;
  286.                 case 'j':
  287.                     /* Jewish holidays */
  288.                     holiday_j = 1;
  289.                     break;
  290.                 case 's':
  291.                     /* secular holidays */
  292.                     holiday_s = 1;
  293.                     break;
  294.                 default:
  295.                     fprintf(stderr, "unknown holiday option (must be one of \"Aacijs\")");
  296.                     break;
  297.             }
  298.             break;
  299.  
  300.             case 'H':
  301.             /* show certain holidays day/week display only */
  302.             switch (*optarg) {
  303.                 case 'A':
  304.                     /* all holidays */
  305.                     holiday_a = holiday_c = holiday_i = 2;
  306.                     holiday_j = holiday_s = 2;
  307.                     break;
  308.                 case 'a':
  309.                     /* astronomical events */
  310.                     holiday_a = 2;
  311.                     break;
  312.                 case 'c':
  313.                     /* Christian holidays */
  314.                     holiday_c = 2;
  315.                     break;
  316.                 case 'i':
  317.                     /* Islamic holidays */
  318.                     holiday_i = 2;
  319.                     break;
  320.                 case 'j':
  321.                     /* Jewish holidays */
  322.                     holiday_j = 2;
  323.                     break;
  324.                 case 's':
  325.                     /* secular holidays */
  326.                     holiday_s = 2;
  327.                     break;
  328.                 default:
  329.                     fprintf(stderr, "unknown holiday option (must be one of \"Aacijs\")");
  330.                     break;
  331.             }
  332.             break;
  333. #else
  334.             case 'h':
  335.             case 'H':
  336.                 fprintf(stderr, "-h and -H options not available\n");
  337.                 break;
  338. #endif
  339.             case '?':
  340.             default:
  341.             fprintf(stderr, "usage: %s [options...]\nwhere <options> are:\n", progname);
  342.             fprintf(stderr, " -f <appointment_file>\n");
  343.             fprintf(stderr, " -r        // readonly\n");
  344.             fprintf(stderr, " -p        // print selected days appts and exit\n");
  345.             fprintf(stderr, " -P        // like -p, only don't print marked notes\n");
  346.             fprintf(stderr, " -m <user>    // mail selected days appts to <user>\n");
  347.             fprintf(stderr, " [-5|-7]    // 5-day or 7-day week display\n");
  348.             fprintf(stderr, " -d <date>    // display appts for <date>\n");
  349.             fprintf(stderr, " -b        // beep and display message when appt is pending\n");
  350.             fprintf(stderr, " -i        // auto-include outdated appts files\n");
  351.             fprintf(stderr, " -o        // create outdated include files\n");
  352.             fprintf(stderr, " -t        // display time below icon\n");
  353.             fprintf(stderr, " -u <interval>    // time update interval (seconds)\n");
  354.             fprintf(stderr, " -w        // don't display 'Working!' message\n");
  355. #ifndef NO_HOLIDAYS
  356.             fprintf(stderr, " -h <Aacijs>    // display selected computed holidays\n");
  357.             fprintf(stderr, "        // A=All, a=astronomical, c=Christian,\n");
  358.             fprintf(stderr, "        // i=Islamic, j=Jewish, s=secular\n");
  359.             fprintf(stderr, " -H <Aacijs>    // like -h, only flag them as marked\n");
  360. #endif
  361.             fprintf(stderr, " -z        // conversion flag (see INSTALL)\n");
  362.             fprintf(stderr, " <window_opts>    // Suntools -W options\n");
  363.             exit(1);
  364.             break;
  365.         }
  366.  
  367.  
  368.     if (toolrunning) {
  369.         (void) notify_set_signal_func(frame, cleanup, SIGHUP, NOTIFY_ASYNC);
  370.         (void) notify_set_signal_func(frame, cleanup, SIGINT, NOTIFY_ASYNC);
  371.         (void) notify_set_signal_func(frame, cleanup, SIGTERM, NOTIFY_ASYNC);
  372.     }
  373.  
  374.     /* 
  375.     ** Find the calendar file, etc.
  376.     */
  377.     if (do_files(FALSE))
  378.         /* can't open (or create) appts file */
  379.         exit(1);
  380.     strcpy(orig_apts_pathname, apts_pathname);
  381.     orig_ro = read_only;
  382.     get_printer();
  383.     
  384.     if (printit) {
  385.         print_apts(printit);
  386.         exit(0);
  387.     }
  388.  
  389.     get_fonts();
  390.  
  391.     if (!update_interval) {
  392.         if (!strcmp(UPDATE_RATE, "minute"))
  393.             update_interval = 60;
  394.         else if (!strcmp(UPDATE_RATE, "second"))
  395.             update_interval = 1; /* check in 1 sec */
  396.         else {
  397.             err_rpt("unknown update interval, defaulting to seconds", NON_FATAL);
  398.             update_interval = 1; /* check in 1 sec */
  399.         }
  400.     }
  401.  
  402.     /* create the cursors */
  403.     year_cursor = cursor_create(CURSOR_IMAGE, &year_cursor_pr,
  404.             CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  405.             CURSOR_OP, PIX_SRC^PIX_DST,
  406.             0);
  407.     month_cursor = cursor_create(CURSOR_IMAGE, &month_cursor_pr,
  408.             CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  409.             CURSOR_OP, PIX_SRC^PIX_DST,
  410.             0);
  411.     week_cursor = cursor_create(CURSOR_IMAGE, &week_cursor_pr,
  412.             CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  413.             CURSOR_OP, PIX_SRC^PIX_DST,
  414.             0);
  415.     day_cursor = cursor_create(CURSOR_IMAGE, &day_cursor_pr,
  416.             CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  417.             CURSOR_OP, PIX_SRC^PIX_DST,
  418.             0);
  419.     wait_cursor = cursor_create(CURSOR_IMAGE, &wait_cursor_pr,
  420.             CURSOR_XHOT, 7, CURSOR_YHOT, 7,
  421.             CURSOR_OP, PIX_SRC^PIX_DST,
  422.             0);
  423.  
  424.     /* create the icons */
  425.     /*
  426.      * make the icon big enough to display the time
  427.      * underneath the base icon image if -t option
  428.      */
  429.     ic_pr = mem_create(64, (show_time ? 77 : 64), 1);
  430.     rev_ic_pr = mem_create(64, (show_time ? 77 : 64), 1);
  431.     na_ic_pr = mem_create(64, (show_time ? 77 : 64), 1);
  432.     icon = icon_create(0);
  433.     rev_icon = icon_create(0);
  434.     na_icon = icon_create(0);
  435.     strncpy(datestr_mon, todays_date+4, 3);
  436.     datestr_mon[3] = '\0';
  437.     strncpy(datestr_day, todays_date+8, 2);
  438.     datestr_day[2] = '\0';
  439.     /* the basic standard icon */
  440.     pr_rop(ic_pr, 0, 0, 64, 64, PIX_SRC, &ic_mpr, 0, 0);
  441.     if (show_time) {
  442.         /* time string displayed below icon */
  443.         strcpy(timestr, todays_date+10);
  444.         if (update_interval == 60) {
  445.             /* display hh:mm */
  446.             timestr[6] = '\0';
  447.             ilabel_rect.r_left += 2*sfont->pf_defaultsize.x - 2;
  448.             ilabel_rect.r_width -= 2*sfont->pf_defaultsize.x;
  449.         } else
  450.             /* display hh:mm:ss */
  451.             timestr[9] = '\0';
  452.         /* draw a box around the time appendage */
  453.         pr_vector(ic_pr, 0, 64, 63, 64, PIX_SET, 1);
  454.         pr_vector(ic_pr, 63, 64, 63, 76, PIX_SET, 1);
  455.         pr_vector(ic_pr, 63, 76, 0, 76, PIX_SET, 1);
  456.         pr_vector(ic_pr, 0, 76, 0, 64, PIX_SET, 1);
  457.  
  458.         pr_rop(rev_ic_pr, 0, 0, 64, 77, PIX_SRC, ic_pr, 0, 0);
  459.         pr_rop(rev_ic_pr, 0, 0, 64, 64, PIX_SRC, &rev_ic_mpr, 0, 0);
  460.         pr_rop(na_ic_pr, 0, 0, 64, 77, PIX_SRC, ic_pr, 0, 0);
  461.         pr_rop(na_ic_pr, 0, 0, 64, 64, PIX_SRC, &na_ic_mpr, 0, 0);
  462.     } else {
  463.         pr_rop(rev_ic_pr, 0, 0, 64, 64, PIX_SRC, &rev_ic_mpr, 0, 0);
  464.         pr_rop(na_ic_pr, 0, 0, 64, 64, PIX_SRC, &na_ic_mpr, 0, 0);
  465.     }
  466.     /* add in the date */
  467.     where.pr = ic_pr;
  468.     where.pos.x = 13;
  469.     where.pos.y = 49 + 5;
  470.     pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day);
  471.     where.pr = na_ic_pr;
  472.     pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day);
  473.     where.pr = rev_ic_pr;
  474.     pf_ttext(where, PIX_SRC, sfont, datestr_day);
  475.     where.pos.x = 39;
  476.     where.pr = ic_pr;
  477.     pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_mon);
  478.     where.pr = na_ic_pr;
  479.     pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_mon);
  480.     where.pr = rev_ic_pr;
  481.     pf_ttext(where, PIX_SRC, sfont, datestr_mon);
  482.     (void)icon_init_from_pr(icon, ic_pr);
  483.     (void)icon_init_from_pr(rev_icon, rev_ic_pr);
  484.     (void)icon_init_from_pr(na_icon, na_ic_pr);
  485.     if (show_time) {
  486.         /* add label field */
  487.         icon_set(icon, ICON_LABEL_RECT, &ilabel_rect,
  488.                 ICON_LABEL, timestr,
  489.                 ICON_FONT, sfont,
  490.                 0);
  491.         icon_set(rev_icon, ICON_LABEL_RECT, &ilabel_rect,
  492.                 ICON_LABEL, timestr,
  493.                 ICON_FONT, sfont,
  494.                 0);
  495.         icon_set(na_icon, ICON_LABEL_RECT, &ilabel_rect,
  496.                 ICON_LABEL, timestr,
  497.                 ICON_FONT, sfont,
  498.                 0);
  499.     }
  500.  
  501.     week_message_size = WEEK_MESSAGE_SIZE;
  502.     weekslot_width = (font->pf_defaultsize.x * week_message_size) + 6;
  503.     dayslot_width = (nr_weekdays - 1) * weekslot_width;
  504.     day_message_size = dayslot_width / font->pf_defaultsize.x;
  505.     ybox_height = dayslot_height = weekslot_height = font->pf_defaultsize.y + 6;
  506.     ybox_width = 3 * font->pf_defaultsize.x;
  507.  
  508.     init_pixrects();    /* Initialize pictures. */
  509.  
  510.     /* Create the rest of the tool */
  511.     if (user_pos)
  512.         window_set(frame,
  513.              WIN_WIDTH, (nr_weekdays+1)*weekslot_width+40,
  514.              WIN_HEIGHT, (N_SLOTS+5)*weekslot_height+72,
  515.              FRAME_ICON, icon,
  516.              0);
  517.     else
  518.         /* supply default position */
  519.         window_set(frame,
  520.              WIN_WIDTH, (nr_weekdays+1)*weekslot_width+40,
  521.              WIN_HEIGHT, (N_SLOTS+5)*weekslot_height+72,
  522.              WIN_X, 100, WIN_Y, 56,
  523.              FRAME_ICON, icon,
  524.              0);
  525.  
  526.     create_panel();
  527.     create_main_window();
  528.     create_attr_frame();    /* normally hidden */
  529.     create_del_frame();    /* normally hidden */
  530.     create_file_frame();    /* normally hidden */
  531.     create_date_frame();    /* normally hidden */
  532. #ifndef NO_PRINTER
  533.     create_print_frame();    /* normally hidden */
  534. #endif
  535.     check_calendar();    /* set proper icon */
  536.  
  537.     /* interpose on frame events (specifically open/close) */
  538.     (void) notify_interpose_event_func(frame, myframe_interposer, NOTIFY_SAFE);
  539.     /**
  540.     (void) notify_interpose_event_func(panel, myframe_interposer, NOTIFY_SAFE);
  541.     **/
  542.  
  543.     timerclear(&(cal_timer.it_interval));
  544.     timerclear(&(cal_timer.it_value));
  545.     cal_timer.it_value.tv_sec = (long)update_interval;
  546.     cal_timer.it_value.tv_usec = 0L;
  547.     (void) notify_set_itimer_func(frame, itimer_handler, ITIMER_REAL, &cal_timer, NULL);
  548.  
  549.     window_main_loop(frame);
  550.  
  551.     cleanup();
  552. }            
  553.              
  554.  
  555. static Notify_value
  556. itimer_handler(me, which)
  557. Notify_client me;
  558. int which;
  559. {
  560.     static int timeout_cntr = 0;
  561.     Icon cur_icon;
  562.  
  563.     timerclear(&(cal_timer.it_interval));
  564.     timerclear(&(cal_timer.it_value));
  565.     cal_timer.it_value.tv_sec = (long)update_interval;
  566.     cal_timer.it_value.tv_usec = 0L;
  567.     (void) notify_set_itimer_func(frame, itimer_handler, ITIMER_REAL, &cal_timer, NULL);
  568.     get_today();
  569.     /* update date/time displayed in the panel */
  570.     panel_set(clock_pi, PANEL_LABEL_STRING, todays_date, 0);
  571.     if (show_time && (int)window_get(frame, FRAME_CLOSED)) {
  572.         strcpy(timestr, todays_date+10);
  573.         if (update_interval == 60)
  574.             /* display hh:mm */
  575.             timestr[6] = '\0';
  576.         else
  577.             /* display hh:mm:ss */
  578.             timestr[9] = '\0';
  579.         cur_icon = (Icon) window_get(frame, FRAME_ICON);
  580.         icon_set(cur_icon, ICON_LABEL, timestr, 0);
  581.         window_set(frame, FRAME_ICON, cur_icon, 0);
  582.     }
  583. #ifndef NO_SUN_MOON
  584.     /* update data in Sun Data frame (if it's open) */
  585.     if (sframe)
  586.         write_times();
  587. #endif
  588.     /* only check appointments every TIME_OUT minutes */
  589.     timeout_cntr += update_interval;
  590.     if (timeout_cntr/60 < TIME_OUT)
  591.         return(NOTIFY_DONE);
  592.     timeout_cntr = 0;
  593.     /* check todays appointments */
  594.     check_calendar();
  595.     return(NOTIFY_DONE);
  596. }
  597.  
  598. /*
  599.  * When timer has expired check to see if we are close to an
  600.  * appointment. If so, switch to the other icon so we have a
  601.  * visual indication and beep the console (if enabled).
  602.  */
  603. check_calendar()
  604. {
  605.     int appt_pending = 0;     /* no appointments pending */
  606.     int some_appts = 0;    /* no appointments today */
  607.     int slotno = 0;     /* start with first timeslot */
  608.     static int icon_in_use = STD_ICON;
  609.     static int echoed_sno = -1;
  610.     static int new_day = 0;
  611.     int sno;
  612.     Icon cur_icon;
  613.     struct timeval gtime;
  614.     struct timezone tz;
  615.     struct tm Save;
  616.     FILE *console, *msgf;
  617.     char msgfile[128];
  618.     char *getenv();
  619.  
  620.     sno = echoed_sno;    /* assume no console echo */
  621.     Save = current;
  622.     strcpy(msgfile, getenv("HOME"));
  623.     strcat(msgfile, "/.msgfile");
  624.     /*
  625.      * Check to see if we've run over into the next day. If so,
  626.      * we need to update our slot information.
  627.      */
  628.     if (ymd_compare(current, today) != 0) {
  629.         if (day_is_open)
  630.             close_day();
  631.         current = today;
  632.         err2console(TRUE);
  633.         get_day_appts();
  634.         err2console(FALSE);
  635.         day_is_open = TRUE;
  636.         if (!new_day) {
  637.             new_day++;
  638.             sno = echoed_sno = -1;
  639.         }
  640.     } else
  641.         new_day = 0;
  642.     if (today.tm_hour >= START_HOUR) {
  643.         slotno = (today.tm_hour - START_HOUR)*2 + today.tm_min/30;
  644.         if (slotno < n_tslots) {
  645.             if (slots[slotno].active != INACTIVE) {
  646.                 /* appointment is happening now */
  647.                 appt_pending++;
  648.                 if (slots[slotno].active == ACTIVE)
  649.                     sno = slotno;
  650.             } else if (slotno+1 < n_tslots) {
  651.                 if (slots[slotno+1].active != INACTIVE)
  652.                     /* are we within 10 mins of an appointment? */
  653.                     if ((today.tm_min % 30) >= 20) {
  654.                         appt_pending++;
  655.                         if (slots[slotno+1].active == ACTIVE)
  656.                             sno = slotno+1;
  657.                     }
  658.             }
  659.         }
  660.     }
  661.     if (!appt_pending) {
  662.         /*
  663.          * Is there anything happening today (optionally
  664.          * including memos)?
  665.          * Don't care about things that happened before now
  666.          * so start looking at <slotno>, which was set above to
  667.          * reflect the current hour (or 0 if before START_HOUR).
  668.          */
  669.         /*
  670.          * APPT_CHECK_LIMIT is typically either "n_tslots"
  671.          * or "N_SLOTS" depending on whether we include the
  672.          * notes section when indicating that we still have
  673.          * appts today.
  674.          */
  675.         while (slotno < APPT_CHECK_LIMIT)
  676.             if (slots[slotno++].active != INACTIVE) {
  677.                 some_appts++;
  678.                 break;
  679.             }
  680.         /* maybe change the icon */
  681.         if ((some_appts && (icon_in_use != STD_ICON)) ||
  682.            (!some_appts && (icon_in_use != NA_ICON))) {
  683.             window_set(frame,
  684.                 FRAME_ICON, (some_appts?
  685.                 icon : na_icon),
  686.                 0);
  687.             icon_in_use = some_appts ? STD_ICON : NA_ICON;
  688.         }
  689.         /* clean out the ~/.msgfile file */
  690.         if (beep && ((msgf = fopen(msgfile, "w")) != NULL)) {
  691.             fprintf(msgf, "I'm out running around.");
  692.             fclose(msgf);
  693.         }
  694.     } else {
  695.          /* notify the user via the console (once) ... */
  696.         if (beep && sno != echoed_sno) {
  697.             echoed_sno = sno;
  698.             window_bell(frame);
  699.             if ((console = fopen("/dev/console", "w")) != NULL) {
  700.                 fprintf(console, "%s\n", slots[sno].cur_appt->str);
  701.                 fclose(console);
  702.             }
  703.             /*
  704.              * also put a copy in ~/.msgfile, in case
  705.              * nlock(1) is running
  706.              */
  707.             if ((msgf = fopen(msgfile, "w")) != NULL) {
  708.                 fprintf(msgf, "%s", slots[sno].cur_appt->str);
  709.                 fclose(msgf);
  710.             }
  711.         }
  712.          /* ... and change the icon */
  713.         if (icon_in_use != REV_ICON) {
  714.             window_set(frame,
  715.                 FRAME_ICON, rev_icon,
  716.                 0);
  717.             icon_in_use = REV_ICON;
  718.         }
  719.     }
  720.     if (new_day) {
  721.         /* if we're iconic, then go ahead and update the current
  722.          * day, otherwise restore it to what it was before.
  723.          */
  724.         if ((int)window_get(frame, FRAME_CLOSED)) {
  725.             /* so that it opens on today */
  726.             olddate = current = today;
  727.             /* update date field of the icons */
  728.             strncpy(datestr_mon, todays_date+4, 3);
  729.             strncpy(datestr_day, todays_date+8, 2);
  730.             /* replace the date */
  731.             where.pr = ic_pr;
  732.             where.pos.x = 13;
  733.             where.pos.y = 49 + 5;
  734.             pr_rop(where.pr, 14, 47, 10, 8, PIX_CLR, NULL, 0, 0);
  735.             pr_rop(where.pr, 40, 47, 16, 8, PIX_CLR, NULL, 0, 0);
  736.             pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day);
  737.             where.pr = na_ic_pr;
  738.             pr_rop(where.pr, 14, 47, 10, 8, PIX_CLR, NULL, 0, 0);
  739.             pr_rop(where.pr, 40, 47, 16, 8, PIX_CLR, NULL, 0, 0);
  740.             pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_day);
  741.             where.pr = rev_ic_pr;
  742.             pr_rop(where.pr, 14, 47, 10, 8, PIX_SET, NULL, 0, 0);
  743.             pr_rop(where.pr, 40, 47, 16, 8, PIX_SET, NULL, 0, 0);
  744.             pf_ttext(where, PIX_SRC, sfont, datestr_day);
  745.             where.pos.x = 39;
  746.             where.pr = ic_pr;
  747.             pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_mon);
  748.             where.pr = na_ic_pr;
  749.             pf_ttext(where, PIX_NOT(PIX_SRC), sfont, datestr_mon);
  750.             where.pr = rev_ic_pr;
  751.             pf_ttext(where, PIX_SRC, sfont, datestr_mon);
  752.             icon_set(icon, ICON_IMAGE, ic_pr, 0);
  753.             icon_set(rev_icon, ICON_IMAGE, rev_ic_pr, 0);
  754.             icon_set(na_icon, ICON_IMAGE, na_ic_pr, 0);
  755.             switch (icon_in_use) {
  756.                 case STD_ICON:
  757.                     window_set(frame, FRAME_ICON, icon, 0);
  758.                     break;
  759.                 case REV_ICON:
  760.                     window_set(frame, FRAME_ICON, rev_icon, 0);
  761.                     break;
  762.                 case NA_ICON:
  763.                     window_set(frame, FRAME_ICON, na_icon, 0);
  764.                     break;
  765.             }
  766.             new_day = 0;
  767.         } else {
  768.             if (day_is_open)
  769.                 close_day();
  770.             current = Save;
  771.             err2console(TRUE);
  772.             get_day_appts();
  773.             err2console(FALSE);
  774.             day_is_open = TRUE;
  775.         }
  776.         show_future = 1;    /* show future appts again */
  777.     }
  778. }
  779.  
  780. static Notify_value
  781. cleanup(me, signal, when)
  782. Notify_client me;
  783. int signal;
  784. Notify_signal_mode when;
  785. {
  786.     if (day_is_open)
  787.         close_day();
  788.     if (access(tmpapts_pathname, R_OK) == 0 && unlink(tmpapts_pathname) < 0)
  789.         perror(tmpapts_pathname);
  790.     exit(0);
  791.     /* NOTREACHED */
  792.     return(NOTIFY_DONE);
  793. }
  794.