home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / monthtool / monthtool.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-10-03  |  33.7 KB  |  1,415 lines

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