home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume9 / month / part01 next >
Text File  |  1987-04-13  |  59KB  |  3,037 lines

  1. Subject:  v09i049:  REPOST of Visual calendar program, Part01/02
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.TMC.COM
  4.  
  5. Submitted by: ihnp4!sdcrdcf!trwrb!ries (Marc Ries)
  6. Mod.sources: Volume 9, Issue 49
  7. Archive-name: month/Part01
  8.  
  9. [  This time I've got all my marbles -- and all the pieces.  --r$  ]
  10.  
  11. The  following  is  a  stable  version  of  "month",   being   in
  12. "production" mode for several months without major incident.
  13.  
  14. The man page is very complete.
  15.  
  16.         Marc A. Ries
  17.  
  18.         sdcrdcf!---\ 
  19.                 ihnp4!------\----- trwrb! --- ries
  20.  
  21. # Cut_Here-----Cut_Here-----Cut_Here---------Cut_Here
  22. # !/bin/sh
  23. # This is a shell archive, meaning:
  24. # 1. Remove everything above the /bin/sh line.
  25. # 2. Save the resulting text in a file.
  26. # 3. Execute the file with /bin/sh (not csh).
  27. #
  28. #    This archive created: Mar 10 1987
  29. #    By:    Marc Ries 
  30. #
  31. export PATH; PATH=/bin:/usr/bin:$PATH
  32. #
  33. if `test ! -s ./help.c`
  34. then
  35. echo "writting ./help.c"
  36. cat > ./help.c << 'RiesES_PIECES'
  37. /*
  38.  * Modification History 
  39.  *
  40.  * Origional Author:  Jeff Bauer@ETA Systems[eta!bauer] 
  41.  * Modifications by:  Marc Ries@TRW[trwrb!ries] 
  42.  *
  43.  */
  44.  
  45. #include <curses.h>
  46.  
  47. help()
  48. {
  49.     clear();
  50.     standout();
  51.     mvaddstr(0, 25, " Keys and their Functions");
  52.     standend();
  53.     mvaddstr(1, 2, "h, l, k, j       - move cursor left, right, up, down");
  54.     mvaddstr(2, 2, "<CR> and <LF>    - select items/commands/scroll-areas");
  55.     mvaddstr(3, 2, "0-9              - direct entry of date or marker numbers");
  56.     mvaddstr(4, 2, "/  - directly type in complete date (i.e. 5/6/86) | <ESC> - abort function");
  57.     mvaddstr(5, 2, "<SPACE>/<BACKSPACE> - scroll hours/minutes forward/backward");
  58.     mvaddstr(6, 2, "m, d - and y     - move into the months, days, years areas");
  59.     mvaddstr(7, 2, "n or +, p or '-' - go to the next or previous month, day, or year");
  60.     mvaddstr(8, 2, "M - mark the currently displayed date  | G - go to a previously marked date");
  61.     mvaddstr(9, 2, ";                - go to last visited date outside of current displayed month");
  62.     mvaddstr(10, 2, "T                - go to today's actual date (initial date displayed)");
  63.     mvaddstr(11, 2, "O                - display schedule grid for currently displayed day");
  64.     mvaddstr(12, 2, "A                - show days in current month that have items scheduled");
  65.     mvaddstr(13, 2, "S                - scan the events for the currently displayed day");
  66.     mvaddstr(14, 2, "  n : go to next event      p : go to previous event    d : delete this event");
  67.     mvaddstr(15, 2, "  e : edit this event       q : quit the scan           <ESC>: same as 'q'");
  68.     mvaddstr(16, 2, "E                - scan every stored event");
  69.     mvaddstr(17, 2, "F                - save events on disk file");
  70.     mvaddstr(18, 2, "P                - post an event (see man page)");
  71.     mvaddstr(19, 2, "L                - print picture of moon for 11:00 PM of current day");
  72.     mvaddstr(20, 2, "Q                - quit, store any event changes");
  73.     mvaddstr(21, 2, "^L, ^R           - redraw screen (including this page)");
  74.     mvaddstr(22, 2, "^C, ^\           - quit, ignore any event changes");
  75.     standout();
  76.     mvaddstr(23, 18, " Press any key to return to your calendar.");
  77.     standend();
  78.     refresh();
  79.     get_char();
  80.     clear();
  81.     print_screen();
  82. }
  83. RiesES_PIECES
  84. else
  85.   echo "will not over write ./help.c"
  86. fi
  87. if `test ! -s ./lunar.c`
  88. then
  89. echo "writting ./lunar.c"
  90. cat > ./lunar.c << 'RiesES_PIECES'
  91. /*
  92.  * Modification History 
  93.  *
  94.  * Origional Author:  Tom Stoehn@Tektronics[zeus!tims] 
  95.  * Modifications by:  Marc Ries@TRW[trwrb!ries] 
  96.  *
  97.  */
  98.  
  99. #include <curses.h>
  100. #include <math.h>
  101. #include <sys/types.h>
  102. #include <time.h>
  103.  
  104. /* Globals. */
  105. double          Fraction;
  106.  
  107. /* Linked in later. */
  108. time_t          time();
  109. struct tm      *localtime();
  110.  
  111.  
  112. #define LINES        24
  113. #define WIDTH        80
  114. #define CENTER        ((WIDTH - 2 * LINES) / 2)
  115. #define BRIGHT        '@'
  116. #define LEDGE        '('
  117. #define REDGE        ')'
  118. #define FULL        0.5
  119. #define TwoPi        (2 * 3.14159)
  120. #define ZERO        0.03
  121.  
  122. extern short    month, day, year;
  123.  
  124. long
  125. Calculate(julian, year, hour, minute)
  126.     long      year, julian, hour, minute;
  127. {
  128. register long   Length;
  129. register long   Phase;
  130. register long   Delta;
  131. register long   offset;
  132.     /*
  133.      * time_t         tick; 
  134.      *
  135.      * static short called_before = 0; 
  136.      *
  137.      * if (!called_before) { tick    = time((time_t *)0); tm        =
  138.      * localtime(&tick); called_before = 1; } else { tm->tm_yday++; }
  139.      * julian    = tm->tm_yday + 1; year    = tm->tm_year - 78; hour
  140.      * = tm->tm_hour; minute    = tm->tm_min; 
  141.      */
  142.  
  143.     year -= 78;
  144.     Length = (double) 2551 / 60 * 1000 + (double) 443 / 60;
  145.     offset = ((year * 365L + julian) * 24L + hour) * 60L + minute;
  146.     Delta = offset - (273L * 24L + 13L) * 60L + 23L;
  147.     Phase = Delta - (Delta / Length) * Length;
  148.  
  149.     Fraction = (double) Phase / Length;
  150.     return (Phase);
  151. }
  152.  
  153. int
  154. CharPos(x)
  155.     double          x;
  156. {
  157. register int    i;
  158.  
  159.     i = x * LINES + 0.5;
  160.     if ((i += LINES + CENTER) < 1)
  161.         i = 1;
  162.     return (i);
  163. }
  164.  
  165.  
  166. Draw()
  167. {
  168. register char  *p;
  169. register int    i;
  170. register int    end;
  171. register double y;
  172. register double cht;
  173. register double squisher;
  174. register double horizon;
  175. register double terminator;
  176. char            Buffer[256];
  177. int             line = 1;
  178.  
  179.     /* Clear screen? */
  180.     clear();
  181.  
  182.     if (Fraction < FULL)
  183.         squisher = cos(TwoPi * Fraction);
  184.     else
  185.         squisher = cos(TwoPi * (Fraction - FULL));
  186.  
  187.     cht = (double) 2.0 / (LINES - 6.0);
  188.     for (y = 0.93; y > -1.0; y -= cht)
  189.     {
  190.         for (i = sizeof Buffer, p = Buffer; --i >= 0;)
  191.             *p++ = ' ';
  192.         horizon = sqrt(1.0 - y * y);
  193.         Buffer[CharPos(-horizon)] = LEDGE;
  194.         Buffer[i = CharPos(horizon)] = REDGE;
  195.         Buffer[++i] = '\0';
  196.         terminator = horizon * squisher;
  197.         if (Fraction > ZERO && Fraction < (1.0 - ZERO))
  198.         {
  199.             if (Fraction < FULL)
  200.             {
  201.                 i = CharPos(terminator);
  202.                 end = CharPos(horizon);
  203.             } else
  204.             {
  205.                 i = CharPos(-horizon);
  206.                 end = CharPos(terminator);
  207.             }
  208.             while (i <= end)
  209.                 Buffer[i++] = BRIGHT;
  210.         }
  211.         mvaddstr(line++, 1, Buffer);
  212.     }
  213.     move(LINES - 1, 0);
  214.     refresh();
  215. }
  216.  
  217. lunar()
  218. {
  219. long            yday;
  220. extern int      lflag;
  221.  
  222.     yday = (long) (days_since_jan1(month, day, year) + 1);
  223.     (void) Calculate(yday, ((long) (year - 1900)), 11L, 0L);
  224.     Draw();
  225.     refresh();
  226.     if (lflag) {
  227.         clear();
  228.         endwin();
  229.         exit(0);
  230.     }
  231.     else {
  232.         get_char();
  233.         clear();
  234.         print_screen();
  235.     }
  236. }
  237. RiesES_PIECES
  238. else
  239.   echo "will not over write ./lunar.c"
  240. fi
  241. if `test ! -s ./month.1`
  242. then
  243. echo "writting ./month.1"
  244. cat > ./month.1 << 'RiesES_PIECES'
  245. .TH MONTH 1L "Pyramid OSx" "" "User Contributed Software"
  246. .SH NAME
  247. month \- a visual calendar and time/event organizer
  248. .SH SYNOPSIS
  249. .B month
  250. [
  251. .B \-ABCdv
  252. ] [
  253. .B \-N
  254. [ arg ]]
  255. .SH OPTIONS
  256. .TP
  257. .B \-d
  258. Create background daemon that will wake up at 15 minute intervals 
  259. during the current login session, 
  260. check your event database, and print a message to your
  261. terminal with a bell if it finds an event that is 15 minutes, or less, away.  
  262. It will do this on invocation, then 
  263. every 15-minutes until killed or you log out.
  264. .TP
  265. .B \-A
  266. Output the 
  267. .I month 
  268. data file in a format compatible with 
  269. .I appt (1). 
  270. .TP
  271. .B \-B
  272. Output the current day's events.
  273. .TP
  274. .B \-C
  275. Output the 
  276. .I month 
  277. data file in a format compatible with
  278. .I calendar (1).
  279. .TP
  280. .B \-L
  281. Output the lunar picture of what the moon will
  282. look like at 11:00PM of the current day, and exit.
  283. .TP
  284. .B \-N [ arg ]
  285. Output the current day's events in a format compatable with
  286. .I nag (1).
  287. An optional argument 
  288. .B arg 
  289. specifies what program 
  290. .I nag
  291. should invoke for the user (the default is
  292. .I echo
  293. ).
  294. .TP
  295. .B \-v
  296. Output the version ID of 
  297. .I month
  298. being run. 
  299. .SH DESCRIPTION
  300. .TP
  301. .B Overview
  302. .br
  303. .sp 1
  304. .I Month 
  305. displays a calendar of the current month of the current year,
  306. with the current day highlighted.  
  307. It then allows the user to browse to any month/day/year, 
  308. and to schedule and recall events for a day or for some regular 
  309. repeating series of days.
  310. Note that the UPPER/lower case of commands are significant.
  311. .br
  312. .TP
  313. .B Screen Areas
  314. .br
  315. .sp 1
  316. There are four distinct areas of the screen:  the 
  317. .I days 
  318. area where the days of the month are listed in calendar format, the 
  319. .I months 
  320. area where the months of the year are listed, the 
  321. .I years 
  322. area where a sequence of years are listed, and the 
  323. .I schedule 
  324. area, which may be blank and occupies lines 19-24 on the terminal 
  325. (lines below 24 are not used).
  326. .br
  327. .TP
  328. .B Commands
  329. .br
  330. .I Quitting
  331. .br
  332. .sp 1
  333. You may type 'Q' almost any time to quit.  This will update
  334. the event database if any changes have been made.
  335. The event database is a file called 
  336. .B .month 
  337. in your home directory.
  338. .I <CNTL-c> 
  339. can be used any time for an immediate abort and no event database update.
  340. When you quit, you will be informed of the update status of your event database.
  341. .br
  342. .sp 1 
  343. .I Cursor motion
  344. .br
  345. .sp 1 
  346. The 
  347. .B h, l, k, 
  348. and 
  349. .B j 
  350. keys are used to move the cursor left, right, up and down respectively 
  351. within a screen area.  
  352. Sometimes, as explained later, 
  353. .B j 
  354. and 
  355. .B k 
  356. will not work, and a
  357. .I <TAB> 
  358. or 
  359. .I <CR>
  360. provides movement between fields in a circular fashion.
  361. .br
  362. .sp 1 
  363. .I Selection
  364. .br
  365. .sp 1 
  366. .I <CR> 
  367. and 
  368. .I <LF> 
  369. are used to select items/commands at the cursor position.
  370. .br
  371. .sp 1 
  372. .I Direct entry of numbers
  373. .br
  374. .sp 1 
  375. The user may type the number of a desired month, day, or year
  376. whenever the cursor is appropriately positioned.  
  377. This is true in all screen areas.  
  378. .I <ESC> 
  379. can be used to abort any function.
  380. .br
  381. .sp 1 
  382. .I Scrolling numbers
  383. .br
  384. .sp 1 
  385. In the schedule area, numbers may be scrolled forwards and
  386. backwards with the 
  387. .I <SPACE> 
  388. and 
  389. .I <BACKSPACE> 
  390. keys respectively.
  391. This is the only way to change hours and minutes.
  392. .br
  393. .sp 1 
  394. .I Time browsing
  395. .br
  396. .sp 1 
  397. The keys 'm', 'd' and 'y' are used to move into the months area, the
  398. days area or the years area respectively.  This is only when
  399. time browsing in these three panes.  To get to a particular
  400. month or year, move to the appropriate area and onto the
  401. desired month or year, and select it via 
  402. .I <CR>.
  403. Years may be
  404. scrolled a year at a time by using the scroll areas marked
  405. by '<<' and '>>'.  Attempting to move passed these areas will
  406. scroll by one year, selecting them scrolls by ten years.
  407. The last month of the previous year, or the first month of
  408. next year, may be obtained by selecting the area above
  409. January or below December respectively.  
  410. The cursor is the positioned for immediate return via a later selection.
  411. .br
  412. .sp 1
  413. The keys 
  414. .B n 
  415. and 
  416. .B p 
  417. can be used to go to the next or previous month,
  418. day, or year, depending on the screen area you are in.
  419. .br
  420. .sp 1
  421. The 
  422. .B M 
  423. key will mark a specific date.  You will be prompted for
  424. an identifier that is a single digit between '0' and '9'.
  425. Once a mark has been set at a certain date, you may jump to
  426. that date from any other date with the command below.
  427. .br
  428. .sp 1
  429. The 
  430. .B G 
  431. key controls movement to a previously set mark.  
  432. You will be prompted for the mark's identifying digit.
  433. .br
  434. .sp 1
  435. The key 
  436. .B ';' 
  437. provides access directly to the last date you viewed that
  438. was in a different month than currently displayed.  
  439. Use the same command again to return to where you were originally.
  440. .br
  441. .sp 1
  442. The
  443. .B T 
  444. key goes directly to the actual, real current date.
  445. This is the date initially displayed on startup.
  446. .br
  447. .sp 1
  448. The key 
  449. .B '/' 
  450. allows direct access to a date to be fully specified by the user.  
  451. A prompt is given and the user should respond with
  452. a date in the form m/d/y, such as 5/6/86.  Years less than
  453. 100 are assumed to be in this century, hence, 5/6/80 is the same as 5/6/1986.
  454. .TP
  455. .B Overviewing a day
  456. .br
  457. .sp 1
  458. The
  459. .B O 
  460. key will fill the schedule area with a read only view
  461. of your day according to your event database.  
  462. Four six-hour grids appear showing the hours of the day 
  463. that have been pre-scheduled.  
  464. The cursor must be placed on the day to be viewed with this function.
  465. .TP
  466. .B Overviewing a month
  467. .br
  468. .sp 1
  469. The 
  470. .B A 
  471. key will mark all the days on the calendar that have
  472. at least one event posted.  This feature is especially
  473. useful before scanning; described next.
  474. .TP
  475. .B Scanning events
  476. .br
  477. .sp 1
  478. The 
  479. .B S 
  480. key will cause a sequential list of events for the current day
  481. to be displayed in the schedule area.  The events for any given
  482. day may be scanned, deleted, or modified.
  483. After displaying each one, the prompt "
  484. .B [n,p,d,e,q]
  485. " is put up and will respond to these character commands:
  486. .br
  487. .sp 1
  488. .I 'n':
  489. go to next event
  490. .br
  491. .I 'p':
  492. go to previous event
  493. .br
  494. .I 'd':
  495. delete this event
  496. .br
  497. .I 'e':
  498. edit this event as during a posting described below
  499. .br
  500. .I 'q':
  501. quit the scan and return to calendar
  502. .br
  503. .I <ESC>:
  504. same as 'q'
  505. .br
  506. .TP
  507. .B Every event scan
  508. .sp 1
  509. .I 'E'
  510. will display, one at a time, absolutely every event
  511. in your event database.  The prompt "
  512. .B ['n','q']
  513. " is displayed
  514. and will respond to these character commands:
  515. .br
  516. .I 'n':
  517. go to next event
  518. .br
  519. .I 'q':
  520. quit the scan and return to calendar
  521. .br
  522. .I <ESC>:
  523. same as 'q'
  524. .br
  525. .TP
  526. .B Posting an event
  527. .sp 1
  528. .I 'P'
  529. is the command used to post an event.  The
  530. cursor is placed into the schedule area with a host of
  531. information displayed.  
  532. .sp 1
  533. To abort  at any point, use 
  534. .I <ESC>.
  535. .sp 1
  536. The cursor first appears on the first line of the schedule area.  
  537. This line gives the starting date for the event, and when it shall occur.  
  538. The user may move through the highlighted starting date field
  539. (using the 
  540. .B h
  541. and
  542. .B l
  543. keys) and change the month, day or year by scrolling with 
  544. .I <SPACE> 
  545. and 
  546. .I <BACKSPACE>,
  547. or by direct input.  
  548. .br
  549. .sp
  550. The other fields in this first line may also be moved onto and selected
  551. in a similar fashion (but without direct entry).
  552. .br
  553. .sp
  554. .I <TAB> 
  555. will move the cursor to the next line that contains the
  556. time that the event occurs.  
  557. Again, the 
  558. .B h,
  559. .B l,
  560. .I <SPACE>,
  561. and 
  562. .I <BACKSPACE>
  563. keys manipulate the hours and minutes fields.
  564. The AM/PM indicator changes as the hours scroll across 12:00 boundaries.  
  565. .br
  566. .sp
  567. .I <TAB> 
  568. will move the cursor to the next line that gives the duration of the event, 
  569. and it is edited in the same fashion.  
  570. .br
  571. .sp
  572. .I <TAB> 
  573. moves the cursor to the next line that is a one line description of the
  574. event, to be typed whenever the cursor is placed here.
  575. .I <TAB> 
  576. moves the cursor the last line in the schedule area and
  577. allows the user to select ACCEPT or CANCEL.  
  578. The 
  579. .B h
  580. and 
  581. .B l
  582. keys toggle between ACCEPT and CANCEL.
  583. Pressing
  584. .I <RETURN>
  585. when the cursor is in the ACCEPT field will put the event 
  586. into the user's event database, after verification.
  587. CANCEL aborts the process.  
  588. .br
  589. .sp
  590. The
  591. .I <TAB> 
  592. key can be used to circulate through the fields. 
  593. .TP
  594. .B Event scheduling
  595. .sp 1
  596. When and how often will an event occur?  This information
  597. is contained in the first line of the schedule area.  The
  598. date entered there is the starting date for the event,
  599. that is, the event will not be recalled until that date.
  600. This date is best entered by browsing to it, placing the
  601. cursor in the days area on the desired day, and then
  602. type 'P' to post the event, in which case the desired date
  603. automatically appears as the default, but may be edited.
  604. .br
  605. .sp
  606. In the following examples, only the fields that need to be
  607. selected are mentioned, all others should be turned off.
  608. (not highlighted)  Examples:
  609. .ta +2.5i
  610. .br
  611. .sp 1
  612. .I March 5, 1990 (once only):    
  613. .B 3/5/1990
  614. .br        
  615. .sp 1
  616. .I Every Tuesday and Wednesday:    
  617. .B m/d/y every TueWed
  618. .br    
  619. .sp 1
  620. .I The 7th of each month:    
  621. .B m/7/y monthly
  622. .br        
  623. .sp 1
  624. .I Each July 4th:    
  625. .B 7/4/y yearly
  626. .br
  627. .sp 1
  628. .I The 2nd and last sunday of 
  629. .I each month:
  630. .B m/d/y monthly every 2nd last Sun
  631. .br
  632. .sp 1
  633. .I The 1st and last friday of 
  634. .I each year:
  635. .B \ \ m/d/y yearly every 1st last Fri
  636. .br
  637. .sp 1
  638. .I Every other thursday:    
  639. .B m/d/y every 2nd Thu
  640. .br
  641. .sp 1
  642. Note, this will include the 1st, 3rd, 5th, 7th, etc.
  643. thursday, 
  644. .I starting 
  645. from the specified m/d/y
  646. .TP
  647. .B Miscellaneous
  648. .sp 1
  649. The 
  650. .B L 
  651. key stands for lunar, and causes a picture of what the moon will
  652. look like at 11:00PM on the day on which the cursor is placed.
  653. .I <CNTL-L>
  654. or 
  655. .I <CNTL-R>
  656. will redraw the screen.
  657. .br 
  658. .sp 1
  659. The 
  660. .B F
  661. key is used for storing event descriptions to a file.  
  662. The user is prompted for whether he would like to store ALL the events
  663. in his database or just those for the current day.  
  664. The user is then prompted for a file name, and if that file exists already,
  665. the user is given a chance to abort the operation or continue.
  666. .SH EXAMPLES
  667. .br
  668. .sp 1
  669. .ti +1i
  670. cp \ $HOME/.apptrc \ $HOME/.appt\ ;\ month -A \ >> \ $HOME/.appt
  671. .sp
  672. .br
  673. month -N > \ $HOME/.nag\ ;\ nag
  674. .sp
  675. .ti -1i
  676. .SH AUTHORS
  677. .ta +1.15i
  678. Jeff Bauer    (bauer@etc)
  679. .br
  680. Robert Dextor    (robertd@tekigm2)
  681. .br
  682. Marc Ries    (ries@trwrb)
  683. .br
  684. Tom Stoehn    (tims@zeus)
  685. .SH FILES
  686. $HOME/.month
  687. .SH SEE ALSO
  688. appt (1), calendar (1), and nag (1).
  689. .SH DIAGNOSTICS
  690. month: unknown option \fIarg\fR 
  691. .br
  692. Usage: month [-A] [-B] [-C] [-d] [-N [arg]] [-v]
  693. .SH BUGS
  694. Few attempts have been made to prevent the user from browsing
  695. through negatively numbered years or years with more than four
  696. digits in them, the latter causing the years area to get messed up,
  697. but remains functional.
  698. Rarely, events with a starting date before the year 1753,
  699. will not be recalled correctly.
  700.  
  701. With the 
  702. .B -A 
  703. flag, any date that does not have a time that pertains
  704. to it (i.e. birthdays, holidays, ...), set the starting time to 12:00 AM. 
  705. .I Month 
  706. requires a starting time whereas 
  707. .I appt 
  708. does not.
  709. .SH DATE
  710. 2/9/87
  711. RiesES_PIECES
  712. else
  713.   echo "will not over write ./month.1"
  714. fi
  715. if `test ! -s ./month.c`
  716. then
  717. echo "writting ./month.c"
  718. cat > ./month.c << 'RiesES_PIECES'
  719. /*            Modification History
  720.  *
  721.  *  Origional Author:  Tom Stoehn@Tektronics[zeus!tims]
  722.  *  Modifications by:  Marc Ries@TRW[trwrb!ries]
  723.  *
  724.  */
  725.  
  726. #include <curses.h>
  727. #include <signal.h>
  728. #include <sys/types.h>
  729. #include <utmp.h>
  730. #include "month.h"
  731.  
  732. short initd = 0;
  733. short dhour, dminute, dsecond;
  734. extern short crow, ccol, update_schedule, updating;
  735. extern short this_month, this_day, this_year, SCHEDULE_ROW, SKID_ROW;
  736. extern struct event_rec events;
  737. extern struct mdate mdates[];
  738. extern char *strcpy();
  739.  
  740. extern short start_day;
  741.  
  742. short calflag, nagflag;
  743. char *nagprog = "";
  744.  
  745. int lflag = 0;
  746.  
  747. main(argc, argv)
  748. int argc;
  749. char **argv;
  750. {
  751.     extern int optind;
  752.     extern char *optarg;
  753.     int argch;
  754.  
  755.     while ( (argch=getopt(argc,argv,"ABCN:Ldhv?")) != EOF ) {
  756.     switch (argch) {
  757.         case 'd': /* Place in background */ 
  758.                 if (!fork()) {
  759.             (void) signal(SIGINT, SIG_IGN);
  760.             (void) signal(SIGQUIT, SIG_IGN);
  761.             daemonize();
  762.         }
  763.         exit(0);
  764.             case 'N': /* Output in nag format  */
  765.             nagflag++;
  766.         if (optind > argc) {
  767.             (void) strcpy(nagprog, "echo");
  768.         } else {
  769.             nagprog = optarg;
  770.         }
  771.             case 'B': /* Output Time and Event */
  772.                 get_current_date();
  773.              read_schedule();
  774.                 psched2();
  775.                 exit(0);
  776.                 break;
  777.             case 'C': /* Output in calendar format  */
  778.         calflag++;
  779.             case 'A': /* Output in APPT format */
  780.                 get_current_date();
  781.             read_schedule();
  782.                 scan_every_event_for_appt(); 
  783.                 exit(0);
  784.                 break;
  785.         case 'L': /* Output Lunar display only */
  786.         init();
  787.                 get_current_date();
  788.         ++lflag;
  789.         lunar();
  790.         exit(0);
  791.             case 'v': /* Output Version Info */
  792.             (void) fprintf(stderr, "  MONTH [version %s]\n", VERSION);
  793.         sleep(3);
  794.                 break;
  795.         case '?':
  796.         case 'h':
  797.         default:
  798.            (void) printf("Usage: %s [-A] [-B] [-C] [-L] [-d] [-N [arg]] [-v]\n", *argv);
  799.           (void) printf("              |    |    |    |    |    |    |     |\n");
  800.            (void) printf("              |    |    |    |    |    |    |     +-- version id\n");
  801.            (void) printf("              |    |    |    |    |    |    +-- program to \"nag\" with\n");
  802.            (void) printf("              |    |    |    |    |    +-- .nag format\n");
  803.            (void) printf("              |    |    |    |    +-- daemonize\n");
  804.         (void) printf("              |    |    |    +-- lunar display\n");
  805.            (void) printf("              |    |    +-- calendar format\n");
  806.            (void) printf("              |    +-- today's events\n");
  807.            (void) printf("              +-- .appt format\n");
  808.         terminate();
  809.         }
  810.     }
  811.     init();
  812.     print_screen();
  813.     start_display();
  814.     user();
  815.     terminate();
  816. }
  817.  
  818. init()
  819. {
  820.     int blast_out(), i;
  821.  
  822.     (void) signal(SIGINT, blast_out);
  823.     (void) signal(SIGQUIT, blast_out);
  824.     get_current_date();
  825.     read_schedule();
  826.  
  827.     for (i = 0; i < 12; i++) {
  828.         mdates[i].month = this_month;
  829.         mdates[i].year = this_year;
  830.     }
  831.     initscr();
  832.     SCHEDULE_ROW = (LINES < 25) ? 17 : 18;
  833.     SKID_ROW = 18;
  834.     initd = 1;
  835.     crmode();
  836.     noecho();
  837. }
  838.  
  839. terminate()
  840. {
  841.     if (updating) {
  842.         return;
  843.     }
  844.     (void) signal(SIGINT, SIG_IGN);
  845. #ifdef  BSD
  846.     (void) signal(SIGTSTP, SIG_IGN);
  847. #endif
  848.     (void) signal(SIGQUIT, SIG_IGN);
  849.     (void) signal(SIGHUP, SIG_IGN);
  850.  
  851.     if (initd) {
  852.         if (update_schedule) {
  853.             mvaddstr(0, 0, "updating schedule\t");
  854.         } else {
  855.             mvaddstr(0, 0, "schedule unchanged\t");
  856.         }
  857.         refresh();
  858.         if (update_schedule) {
  859.             if (write_schedule() == -1) {
  860.                 sound_bell();
  861.                 mvaddstr(0, 0, "cannot create .month");
  862.             }
  863.         }
  864.     move(LINES-1, 0);
  865.     clrtoeol();
  866.     refresh();
  867.     endwin();
  868.     }
  869.     exit(0);
  870. }
  871.  
  872. blast_out()
  873. {
  874.     update_schedule = 0;
  875.     terminate();
  876. }
  877.  
  878. daemonize()
  879. {
  880.     int do_nothing();
  881.     struct event_rec *eptr;
  882.     short minutes, eminutes, diff;
  883.     unsigned short seconds;
  884.  
  885.     (void) fflush(stdout);
  886. AGAIN:
  887.     get_current_date();
  888.     minutes = (60 * dhour) + dminute;
  889.  
  890.     seconds = (60 * (15 - (dminute % 15) - 1)) + (60 - dsecond);
  891.     if (seconds < 60) {
  892.         seconds = 900;
  893.     }
  894.     (void) signal(SIGALRM, do_nothing);
  895.     (void) alarm(seconds);
  896.     if (!logged_in()) {
  897.         terminate();
  898.     }
  899.     read_schedule();
  900.  
  901.     eptr = events.next_event;
  902.  
  903.     while (eptr) {
  904.  
  905.         if (event_matches_date(eptr)) {
  906.             eminutes = (((short)60) * ((short)eptr->hour)) +
  907.                 ((short)eptr->minute);
  908.             diff = eminutes - minutes;
  909.             if ((diff >= 0) && (diff <= 15)) {
  910.                 remind(eptr->event_string, diff);
  911.             }
  912.         }
  913.         eptr = eptr->next_event;
  914.     }
  915.     pause();
  916.     goto AGAIN;
  917. }
  918.  
  919. logged_in()
  920. {
  921.     static struct utmp u_buf;
  922.     struct utmp t_buf;
  923.     int fd, retval = 0;
  924.     static short called_before = 0;
  925.     char *ttyname(), *tname;
  926. AGAIN:
  927.     if ((fd = open("/etc/utmp", 0)) < 0) {
  928.         return(0);
  929.     }
  930.     if (!called_before) {
  931.         tname = ttyname(0) + 5;
  932.     }
  933.     while (read(fd, (char *)&t_buf, sizeof(struct utmp)) > 0) {
  934.         if (!called_before) {
  935.             if (!strcmp(tname, t_buf.ut_line)) {
  936.                 u_buf = t_buf;
  937.                 break;
  938.             }
  939.         } else if (byte_comp((char *)&u_buf, (char *)&t_buf, sizeof(struct utmp))) {
  940.                 (void) close(fd);
  941.                 retval = 1;
  942.                 break;
  943.         }
  944.     }
  945.     (void) close(fd);
  946.     if (!called_before) {
  947.         called_before = 1;
  948.         goto AGAIN;
  949.     }
  950.     return(retval);
  951. }
  952.  
  953. do_nothing()
  954. {
  955. }
  956.  
  957. byte_comp(s1, s2, n)
  958. register char *s1, *s2;
  959. register int n;
  960. {
  961.     short i;
  962.  
  963.     for (i = 0; i < n; i++) {
  964.         if (*(s1++) != *(s2++)) {
  965.             return(0);
  966.         }
  967.     }
  968.     return(1);
  969. }
  970.  
  971. #ifdef BSD
  972. /*  File   : getopt.c
  973.     Author : Henry Spencer, University of Toronto
  974.     Updated: 28 April 1984
  975.     Purpose: get option letter from argv.
  976. */
  977.  
  978. extern char *index();
  979.  
  980. #ifndef    NullS
  981. #define    NullS    (char*)0
  982. #endif    NullS
  983.  
  984. char    *optarg;    /* Global argument pointer. */
  985. int    optind = 0;    /* Global argv index. */
  986.  
  987. int getopt(argc, argv, optstring)
  988.     int argc;
  989.     char *argv[];
  990.     char *optstring;
  991.     {
  992.     register int c;
  993.     register char *place;
  994.     static char *scan = NullS;    /* Private scan pointer. */
  995.  
  996.     optarg = NullS;
  997.  
  998.     if (scan == NullS || *scan == '\0') {
  999.         if (optind == 0) optind++;
  1000.         if (optind >= argc) return EOF;
  1001.         place = argv[optind];
  1002.         if (place[0] != '-' || place[1] == '\0') return EOF;
  1003.         optind++;
  1004.         if (place[1] == '-' && place[2] == '\0') return EOF;
  1005.         scan = place+1;
  1006.     }
  1007.  
  1008.     c = *scan++;
  1009.     place = index(optstring, c);
  1010.     if (place == NullS || c == ':') {
  1011.         (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
  1012.         return '?';
  1013.     }
  1014.     if (*++place == ':') {
  1015.         if (*scan != '\0') {
  1016.         optarg = scan, scan = NullS;
  1017.         } else {
  1018.         optarg = argv[optind], optind++;
  1019.         }
  1020.     }
  1021.     return c;
  1022.     }
  1023. #endif BSD
  1024. RiesES_PIECES
  1025. else
  1026.   echo "will not over write ./month.c"
  1027. fi
  1028. if `test ! -s ./month.h`
  1029. then
  1030. echo "writting ./month.h"
  1031. cat > ./month.h << 'RiesES_PIECES'
  1032. #define VERSION        "1.4 (USENET) 03/01/87" /* Version number!  SCCS should agree */
  1033.  
  1034. #define TOP_MONTH_ROW 3
  1035. #define YEAR_ROW 16
  1036. #define YEAR_COL 12
  1037. #define TIME_ROW 20
  1038. #define DURATION_ROW 21
  1039. #define DESCRIPTION_ROW 22
  1040. #define ACCEPT_ROW 23
  1041. #define LAST_YEAR_COL 75
  1042. #define DATE_COL 0
  1043. #define MONTHLY_COL 15
  1044. #define YEARLY_COL 23
  1045. #define EVERY_COL 30
  1046. #define NTH_COL 36
  1047. #define LAST_COL 41
  1048. #define SMTWTFS_COL 46
  1049. #define TIME_COL 11
  1050. #define MINUTE_COL 14
  1051. #define ACCEPT_COL 11
  1052. #define CANCEL_COL 18
  1053. #define SMONTH_COL 0
  1054. #define SDAY_COL 3
  1055. #define SYEAR_COL 6
  1056.  
  1057. #define MONTHS 0
  1058. #define YEARS 1
  1059. #define DAYS 2
  1060. #define SCHEDULE 3
  1061.  
  1062. #define MAX_EVENTS 250
  1063.  
  1064. #define MAX_EVENT_STRING_LENGTH 70
  1065.  
  1066. #define NOTHING 0
  1067. #define ACCEPT 1
  1068. #define CANCEL 2
  1069.  
  1070. struct event_rec {
  1071.     char event_month;        /* month of the event */
  1072.     char event_day;            /* day of the event */
  1073.     short event_year;        /* year of the event */
  1074.     char monthly;            /* does event occur monthly? */
  1075.     char yearly;            /* does event occur yearly? */
  1076.     char every;                /* does event occur on every something? */
  1077.     char smtwtfs[7];        /* which days of the week are relevent? */
  1078.     char nth, last;            /* does event occurn on an nth or last somehting? */
  1079.     char nth_is_on;            /* is 'nth' selected by user, n is nth above */
  1080.     char hour;                /* hour of the event */
  1081.     char minute;            /* minute of the event */
  1082.     char span_hours;    /* hours event lasts */
  1083.     char span_minutes;    /* minutes event lasts, multiple of 15 */
  1084.     char event_string[MAX_EVENT_STRING_LENGTH];    /* short description of event */
  1085.     struct event_rec *next_event;    /* next event */
  1086. };
  1087.  
  1088. struct mdate {
  1089.     short month;
  1090.     short year;
  1091. };
  1092. RiesES_PIECES
  1093. else
  1094.   echo "will not over write ./month.h"
  1095. fi
  1096. if `test ! -s ./psched.c`
  1097. then
  1098. echo "writting ./psched.c"
  1099. cat > ./psched.c << 'RiesES_PIECES'
  1100. /*
  1101.  * Modification History 
  1102.  *
  1103.  * Origional Author:  Tom Stoehn@Tektronics[zeus!tims] Modifications by:  Marc
  1104.  * Ries@TRW[trwrb!ries] 
  1105.  *
  1106.  */
  1107.  
  1108. #include <curses.h>
  1109. #include "month.h"
  1110.  
  1111. /*
  1112.  * A routine that will print out the schedule for the day, i.e., 
  1113.  *
  1114.  * 8:45 - 9:45  Foo Bar Baz and so on... 
  1115.  */
  1116.  
  1117. extern short    nagflag, month, day, year;
  1118. extern char    *nagprog;
  1119.  
  1120. psched()
  1121. {
  1122. short           i, shour, sminute, ehour, eminute, n;
  1123. struct event_rec *events_today[MAX_EVENTS];
  1124.  
  1125.     get_daily_events(events_today);
  1126.     for (n = 0; events_today[n]; n++);
  1127.     sort_events(events_today, n);
  1128.  
  1129.     clear();
  1130.     move(0, 0);
  1131.     i = 0;
  1132.     while (events_today[i])
  1133.     {
  1134.  
  1135.         shour = events_today[i]->hour;
  1136.         sminute = events_today[i]->minute;
  1137.         ehour = shour + (events_today[i]->span_hours);
  1138.         eminute = sminute + (events_today[i]->span_minutes);
  1139.  
  1140.         printw("%2d:%02d%2s-%2d:%02d%2s %s\n", 
  1141.                    (shour <= 12) ? shour : (shour % 12), sminute,
  1142.                ((shour < 12) ? "AM" : "PM"),
  1143.                (ehour <= 12) ? ehour : (ehour % 12), eminute,
  1144.                (((ehour % 24) < 12) ? "AM" : "PM"),
  1145.                events_today[i]->event_string);
  1146.         i++;
  1147.     }
  1148.     refresh();
  1149.     get_char();
  1150.     clear();
  1151.     print_screen();
  1152. }
  1153.  
  1154. psched2()
  1155. {
  1156. short           i, shour, sminute, ehour, eminute, n;
  1157. struct event_rec *events_today[MAX_EVENTS];
  1158.  
  1159.     get_daily_events(events_today);
  1160.     for (n = 0; events_today[n]; n++);
  1161.     sort_events(events_today, n);
  1162.  
  1163.     i = 0;
  1164.     while (events_today[i])
  1165.     {
  1166.  
  1167.         shour = events_today[i]->hour;
  1168.         sminute = events_today[i]->minute;
  1169.         ehour = shour + (events_today[i]->span_hours);
  1170.         eminute = sminute + (events_today[i]->span_minutes);
  1171.  
  1172.         if (nagflag)
  1173.         {
  1174.             (void) printf(" %02d/%02d/%d", month, day, year);
  1175.             (void) printf(" %02d:%02d%2s ",
  1176.                    (shour <= 12) ? shour : (shour % 12), sminute,
  1177.                    ((shour < 12) ? "AM" : "PM"));
  1178.             (void) printf("-20:-9:-6:-4:-2 ");
  1179.             (void) printf("%s \"%s at \$then in \$pretime minutes.\"\n",
  1180.                    nagprog, events_today[i]->event_string);
  1181.         } else
  1182.         {
  1183.             (void) printf("%2d:%02d%2s-%2d:%02d%2s ",
  1184.                    (shour <= 12) ? shour : (shour % 12), sminute,
  1185.                    ((shour < 12) ? "AM" : "PM"),
  1186.                    (ehour <= 12) ? ehour : (ehour % 12), eminute,
  1187.                    ((ehour < 12) ? "AM" : "PM"));
  1188.             (void) printf("%s\n", events_today[i]->event_string);
  1189.         }
  1190.         i++;
  1191.     }
  1192. }
  1193. RiesES_PIECES
  1194. else
  1195.   echo "will not over write ./psched.c"
  1196. fi
  1197. if `test ! -s ./schedule.c`
  1198. then
  1199. echo "writting ./schedule.c"
  1200. cat > ./schedule.c << 'RiesES_PIECES'
  1201. /*
  1202.  * Modification History 
  1203.  *
  1204.  * Origional Author:  Tom Stoehn@Tektronics[zeus!tims] Modifications by:  Marc
  1205.  * Ries@TRW[trwrb!ries] 
  1206.  *
  1207.  */
  1208.  
  1209. #include <curses.h>
  1210. #include "month.h"
  1211. #include <sys/types.h>
  1212. #include <sys/file.h>
  1213.  
  1214. extern char *strcpy(), *strcat();
  1215. extern char *getenv(), *malloc();
  1216.  
  1217. #ifndef F_OK
  1218. #define F_OK    00
  1219. #endif
  1220.  
  1221. struct event_rec events = {0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0},
  1222.                0, 0, 0, 0, 0, 0, 0, 0, 0};
  1223. struct event_rec current_event = {0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0},
  1224.                   1, 0, 0, 10, 0, 1, 0, "", 0};
  1225. short           update_schedule = 0;
  1226. short           updating = 0, edit_flag = 0, put_into_schedule, parsed_correctly;
  1227. char            schedule_file_name[75];
  1228. short           SCHEDULE_ROW, SKID_ROW;
  1229.  
  1230. char           *grids[] = {
  1231. "mid.  .  .  1a .  .  .  2a .  .  .  3a .  .  .  4a .  .  .  5a .  .  .  6a",
  1232.                "6a .  .  .  7a .  .  .  8a .  .  .  9a .  .  .  10a.  .  .  11a.  .  .  noon",
  1233. "noon  .  .  1p .  .  .  2p .  .  .  3p .  .  .  4p .  .  .  5p .  .  .  6p",
  1234. "6p .  .  .  7p .  .  .  8p .  .  .  9p .  .  .  10p.  .  .  11p.  .  .  mid"
  1235. };
  1236. extern short    month, day, year, days, message_line_filled;
  1237.  
  1238. post_event(month, day, year)
  1239.     short           month, day, year;
  1240. {
  1241.     goto_schedule();
  1242.     current_event.event_month = month;
  1243.     current_event.event_day = day;
  1244.     current_event.event_year = year;
  1245.     display_event(¤t_event);
  1246. }
  1247.  
  1248. read_schedule()
  1249. {
  1250. char            *s;
  1251. int             fd, rec_size;
  1252. struct event_rec *event_ptr, *chain_ptr;
  1253.  
  1254.     chain_ptr = events.next_event;    /* free old events */
  1255.     while (chain_ptr)
  1256.     {
  1257.         event_ptr = chain_ptr;
  1258.         chain_ptr = chain_ptr->next_event;
  1259.         free((char *)event_ptr);
  1260.     }
  1261.     events.next_event = 0;
  1262.  
  1263.     if (!(s = getenv("HOME")))
  1264.     {
  1265.         s = ".";
  1266.     }
  1267.     (void) strcpy(schedule_file_name, s);
  1268.     (void) strcat(schedule_file_name, "/.month");
  1269.  
  1270.     rec_size = sizeof(struct event_rec);
  1271.  
  1272.     if ((fd = open(schedule_file_name, 0)) != -1)
  1273.     {
  1274.  
  1275.         chain_ptr = &events;
  1276.  
  1277.         for (;;)
  1278.         {
  1279.             if ((!(event_ptr = (struct event_rec *) malloc(rec_size))) ||
  1280.                 (read(fd, (char *)event_ptr, rec_size) != rec_size))
  1281.             {
  1282.                 break;
  1283.             }
  1284.             chain_ptr->next_event = event_ptr;
  1285.             chain_ptr = event_ptr;
  1286.             chain_ptr->next_event = (struct event_rec *) 0;
  1287.         }
  1288.         (void) close(fd);
  1289.     }
  1290. }
  1291.  
  1292. write_schedule()
  1293. {
  1294. int             fd;
  1295. struct event_rec *chain_ptr;
  1296.  
  1297.     updating = 1;
  1298.  
  1299.     if ((fd = creat(schedule_file_name, 0640)) == -1)
  1300.     {
  1301.         return (-1);
  1302.     }
  1303.     chain_ptr = events.next_event;
  1304.  
  1305.     while (chain_ptr)
  1306.     {
  1307.         if (!is_passed_event(chain_ptr))
  1308.         {
  1309.             (void) write(fd, (char *) chain_ptr, sizeof(struct event_rec));
  1310.         }
  1311.         chain_ptr = chain_ptr->next_event;
  1312.     }
  1313.     (void) close(fd);
  1314.     updating = 0;
  1315.     return (0);
  1316. }
  1317.  
  1318. select_regularity_col(col)
  1319.     register        col;
  1320. {
  1321. short           i, hflag;
  1322.  
  1323.     switch (col)
  1324.     {
  1325.     case MONTHLY_COL:
  1326.         hl_all(¤t_event, (current_event.monthly ? 0 : 1),
  1327.                0, -1, -1, -1, -1);
  1328.         break;
  1329.     case YEARLY_COL:
  1330.         hl_all(¤t_event, 0, (current_event.yearly ? 0 : 1),
  1331.                -1, -1, -1, -1);
  1332.         break;
  1333.     case EVERY_COL:
  1334.         hl_all(¤t_event, -1, -1,
  1335.                (current_event.every ? 0 : 1), -1, -1, -1);
  1336.         break;
  1337.     case SMTWTFS_COL:
  1338.     case SMTWTFS_COL + 3:
  1339.     case SMTWTFS_COL + 6:
  1340.     case SMTWTFS_COL + 9:
  1341.     case SMTWTFS_COL + 12:
  1342.     case SMTWTFS_COL + 15:
  1343.     case SMTWTFS_COL + 18:
  1344.         i = (col - SMTWTFS_COL) / 3;
  1345.         hflag = (current_event.smtwtfs[i] = !current_event.smtwtfs[i]);
  1346.         hl_schedule(col, hflag);
  1347.         hl_all(¤t_event, -1, -1, -1, -1, -1, -1);
  1348.         break;
  1349.     case NTH_COL:
  1350.         hl_all(¤t_event, -1, -1, -1,
  1351.                (current_event.nth_is_on ? 0 : 1), -1, -1);
  1352.         break;
  1353.     case LAST_COL:
  1354.         hl_all(¤t_event, -1, -1, -1, -1,
  1355.                (current_event.last ? 0 : 1), -1);
  1356.         break;
  1357.     }
  1358. }
  1359.  
  1360. accept_cancel(is_accept)
  1361.     short           is_accept;
  1362. {
  1363.     if (is_accept)
  1364.     {
  1365.         accept_current_event();
  1366.     } else
  1367.     {
  1368.         cancel_current_event();
  1369.         display_event(¤t_event);
  1370.     }
  1371.     if (edit_flag)
  1372.     {
  1373.         clear_message_line();
  1374.     } else
  1375.     {
  1376.         message_line_filled = 1;
  1377.     }
  1378.     goto_day(day);
  1379. }
  1380.  
  1381. accept_current_event()
  1382. {
  1383.     if ((parse_event(¤t_event) != -1))
  1384.     {
  1385.         if (get_answer("Put into schedule? ", "change cancelled", "done",
  1386.                    'n', 'y')
  1387.             == 'y')
  1388.         {
  1389.             if (!edit_flag)
  1390.             {
  1391.                 link_event(¤t_event);
  1392.             }
  1393.             put_into_schedule = 1;
  1394.         }
  1395.     }
  1396. }
  1397.  
  1398. cancel_current_event()
  1399. {
  1400.     if (!edit_flag)
  1401.     {
  1402.         current_event = events;
  1403.     }
  1404. }
  1405.  
  1406. link_event(event)
  1407.     struct event_rec *event;
  1408. {
  1409. struct event_rec *t, *ptr;
  1410.  
  1411.     if (!(ptr = (struct event_rec *)
  1412.           malloc(sizeof(struct event_rec))))
  1413.     {
  1414.         return;
  1415.     }
  1416.     *ptr = *event;
  1417.     t = events.next_event;
  1418.     events.next_event = ptr;
  1419.     ptr->next_event = t;
  1420.     update_schedule++;
  1421. }
  1422.  
  1423. parse_event(event)
  1424.     struct event_rec *event;
  1425. {
  1426. short           hs;
  1427.  
  1428.     hs = has_smtwtfs(event->smtwtfs);
  1429.  
  1430.     if ((event->every || event->nth_is_on || event->last) && !hs)
  1431.     {
  1432.         error_message("missing day of week", 1);
  1433.         return (-1);
  1434.     }
  1435.     if (hs && !event->every && !event->nth_is_on && !event->last)
  1436.     {
  1437. MQ:        error_message("missing qualifier", 1);
  1438.         return (-1);
  1439.     }
  1440.     if (!event->every &&
  1441.         (event->monthly || event->yearly) &&
  1442.         (event->nth_is_on || event->last))
  1443.     {
  1444.         error_message("need 'every'", 1);
  1445.         return (-1);
  1446.     }
  1447.     if (event->last && !event->monthly && !event->yearly)
  1448.     {
  1449.         error_message("monthly or yearly?", 1);
  1450.         return (-1);
  1451.     }
  1452.     if ((event->nth_is_on || event->last) &&
  1453.         (!event->monthly && !event->yearly && !event->every))
  1454.     {
  1455.         goto MQ;
  1456.     }
  1457.     parsed_correctly = 1;
  1458.     return (0);
  1459. }
  1460.  
  1461.  
  1462. overview()
  1463. {
  1464. short           i, j, row, col, hour, minute, span, n;
  1465. struct event_rec *event_list[MAX_EVENTS];
  1466. char           *grid;
  1467.  
  1468.     (void) get_daily_events(event_list);
  1469.  
  1470.     clear_schedule_area();
  1471.  
  1472.     for (i = 0; i < 4; i++)
  1473.     {
  1474.         mvaddstr((SCHEDULE_ROW + i + i), 1, grids[i]);
  1475.     }
  1476.  
  1477.     standout();
  1478.     i = 0;
  1479.  
  1480.     while (event_list[i])
  1481.     {
  1482.  
  1483.         hour = event_list[i]->hour;
  1484.         minute = event_list[i]->minute;
  1485.  
  1486.         row = SCHEDULE_ROW + ((hour / 6) * 2);
  1487.  
  1488.         if (row > (LINES - 1))
  1489.         {
  1490.             break;
  1491.         }
  1492.         span = (event_list[i]->span_hours * 60) +
  1493.             event_list[i]->span_minutes;
  1494.         col = 1 + (12 * (hour % 6)) + (3 * (minute / 15));
  1495.         n = hour / 6;
  1496.         grid = grids[n];
  1497.         span /= 15;
  1498.  
  1499.         move(row, col);
  1500.  
  1501.         for (j = 0; j < span; j++)
  1502.         {
  1503.             addch(grid[col - 1]);
  1504.             addch(grid[col]);
  1505.             addch(grid[col + 1]);
  1506.  
  1507.             col += 3;
  1508.             if (col > 72)
  1509.             {
  1510.                 col = 1;
  1511.                 row += 2;
  1512.  
  1513.                 if (row > (SCHEDULE_ROW + 6))
  1514.                 {
  1515.                     row = SCHEDULE_ROW;
  1516.                 }
  1517.                 move(row, col);
  1518.                 grid = grids[++n % 4];
  1519.             }
  1520.         }
  1521.         i++;
  1522.     }
  1523.     standend();
  1524. }
  1525.  
  1526. get_daily_events(event_list)
  1527.     struct event_rec *event_list[];
  1528. {
  1529. short           i = 0;
  1530. struct event_rec *eptr;
  1531.  
  1532.     eptr = events.next_event;
  1533.  
  1534.     while (eptr && (i < (MAX_EVENTS - 1)))
  1535.     {
  1536.         if (event_matches_date(eptr))
  1537.         {
  1538.             event_list[i++] = eptr;
  1539.         }
  1540.         eptr = eptr->next_event;
  1541.     }
  1542.     event_list[i] = 0;
  1543.     return (i);
  1544. }
  1545.  
  1546. get_every_event(event_list)
  1547.     struct event_rec *event_list[];
  1548. {
  1549. short           i = 0;
  1550. struct event_rec *eptr;
  1551.  
  1552.     eptr = events.next_event;
  1553.  
  1554.     while (eptr && (i < (MAX_EVENTS - 1)))
  1555.     {
  1556.         event_list[i++] = eptr;
  1557.         eptr = eptr->next_event;
  1558.     }
  1559.     event_list[i] = 0;
  1560.     return (i);
  1561. }
  1562.  
  1563. scan_events(schar)
  1564.     int             schar;
  1565. {
  1566. struct event_rec *event_list[MAX_EVENTS];
  1567. short           i, j, k, ch, n;
  1568.  
  1569.     if (schar == 'S')
  1570.     {            /* scan todays events */
  1571.         if ((n = get_daily_events(event_list)) <= 0)
  1572.         {
  1573.             error_message("No events this day", 0);
  1574.             clear_schedule_area();
  1575.             return;
  1576.         }
  1577.     } else
  1578.     {            /* scan all events */
  1579.         if ((n = get_every_event(event_list)) <= 0)
  1580.         {
  1581.             error_message("No events", 0);
  1582.             clear_schedule_area();
  1583.             return;
  1584.         }
  1585.     }
  1586.     sort_events(event_list, n);
  1587.  
  1588.     for (i = 0; i < n; i++)
  1589.     {
  1590.         current_event = *event_list[i];
  1591.         display_event(event_list[i]);
  1592. GETCH:
  1593.         ch = get_npdeq();
  1594.  
  1595.         switch (ch)
  1596.         {
  1597.         case '\0':
  1598.             i--;
  1599.             break;
  1600.         case '\033':
  1601.         case 'q':
  1602.             goto OUT;
  1603.         case 'n':
  1604.             j = i + 1;
  1605.             while ((j < n) && (!event_list[j]))
  1606.             {
  1607.                 j++;
  1608.             }
  1609.             if (j >= n)
  1610.             {
  1611.                 /*
  1612.                  * sound_bell(); goto GETCH; 
  1613.                  */
  1614.                 goto OUT;
  1615.             }
  1616.             i = j - 1;
  1617.             break;
  1618.         case 'p':
  1619.             j = i - 1;
  1620.             while ((j >= 0) && (!event_list[j]))
  1621.             {
  1622.                 j--;
  1623.             }
  1624.             if (j < 0)
  1625.             {
  1626.                 sound_bell();
  1627.                 goto GETCH;
  1628.             }
  1629.             i = j - 1;
  1630.             break;
  1631.         case 'd':
  1632.             delete_event(event_list[i]);
  1633.             event_list[i] = 0;
  1634.             for (k = i + 1; k < n; k++)
  1635.             {
  1636.                 if (event_list[k] != 0)
  1637.                 {
  1638.                     i = k;
  1639.                     break;
  1640.                 }
  1641.             }
  1642.             if (event_list[i] == 0)
  1643.             {
  1644.                 for (k = i - 1; k >= 0; k--)
  1645.                 {
  1646.                     if (event_list[k] != 0)
  1647.                     {
  1648.                         i = k;
  1649.                         break;
  1650.                     }
  1651.                 }
  1652.             }
  1653.             if (event_list[i] != 0)
  1654.             {
  1655.                 i--;
  1656.             } else
  1657.             {
  1658.                 goto OUT;
  1659.             }
  1660.             break;
  1661.         case 'e':
  1662.     EDIT:        goto_schedule();
  1663.             edit_flag = 1;
  1664.             parsed_correctly = 0;
  1665.             put_into_schedule = 0;
  1666.             if (user() == ACCEPT)
  1667.             {
  1668.                 if (parsed_correctly && put_into_schedule)
  1669.                 {
  1670.                     *event_list[i] = current_event;
  1671.                     update_schedule++;
  1672.                 } else if (!parsed_correctly)
  1673.                 {
  1674.                     goto EDIT;
  1675.                 }
  1676.             } else
  1677.             {
  1678.                 display_event(event_list[i]);
  1679.             }
  1680.             edit_flag = 0;
  1681.             i--;
  1682.             break;
  1683.         }
  1684.     }
  1685. OUT:    goto_day(day);
  1686. }
  1687.  
  1688. delete_event(event)
  1689.     struct event_rec *event;
  1690. {
  1691. struct event_rec *ptr;
  1692.  
  1693.     ptr = &events;
  1694.  
  1695.     while (ptr && (ptr->next_event != event))
  1696.     {
  1697.         ptr = ptr->next_event;
  1698.     }
  1699.     if (ptr)
  1700.     {
  1701.         ptr->next_event = ptr->next_event->next_event;
  1702.         free((char *) event);
  1703.     }
  1704.     update_schedule++;
  1705. }
  1706.  
  1707. sort_events(e, n)
  1708.     register struct event_rec *e[];
  1709. int             n;
  1710. {
  1711. register struct event_rec *t;
  1712. register        i, j;
  1713. short           f;
  1714.  
  1715.     for (i = 0; i < n; i++)
  1716.     {
  1717.         for (j = (n - 1), f = 0; j > 0; j--)
  1718.         {
  1719.             if ((e[j]->hour < e[j - 1]->hour) ||
  1720.                 ((e[j]->hour == e[j - 1]->hour) &&
  1721.                  (e[j]->minute < e[j - 1]->minute)))
  1722.             {
  1723.                 t = e[j];
  1724.                 e[j] = e[j - 1];
  1725.                 e[j - 1] = t;
  1726.                 f++;
  1727.             }
  1728.         }
  1729.         if (f == 0)
  1730.         {
  1731.             break;
  1732.         }
  1733.     }
  1734. }
  1735.  
  1736. show_all_events(month, year)
  1737.     register        month, year;
  1738. {
  1739. register struct event_rec *eptr;
  1740. short           i;
  1741. char            match_list[32];
  1742. short           tday;
  1743.  
  1744.     tday = day;
  1745.  
  1746.     for (i = 1; i <= days; i++)
  1747.     {
  1748.  
  1749.         eptr = events.next_event;
  1750.         match_list[i] = 0;
  1751.         day = i;
  1752.  
  1753.         while (eptr)
  1754.         {
  1755.             if (event_matches_date(eptr))
  1756.             {
  1757.                 if (!eptr->monthly && !eptr->yearly && !eptr->every)
  1758.                 {
  1759.                     match_list[i] = 2;
  1760.                     break;
  1761.                 } else
  1762.                 {
  1763.                     match_list[i] = 1;
  1764.                 }
  1765.             }
  1766.             eptr = eptr->next_event;
  1767.         }
  1768.     }
  1769.     day = tday;
  1770.     print_cal(month, year, match_list);
  1771. }
  1772.  
  1773. file_events()
  1774. {
  1775. struct event_rec *event_list[MAX_EVENTS];
  1776. short           i, ch, n;
  1777. char            buf[256];
  1778. int             fd;
  1779.  
  1780.     if ((ch = get_answer("all, or current? [ac] ",
  1781.                  "", "", 'a', 'c')) == 'c')
  1782.     {
  1783.         if ((n = get_daily_events(event_list)) <= 0)
  1784.         {
  1785.             error_message("No events this day", 0);
  1786.             return;
  1787.         }
  1788.     } else if (ch == 'a')
  1789.     {            /* scan all events */
  1790.         if ((n = get_every_event(event_list)) <= 0)
  1791.         {
  1792.             error_message("No events", 0);
  1793.             return;
  1794.         }
  1795.     } else
  1796.     {
  1797.         return;
  1798.     }
  1799.     if (!get_input_line("file: ", buf))
  1800.     {
  1801.         return;
  1802.     }
  1803.     if (!access(buf, F_OK))
  1804.     {
  1805.         if (get_answer("file already exists, use it? ", "aborted", "OK",
  1806.                    'n', 'y') == 'n')
  1807.         {
  1808.             return;
  1809.         }
  1810.     }
  1811.     if ((fd = creat(buf, 0640)) < 0)
  1812.     {
  1813.         error_message("permission denied", 1);
  1814.     } else
  1815.     {
  1816.         if (ch == 'c')
  1817.         {
  1818.             (void) strcpy(buf, "\n\t\t\tEvents for ");
  1819.             print_date(event_list[0]->event_month, event_list[0]->event_day,
  1820.                    event_list[0]->event_year, buf + strlen(buf));
  1821.         } else
  1822.         {
  1823.             (void) strcpy(buf, "\n\t\t\tAll Events Listing");
  1824.         }
  1825.         (void) strcat(buf, "\n\n\n");
  1826.         (void) write(fd, buf, strlen(buf));
  1827.         for (i = 0; i < n; i++)
  1828.         {
  1829.             (void) strcpy(buf, "    ");
  1830.             print_time(event_list[i], buf + strlen(buf));
  1831.             (void) strcat(buf, "\n");
  1832.             print_span(event_list[i], buf + strlen(buf));
  1833.             (void) strcat(buf, "\n   ");
  1834.             print_event_description(event_list[i], buf + strlen(buf));
  1835.             (void) strcat(buf, "\n\n* * * * * * * * * *\n\n");
  1836.             (void) write(fd, buf, strlen(buf));
  1837.         }
  1838.         (void) close(fd);
  1839.         error_message("done", 0);
  1840.     }
  1841. }
  1842.  
  1843. scan_every_event_for_appt()
  1844. {
  1845. struct event_rec *ptr;
  1846.  
  1847.     ptr = events.next_event;
  1848.  
  1849.     while (ptr)
  1850.     {
  1851.         current_event = *ptr;
  1852.         display_appt(ptr);
  1853.  
  1854.         ptr = ptr->next_event;
  1855.     }
  1856. }
  1857. RiesES_PIECES
  1858. else
  1859.   echo "will not over write ./schedule.c"
  1860. fi
  1861. if `test ! -s ./time.c`
  1862. then
  1863. echo "writting ./time.c"
  1864. cat > ./time.c << 'RiesES_PIECES'
  1865. /*
  1866.  * Modification History 
  1867.  *
  1868.  * Origional Author:  Tom Stoehn@Tektronics[zeus!tims] Modifications by:  Marc
  1869.  * Ries@TRW[trwrb!ries] 
  1870.  *
  1871.  */
  1872.  
  1873. #ifdef BSD
  1874. #  include <sys/time.h>
  1875. #else
  1876. #include <sys/types.h>
  1877. #  include <time.h>
  1878. #endif
  1879.  
  1880. #include <ctype.h>
  1881.  
  1882. #ifdef BSD
  1883. # undef tolower
  1884. # undef toupper
  1885. #endif
  1886.  
  1887. #include "month.h"
  1888.  
  1889. #ifdef BSD
  1890. char           *timezone();
  1891. #else
  1892. extern char    *tzname[];
  1893. #endif
  1894.  
  1895.  
  1896. short           month, year, day;
  1897. short           this_month, this_day, this_year;
  1898. short           start_day;
  1899. long            time();
  1900.  
  1901. extern short    dhour, dminute, dsecond, days;
  1902.  
  1903. get_current_date()
  1904. {
  1905. struct tm      *tmp,    /* Time structure, see CTIME(3C) */
  1906.                *localtime();
  1907. long            junk;    /* time in seconds....         */
  1908. #ifdef BSD
  1909. struct timeval  tp;
  1910. struct timezone tzp;
  1911. #endif
  1912.  
  1913. #ifdef BSD
  1914.     (void) gettimeofday(&tp, &tzp);
  1915.     junk = tp.tv_sec;
  1916. #else
  1917.     junk = (long) time(0);    /* this must be here for it to work! */
  1918. #endif
  1919.     tmp = localtime(&junk);
  1920.     year = this_year = 1900 + tmp->tm_year;
  1921.     month = this_month = tmp->tm_mon + 1;
  1922.     day = this_day = tmp->tm_mday;
  1923.     dhour = tmp->tm_hour;
  1924.     dminute = tmp->tm_min;
  1925.     dsecond = tmp->tm_sec;
  1926.  
  1927.     start_day = get_start_day(this_month, this_year);
  1928. }
  1929.  
  1930. jan1(year)
  1931.     register        year;
  1932. {
  1933. register        day;
  1934.  
  1935.     day = 4 + year + (year + 3) / 4;
  1936.  
  1937.     if (year > 1800)
  1938.     {
  1939.         day -= (year - 1701) / 100;
  1940.         day += (year - 1601) / 400;
  1941.     }
  1942.     if (year > 1752)
  1943.         day += 3;
  1944.  
  1945.     return (day % 7);
  1946. }
  1947.  
  1948. is_leap_year(year)
  1949.     int             year;
  1950. {
  1951. int             day;
  1952.  
  1953.     day = jan1(year);
  1954.     return ((((jan1(year + 1) + 7 - day) % 7) == 2) ? 1 : 0);
  1955. }
  1956.  
  1957. get_start_day(month, year)
  1958.     register        month, year;
  1959. {
  1960. short           day, i;
  1961.  
  1962.     day = jan1(year);
  1963.  
  1964.     for (i = 1; i < month; i++)
  1965.     {
  1966.         day = (day + days_in(i, year)) % 7;
  1967.     }
  1968.     return (day);
  1969. }
  1970.  
  1971. days_in(month, year)
  1972.     register        month, year;
  1973. {
  1974. int             days;
  1975.  
  1976.     switch (month)
  1977.     {
  1978.     case 1:
  1979.     case 3:
  1980.     case 5:
  1981.     case 7:
  1982.     case 8:
  1983.     case 10:
  1984.     case 12:
  1985.         days = 31;
  1986.         break;
  1987.     case 4:
  1988.     case 6:
  1989.     case 9:
  1990.     case 11:
  1991.         days = 30;
  1992.         break;
  1993.     case 2:
  1994.         days = 28 + is_leap_year(year);
  1995.         break;
  1996.     }
  1997.     return (days);
  1998. }
  1999.  
  2000. is_passed_event(event)
  2001.     struct event_rec *event;
  2002. {
  2003.     if (event->monthly || event->yearly || event->every ||
  2004.         (event->event_year > this_year))
  2005.     {
  2006.         return (0);
  2007.     }
  2008.     if (event->event_year < this_year)
  2009.     {
  2010.         return (1);
  2011.     }
  2012.     /* now we know it's this year */
  2013.     if (event->event_month > this_month)
  2014.     {
  2015.         return (0);
  2016.     }
  2017.     if (event->event_month < this_month)
  2018.     {
  2019.         return (1);
  2020.     }
  2021.     /* now we know it's this month */
  2022.     if (event->event_day < this_day)
  2023.     {
  2024.         return (1);
  2025.     }
  2026.     return (0);
  2027. }
  2028.  
  2029. is_before(m, d, y, month, day, year)
  2030.     register        m, d, y, month, day, year;
  2031. {
  2032.     if (y < year)
  2033.     {
  2034.         return (1);
  2035.     }
  2036.     if (y > year)
  2037.     {
  2038.         return (0);
  2039.     }
  2040.     if (m < month)
  2041.     {
  2042.         return (1);
  2043.     }
  2044.     if (m > month)
  2045.     {
  2046.         return (0);
  2047.     }
  2048.     if (d < day)
  2049.     {
  2050.         return (1);
  2051.     }
  2052.     return (0);
  2053. }
  2054.  
  2055. has_smtwtfs(smtwtfs)
  2056.     register char  *smtwtfs;
  2057. {
  2058. register        i;
  2059.  
  2060.     for (i = 0; i < 7; i++)
  2061.     {
  2062.         if (smtwtfs[i])
  2063.         {
  2064.             return (1);
  2065.         }
  2066.     }
  2067.     return (0);
  2068. }
  2069.  
  2070. event_matches_date(event)
  2071.     register struct event_rec *event;
  2072. {
  2073. short           last;
  2074. int             n;
  2075.     /* check if current date is before start date of event */
  2076.  
  2077.     if (is_before(month, day, year, event->event_month, event->event_day,
  2078.               event->event_year))
  2079.     {
  2080.         return (0);
  2081.     }
  2082.     /* one time events */
  2083.  
  2084.     if ((event->event_year == year) && (event->event_month == month) &&
  2085.         (event->event_day == day) && !event->every &&
  2086.         !event->nth_is_on && !event->last)
  2087.     {
  2088.         return (1);
  2089.     }
  2090.     /* once monthly or once yearly events */
  2091.  
  2092.     if (!event->every && !event->nth_is_on && !event->last)
  2093.     {
  2094.         if (event->monthly)
  2095.         {
  2096.             if (event->event_day == day)
  2097.             {
  2098.                 return (1);
  2099.             }
  2100.         } else if (event->yearly)
  2101.         {
  2102.             if ((event->event_month == month) &&
  2103.                 (event->event_day == day))
  2104.             {
  2105.                 return (1);
  2106.             }
  2107.         }
  2108.     }
  2109.     if ((event->monthly || event->yearly) && !event->every &&
  2110.         !event->nth_is_on && !event->last)
  2111.     {
  2112.         if (event->monthly && (event->event_day == day))
  2113.         {
  2114.             return (1);
  2115.         }
  2116.         if (event->yearly && (event->event_month == month) &&
  2117.             (event->event_day == day))
  2118.         {
  2119.             return (1);
  2120.         }
  2121.     }
  2122.     if (!event->smtwtfs[(day - 1 + start_day) % 7])
  2123.     {
  2124.         return (0);
  2125.     }
  2126.     /* everys */
  2127.  
  2128.     if (event->every)
  2129.     {
  2130.  
  2131.         /* every smtwtf */
  2132.  
  2133.         if (!event->nth_is_on && !event->last)
  2134.         {
  2135.     EVDAY:        if (event->smtwtfs[((day - 1 + start_day) % 7)])
  2136.             {
  2137.                 return (1);
  2138.             }
  2139.             return (0);
  2140.         }
  2141.         /* every monthly/yearly */
  2142.  
  2143.         if (event->monthly || event->yearly)
  2144.         {
  2145.             /* every monthly not-1st2nd3rdlast */
  2146.             if (!event->nth_is_on && !event->last)
  2147.             {
  2148.                 goto EVDAY;
  2149.             }
  2150.             /* every monthly/yearly with one of 1st2nd3rdlast */
  2151.  
  2152.             if (event->nth_is_on)
  2153.             {
  2154.                 if (event->monthly &&
  2155.                     (nth_smtwtfs_of_month(&last) ==
  2156.                      (event->nth - 1)))
  2157.                 {
  2158.                     return (1);
  2159.                 }
  2160.                 if (event->yearly &&
  2161.                     (nth_smtwtfs_of_year(&last) ==
  2162.                      (event->nth - 1)))
  2163.                 {
  2164.                     return (1);
  2165.                 }
  2166.             }
  2167.             if (event->last)
  2168.             {
  2169.                 if (event->monthly)
  2170.                 {
  2171.                     (void) nth_smtwtfs_of_month(&last);
  2172.                     if (last)
  2173.                     {
  2174.                         return (1);
  2175.                     }
  2176.                 }
  2177.                 if (event->yearly)
  2178.                 {
  2179.                     (void) nth_smtwtfs_of_year(&last);
  2180.                     if (last)
  2181.                     {
  2182.                         return (1);
  2183.                     }
  2184.                 }
  2185.             }
  2186.         } else
  2187.         {
  2188.             /* every not-monthly and not-yearly */
  2189.             if (!event->nth_is_on && !event->last)
  2190.             {
  2191.                 goto EVDAY;
  2192.             }
  2193.             /* every nth/dayofweek */
  2194.             if (event->nth == 1)
  2195.             {
  2196.                 return (1);
  2197.             }
  2198.             n = how_many_since(event->event_month,
  2199.                     event->event_day, event->event_year);
  2200.             if ((n % (event->nth)) == 1)
  2201.             {
  2202.                 return (1);
  2203.             }
  2204.         }
  2205.     }
  2206.     return (0);
  2207. }
  2208.  
  2209. nth_smtwtfs_of_month(last)
  2210.     short          *last;
  2211. {
  2212.     *last = ((day + 7) > days) ? 1 : 0;
  2213.     return ((day - 1) / 7);
  2214. }
  2215.  
  2216. nth_smtwtfs_of_year(last)
  2217.     short          *last;
  2218. {
  2219. short           days, i;
  2220.  
  2221.     for (i = 1, days = day; i < month; i++)
  2222.     {
  2223.         days += days_in(i, year);
  2224.     }
  2225.  
  2226.     *last = ((days + 7) > (365 + is_leap_year(year))) ? 1 : 0;
  2227.     return ((days - 1) / 7);
  2228. }
  2229.  
  2230. how_many_since(m, d, y)
  2231.     int             m, d, y;
  2232. {
  2233. register        total_days_passed;
  2234. int             i;
  2235.  
  2236.     if (y < year)
  2237.     {
  2238.         total_days_passed = 0;
  2239.         for (i = m; i <= 12; i++)
  2240.         {
  2241.             total_days_passed += days_in(i, y);
  2242.         }
  2243.         total_days_passed -= (d - 1);
  2244.         for (i = (y + 1); i < year; i++)
  2245.         {
  2246.             total_days_passed += (365 + is_leap_year(i));
  2247.         }
  2248.         for (i = 1; i < month; i++)
  2249.         {
  2250.             total_days_passed += days_in(i, year);
  2251.         }
  2252.         total_days_passed += day;
  2253.     } else if (m == month)
  2254.     {
  2255.         total_days_passed = day - d + 1;
  2256.     } else
  2257.     {
  2258.         total_days_passed = 1 - d;
  2259.         for (i = m; i < month; i++)
  2260.         {
  2261.             total_days_passed += days_in(i, year);
  2262.         }
  2263.         total_days_passed += day;
  2264.     }
  2265.     return ((((total_days_passed - 1) / 7) + 1));
  2266. }
  2267.  
  2268. days_since_jan1(month, day, year)
  2269. {
  2270. int             days = 0, i;
  2271.  
  2272.     for (i = 1; i < month; i++)
  2273.     {
  2274.         days += days_in(i, year);
  2275.     }
  2276.     days += day;
  2277.     return (days);
  2278. }
  2279. RiesES_PIECES
  2280. else
  2281.   echo "will not over write ./time.c"
  2282. fi
  2283. if `test ! -s ./user.c`
  2284. then
  2285. echo "writting ./user.c"
  2286. cat > ./user.c << 'RiesES_PIECES'
  2287. /*
  2288.  * Modification History 
  2289.  *
  2290.  * Origional Author:  Tom Stoehn@Tektronics[zeus!tims] Modifications by:  Jeff
  2291.  * Bauer@ETA Systems[eta!bauer] Marc Ries@TRW[trwrb!ries] 
  2292.  *
  2293.  */
  2294.  
  2295. #include <curses.h>
  2296. #include "month.h"
  2297.  
  2298. extern short    crow, ccol, current_area, month, day, year, edit_flag;
  2299. extern short    this_month, this_day, this_year, message_line_filled, days;
  2300. extern struct event_rec current_event;
  2301. extern struct mdate mdates[];
  2302. struct mdate    mdates[12];
  2303.  
  2304. user()
  2305. {
  2306. register short  ch;
  2307. short           n, m, y;
  2308. char           *prompt;
  2309. struct mdate    tmp;
  2310.  
  2311.     for (;;)
  2312.     {
  2313. MR:        move(crow, ccol);
  2314.         refresh();
  2315.  
  2316.         m = month;
  2317.         y = year;
  2318. GETCH:
  2319.         ch = get_char();
  2320.  
  2321.         switch (ch)
  2322.         {
  2323.         case '/':
  2324.             date_search();
  2325.             break;
  2326.         case ';':
  2327.         case ':':
  2328.             if (current_area != SCHEDULE)
  2329.             {
  2330.                 goto_this_day(mdates[10].month, 1, mdates[10].year);
  2331.                 tmp = mdates[10];
  2332.                 mdates[10] = mdates[11];
  2333.                 mdates[11] = tmp;
  2334.                 goto MR;
  2335.             }
  2336.             break;
  2337.         case 'Q':
  2338.             if (current_area != SCHEDULE)
  2339.             {
  2340.                 terminate();
  2341.             }
  2342.             break;
  2343.         case '\033':
  2344.             if (edit_flag)
  2345.             {
  2346.                 return (CANCEL);
  2347.             } else if (current_area == SCHEDULE)
  2348.             {
  2349.                 accept_cancel(0);
  2350.             }
  2351.             break;
  2352.         case 'L':
  2353.             if (current_area == DAYS)
  2354.             {
  2355.                 lunar();
  2356.             } else if ((current_area == MONTHS) || (current_area == YEARS))
  2357.             {
  2358.                 warn_day();
  2359.             }
  2360.             break;
  2361.         case 'j':
  2362.         case 'k':
  2363.         case 'l':
  2364.         case 'h':
  2365.         case 'y':
  2366.         case 'm':
  2367.         case 'd':
  2368.         case '\t':
  2369.             move_cursor(ch);
  2370.             break;
  2371.         case 'n':
  2372.         case '+':
  2373.         case 'p':
  2374.         case '-':
  2375.             incr(ch);
  2376.             break;
  2377.         case '\n':
  2378.         case '\r':
  2379.             if ((n = selection()) != NOTHING)
  2380.             {
  2381.                 return (n);
  2382.             }
  2383.             break;
  2384.         case ' ':
  2385.         case '\b':
  2386.             scroll_time(ch);
  2387.             break;
  2388.         case '0':
  2389.         case '1':
  2390.         case '2':
  2391.         case '3':
  2392.         case '4':
  2393.         case '5':
  2394.         case '6':
  2395.         case '7':
  2396.         case '8':
  2397.         case '9':
  2398.             switch (current_area)
  2399.             {
  2400.             case DAYS:
  2401.                 prompt = "day: ";
  2402.                 break;
  2403.             case MONTHS:
  2404.                 prompt = "month: ";
  2405.                 break;
  2406.             case YEARS:
  2407.                 prompt = "year: ";
  2408.                 break;
  2409.             case SCHEDULE:
  2410.                 switch (ccol)
  2411.                 {
  2412.                 case SMONTH_COL:
  2413.                     prompt = "month: ";
  2414.                     break;
  2415.                 case SDAY_COL:
  2416.                     prompt = "day: ";
  2417.                     break;
  2418.                 case SYEAR_COL:
  2419.                     prompt = "year: ";
  2420.                     break;
  2421.                 case NTH_COL:
  2422.                     prompt = "nth: ";
  2423.                     break;
  2424.                 default:
  2425.                     goto GETCH;
  2426.                 }
  2427.                 break;
  2428.             default:
  2429.                 goto GETCH;
  2430.             }
  2431.             if ((n = enter_number(ch, prompt)) >= 0)
  2432.             {
  2433.                 do_number(n);
  2434.             }
  2435.             break;
  2436.         case 'P':
  2437.             if (current_area == DAYS)
  2438.             {
  2439.                 post_event(month, day, year);
  2440.             } else
  2441.             {
  2442.                 warn_day();
  2443.             }
  2444.             break;
  2445.         case 'A':
  2446.             if (current_area != SCHEDULE)
  2447.             {
  2448.                 show_all_events(month, year);
  2449.             }
  2450.             break;
  2451.         case 'F':
  2452.             file_events();
  2453.             break;
  2454.         case 'S':
  2455.             if (current_area == DAYS)
  2456.             {
  2457.                 scan_events(ch);
  2458.             } else if ((current_area == MONTHS) || (current_area == YEARS))
  2459.             {
  2460.                 warn_day();
  2461.             }
  2462.             break;
  2463.         case 'E':
  2464.             if (current_area != SCHEDULE)
  2465.             {
  2466.                 scan_events(ch);
  2467.             }
  2468.             break;
  2469.         case 'O':
  2470.             if (current_area == DAYS)
  2471.             {
  2472.                 overview();
  2473.             } else if ((current_area == MONTHS) || (current_area == YEARS))
  2474.             {
  2475.                 clear_schedule_area();
  2476.                 warn_day();
  2477.             }
  2478.             break;
  2479.         case 'T':
  2480.             if (current_area != SCHEDULE)
  2481.             {
  2482.                 goto_this_day(this_month, this_day, this_year);
  2483.             }
  2484.             break;
  2485.         case 'M':
  2486.         case 'G':
  2487.             if (current_area != SCHEDULE)
  2488.             {
  2489.                 mark_day((ch == 'G'));
  2490.             }
  2491.             break;
  2492.         case 'B':
  2493.             psched();
  2494.             break;
  2495.         case '?':
  2496.             help();
  2497.             break;
  2498.         default:
  2499.             standout();
  2500.             mvaddstr(23, 60, " Press ? for help");
  2501.             standend();
  2502.             refresh();
  2503.             goto GETCH;
  2504.             break;
  2505.         }
  2506.         if ((m != month) || (y != year))
  2507.         {        /* changed months */
  2508.             mdates[10] = mdates[11];
  2509.             mdates[11].month = month;
  2510.             mdates[11].year = year;
  2511.         }
  2512.     }
  2513. }
  2514.  
  2515. enter_number(ch, prompt)
  2516.     short           ch;
  2517.     char           *prompt;
  2518. {
  2519. char            nbuf[6];
  2520. short           col, first_col, i = 0;
  2521. int             retval = -1;
  2522.  
  2523.     first_col = col = strlen(prompt);
  2524.  
  2525.     mvaddstr(0, 0, prompt);
  2526.  
  2527.     for (;;)
  2528.     {
  2529.         if ((ch >= '0') && (ch <= '9'))
  2530.         {
  2531.             if ((col < (first_col + 2)) ||
  2532.                 (((current_area == YEARS) ||
  2533.                   ((current_area == SCHEDULE)) &&
  2534.                   (ccol == SYEAR_COL)) &&
  2535.                  (col < (first_col + 4))))
  2536.             {
  2537.                 nbuf[i++] = ch;
  2538.                 mvaddch(0, col++, ch);
  2539.                 refresh();
  2540.             }
  2541.         } else if ((ch == '\n') || (ch == '\r'))
  2542.         {
  2543.             nbuf[i] = 0;
  2544.             retval = atoi(nbuf);
  2545.             break;
  2546.         } else if (ch == '\b')
  2547.         {
  2548.             if (col > first_col)
  2549.             {
  2550.                 i--;
  2551.                 col--;
  2552.                 mvaddch(0, col, ' ');
  2553.                 move(0, col);
  2554.                 refresh();
  2555.             }
  2556.         } else if (ch == '\033')
  2557.         {
  2558.             break;
  2559.         }
  2560.         ch = get_char();
  2561.     }
  2562.     clear_message_line();
  2563.     return (retval);
  2564. }
  2565.  
  2566. do_number(n)
  2567.     short           n;
  2568. {
  2569.     if (current_area == YEARS)
  2570.     {
  2571.         if (n > 0)
  2572.         {
  2573.             shift_years(n - year);
  2574.             goto_year(year);
  2575.         }
  2576.     } else if (current_area == MONTHS)
  2577.     {
  2578.         if ((n <= 12) && (n >= 1))
  2579.         {
  2580.             crow = TOP_MONTH_ROW + n;
  2581.             selection();
  2582.         }
  2583.     } else if (current_area == DAYS)
  2584.     {
  2585.         if ((n >= 1) && (n <= days))
  2586.         {
  2587.             goto_day(n);
  2588.         }
  2589.     } else if (current_area == SCHEDULE)
  2590.     {
  2591.         switch (ccol)
  2592.         {
  2593.         case SMONTH_COL:
  2594.             if ((n >= 1) && (n <= 12))
  2595.             {
  2596.                 current_event.event_month = n;
  2597.             }
  2598.             break;
  2599.         case SDAY_COL:
  2600.             if ((n >= 1) && (n <= days))
  2601.             {
  2602.                 current_event.event_day = n;
  2603.             }
  2604.             break;
  2605.         case SYEAR_COL:
  2606.             if (n > 0)
  2607.             {
  2608.                 current_event.event_year = n;
  2609.             }
  2610.             break;
  2611.         case NTH_COL:
  2612.             if ((n > 0) && (n <= 53))
  2613.             {
  2614.                 current_event.nth = n;
  2615.                 current_event.nth_is_on = 1;
  2616.                 print_nth(¤t_event);
  2617.             }
  2618.             break;
  2619.         default:
  2620.             return;
  2621.         }
  2622.         if (ccol != NTH_COL)
  2623.         {
  2624.             print_date(current_event.event_month,
  2625.             current_event.event_day, current_event.event_year, 0);
  2626.         }
  2627.     }
  2628. }
  2629.  
  2630. handle_event_description()
  2631. {
  2632. short           ch;
  2633.  
  2634.     for (;;)
  2635.     {
  2636.         move(crow, ccol);
  2637.         refresh();
  2638.         ch = get_char();
  2639.  
  2640.         if ((ch >= ' ') && (ch <= '~'))
  2641.         {
  2642.             if (ccol <= 78)
  2643.             {
  2644.                 addch(ch);
  2645.                 current_event.event_string[ccol - TIME_COL] = ch;
  2646.                 ccol++;
  2647.                 current_event.event_string[ccol - TIME_COL] = 0;
  2648.             }
  2649.         } else
  2650.         {
  2651.             switch (ch)
  2652.             {
  2653.             case '\n':
  2654.             case '\r':
  2655.             case '\t':
  2656.                 schedule_move_cursor(ch);
  2657.                 return;
  2658.                 break;
  2659.             case '\b':
  2660.                 if (ccol > TIME_COL)
  2661.                 {
  2662.                     ccol--;
  2663.                     mvaddch(crow, ccol, ' ');
  2664.                     current_event.event_string
  2665.                         [ccol - TIME_COL] = 0;
  2666.                 }
  2667.                 break;
  2668.             case '\004':
  2669.             case '\025':
  2670.             case '\030':
  2671.                 current_event.event_string[0] = 0;
  2672.                 ccol = TIME_COL;
  2673.                 move(crow, TIME_COL);
  2674.                 clrtoeol();
  2675.                 break;
  2676.             case '\027':
  2677.                 while ((ccol > TIME_COL) && (current_event.event_string
  2678.                         [--ccol - TIME_COL] == ' '));
  2679.                 while ((ccol > TIME_COL) && (current_event.event_string
  2680.                          [(ccol - 1) - TIME_COL] != ' '))
  2681.                 {
  2682.                     ccol--;
  2683.                 }
  2684.                 move(crow, ccol);
  2685.                 clrtoeol();
  2686.                 break;
  2687.             }
  2688.         }
  2689.     }
  2690. }
  2691.  
  2692. get_answer(prompt, yes_string, no_string, char1, char2)
  2693.     char           *prompt, *yes_string, *no_string;
  2694.     int             char1, char2;
  2695. {
  2696. char           *s;
  2697. short           retval, col;
  2698.  
  2699.     mvaddstr(0, 0, prompt);
  2700.     refresh();
  2701.  
  2702.     do
  2703.     {
  2704.         retval = get_char();
  2705.         if ((retval == (char1 - 32)) || (retval == (char2 - 32)))
  2706.         {
  2707.             retval += 32;
  2708.         }
  2709.     } while ((retval != char1) && (retval != char2) && (retval != '\033'));
  2710.  
  2711.     s = (retval == char1) ? yes_string : no_string;
  2712.     mvaddstr(0, 0, s);
  2713.     col = strlen(s);
  2714.  
  2715.     if (edit_flag)
  2716.     {
  2717.         addstr(" -more-");
  2718.         move(0, col + 7);
  2719.         blank_out(col + 7);
  2720.         move(0, col + 7);
  2721.         refresh();
  2722.         (void) get_char();
  2723.     } else
  2724.     {
  2725.         blank_out(col);
  2726.     }
  2727.     message_line_filled = 1;
  2728.     return (retval);
  2729. }
  2730.  
  2731. get_nq()
  2732. {
  2733. register        ch;
  2734.  
  2735.     mvaddstr(0, 0, "[n,q] ");
  2736.     refresh();
  2737.  
  2738.     for (;;)
  2739.     {
  2740.         ch = get_char();
  2741.  
  2742.         switch (ch)
  2743.         {
  2744.         case 'q':
  2745.         case '\033':
  2746.             clear_message_line();
  2747.             return ('q');
  2748.             break;
  2749.         case 'n':
  2750.         case '\n':
  2751.         case '\r':
  2752.             clear_message_line();
  2753.             return ('n');
  2754.             break;
  2755.         }
  2756.     }
  2757. }
  2758.  
  2759. get_npdeq()
  2760. {
  2761. register        ch;
  2762.  
  2763.     mvaddstr(0, 0, "[n,p,d,e,q] ");
  2764.     refresh();
  2765.  
  2766.     for (;;)
  2767.     {
  2768.         ch = get_char();
  2769.  
  2770.         switch (ch)
  2771.         {
  2772.         case '\n':
  2773.         case '\r':
  2774.             ch = 'n';    /* no break statement */
  2775.         case 'n':
  2776.         case 'p':
  2777.         case 'e':
  2778.         case '\033':
  2779.         case 'q':
  2780.             clear_message_line();
  2781.             return (ch);
  2782.             break;
  2783.         case 'd':
  2784.             ch = get_answer("really delete? ", "", "", 'n', 'y');
  2785.             if (ch == 'y')
  2786.             {
  2787.                 mvaddstr(0, 0, "deleted");
  2788.             } else
  2789.             {
  2790.                 mvaddstr(0, 0, "not deleted");
  2791.             }
  2792.             addstr(" -more-");
  2793.             refresh();
  2794.             (void) get_char();
  2795.             clear_message_line();
  2796.             return ((ch == 'y') ? 'd' : '\0');
  2797.             break;
  2798.         }
  2799.     }
  2800. }
  2801.  
  2802. mark_day(goto_flag)
  2803.     short           goto_flag;
  2804. {
  2805. short           ch;
  2806.  
  2807.     mvaddstr(0, 0, "mark: ");
  2808.     refresh();
  2809.  
  2810.     for (;;)
  2811.     {
  2812.         ch = get_char();
  2813.  
  2814.         switch (ch)
  2815.         {
  2816.         case '0':
  2817.         case '1':
  2818.         case '2':
  2819.         case '3':
  2820.         case '4':
  2821.         case '5':
  2822.         case '6':
  2823.         case '7':
  2824.         case '8':
  2825.         case '9':
  2826.  
  2827.             mvaddch(0, 6, ch);
  2828.             refresh();
  2829.             message_line_filled = 1;
  2830.  
  2831.             ch -= '0';
  2832.  
  2833.             if (goto_flag)
  2834.             {
  2835.                 goto_this_day(mdates[ch].month, 1, mdates[ch].year);
  2836.             } else
  2837.             {
  2838.                 mdates[ch].month = month;
  2839.                 mdates[ch].year = year;
  2840.             }
  2841.             return;
  2842.             break;
  2843.         case '\033':
  2844.         case '\n':
  2845.         case '\r':
  2846.             clear_message_line();
  2847.             return;
  2848.             break;
  2849.         }
  2850.     }
  2851. }
  2852.  
  2853. get_char()
  2854. {
  2855. register int    ch;
  2856. GETCH:
  2857.     ch = getchar() & 0377;
  2858.  
  2859.     if (message_line_filled)
  2860.     {
  2861.         clear_message_line();
  2862.     }
  2863.     switch (ch)
  2864.     {
  2865.     case '\014':
  2866.     case '\022':
  2867.         wrefresh(curscr);
  2868.         goto GETCH;
  2869.         break;
  2870.     }
  2871.     return (ch);
  2872. }
  2873.  
  2874. date_search()
  2875. {
  2876. register short  ch;
  2877. short           col, slash_count;
  2878. char            buf[16];
  2879. int             m, d, y;
  2880.  
  2881. STARTOVER:
  2882.  
  2883.     mvaddstr(0, 0, "date: ");
  2884.     buf[col = 0] = 0;
  2885.     slash_count = 0;
  2886.  
  2887.     for (;;)
  2888.     {
  2889.         refresh();
  2890. GETCH:
  2891.         ch = get_char();
  2892.  
  2893.         switch (ch)
  2894.         {
  2895.         case '\b':
  2896.             if (col > 0)
  2897.             {
  2898.                 if (buf[col - 1] == '/')
  2899.                 {
  2900.                     slash_count--;
  2901.                 }
  2902.                 buf[--col] = 0;
  2903.                 mvaddch(0, col + 6, ' ');
  2904.                 move(0, col + 6);
  2905.             }
  2906.             break;
  2907.         case '/':
  2908.             if ((slash_count >= 2) || ((col > 0) && (buf[col - 1] == '/')) ||
  2909.                 (col == 0))
  2910.             {
  2911.                 sound_bell();
  2912.             } else
  2913.             {
  2914.                 addch(ch);
  2915.                 buf[col++] = ch;
  2916.                 buf[col] = 0;
  2917.                 slash_count++;
  2918.             }
  2919.             break;
  2920.         case '0':
  2921.             if ((col == 0) || (buf[col - 1] == '/'))
  2922.             {
  2923.                 goto GETCH;
  2924.             }    /* no break statement */
  2925.         case '1':
  2926.         case '2':
  2927.         case '3':
  2928.         case '4':
  2929.         case '5':
  2930.         case '6':
  2931.         case '7':
  2932.         case '8':
  2933.         case '9':
  2934.             if (
  2935.                 ((col == 2) && (buf[col - 1] != '/')) ||
  2936.                 ((slash_count == 1) && (buf[col - 1] != '/') && (buf[col - 2] != '/')) ||
  2937.                 ((slash_count == 2) && (buf[col - 1] != '/') && (buf[col - 2] != '/') &&
  2938.                (buf[col - 3] != '/') && (buf[col - 4] != '/')) ||
  2939.                 ((col == 1) && ((ch > '2') || (buf[0] > '1')))
  2940.                 )
  2941.             {
  2942.                 sound_bell();
  2943.                 goto GETCH;
  2944.             } else
  2945.             {
  2946.                 addch(ch);
  2947.                 buf[col++] = ch;
  2948.                 buf[col] = 0;
  2949.             }
  2950.             break;
  2951.         case '\n':
  2952.         case '\r':
  2953.             if ((slash_count < 2) || (buf[col - 1] == '/'))
  2954.             {
  2955.                 sound_bell();
  2956.                 goto GETCH;
  2957.             } else
  2958.             {
  2959.                 (void) sscanf(buf, "%d/%d/%d", &m, &d, &y);
  2960.                 if (y < 100)
  2961.                 {
  2962.                     y += 1900;
  2963.                 }
  2964.                 goto_this_day(m, d, y);    /* no break statement! */
  2965.             }
  2966.         case '\033':
  2967.             goto RET;
  2968.             break;
  2969.         case '\004':
  2970.         case '\025':
  2971.         case '\030':
  2972.             clear_message_line();
  2973.             goto STARTOVER;
  2974.             break;
  2975.         default:
  2976.             goto GETCH;
  2977.             break;
  2978.         }
  2979.     }
  2980. RET:
  2981.     clear_message_line();
  2982. }
  2983.  
  2984. warn_day()
  2985. {
  2986.     error_message("put cursor on day", 1);
  2987. }
  2988.  
  2989. get_input_line(prompt, buf)
  2990.     char           *prompt, *buf;
  2991. {
  2992. short           col, i = 0, ch;
  2993.  
  2994.     clear_message_line();
  2995.     mvaddstr(0, 0, prompt);
  2996.     col = strlen(prompt);
  2997.     move(0, col);
  2998.     refresh();
  2999.  
  3000.     while (((ch = get_char()) != '\n') && (ch != '\r') && (ch != '\033'))
  3001.     {
  3002.         if ((ch > ' ') && (ch < '~'))
  3003.         {
  3004.             if ((i + col) <= 30)
  3005.             {
  3006.                 buf[i++] = ch;
  3007.                 addch(ch);
  3008.                 refresh();
  3009.             }
  3010.         } else if (ch == '\b')
  3011.         {
  3012.             if (i > 0)
  3013.             {
  3014.                 i--;
  3015.                 mvaddch(0, (col + i), ' ');
  3016.                 move(0, (col + i));
  3017.                 refresh();
  3018.             }
  3019.         }
  3020.     }
  3021.     buf[i] = 0;
  3022.     clear_message_line();
  3023.     if ((i == 0) || (ch == '\033'))
  3024.     {
  3025.         return (0);
  3026.     }
  3027.     return (1);
  3028. }
  3029. RiesES_PIECES
  3030. else
  3031.   echo "will not over write ./user.c"
  3032. fi
  3033. echo "Finished archive 1 of 2"
  3034. exit 0
  3035.  
  3036.  
  3037.