home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume15 / monthtool2 / part02 / monthtool.c
Encoding:
C/C++ Source or Header  |  1988-06-01  |  42.5 KB  |  1,678 lines

  1. /*  @(#)monthtool.c    5.1 2/20/88 */
  2.  
  3. /*
  4.     Name:        monthtool
  5.   
  6.     Purpose:     visual appointment calendar 
  7.   
  8.     Author:        Sarah Metcalfe apres Mike Essex & Rich Burridge
  9.   
  10.     Discussion: Displays a calendar to the screen for a given month.  
  11.                 User may move the mouse to any day of the
  12.                 month and view or enter appointments for that date. 
  13.  
  14.     Modifications:
  15.                 10 Oct 87:    Sarah Metcalfe
  16.                             Allow weekly appointments.
  17.                             Automatically save on close and reload on open.
  18.                             Automatically switch to today on open.
  19.                  9 Nov 87:    D. Brent Chapman (capmkt!brent) 
  20.                             Set the "DEFAULT_FONT" environment variable to 
  21.                             the monthtool font, so that the program works 
  22.                             properly under SunOS 3.4.
  23.                 25 Nov 87:    Steve Schlaifer (jplgodo!steve) 
  24.                             Better fix for above problem.
  25.                 25 Nov 87:    Sarah Metcalfe 
  26.                             Create half-shaded date boxes for days with only
  27.                             yearly, monthly, weekly appts.
  28.                 20 Feb 88:    Sarah Metcalfe 
  29.                             Fix message length bug (at least somewhat).
  30.  
  31. */
  32.  
  33.  
  34.  
  35.  
  36. #include "monthtool.h"
  37.  
  38. static Notify_value     openCloseEvent();
  39.  
  40. void             dateEvent();
  41.  
  42. void             monthEvent();
  43. void             todayBtnHit();
  44. void             upBtnHit();
  45. void             downBtnHit();
  46. void             monthBackgroundHit();
  47.  
  48. void             notesBackgroundHit();
  49. void             notesPanelEvent();
  50. void             notesRadioHit();
  51.  
  52. Canvas             datesDsply;
  53. Textsw             notesDsply;
  54. Panel             monthPanel,
  55.                  notesPanel;
  56. Frame             frame;
  57. Menu             mainMenu,
  58.                  fileMenu;
  59. Panel_item         monthItem,
  60.                  notesTypeItem;
  61. Pixwin            *datesCrayon;
  62. struct pixfont     *font,
  63.                 *notesFont;
  64.  
  65.  
  66. short             dayIcon[] = {
  67.     0xFFFF,0xFFFF,0xFF00,0x0000,0x8000,0x0000,0x0100,0x0000,
  68.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  69.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  70.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  71.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  72.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  73.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  74.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  75.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  76.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  77.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  78.     0x8000,0x0000,0x0100,0x0000,0x8000,0x0000,0x0100,0x0000,
  79.     0x8000,0x0000,0x0100,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  80.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  81.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  82.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  83.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  84.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  85.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  86.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  87.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  88.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  89.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  90.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  91.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  92.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  93.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  94.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  95.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  96.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  97.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  98.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
  99. };
  100. mpr_static(dayPr, 64, 64, 1, dayIcon);
  101.  
  102. short             halfDayIcon[] = {
  103.     0xFFFF,0xFFFF,0xFF00,0x0000,0x8000,0x0000,0x0100,0x0000,
  104.     0xBFFF,0xFFFF,0xFD00,0x0000,0xA000,0x0000,0x0500,0x0000,
  105.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  106.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  107.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  108.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  109.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  110.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  111.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  112.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  113.     0xA000,0x0000,0x0500,0x0000,0xA000,0x0000,0x0500,0x0000,
  114.     0xA000,0x0000,0x0500,0x0000,0xBFFF,0xFFFF,0xFD00,0x0000,
  115.     0x8000,0x0000,0x0100,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  116.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  117.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  118.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  119.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  120.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  121.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  122.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  123.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  124.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  125.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  126.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  127.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  128.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  129.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  130.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  131.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  132.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  133.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  134.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
  135. };
  136. mpr_static(halfDayPr, 64, 64, 1, halfDayIcon);
  137.  
  138. short             fullDayIcon[] = {
  139.     0xFFFF,0xFFFF,0xFF00,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  140.     0xFFFF,0xFFFF,0xFF00,0x0000,0xE000,0x0000,0x0700,0x0000,
  141.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  142.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  143.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  144.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  145.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  146.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  147.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  148.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  149.     0xE000,0x0000,0x0700,0x0000,0xE000,0x0000,0x0700,0x0000,
  150.     0xE000,0x0000,0x0700,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  151.     0xFFFF,0xFFFF,0xFF00,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  152.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  153.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  154.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  155.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  156.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  157.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  158.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  159.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  160.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  161.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  162.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  163.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  164.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  165.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  166.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  167.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  168.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  169.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  170.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
  171. };
  172. mpr_static(fullDayPr, 64, 64, 1, fullDayIcon);
  173.  
  174. short             daySelIcon[] = {
  175.     0xFFFF,0xFFFF,0xFF00,0x0000,0xA222,0x2222,0x2300,0x0000,
  176.     0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
  177.     0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
  178.     0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
  179.     0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
  180.     0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
  181.     0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
  182.     0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
  183.     0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
  184.     0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
  185.     0x8888,0x8888,0x8900,0x0000,0xA222,0x2222,0x2300,0x0000,
  186.     0xC444,0x4444,0x4500,0x0000,0x9111,0x1111,0x1100,0x0000,
  187.     0x8888,0x8888,0x8900,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  188.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  189.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  190.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  191.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  192.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  193.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  194.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  195.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  196.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  197.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  198.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  199.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  200.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  201.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  202.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  203.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  204.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  205.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  206.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
  207. };
  208. mpr_static(daySelPr, 64, 64, 1, daySelIcon);
  209.  
  210. short             halfDaySelIcon[] = {
  211.     0xFFFF,0xFFFF,0xFF00,0x0000,0x8000,0x0000,0x0100,0x0000,
  212.     0xBFFF,0xFFFF,0xFD00,0x0000,0xB111,0x1111,0x1500,0x0000,
  213.     0xA888,0x8888,0x8D00,0x0000,0xA222,0x2222,0x2500,0x0000,
  214.     0xA444,0x4444,0x4500,0x0000,0xB111,0x1111,0x1500,0x0000,
  215.     0xA888,0x8888,0x8D00,0x0000,0xA222,0x2222,0x2500,0x0000,
  216.     0xA444,0x4444,0x4500,0x0000,0xB111,0x1111,0x1500,0x0000,
  217.     0xA888,0x8888,0x8D00,0x0000,0xA222,0x2222,0x2500,0x0000,
  218.     0xA444,0x4444,0x4500,0x0000,0xB111,0x1111,0x1500,0x0000,
  219.     0xA888,0x8888,0x8D00,0x0000,0xA222,0x2222,0x2500,0x0000,
  220.     0xA444,0x4444,0x4500,0x0000,0xB111,0x1111,0x1500,0x0000,
  221.     0xA888,0x8888,0x8D00,0x0000,0xA222,0x2222,0x2500,0x0000,
  222.     0xA444,0x4444,0x4500,0x0000,0xBFFF,0xFFFF,0xFD00,0x0000,
  223.     0x8000,0x0000,0x0100,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  224.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  225.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  226.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  227.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  228.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  229.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  230.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  231.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  232.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  233.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  234.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  235.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  236.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  237.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  238.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  239.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  240.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  241.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  242.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
  243. };
  244. mpr_static(halfDaySelPr, 64, 64, 1, halfDaySelIcon);
  245.  
  246. short             fullDaySelIcon[] = {
  247.     0xFFFF,0xFFFF,0xFF00,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  248.     0xFFFF,0xFFFF,0xFF00,0x0000,0xF111,0x1111,0x1700,0x0000,
  249.     0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
  250.     0xE444,0x4444,0x4700,0x0000,0xF111,0x1111,0x1700,0x0000,
  251.     0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
  252.     0xE444,0x4444,0x4700,0x0000,0xF111,0x1111,0x1700,0x0000,
  253.     0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
  254.     0xE444,0x4444,0x4700,0x0000,0xF111,0x1111,0x1700,0x0000,
  255.     0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
  256.     0xE444,0x4444,0x4700,0x0000,0xF111,0x1111,0x1700,0x0000,
  257.     0xE888,0x8888,0x8F00,0x0000,0xE222,0x2222,0x2700,0x0000,
  258.     0xE444,0x4444,0x4700,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  259.     0xFFFF,0xFFFF,0xFF00,0x0000,0xFFFF,0xFFFF,0xFF00,0x0000,
  260.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  261.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  262.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  263.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  264.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  265.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  266.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  267.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  268.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  269.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  270.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  271.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  272.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  273.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  274.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  275.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  276.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  277.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  278.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
  279. };
  280. mpr_static(fullDaySelPr, 64, 64, 1, fullDaySelIcon);
  281.  
  282.  
  283. short             upBtnIcon[] = {
  284.     0x3FFF,0xE000,0x7FFF,0xF000,
  285.     0xE000,0x3800,0xC000,0x1800,
  286.     0xC020,0x1800,0xC070,0x1800,
  287.     0xC0F8,0x1800,0xC1FC,0x1800,
  288.     0xC3FE,0x1800,0xC7FF,0x1800,
  289.     0xCFFF,0x9800,0xC0F8,0x1800,
  290.     0xC0F8,0x1800,0xC0F8,0x1800,
  291.     0xC0F8,0x1800,0xC000,0x1800,
  292.     0xE000,0x3800,0x7FFF,0xF000,
  293.     0x3FFF,0xE000,0x0000,0x0000
  294. };
  295. mpr_static(upBtnPr, BTN_WIDTH, BTN_HEIGHT, 1, upBtnIcon);
  296.  
  297. short             downBtnIcon[] = {
  298.     0x3FFF,0xE000,0x7FFF,0xF000,
  299.     0xE000,0x3800,0xC000,0x1800,
  300.     0xC0F8,0x1800,0xC0F8,0x1800,
  301.     0xC0F8,0x1800,0xC0F8,0x1800,
  302.     0xCFFF,0x9800,0xC7FF,0x1800,
  303.     0xC3FE,0x1800,0xC1FC,0x1800,
  304.     0xC0F8,0x1800,0xC070,0x1800,
  305.     0xC020,0x1800,0xC000,0x1800,
  306.     0xE000,0x3800,0x7FFF,0xF000,
  307.     0x3FFF,0xE000,0x0000,0x0000
  308. };
  309. mpr_static(downBtnPr, BTN_WIDTH, BTN_HEIGHT, 1, downBtnIcon);
  310.  
  311.  
  312. short             toolIcon[] = {
  313.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8C08,0x87C2,0x21F0,0xF031,
  314.     0x920D,0x8102,0x2040,0x8049,0x880A,0x8102,0xA040,0xE021,
  315.     0x840A,0x8102,0xA040,0x8011,0x9208,0x8103,0x6040,0x8049,
  316.     0x8C08,0x8102,0x2040,0x8031,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  317.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8040,0x2010,0x0804,0x0201,
  318.     0x8040,0x2814,0x0A05,0x0281,0x8040,0x2814,0x0A05,0x0281,
  319.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
  320.     0x8040,0x2013,0xA804,0x0201,0x8040,0x2010,0x0804,0x0201,
  321.     0x8040,0x2016,0x8804,0x0201,0x8040,0x2010,0x0804,0x0201,
  322.     0x8040,0x2010,0x0804,0x0201,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  323.     0x8040,0x2010,0x0804,0x0201,0xA050,0x2814,0x0B05,0x82C1,
  324.     0xA050,0x2814,0x0B05,0x82C1,0x8040,0x2010,0x0804,0x0201,
  325.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0805,0xD201,
  326.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
  327.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
  328.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8040,0x2010,0x0804,0x0201,
  329.     0xB058,0x2C16,0x0B05,0x82C1,0xB058,0x2C16,0x0B05,0x82C1,
  330.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2F50,0x0804,0x0201,
  331.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2D50,0x0804,0x0201,
  332.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
  333.     0x8040,0x2010,0x0804,0x0201,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  334.     0x8040,0x2010,0x0804,0x0201,0xB058,0x2C16,0x0B05,0x82C1,
  335.     0xB058,0x2C16,0x0B05,0x82C1,0x8040,0x2010,0x0804,0x0201,
  336.     0x8040,0x2010,0x0BE4,0x0201,0x8040,0x2010,0x0804,0x0201,
  337.     0x8040,0x2010,0x0BA4,0x0201,0x8040,0x2010,0x0804,0x0201,
  338.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
  339.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8040,0x2010,0x0804,0x0201,
  340.     0xB058,0x2C16,0x0B04,0x0201,0xB058,0x2C16,0x0B04,0x0201,
  341.     0x8040,0x2010,0x0804,0x0201,0x8040,0x2010,0x0804,0x0201,
  342.     0xBA40,0x2017,0xC804,0x0201,0x8040,0x2010,0x0804,0x0201,
  343.     0x8040,0x2013,0xC804,0x0201,0x9240,0x2010,0x0804,0x0201,
  344.     0x8040,0x2010,0x0804,0x0201,0xFFFF,0xFFFF,0xFFFF,0xFFFF
  345. };
  346. DEFINE_ICON_FROM_IMAGE(monthIcon, toolIcon);
  347.  
  348.  
  349.  
  350. struct dateBox         monthBoxes[DATE_ROWS][DATE_COLS];
  351.  
  352.  
  353. struct apptsData     *firstApptRecord[NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/];
  354. struct apptsData     *lastApptRecord[NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/];
  355.  
  356.     
  357. int                     tmonth, tday, tyear;
  358. int                     firstDow;
  359.  
  360. int                     yearToShow, monthToShow;
  361. int                     dayToShow = 0;
  362. int                     dateNumToShow[NUM_NOTES_TYPE];
  363.  
  364. int                     editCount = 0;
  365. int                     notesModified = 0;
  366. int                     hasWeeklyNotes;
  367.  
  368. char                 toolFile[80];
  369. struct stat             lastStatus;
  370.  
  371. char                 typeChar[NUM_NOTES_TYPE] = { 0x90, 0x91, 0x92, 0x93, 0x94 }; 
  372. char                 typeMark[3] = "  ";
  373.                             
  374. char                *smon[] = { "January", "February", "March",
  375.                                 "April", "May", "June",
  376.                                 "July", "August", "September",
  377.                                 "October", "November", "December"
  378.                               };
  379. int                     mon[] = { 0,     31, 29, 31, 
  380.                                     30, 31, 30,
  381.                                     31, 31, 30, 
  382.                                     31, 30, 31, 
  383.                               };
  384.  
  385.  
  386. main(argc, argv)
  387.  
  388. int         argc;
  389. char    *argv[];
  390.  
  391. {
  392.     char    fontString[80];
  393.     char    choiceString[2];
  394.     int        type;
  395.  
  396.     /* set default font */
  397.  
  398.     strcpy(fontString, FONTDIR);
  399.     strcat(fontString, NORMALFONT);
  400.  
  401.     font = pf_open(LARGEFONT);              /* Open large sized font. */
  402.     notesFont = pf_open(fontString);        /* Open regular sized font. */
  403.  
  404.     /* Set up menus */
  405.                         
  406.     fileMenu = menu_create(MENU_ITEM,
  407.                                 MENU_STRING,    "Save",
  408.                                 MENU_VALUE,         MENU_SAVE,
  409.                                 0,
  410.                             MENU_ITEM,
  411.                                 MENU_STRING,    "Reload",
  412.                                 MENU_VALUE,         MENU_RELOAD,
  413.                                 0,
  414.                             0);
  415.  
  416.     mainMenu = menu_create(MENU_ITEM,
  417.                                 MENU_STRING,    "Close (with Save)",
  418.                                 MENU_VALUE,         MENU_CLOSE,
  419.                                 0,
  420.                             MENU_ITEM,
  421.                                 MENU_STRING,    "Update Appts.",
  422.                                 MENU_PULLRIGHT,     fileMenu,
  423.                                 0,
  424.                             MENU_ITEM,
  425.                                 MENU_STRING,    "Quit (with Save)",
  426.                                 MENU_VALUE,         MENU_QUIT,
  427.                                 0,
  428.                             0);
  429.                         
  430.  
  431.     /*    Set up windows */
  432.  
  433.     frame = window_create(0, FRAME,
  434.                 FRAME_ICON, &monthIcon,
  435.                 FRAME_SHOW_LABEL, FALSE,
  436.                 FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
  437.                 FRAME_NO_CONFIRM, FALSE,
  438.                 WIN_HEIGHT, DATES_HEIGHT + MONTH_HEIGHT + 
  439.                     NOTES_PANEL_HEIGHT + NOTES_HEIGHT + 25,
  440.                 WIN_WIDTH, WINDOW_WIDTH + 10,
  441.                 FRAME_ARGS, argc, argv,
  442.                 0);
  443.     (void) notify_interpose_event_func( frame, openCloseEvent, NOTIFY_SAFE );
  444.  
  445.     monthPanel = window_create(frame, PANEL,
  446.                 WIN_X, 0,
  447.                 WIN_Y, 0,
  448.                 WIN_HEIGHT, MONTH_HEIGHT,
  449.                 WIN_WIDTH, WINDOW_WIDTH,
  450.                 WIN_FONT, font,
  451.                 PANEL_BACKGROUND_PROC, monthBackgroundHit,
  452.                 PANEL_EVENT_PROC, monthEvent,
  453.                 0);
  454.  
  455.     datesDsply = window_create(frame, CANVAS,
  456.                 WIN_X, 0,
  457.                 WIN_BELOW, monthPanel,
  458.                 WIN_HEIGHT, DATES_HEIGHT,
  459.                 WIN_WIDTH, WINDOW_WIDTH,
  460.                 WIN_FONT, font,
  461.                 WIN_EVENT_PROC, dateEvent,
  462.                 WIN_CONSUME_KBD_EVENTS, WIN_ASCII_EVENTS, WIN_LEFT_KEYS, 0,
  463.                 0);
  464.  
  465.     datesCrayon = canvas_pixwin(datesDsply);
  466.  
  467.     notesPanel = window_create(frame, PANEL,
  468.                 WIN_X, 0,
  469.                 WIN_BELOW, datesDsply,
  470.                 WIN_HEIGHT, NOTES_PANEL_HEIGHT,
  471.                 WIN_WIDTH, WINDOW_WIDTH,
  472.                 WIN_FONT, notesFont,
  473.                 PANEL_BACKGROUND_PROC, notesBackgroundHit,
  474.                 PANEL_EVENT_PROC, notesPanelEvent,
  475.                 0);
  476.  
  477.     notesDsply = window_create(frame, TEXTSW,
  478.                 WIN_X, 0,
  479.                 WIN_BELOW, notesPanel,
  480.                 WIN_HEIGHT, WIN_EXTEND_TO_EDGE,
  481.                 WIN_WIDTH, 10000 /* very large number, cuts to actual width */,
  482.                 WIN_FONT, notesFont,
  483.                 TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY,
  484.                 0);
  485.     /* For bug in Sun Version 3.4 */
  486.     window_set( notesDsply, WIN_FONT, notesFont, 0);
  487.  
  488.     /* Set up panels */
  489.  
  490.  
  491.     monthItem = panel_create_item(monthPanel, PANEL_MESSAGE,
  492.                     PANEL_LABEL_X, 5,
  493.                     PANEL_LABEL_Y, 10,
  494.                   0);
  495.                         
  496.  
  497.     panel_create_item( monthPanel, PANEL_BUTTON,
  498.                         PANEL_ITEM_X, WINDOW_WIDTH - 2 * (BTN_WIDTH + GAP) - 55,
  499.                         PANEL_ITEM_Y, 10,
  500.                           PANEL_NOTIFY_PROC, todayBtnHit, 
  501.                            PANEL_LABEL_IMAGE,
  502.                             panel_button_image(monthPanel,"Today",0,notesFont),
  503.                         0);
  504.  
  505.     panel_create_item( monthPanel, PANEL_BUTTON,
  506.                         PANEL_ITEM_X, WINDOW_WIDTH - 2 * (BTN_WIDTH + GAP),
  507.                         PANEL_ITEM_Y, 10,
  508.                           PANEL_NOTIFY_PROC, upBtnHit, 
  509.                            PANEL_LABEL_IMAGE, &upBtnPr,
  510.                         0);
  511.  
  512.     panel_create_item( monthPanel, PANEL_BUTTON,
  513.                         PANEL_ITEM_X, WINDOW_WIDTH - (BTN_WIDTH + GAP),
  514.                         PANEL_ITEM_Y, 10,
  515.                           PANEL_NOTIFY_PROC, downBtnHit, 
  516.                            PANEL_LABEL_IMAGE, &downBtnPr,
  517.                         0);
  518.  
  519.  
  520.     notesTypeItem = panel_create_item( notesPanel, PANEL_CHOICE,
  521.                         PANEL_LABEL_STRING, "Reminder Types:",
  522.                         PANEL_FEEDBACK, PANEL_NONE,
  523.                         PANEL_NOTIFY_PROC, notesRadioHit,
  524.                     0);
  525.     choiceString[1] = '\0';
  526.     for (type = 0; type < NUM_NOTES_TYPE; type++) {
  527.         choiceString[0] = typeChar[type];
  528.         panel_set( notesTypeItem, PANEL_CHOICE_STRING, type, choiceString, 0);
  529.         panel_set( notesTypeItem, PANEL_CHOICE_X, type, 100 + 35*(type+1), 0);
  530.         panel_set( notesTypeItem, PANEL_CHOICE_Y, type, 4, 0);
  531.     }
  532.     panel_set( notesTypeItem, PANEL_LABEL_X, 4, 0);
  533.     panel_set( notesTypeItem, PANEL_LABEL_Y, 4, 0);
  534.  
  535.     /* Get monthtool filename */
  536.  
  537.     strcpy(toolFile, getenv("HOME"));
  538.     strcat(toolFile, "/.monthtool");
  539.  
  540.     /* Get today's date */
  541.  
  542.     todaySet();
  543.     yearToShow = tyear;
  544.     monthToShow = tmonth;
  545.  
  546.     /* Load the appointments file and show this month's calendar */
  547.     
  548.     loadData();    
  549.     firstDowSet();
  550.     dayHit(tday);    
  551.  
  552.     /* Wait for events */
  553.  
  554.     window_main_loop(frame);
  555.  
  556.     /* When done, leave */
  557.  
  558.     freeData();
  559.     exit(0);
  560.  
  561. }
  562.  
  563. static Notify_value    openCloseEvent(frame, event, arg, type)
  564.  
  565. Frame                 frame;
  566. Event                *event;
  567. Notify_arg             arg;
  568. Notify_event_type     type;
  569.  
  570. {
  571.     int                    initialClosed, finalClosed;
  572.     Notify_value        value;
  573.  
  574.     initialClosed = (int) window_get( frame, FRAME_CLOSED );
  575.     value = notify_next_event_func( frame, event, arg, type );
  576.     finalClosed = (int) window_get( frame, FRAME_CLOSED );
  577.  
  578.     if ( initialClosed != finalClosed ) {
  579.         if ( finalClosed ) {
  580.             saveData();
  581.         }else{
  582.             reloadData();
  583.             todaySet();
  584.             monthToShow = tmonth;
  585.             yearToShow = tyear;
  586.             monthDisplay();
  587.             dayHit(tday);
  588.         }
  589.     }
  590.  
  591.     return( value );
  592.         
  593. }
  594.  
  595. static void    monthEvent(item, event)
  596.  
  597. Panel_item     item;
  598. Event        *event;
  599.  
  600. {
  601.     switch (event_id(event)) {
  602.     case MS_RIGHT:
  603.         if (event_is_down(event)) {
  604.             rootMenuDisplay(monthPanel,event);
  605.         }
  606.         break;
  607.     case MS_LEFT:
  608.         panel_default_handle_event(item,event);
  609.         break;
  610.     default:
  611.         return;
  612.     }
  613.  
  614. }
  615.  
  616. static void    todayBtnHit(item, event)
  617.  
  618. Panel_item     item;
  619. Event        *event;
  620.  
  621. {
  622.     todaySet();
  623.     if ( (monthToShow != tmonth) || (yearToShow != tyear) ) {
  624.         notesSave();
  625.         monthToShow = tmonth;
  626.         yearToShow = tyear;
  627.         monthDisplay();
  628.         dayHit(tday);
  629.     }else{
  630.         if (dayToShow != tday) {
  631.             notesSave();
  632.             dayHit(tday);
  633.         }
  634.     }
  635. }
  636.  
  637. static void    upBtnHit(item, event)
  638.  
  639. Panel_item     item;
  640. Event        *event;
  641.  
  642. {
  643.     notesSave();
  644.     if (--monthToShow < 1) {
  645.         monthToShow = 12;
  646.         yearToShow--;
  647.     }
  648.     monthDisplay();
  649.     dayHit(1);
  650.  
  651. }
  652.  
  653. static void    downBtnHit(item, event)
  654.  
  655. Panel_item     item;
  656. Event        *event;
  657.  
  658. {
  659.     notesSave();
  660.     if (++monthToShow == 13) {
  661.         monthToShow = 1;
  662.         yearToShow++;
  663.     }
  664.     monthDisplay();
  665.     dayHit(1);
  666.  
  667. }
  668.  
  669. static void    monthBackgroundHit(panel, event)
  670.  
  671. Panel         panel;
  672. Event        *event;
  673.  
  674. {
  675.     switch (event_id(event)) {
  676.     case MS_RIGHT:
  677.         if (event_is_down(event)) {
  678.             rootMenuDisplay(monthPanel,event);
  679.         }
  680.         break;
  681.     default:
  682.         return;
  683.     }
  684.  
  685. }
  686.  
  687. static void    dateEvent(win, event, arg)
  688.  
  689. Canvas         win;
  690. Event        *event;
  691. caddr_t         arg;
  692.  
  693. {
  694.     int            column,
  695.                 row;
  696.  
  697.     if (event_is_up(event)) {
  698.         return;
  699.     }
  700.  
  701.     switch (event_id(event)) {
  702.     case MS_LEFT:
  703.         notesSave();
  704.         column = event_x(event) / (DATE_BOX_WIDTH + GAP);
  705.         row = (event_y(event)) / (DATE_BOX_HEIGHT + GAP);
  706.         dayHit(monthBoxes[row][column].date);
  707.         break;
  708.     case MS_RIGHT:
  709.         rootMenuDisplay(win,event);
  710.         break;
  711.     case WIN_REPAINT:
  712.         notesSave();
  713.         monthDisplay();
  714.         dayHit(dayToShow);
  715.         break;
  716.     default:
  717.         return;
  718.     }
  719.  
  720. }
  721.  
  722. dayHit(date)
  723.  
  724. int    date;
  725.  
  726. {
  727.     int                     row,
  728.                          column;
  729.  
  730.     if (date != 0) {
  731.         if (dayToShow != 0) {
  732.             for (row = 0; row < DATE_ROWS; row++) {
  733.                 for (column = 0; column < DATE_COLS; column++) {
  734.                     if (dayToShow == monthBoxes[row][column].date) {
  735.                         dateBoxDisplay(row, column, NOHIGHLIGHT);
  736.                     }
  737.                 }
  738.             }
  739.         }
  740.         for (row = 0; row < DATE_ROWS; row++) {
  741.             for (column = 0; column < DATE_COLS; column++) {
  742.                 if (date == monthBoxes[row][column].date) {
  743.                     dateBoxDisplay(row, column, HIGHLIGHT);
  744.                 }
  745.             }
  746.         }
  747.  
  748.         dayToShow = date;
  749.  
  750.         dateNumToShow[NOTES_ALL_ALL_ALL] = 0;
  751.  
  752.         dateNumToShow[NOTES_D_ALL_ALL] = dayToShow;
  753.  
  754.         dateNumToShow[NOTES_D_M_ALL] = dayToShow + 100 * monthToShow;
  755.  
  756.         dateNumToShow[NOTES_WEEKLY] = ((dayToShow + firstDow) % DATE_COLS);        
  757.         if ( dateNumToShow[NOTES_WEEKLY] == 0 ) {
  758.             dateNumToShow[NOTES_WEEKLY] = DATE_COLS;
  759.         }
  760.         dateNumToShow[NOTES_WEEKLY] += 100 * 99;
  761.  
  762.         dateNumToShow[NOTES_D_M_Y] = dayToShow + 100 * monthToShow + 10000 * yearToShow;
  763.  
  764.         notesDisplay();
  765.  
  766.     }
  767.  
  768. }
  769.  
  770. static void    notesPanelEvent(item, event)
  771.  
  772. Panel_item     item;
  773. Event        *event;
  774.  
  775. {
  776.  
  777.     switch (event_id(event)) {
  778.     case MS_RIGHT:
  779.         if (event_is_down(event)) {
  780.             rootMenuDisplay(notesPanel,event);
  781.         }
  782.         break;
  783.     case MS_LEFT:
  784.         panel_default_handle_event(item,event);
  785.         break;
  786.     default:
  787.         return;
  788.     }
  789.  
  790. }
  791.  
  792. static void    notesRadioHit(item, value, event)
  793.  
  794. Panel_item     item;
  795. int             value;
  796. Event        *event;
  797.  
  798. {
  799.     int            caretIndex,
  800.                 endIndex,
  801.                 lineStartIndex,
  802.                 nextLineStartIndex,
  803.                 ptrnStartIndex,
  804.                 ptrnEndIndex,
  805.                 ptrnLen,
  806.                 type,
  807.                 result,
  808.                 lineNo;
  809.  
  810.     typeMark[0] = typeChar[value];
  811.     ptrnLen = strlen(typeMark);
  812.  
  813.     caretIndex = (int)window_get( notesDsply, TEXTSW_INSERTION_POINT );
  814.  
  815.     lineNo = 0;
  816.     lineStartIndex = 0;
  817.     while (1) {
  818.         nextLineStartIndex = (int)textsw_index_for_file_line(notesDsply, lineNo+1);
  819.         if ( (nextLineStartIndex < 0) || (nextLineStartIndex > caretIndex) ) {
  820.             break;
  821.         }
  822.         lineNo++;
  823.         lineStartIndex = nextLineStartIndex;
  824.     }
  825.  
  826.     window_set( notesDsply, TEXTSW_INSERTION_POINT, lineStartIndex, 0 );
  827.     textsw_insert( notesDsply, typeMark, ptrnLen );
  828.     caretIndex += ptrnLen;
  829.  
  830.     endIndex = (int)window_get( notesDsply, TEXTSW_LENGTH );
  831.     if ( (nextLineStartIndex < 0) || (nextLineStartIndex > endIndex) ) {
  832.         nextLineStartIndex = endIndex + 1;
  833.     }
  834.     
  835.     lineStartIndex += strlen(typeMark);
  836.     for (type = 0; type < NUM_NOTES_TYPE; type++) {
  837.  
  838.         typeMark[0] = typeChar[type];
  839.         ptrnLen = strlen(typeMark);
  840.         while ( ptrnLen ) {
  841.             do {
  842.                 ptrnStartIndex = lineStartIndex;
  843.                 result = textsw_find_bytes(notesDsply, &ptrnStartIndex, &ptrnEndIndex,
  844.                     typeMark, ptrnLen, 0);
  845.                 if (result != -1) {
  846.                     if ((ptrnEndIndex < nextLineStartIndex) && (ptrnStartIndex >= lineStartIndex)) {
  847.                         textsw_erase(notesDsply, ptrnStartIndex, ptrnEndIndex);
  848.                         caretIndex -= ptrnLen;
  849.                     }else{
  850.                         result = -1;
  851.                     }
  852.                 }
  853.             } while (result != -1);
  854.             ptrnLen--;
  855.         }
  856.             
  857.     }
  858.  
  859.     window_set( notesDsply, TEXTSW_INSERTION_POINT, caretIndex, 0);
  860.  
  861. }
  862.  
  863. static void    notesBackgroundHit(panel, event)
  864.  
  865. Panel         panel;
  866. Event        *event;
  867.  
  868. {
  869.     switch (event_id(event)) {
  870.     case MS_RIGHT:
  871.         if (event_is_down(event)) {
  872.             rootMenuDisplay(notesPanel,event);
  873.         }
  874.         break;
  875.     default:
  876.         return;
  877.     }
  878.  
  879. }
  880.  
  881. rootMenuDisplay(window, event)
  882.  
  883. Window         window;
  884. Event        *event;
  885.  
  886. {
  887.  
  888.     switch( (int)menu_show(mainMenu, window, event, 0) ) {
  889.     case MENU_SAVE:
  890.         saveData();
  891.         break;
  892.     case MENU_RELOAD:
  893.         reloadData();
  894.         monthDisplay();
  895.         dayHit(dayToShow);
  896.         break;
  897.     case MENU_CLOSE:
  898.         saveData();
  899.         window_set(frame, FRAME_CLOSED, TRUE, 0);
  900.         break;
  901.     case MENU_QUIT:
  902.         saveData();
  903.         window_destroy(frame);
  904.         break;
  905.     }
  906.  
  907. }
  908.  
  909. monthDisplay()
  910.  
  911.  
  912. {                
  913.     int                     column,
  914.                          row;
  915.     int                     i, day;
  916.     char                 monthString[20];
  917.     struct apptsData     *cur ;
  918.     struct dateBox        *thisBox;
  919.  
  920.     sprintf(monthString, "%s %4u", smon[monthToShow-1], yearToShow);
  921.     panel_set(monthItem, PANEL_LABEL_STRING, monthString, 0);
  922.  
  923.     firstDowSet();
  924.  
  925.     row = 0;
  926.     for (column = 0; column < firstDow; column++) {
  927.         monthBoxes[row][column].date = 0;
  928.         monthBoxes[row][column].boxOutline = NO_OUTLINE;
  929.     }
  930.  
  931.     for ( day = 1; day <= mon[monthToShow]; day++) {
  932.         monthBoxes[row][column].date = day;
  933.         monthBoxes[row][column].boxOutline = NO_OUTLINE;
  934.         if (column >= (DATE_COLS-1)) {
  935.             row++;
  936.             column = 0;
  937.         }else{
  938.             column++;
  939.         }
  940.     }
  941.  
  942.     for (; row < DATE_ROWS; row++) {
  943.         for (; column < DATE_COLS; column++) {
  944.             monthBoxes[row][column].date = 0;
  945.             monthBoxes[row][column].boxOutline = NO_OUTLINE;
  946.         }
  947.         column = 0;        
  948.     }
  949.  
  950.     for (i = 0; i < NUM_NOTES_TYPE; i++) {
  951.         if  ( i == NOTES_WEEKLY ) { 
  952.             for ( cur = firstApptRecord[i]; cur != NULL; cur = cur->next) {
  953.                 if ( cur->month == 99 ) {
  954.                     for (row = 0; row < DATE_ROWS; row++) {
  955.                         if (monthBoxes[row][cur->day-1].boxOutline != FULL_OUTLINE) {
  956.                             monthBoxes[row][cur->day-1].boxOutline = HALF_OUTLINE;
  957.                          }
  958.                      }
  959.                 }
  960.             }
  961.         }else if  ( i != NOTES_ALL_ALL_ALL ) {  
  962.             for (cur = firstApptRecord[i]; cur != NULL; cur = cur->next) {
  963.                 if (    i==NOTES_D_ALL_ALL ||
  964.                 (             cur->month==monthToShow &&  
  965.                 (                 i==NOTES_D_M_ALL ||
  966.                 (                     cur->year==yearToShow 
  967.                 )))) { 
  968.                     thisBox = &monthBoxes[(cur->day + firstDow-1) / DATE_COLS]
  969.                                          [(cur->day + firstDow-1) % DATE_COLS];
  970.                     if ( i == NOTES_D_M_Y ) {
  971.                         thisBox->boxOutline = FULL_OUTLINE;
  972.                     }else if ( i != NOTES_ALL_ALL_ALL ) {
  973.                         if (thisBox->boxOutline != FULL_OUTLINE) {
  974.                             thisBox->boxOutline = HALF_OUTLINE;
  975.                         }
  976.                     }
  977.                 }
  978.             }
  979.         }
  980.     }
  981.  
  982.     pw_writebackground(datesCrayon, 0, 0, WINDOW_WIDTH, DATES_HEIGHT, PIX_CLR);
  983.  
  984.     for (row = 0; row < DATE_ROWS; row++) {
  985.         for (column = 0; column < DATE_COLS; column++) {
  986.             dateBoxDisplay(row, column, NOHIGHLIGHT);
  987.         }
  988.     }
  989.  
  990. }
  991.  
  992. firstDowSet()
  993.  
  994. {
  995.     int            i;
  996.  
  997.     firstDow = jan1Set(yearToShow);
  998.     mon[2] = 29;
  999.     mon[9] = 30;
  1000.     switch ((jan1Set(yearToShow + 1) + 7 - firstDow) % 7) {
  1001.     case 1:                /* non-leap year */
  1002.         mon[2] = 28;
  1003.         break;
  1004.     case 2:                /* leap year */
  1005.         break;
  1006.     default:            /* 1752 */
  1007.         mon[9] = 19;
  1008.         break;
  1009.     }
  1010.     for (i = 1; i < monthToShow; i++) {    
  1011.         firstDow += mon[i];
  1012.     }
  1013.     firstDow %= 7;
  1014.  
  1015. }
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021. jan1Set(year)
  1022.  
  1023. int             year;
  1024.  
  1025. {
  1026.  
  1027.     register        y, dow;
  1028.  
  1029.     /* normal gregorian calendar one extra day per four years */
  1030.  
  1031.     y = year;
  1032.     dow = 4 + y + (y + 3) / 4;
  1033.  
  1034.     /* julian calendar regular gregorian less three days per 400 */
  1035.  
  1036.     if (y > 1800) {
  1037.         dow -= (y - 1701) / 100;
  1038.         dow += (y - 1601) / 400;
  1039.     }
  1040.  
  1041.     /* great calendar changeover instant */
  1042.  
  1043.     if (y > 1752)
  1044.         dow += 3;
  1045.  
  1046.     return (dow % 7);
  1047.  
  1048.  
  1049. todaySet()
  1050.  
  1051.  
  1052. {
  1053.     struct tm      *tp;        /* time structure */
  1054.     long            tloc;    /* number of seconds since 1970 */
  1055.  
  1056.     time(&tloc);        
  1057.     tp = localtime(&tloc);
  1058.     tyear = tp->tm_year;
  1059.     tmonth = tp->tm_mon + 1;
  1060.     tday = tp->tm_mday;
  1061.     tyear += 1900;
  1062.  
  1063. }
  1064.  
  1065. dateBoxDisplay(row, column, hilite)
  1066.  
  1067. int              row;
  1068. int              column;
  1069. int              hilite;
  1070.  
  1071. {
  1072.     char            dateString[4];
  1073.  
  1074.     if (monthBoxes[row][column].date == 0) {
  1075.         pw_write(datesCrayon, 
  1076.             column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP),
  1077.             row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP),
  1078.             DATE_BOX_WIDTH, DATE_BOX_HEIGHT, PIX_SRC, &dayPr, 0, 0);
  1079.         pw_text(datesCrayon, 
  1080.             column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP) + 8,
  1081.             row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP) + 20,
  1082.             PIX_SRC | PIX_DST, font, "  ");
  1083.     }else{
  1084.         switch (monthBoxes[row][column].boxOutline) {
  1085.         case FULL_OUTLINE:
  1086.             pw_write(datesCrayon, 
  1087.                 column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP),
  1088.                 row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP),
  1089.                 DATE_BOX_WIDTH, DATE_BOX_HEIGHT, PIX_SRC, 
  1090.                 hilite ? &fullDaySelPr : &fullDayPr, 
  1091.                 0, 0);
  1092.             break;
  1093.         case HALF_OUTLINE:
  1094.             pw_write(datesCrayon, 
  1095.                 column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP),
  1096.                 row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP),
  1097.                 DATE_BOX_WIDTH, DATE_BOX_HEIGHT, PIX_SRC, 
  1098.                 hilite ? &halfDaySelPr : &halfDayPr, 
  1099.                 0, 0);
  1100.             break;
  1101.         case NO_OUTLINE:
  1102.             pw_write(datesCrayon, 
  1103.                 column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP),
  1104.                 row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP),
  1105.                 DATE_BOX_WIDTH, DATE_BOX_HEIGHT, PIX_SRC, 
  1106.                 hilite ? &daySelPr : &dayPr, 
  1107.                 0, 0);
  1108.             break;
  1109.         }
  1110.         sprintf(dateString, "%2u", monthBoxes[row][column].date);
  1111.         pw_text(datesCrayon, 
  1112.             column * DATE_BOX_WIDTH + DATE_BORDER + (column * GAP) + 8,
  1113.             row * DATE_BOX_HEIGHT + DATE_BORDER + (row * GAP) + 20,
  1114.             PIX_SRC | PIX_DST, font, dateString);
  1115.     }
  1116.  
  1117. }
  1118.  
  1119. notesDisplay()
  1120.  
  1121.  
  1122. {
  1123.     int                     type,
  1124.                           i;
  1125.     char                 timeString[7];
  1126.     struct apptsData     *cur;
  1127.  
  1128.     hasWeeklyNotes = 0;
  1129.  
  1130.     i = (int)window_get(notesDsply, TEXTSW_LENGTH);
  1131.     if ( i > 0 ) {
  1132.         textsw_erase( notesDsply, 0, i + 1 );
  1133.     }
  1134.  
  1135.     for (type = 0; type < NUM_NOTES_TYPE; type++) {
  1136.  
  1137.         typeMark[0] = typeChar[type];
  1138.  
  1139.         cur = firstApptRecord[type];
  1140.         while ( (cur != NULL) && (cur->dateNum < dateNumToShow[type]) ) {
  1141.             cur = cur->next;                    
  1142.         }
  1143.  
  1144.         while ( (cur != NULL) && (cur->dateNum == dateNumToShow[type]) ) {
  1145.             
  1146.             textsw_insert( notesDsply, typeMark, 2 );
  1147.             if (cur->time != 0) {
  1148.                 sprintf(timeString, "%d:%02d ", 
  1149.                     (int)(cur->time / 100), (cur->time % 100));
  1150.                 textsw_insert( notesDsply, timeString, strlen(timeString) );
  1151.             }
  1152.             textsw_insert( notesDsply, cur->apptMsg, strlen(cur->apptMsg) );
  1153.             textsw_insert( notesDsply, "\n", 1 );
  1154.             cur = cur->next;    
  1155.             if ( type == NOTES_WEEKLY ) {                
  1156.                 hasWeeklyNotes = 1;
  1157.             }
  1158.  
  1159.         }
  1160.     
  1161.     }
  1162.  
  1163.     editCount = (int)window_get(notesDsply, TEXTSW_EDIT_COUNT);
  1164.     window_set(notesDsply, TEXTSW_FIRST_LINE, 0, 0);
  1165.     window_set(notesDsply, TEXTSW_UPDATE_SCROLLBAR, 0);
  1166.  
  1167. }
  1168.  
  1169. notesSave()
  1170.  
  1171.  
  1172. {
  1173.     int                     bufLen,
  1174.                          row, column,
  1175.                          notesFound,
  1176.                          nowHasWeeklyNotes,
  1177.                          type,
  1178.                          newEditCount,
  1179.                          thisTime, thisYear, thisMonth, thisDay;
  1180.     char                *thisMsg,
  1181.                         *untypedMsg,
  1182.                         *notesBuffer;
  1183.     struct apptsData     *cur,
  1184.                         *new,
  1185.                         *old,
  1186.                         *nextAppt[NUM_NOTES_TYPE];
  1187.  
  1188.     newEditCount = (int)window_get(notesDsply, TEXTSW_EDIT_COUNT);
  1189.     if (newEditCount <= editCount) {
  1190.         return;
  1191.     }
  1192.     editCount = newEditCount;
  1193.  
  1194.     for (type = 0; type < NUM_NOTES_TYPE; type++) {
  1195.  
  1196.         cur = firstApptRecord[type];
  1197.         while ( (cur != NULL) && (cur->dateNum < dateNumToShow[type]) ) {
  1198.             cur = cur->next;                    
  1199.         }
  1200.  
  1201.         while ( (cur != NULL) && (cur->dateNum == dateNumToShow[type]) ) {
  1202.             if (cur->prev != NULL) {
  1203.                 cur->prev->next = cur->next;
  1204.             }else{
  1205.                 firstApptRecord[type] = cur->next;
  1206.             }
  1207.             if (cur->next != NULL) {
  1208.                 cur->next->prev = cur->prev;
  1209.             }else{
  1210.                 lastApptRecord[type] = cur->prev;
  1211.             }
  1212.             old = cur;        
  1213.             cur = cur->next;        
  1214.             free(old->apptMsg);
  1215.             free(old);            
  1216.         }
  1217.         nextAppt[type] = cur;
  1218.  
  1219.     }
  1220.  
  1221.     notesFound = NO_OUTLINE;
  1222.     nowHasWeeklyNotes = 0;
  1223.     bufLen = (int)window_get(notesDsply, TEXTSW_LENGTH);
  1224.     
  1225.     if (bufLen > 0) {
  1226.  
  1227.         notesBuffer = (char *)malloc( bufLen + 1 );
  1228.         if ( notesBuffer == (char *)0 ) {
  1229.             fprintf(stderr, "Monthtool error:  Out of memory.\n");
  1230.             exit(4);
  1231.         }
  1232.         window_get( notesDsply, TEXTSW_CONTENTS, 0, notesBuffer, bufLen + 1 );
  1233.     
  1234.         thisMsg = strtok( notesBuffer, "\n" );
  1235.  
  1236.         while ( thisMsg != NULL ) {
  1237.     
  1238.             stripType(thisMsg, &untypedMsg, &type);
  1239.             findTime(&untypedMsg, &thisTime);
  1240.                 
  1241.             if (strlen (untypedMsg) != 0) {
  1242.  
  1243.                 thisYear = thisMonth = thisDay = 0;
  1244.                 switch (type) {
  1245.                     case NOTES_D_M_Y:
  1246.                         thisYear = yearToShow;
  1247.                     case NOTES_D_M_ALL:
  1248.                         thisMonth = monthToShow;
  1249.                     case NOTES_D_ALL_ALL:
  1250.                         thisDay = dayToShow;
  1251.                         break;
  1252.                     case NOTES_WEEKLY:
  1253.                         thisMonth = 99;
  1254.                         thisDay = (dayToShow + firstDow) % DATE_COLS;
  1255.                         if ( thisDay == 0 ) {
  1256.                             thisDay = DATE_COLS;
  1257.                         }
  1258.                         nowHasWeeklyNotes = 1;
  1259.                 }
  1260.  
  1261.                 new = (struct apptsData *)malloc( sizeof( struct apptsData ) );
  1262.                 if ( new == (struct apptsData *)0 ) {
  1263.                     fprintf(stderr, "Monthtool error:  Out of memory.\n");
  1264.                     exit(4);
  1265.                 }
  1266.                 new->year = thisYear;
  1267.                 new->month = thisMonth;
  1268.                 new->day = thisDay;
  1269.                 new->dateNum = dateNumToShow[type];
  1270.                 new->time = thisTime;
  1271.                 new->apptMsg = (char *)malloc( strlen(untypedMsg) + 1 );
  1272.                 if ( new->apptMsg  == (char *)0 ) {
  1273.                     fprintf(stderr, "Monthtool error:  Out of memory.\n");
  1274.                     exit(4);
  1275.                 }
  1276.                 strcpy( new->apptMsg, untypedMsg );
  1277.  
  1278.                 if (nextAppt[type] != NULL) {
  1279.                     new->prev = nextAppt[type]->prev;
  1280.                     if (new->prev != NULL) {
  1281.                         new->prev->next = new;
  1282.                     }else{
  1283.                         firstApptRecord[type] = new;
  1284.                     }                
  1285.                     new->next = nextAppt[type];
  1286.                     if (new->next != NULL) {
  1287.                         new->next->prev = new;
  1288.                     }else{
  1289.                         lastApptRecord[type] = new;
  1290.                     }                
  1291.                 }else{    
  1292.                     if ( lastApptRecord[type] != NULL ) {
  1293.                         new->next = NULL;
  1294.                         new->prev = lastApptRecord[type];
  1295.                         lastApptRecord[type]->next = new;
  1296.                         lastApptRecord[type] = new;
  1297.                     }else{                
  1298.                         firstApptRecord[type] = lastApptRecord[type] = new;
  1299.                         new->prev = new->next = NULL;
  1300.                     }
  1301.                 }    
  1302.     
  1303.                 if (type == NOTES_D_M_Y) {    
  1304.                     notesFound = FULL_OUTLINE;
  1305.                 }else if (type != NOTES_ALL_ALL_ALL) {    
  1306.                     if (notesFound != FULL_OUTLINE) {
  1307.                         notesFound = HALF_OUTLINE;
  1308.                     }
  1309.                 }
  1310.  
  1311.             }
  1312.             free(untypedMsg);
  1313.             thisMsg = strtok( NULL, "\n" );
  1314.  
  1315.         }
  1316.  
  1317.         free(notesBuffer);
  1318.  
  1319.     }
  1320.  
  1321.     if (hasWeeklyNotes == nowHasWeeklyNotes) {
  1322.         for (row = 0; row < DATE_ROWS; row++) {
  1323.             for (column = 0; column < DATE_COLS; column++) {
  1324.                 if (dayToShow == monthBoxes[row][column].date) {
  1325.                     monthBoxes[row][column].boxOutline = notesFound;
  1326.                     dateBoxDisplay(row, column, HIGHLIGHT);
  1327.                 }
  1328.             }
  1329.         }
  1330.     }else{
  1331.         monthDisplay();
  1332.     }
  1333.  
  1334.     notesModified = 1; 
  1335.     hasWeeklyNotes = nowHasWeeklyNotes;
  1336.  
  1337. }
  1338.  
  1339. int     stripType( oldMsg, newMsg, type )
  1340.  
  1341. char         *oldMsg;
  1342. char        **newMsg;
  1343. int             *type;
  1344.  
  1345. {
  1346.     int             i,j,
  1347.                  typeFound, thisIsTypeChar;
  1348.  
  1349.     *newMsg = (char *)malloc( strlen(oldMsg) + 1 );
  1350.     if ( *newMsg  == (char *)0 ) {
  1351.         fprintf(stderr, "Monthtool error:  Out of memory.\n");
  1352.         exit(4);
  1353.     }
  1354.  
  1355.     i = 0;
  1356.     typeFound = 0;
  1357.  
  1358.     while ( *oldMsg != '\0' ) {
  1359.         thisIsTypeChar = 0;
  1360.         for (j = 0; j < NUM_NOTES_TYPE; j++) {
  1361.             if ( *oldMsg == typeChar[j] ) {
  1362.                 *type = j;
  1363.                 thisIsTypeChar = 1;
  1364.                 typeFound = 1;
  1365.             }
  1366.         }            
  1367.         if (thisIsTypeChar) {
  1368.             oldMsg++;
  1369.             while (*oldMsg == ' ') {
  1370.                 oldMsg++;
  1371.             }
  1372.         }else{
  1373.             (*newMsg)[i] = *oldMsg;
  1374.             oldMsg++;
  1375.             i++;
  1376.         }        
  1377.     } 
  1378.     (*newMsg)[i] = '\0';
  1379.  
  1380.     if ( !typeFound ) {
  1381.         *type = NOTES_D_M_Y;
  1382.     }
  1383.  
  1384. }
  1385.  
  1386. findTime(msg, time)
  1387.  
  1388. char     **msg;
  1389. int         *time;
  1390.  
  1391. {
  1392.     char     timeString[5];
  1393.     char    *curChar;
  1394.     int         timeFound;
  1395.  
  1396.     curChar = *msg;                        
  1397.     while (*curChar == ' ') {
  1398.         curChar++;
  1399.     }
  1400.  
  1401.     if (strlen(curChar) >= 4) {        
  1402.  
  1403.         timeFound = 1;
  1404.         if (*(curChar+1) == ':') {
  1405.             timeString[0] = '0';    
  1406.         }else if (*(curChar+2) == ':') {
  1407.             if (isdigit(*curChar)) {
  1408.                 timeString[0] = *curChar;
  1409.                 curChar++;
  1410.             }else{
  1411.                 timeFound = 0;
  1412.             }
  1413.         }else{
  1414.             timeFound = 0;
  1415.         }
  1416.  
  1417.         if (timeFound) {
  1418.             if ( isdigit(*curChar) && isdigit(*(curChar+2)) && isdigit(*(curChar+3)) &&
  1419.                     ( (*(curChar+4) == ' ') || (*(curChar+4) == '\0') ) ) {
  1420.                 timeString[1] = *curChar;
  1421.                 timeString[2] = *(curChar+2);
  1422.                 timeString[3] = *(curChar+3);
  1423.                 timeString[4] = '\0';                        
  1424.             }else{
  1425.                 timeFound = 0;
  1426.             }
  1427.         }
  1428.     }else{
  1429.         timeFound = 0;
  1430.     }
  1431.  
  1432.     if (timeFound) {
  1433.         *time = atoi( timeString );
  1434.         if ( ( (int)(*time / 100) >= 24 ) || ( (*time % 100 ) >= 60 ) ) {
  1435.             *time = 0;
  1436.         }else{
  1437.             curChar += 4;
  1438.             while (*curChar == ' ') {
  1439.                 curChar++;
  1440.             }
  1441.             *msg = curChar;
  1442.         }
  1443.     }else{
  1444.         *time = 0;
  1445.     }
  1446.                                          
  1447. }
  1448.  
  1449. loadData()
  1450.  
  1451.  
  1452. {
  1453.     FILE                *fptr;
  1454.  
  1455.     char                 basedata[MAX_MSG_LEN+100];
  1456.     char                *timestr;
  1457.     char                *apptstring;
  1458.  
  1459.     int                     i;
  1460.     struct apptsData     *new;
  1461.  
  1462.  
  1463.     if ((fptr = fopen(toolFile, "r")) != NULL) {
  1464.  
  1465.         for ( i = 0; i < (NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/); i++ ){
  1466.             firstApptRecord[i] = lastApptRecord[i] = NULL;
  1467.         }
  1468.  
  1469.         while ((fgets(basedata, MAX_MSG_LEN+100, fptr) != NULL)) {
  1470.  
  1471.             basedata[MAX_MSG_LEN+99] = NULL;
  1472.  
  1473.             new = (struct apptsData *)malloc( sizeof( struct apptsData ) );
  1474.             if ( new == (struct apptsData *)0 ) {
  1475.                 fprintf(stderr, "Monthtool error:  Out of memory.\n");
  1476.                 exit(4);
  1477.             }
  1478.  
  1479.             new->month = atoi( strtok(basedata, ",") );
  1480.             new->day = atoi( strtok(NULL, ",") );
  1481.             new->year = atoi( strtok(NULL, ",") );
  1482.             new->dateNum = 10000 * new->year + 100 * new->month + new->day;
  1483.  
  1484.             timestr = strtok(NULL,","); 
  1485.             if (strcmp(timestr, "    ") == 0) {
  1486.                 new->time = 0;
  1487.             }else{
  1488.                 new->time = atoi(timestr);
  1489.             }     
  1490.  
  1491.             apptstring = strtok(NULL, "\n" );
  1492.             new->apptMsg = (char *)malloc(strlen(apptstring) + 1);
  1493.             if ( new->apptMsg == (char *)0 ) {
  1494.                 fprintf(stderr, "Monthtool error:  Out of memory.\n");
  1495.                 exit(4);
  1496.             }
  1497.             strcpy(new->apptMsg, apptstring);
  1498.  
  1499.             if ( new->year != 0 ) {
  1500.                 if ( new->month != 0 ) {
  1501.                     if ( new->day != 0 ) {
  1502.                         i = NOTES_D_M_Y;
  1503.                     }else{
  1504.                         i = NOTES_ERROR;    /* *mmyyyy */
  1505.                     }
  1506.                 }else{
  1507.                     i = NOTES_ERROR;        /* dd*yyyy or **yyyy */
  1508.                 }
  1509.             }else{
  1510.                 if ( new->month == 99 ) {
  1511.                     if ( (new->day >= 1) &&  (new->day <= 7) ) {
  1512.                         i = NOTES_WEEKLY;
  1513.                     }else{
  1514.                         i = NOTES_ERROR;    
  1515.                     }
  1516.                 }else if ( new->month != 0 ) {
  1517.                     if ( new->day != 0 ) {
  1518.                         i = NOTES_D_M_ALL;
  1519.                     }else{
  1520.                         i = NOTES_ERROR;    /* *mm* */
  1521.                     }
  1522.                 }else{
  1523.                     if ( new->day != 0 ) {
  1524.                         i = NOTES_D_ALL_ALL;
  1525.                     }else{
  1526.                         i = NOTES_ALL_ALL_ALL;   
  1527.                     }
  1528.                 }
  1529.             }
  1530.                 
  1531.             if ( i == NOTES_ERROR ) {
  1532.                 fprintf(stderr, "Monthtool warning! Invalid record: %u,%u,%4u,",
  1533.                     new->month, new->day, new->year );
  1534.                 if (new->time != 0) {
  1535.                     fprintf(stderr, "%04u", new->time);
  1536.                 }else{
  1537.                     fprintf(stderr, "    ");
  1538.                 }
  1539.                 fprintf(stderr, ",%s\n", new->apptMsg );
  1540.             }
  1541.  
  1542.             insertApptRecord(new, i);
  1543.                         
  1544.         }
  1545.  
  1546.         fclose(fptr);
  1547.         stat( toolFile, &lastStatus );
  1548.     }
  1549.  
  1550.  
  1551. insertApptRecord(new, type)
  1552.  
  1553. struct apptsData     *new;
  1554. int                     type;
  1555.  
  1556. {
  1557.     struct apptsData     *cur;
  1558.     int                     inserted;
  1559.  
  1560.     if (lastApptRecord[type] == NULL) {
  1561.         firstApptRecord[type] = lastApptRecord[type] = new;
  1562.         new->prev = NULL;                
  1563.         new->next = NULL;    
  1564.     }else{
  1565.         inserted = 0;
  1566.         cur = lastApptRecord[type];
  1567.         do {
  1568.             if (new->dateNum >= cur->dateNum) {
  1569.                 if (cur->next != NULL) {
  1570.                     cur->next->prev = new;
  1571.                 }else{
  1572.                     lastApptRecord[type] = new;
  1573.                 }
  1574.                 new->next = cur->next;
  1575.                 new->prev = cur;
  1576.                 cur->next = new;
  1577.                 inserted = 1;
  1578.             }else{
  1579.                 cur = cur->prev;
  1580.             }
  1581.         } while ( !inserted && cur != NULL );
  1582.         if (!inserted) {
  1583.             new->next = firstApptRecord[type];
  1584.             new->prev = NULL;
  1585.             firstApptRecord[type]->prev = new;
  1586.             firstApptRecord[type] = new;
  1587.         }                        
  1588.     }
  1589.  
  1590. }
  1591.  
  1592. reloadData()
  1593.  
  1594.  
  1595. {
  1596.     struct stat            statusNow;
  1597.  
  1598.  
  1599.     stat( toolFile, &statusNow );
  1600.     if ( statusNow.st_mtime > lastStatus.st_mtime ) {
  1601.         loadData();
  1602.     }
  1603.  
  1604. }
  1605.  
  1606. saveData()
  1607.  
  1608.  
  1609. {
  1610.     FILE                *fptr;
  1611.  
  1612.     int                     i;
  1613.     struct apptsData     *cur;
  1614.  
  1615.  
  1616.     notesSave();
  1617.  
  1618.     if (notesModified) {
  1619.  
  1620.         if ((fptr = fopen(toolFile, "w")) == NULL) {
  1621.             fprintf(stderr, "Monthtool error:  Cannot open %s file", toolFile);
  1622.             return;
  1623.         }
  1624.  
  1625.         for ( i = 0; i < (NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/); i++ ) {
  1626.             for (cur = firstApptRecord[i]; cur != NULL; cur = cur->next) {
  1627.                 fprintf(fptr, "%u,%u,%u,", cur->month, cur->day, cur->year );
  1628.                 if (cur->time != 0) {
  1629.                     fprintf(fptr, "%04u", cur->time);
  1630.                 }else{
  1631.                     fprintf(fptr, "    ");
  1632.                 }
  1633.                 if ( strlen(cur->apptMsg) > (MAX_MSG_LEN-1) ) {
  1634.                     cur->apptMsg[MAX_MSG_LEN-1] = NULL;
  1635.                     fprintf(stderr, "Monthtool warning! Record truncated: %u,%u,%4u,",
  1636.                         cur->month, cur->day, cur->year );
  1637.                     if (cur->time != 0) {
  1638.                         fprintf(stderr, "%04u", cur->time);
  1639.                     }else{
  1640.                         fprintf(stderr, "    ");
  1641.                     }
  1642.                     fprintf(stderr, ",%s\n", cur->apptMsg );
  1643.                 }
  1644.                 fprintf(fptr, ",%s\n", cur->apptMsg );
  1645.             }
  1646.         }
  1647.  
  1648.         fclose(fptr);
  1649.         stat( toolFile, &lastStatus );
  1650.  
  1651.         notesModified = 0;
  1652.  
  1653.     }
  1654.  
  1655. }
  1656.  
  1657. freeData()
  1658.  
  1659.  
  1660. {
  1661.  
  1662.     int                     i;
  1663.     struct apptsData     *cur ;
  1664.  
  1665.     for ( i = 0; i < (NUM_NOTES_TYPE + 1 /*for NOTES_ERROR*/); i++ ) {
  1666.         while( firstApptRecord[i] != NULL) {
  1667.             cur = firstApptRecord[i]; 
  1668.             firstApptRecord[i] = firstApptRecord[i]->next;
  1669.             free(cur->apptMsg);
  1670.             free( cur );
  1671.         }
  1672.     }
  1673.     
  1674. }
  1675.     
  1676.