billr@saab.CNA.TEK.COM (Bill Randle) (04/06/91)
Submitted-by: Bill Randle <billr@saab.CNA.TEK.COM> Posting-number: Volume 17, Issue 97 Archive-name: calentool/part16 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 16 (of 23)." # Contents: ct.h dates/celtic dates/sports month2ct.c utils.c # Wrapped by billr@saab on Thu Mar 28 08:38:27 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'ct.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ct.h'\" else echo shar: Extracting \"'ct.h'\" \(8475 characters\) sed "s/^X//" >'ct.h' <<'END_OF_FILE' X/* X * $Header: ct.h,v 2.5 91/03/27 16:45:12 billr Exp $ X */ X/* X * ct.h - header file for calentool X * X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com> X * X * Original source Copyright (C) 1987, Sun Microsystems, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify this program in source X * or binary form as long as it is not sold for profit and this copyright X * notice remains intact. X * X * X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * X * Changes and additions Copyright (C) 1988, 1989, 1991 Tektronix, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify the modifications in source X * or binary form as long as they are not sold for profit and this copyright X * notice remains intact. X */ X X/* X * If calentool is too big and you want a stripped-down version X * define some or all of these here or in the Makefile. Combined, X * they save ~100K bytes for a statically linked object. X */ X#define NO_PRINTER /* exclude printer support code */ X/*#define NO_HOLIDAYS /* exclude holiday checking code */ X/*#define NO_SUN_MOON /* exclude Sun/Moon data frames */ X X/* ignore several things for calencheck program */ X#ifdef CALENCHECK X# define NO_PRINTER X# define NO_HOLIDAYS X# define NO_SUN_MOON X# define NOTOOL X#endif X X/* directory for date/event files */ X#ifndef DATELIB_DIR X# define DATELIB_DIR "/usr/net/lib/calentool" X#endif X X#ifndef NO_PRINTER X/* command string for sending a file to the Postscript printer */ X# ifndef PRINT_CMD X# define PRINT_CMD "lpr -Plw" X# endif X X/*# define RASTER_ONLY /* define this if no PostScript printer available */ X# ifndef PS_NOTE_FONT X# define PS_NOTE_FONT "Helvetica-Narrow" X# endif X/*# define LANGUAGE /* for natural language support */ X /* see the file pcaldw.c for details */ X#else X# define RASTER_ONLY /* do not change this line */ X#endif /* NO_PRINTER */ X X#ifndef MAILPROG X# define MAILPROG "/usr/ucb/mail" X /* assumes -s option is available */ X#endif X X/* define NR_WEEKDAYS for desired week display */ X/* NR_WEEKDAYS display */ X/* 5 Mon-Fri */ X/* 6 Mon-Sat */ X/* 7 Sun-Sat or Mon-Sun */ X/**/ X#ifndef NR_WEEKDAYS X# define NR_WEEKDAYS 5 X#endif X#ifndef MON_FIRST X# define MON_FIRST 0 /* 0=Sun-Sat, 1=Mon-Sun */ X#endif X X#ifndef START_HOUR X# define START_HOUR 8 /* 8am */ X#endif /* to */ X#ifndef END_HOUR X# define END_HOUR 18 /* 6pm */ X#endif X#ifndef HOUR_24 X# define HOUR_24 0 /* 0=12hr time, 1=24hr time */ X#endif X#ifndef DAY_FIRST X# define DAY_FIRST 0 /* 0=M/D/Y, 1=D/M/Y */ X#endif X X#ifndef START_YEAR X# define START_YEAR 90 X#endif X#ifndef NR_YEARS X# define NR_YEARS 5 /* number of years in menu */ X#endif X X#ifndef N_NOTESLOTS X# define N_NOTESLOTS 10 /* number of slots for notes */ X#endif X X#ifndef UPDATE_RATE X# define UPDATE_RATE "second" /* update time */ X#endif /* options are "second" & "minute" */ X#define TIME_OUT 2 /* check appts every 5 minutes */ X X/* X * APPT_CHECK_LIMIT is typically either "n_tslots" X * or "n_slots" depending on whether we include the X * notes section when indicating that we still have X * appts today. X */ X#ifndef APPT_CHECK_LIMIT X# define APPT_CHECK_LIMIT n_tslots X#endif X X/*********************************************************************/ X/* Nothing below here should need to be changed (typically) */ X/*********************************************************************/ X X#ifndef TRUE X# define TRUE 1 X#endif X#ifndef FALSE X# define FALSE 0 X#endif X X#define MAX_FUTURE_ENTRIES 32 /* number of appts displayed in popup window */ X X/* Dimensions of 30-minute week slot. X * Message size determines width - everything else keyed X * off font size and message size X */ X#define WEEK_MESSAGE_SIZE 12 X X#define MAX_INCLUDE_NESTING 4 /* number of allowed include files */ X X#define DISPLAYING_DAY 1 /* Defs for state of main */ X#define DISPLAYING_WEEK 2 /* subwindow (mainsw_state) */ X#define DISPLAYING_MONTH 3 X#define DISPLAYING_YEAR 4 X X#define BACKSPACE 8 /* editing chars */ X#define CTRL_R 18 X#define CTRL_U 21 X#define CTRL_W 23 X#define DEL 127 X X#define NONE 0 X#define DAY 1 /* Defs for "selected_type" (type of */ X#define WEEK 2 /* object selected by month click). */ X#define MONTH 3 X X#define JUSTIFY_LEFT 0 /* text justification in day slot */ X#define JUSTIFY_RIGHT 1 X#define JUSTIFY_INDEX 2 X X#define FOUND_SLOT 1 /* event tags for day display */ X#define FOUND_MORE 2 X#define FOUND_LARROW 3 X#define FOUND_RARROW 4 X X#define MMODIFY 1 /* order of entries in day menu */ X#define MCUT 2 X#define MPASTE 3 X#define MCOPY 4 X#define MDELETE 5 X#define MUNDELETE 6 X X#define PR_DEFAULT 0 /* print options */ X#define PR_ASCII 1 X#define PR_POSTSCRIPT 2 X#define PR_RASTER 3 X X#define SUN 0 /* days of the week */ X#define MON 1 X#define TUE 2 X#define WED 3 X#define THU 4 X#define FRI 5 X#define SAT 6 X X#define JAN 0 /* selected months */ X#define FEB 1 X#define DEC 11 X X#define ALL_YEARS 0x1 /* flags for special case appts */ X#define ALL_MONTHS 0x2 X#define ALL_DAYS 0x4 X#define REPEAT 0x8 X /* check for any repeating type appt */ X# define Repeating(d) ((d)&(ALL_YEARS|ALL_MONTHS|ALL_DAYS|REPEAT|EVERY_MON_FRI)) X#define A_COMMENT 0x10 X#define EVERY_SUN 0x20 X#define EVERY_MON 0x40 X#define EVERY_TUE 0x60 X#define EVERY_WED 0x80 X#define EVERY_THU 0xa0 X#define EVERY_FRI 0xc0 X#define EVERY_SAT 0xe0 X#define EVERY_SOMEDAY 0xe0 X /* convert flag value to day-of-week number */ X# define Pickday(d) ((((d)&EVERY_SOMEDAY)>>5)-1) X /* convert day of week to flag value */ X# define Setday(d) (((d)+1)<<5) X#define LOOKAHEAD 0x100 X#define READONLY 0x200 X#define A_NOTE 0x400 X#define MARKED 0x800 /* don't show in month/year display */ X#define MARKED_NOTE 0xc00 X#define DELETED 0x1000 /* don't show the appt that matches this */ X#define RUN 0x2000 X#define EVERY_MON_FRI 0x4000 X X/* format of repeat field for every_someday type appts */ X#define WEEK1 0x1 X#define WEEK2 0x2 X#define WEEK3 0x4 X#define WEEK4 0x8 X#define WEEK5 0x10 X#define ALL_WEEKS 0x1f X#define LAST_WEEK 0x20 X#define WEEK_LIMIT 0x3f X X/* error reporting flags */ X#define NON_FATAL 0 X#define FATAL 1 X X/* icon identifiers */ X#define STD_ICON 0 /* flags for icon currently displayed */ X#define REV_ICON 1 X#define NA_ICON 2 X X/* arguments to print_apts() */ X#define PRI_DAY 1 X#define PRI_WEEK 2 X#define PRI_MONTH 3 X#define PRI_XNOTES 4 X#define PRI_DAY_XNOTES (PRI_DAY|PRI_XNOTES) X#define PRI_WEEK_XNOTES (PRI_WEEK|PRI_XNOTES) X#define PRI_MONTH_XNOTES (PRI_MONTH|PRI_XNOTES) X#define DST_STDOUT 1 X#define DST_MAIL 2 X X/* return codes from get_day_appts() */ X#define NO_ENTRIES 0 X#define SOME_APPTS 1 X#define SOME_NOTES 2 X#define SOME_MKNOTES 4 X#define SOME_FUTURES 8 X X/* header line in appts file implies one-based entries and 99 memo flag */ X#define HEADER "# CalenTool V2.2 - DO NOT REMOVE THIS LINE\n" X#define OHEADER "# CalenTool V2 - DO NOT REMOVE THIS LINE\n" X X#define MAX_STRLEN 256 /* max size of strings */ Xstruct appt_entry { X /* describes an entry in the appointments file */ X int year, month, day, hour, minute, arrows; X int repeat, lookahead, flags, sindex; X int runlength, warn; X char str[MAX_STRLEN]; X struct appt_entry *next; /* ptr to next appt in list */ X}; /* NULL if last entry */ X Xstruct rect_pos { X /* location of a given rect in the canvas */ X int top, bottom, left, right; X}; X Xstruct dayslot { X /* struct for storing relevant info for 30 min day slot */ X struct rect_pos slot_pos; /* slot position in day display */ X struct rect_pos larrow_pos; /* position of left scroll arrow */ X struct rect_pos rarrow_pos; /* position of right scroll arrow */ X struct rect_pos moreb_pos; /* position of "more" button */ X int active; /* number of appts that originate here */ X int count; /* number of appts in this slot */ X int arrow_pos; /* bitmap of arrow locations on screen */ X struct appt_entry *cur_appt; /* ptr to current appt in list */ X struct appt_entry *first; /* ptr to first appt in list */ X}; /* NULL if no entries */ X Xstruct weekrect { X /* info for week display */ X struct rect_pos wday_pos; /* screen position of this day */ X struct rect_pos moreb_pos; /* position of "more" button */ X int more; X struct dayslot *weekslots; /* array of slots for this day */ X}; X Xstruct rect_limits { X int lowx; X int lowy; X int highx; X int highy; X}; X Xstruct week_arrow { X int top; X int bottom; X int left; X int right; X int active; X}; END_OF_FILE if test 8475 -ne `wc -c <'ct.h'`; then echo shar: \"'ct.h'\" unpacked with wrong size! fi # end of 'ct.h' fi if test -f 'dates/celtic' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dates/celtic'\" else echo shar: Extracting \"'dates/celtic'\" \(541 characters\) sed "s/^X//" >'dates/celtic' <<'END_OF_FILE' X# CalenTool V2.2 - nflag=1 range=2,11 - DO NOT REMOVE THIS LINE X# $Header: celtic,v 2.3 91/03/07 16:21:04 billr Exp $ X# Special days file for calentool (rel 2.1); modified from network posting by X# RPC Rodgers, UCSF, Nov. 1988 X# Dates of interest to Celts X# X** 02 01 99 99 00 Oimelc (Winter purification & approach of spring) X** 05 01 99 99 00 Beltaine (Feast of sun god Bel) X** 08 01 99 99 00 Lughnasa (Feast of god Lugh, 30 day Celtic feast centers on this day) X** 11 01 99 99 00 Samhain (beginning of Celtic year, most important holiday) END_OF_FILE if test 541 -ne `wc -c <'dates/celtic'`; then echo shar: \"'dates/celtic'\" unpacked with wrong size! fi # end of 'dates/celtic' fi if test -f 'dates/sports' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dates/sports'\" else echo shar: Extracting \"'dates/sports'\" \(8498 characters\) sed "s/^X//" >'dates/sports' <<'END_OF_FILE' X# CalenTool V2.2 - nflag=1 range=1,12 - DO NOT REMOVE THIS LINE X# $Header: sports,v 1.2 91/03/07 16:21:32 billr Exp $ X# Special dates in sports history X# Today in History dates provided by Robert Heckendorn at X# Hewlett-Packard in Fort Collins, Colorado. X# Any corrections or additions may be sent to robert@fc.hp.com X# X# Additional dates provided from ProLine's today file X# X# Converted to calentool format by Larry Virden (lwv27%cas.BITNET@CUNYVM.CUNY.Edu) X# and further edited and merged by Bill Randle (billr@saab.cna.tek.com). X# X** 01 01 99 99 00 1st Rose Bowl game held in Pasadena, California. (1902) X** 01 01 99 99 00 1st running of SF's famed "Bay to Breakers" race (7.63 miles) (1912) X** 01 01 99 99 00 All registered thoroughbred and quarter horses are "born" on this day X** 01 16 99 99 00 First college basketball game, Iowa vs Chicago (1896) X** 01 29 99 99 00 1st athletic letters given: to Univ of Chicago football team. (1904) X** 02 02 99 99 00 National Baseball League formed with 8 teams. (1876) X** 02 04 99 99 00 1st Winter Olympics held (At Lake Placid, NY). (1932) X** 02 12 99 99 00 The six cars entered in the New York to Paris road race set off on their 12116 mile race through Alaska and Russia. America won. (1908) X** 03 11 99 99 00 1st public game of basketball. (1892) X** 03 28 99 99 00 A New York judge rules that the contest between the American catamaran and the Australian monohull was not fair competition and the America's Cup was returned to the Australians (1989) X** 04 04 99 99 00 President William Howard Taft throws out the first ball of the season to a game between Washington and Philadelphia. Thus starting a tradition (1910) X** 04 04 99 99 00 Hank Aaron of Atlanta Braves ties Babe Ruth's home run record at 714 (1974) X** 04 08 99 99 00 Hammerin' Hank Aaron hits 715th home run, beats Babe Ruth's record. (1974) X** 04 11 99 99 00 Jackie Robinson breaks the color barrier in baseball when he plays for the Brooklyn Dodgers (1947) X** 04 12 99 99 00 The catcher's mask was first used in a baseball game. (1877) X** 04 14 99 99 00 President Taft starts the tradition of throwing out the 1st baseball (1910) X** 04 16 99 99 00 Bob Feller of the Cleveland Indians pitched a no-hitter on opening day of the American League season (1940) X** 04 23 99 99 00 Hank Aaron hits his first home run (1954) X** 04 28 99 99 00 Muhammad Ali (Heavyweight Champ) refused to be inducted into Army (1967) X** 05 02 99 99 00 Lou Gehrig sets record for being in most consecutive games (2130). (1939) X** 05 17 99 99 00 First Kentucky Derby held (1875) X** 05 17 99 99 00 The first Kentucky Derby was run at Churchill Downs. (1875) X** 05 25 99 99 00 Babe Ruth hits his 714th and final home run of his career (1935) X** 05 30 99 99 00 Indianapolis 500 car race run for 1st time. (1911) X** 06 01 99 99 00 Lou Gehrig starts in 1st of 2130 consecutive games, a record. (1925) X** 06 11 99 99 00 1st auto race. (1895) X** 06 12 99 99 00 The National Baseball Hall of Fame and Museum was dedicated. (1939) X** 06 12 99 99 00 the 1st baseball game is played in America (1839) X** 06 12 99 99 00 the 3rd baseball strike starts. (1981) X** 07 05 99 99 00 New York Mets defeated Atlanta Braves, 16-13, in 19 inning game that lasted 6 hours and 10 min. ending just before 4 a.m. (1985) X** 07 06 99 99 00 1st All-Star baseball game. American League won 5-2. (1933) X** 07 11 99 99 00 Houston Astros pitcher, Nolan Ryan struck out 4000 batters. (1985) X** 07 13 99 99 00 Women first compete in Olympic games (1908) X** 07 18 99 99 00 Ty Cobb gets 4000th base hit (1927) X** 07 20 99 99 00 admission fee 1st charged to see a baseball game (50 cents). (1859) X** 07 21 99 99 00 Eddy Merckx won his first of five Tour de France victories (1969) X** 07 23 99 99 00 Greg LeMond wins his second Tour de France, beating Laurent Fignon in the final 15 mile time trial by turning a 50 second deficit into a win by 8 seconds! (1989) X** 07 29 99 99 00 King George VI opened the Olympic games in London (1948) X** 08 01 99 99 00 Adolph Hitler opened the Olympic Games in Berlin. (1936) X** 08 02 99 99 00 Several former members of the Chicago White Sox and two others were acquitted in the "Black Sox" scandal (1921) X** 08 06 99 99 00 Cy Young pitches first major league game (1890) X** 08 06 99 99 00 Gertrude Ederle of New York is the first American woman to swim the English Channel (1926) X** 08 08 99 99 00 the first America's Cup race (1870) X** 08 10 99 99 00 Pete Rose tops Stan Musial's record of 3630 hits. (1981) X** 08 20 99 99 00 Diana Nyad becomes the first woman to swim the 89 miles from the Bahamas to Florida (time: 27h 38m) (1979) X** 08 21 99 99 00 Babe Ruth hit his 600th career home run. (1931) X** 08 22 99 99 00 Althea Gibson becomes the first black tennis plaer to be accepted in competition for the national chapionship (1950) X** 08 22 99 99 00 the yacht America wins in race against 14 yachts of England in the first America Cup sailing race (1851) X** 08 25 99 99 00 Captain Matthew Webb becomes the first person to swim the English Channel, travelling from Dover to Calais in 22 hours (1875) X** 08 26 99 99 00 The summer Olympics opened in Munich, West Germany. (1972) X** 08 29 99 99 00 Lou Brock eclipsed the stolen-bases record as he stole two bases against the San Diego Padres, bring his total to 893 (1977) X** 08 31 99 99 00 The 1st U.S. tennis championships were played in Newport, R.I. (1882) X** 09 01 99 99 00 Bobby Fischer defeats Boris Spassky in World Chess Match (1972) X** 09 04 99 99 00 Mark Spitz becomes first man to win 7 gold medals in the Olympics (1972) X** 09 06 99 99 00 Czechoslovakian tennis star, Martina Navratilova, requested political asylum while in New York for the U.S. open (1975) X** 09 07 99 99 00 ESPN, the sports cable network, makes its debut (1979) X** 09 13 99 99 00 Fay Vincent was named commissioner of Major League Baseball. (1989) X** 09 13 99 99 00 The ladies Professional Golf Association of America was formed. (1949) X** 09 17 99 99 00 The American Professional Football Association was formed. (1920) X** 09 23 99 99 00 1st closed circuit pay-TV telecast of a sports event. (1952) X** 09 23 99 99 00 New York Knickerbockers becomes first U.S. Baseball club (1845) X** 09 24 99 99 00 Babe Ruth makes his farewell regular baseball player for the New York Yankees (1934) X** 09 26 99 99 00 Australia II won the America's Cup yacht race. (1983) X** 09 28 99 99 00 eight members of the Chicago White Sox were indicted for allegedly throwing the 1919 World Series against the Cincinnati Reds in the "Black Sox" scandal (1920) X** 09 29 99 99 00 The 1st night football game was played in Mansfield, Pennsylvania. (1892) X** 10 01 99 99 00 1st World Series starts between the National & American Leagues (1903) X** 10 07 99 99 00 Georgia Tech beat Cumberland University 222-0 in a football game. (1916) X** 10 07 99 99 00 Lynnette Woodward becomes the first female Harlem Globetrotter (1985) X** 10 12 99 99 00 The race horse Man O'War's last race (1920) X** 10 13 99 99 00 The International Olympic committee announced it would restore the two gold medals it had taken from Jim Thorpe (1982) X** 10 13 99 99 00 The first world series game is played (1903) X** 10 18 99 99 00 Connie Mack, the "Grand Old Man" of major league baseball, announced he would retire as manager of the Philadelphia Athletics (1950) X** 10 18 99 99 00 the Ivy League establishes rules for college football. (1873) X** 10 19 99 99 00 Jim Ochowicz, manager of the Seven-Eleven cycling team announced that the team will be sponsored by Motorola (1990) X** 11 01 99 99 00 Notre Dame's football team upsets Army 35-13 in a game that help popularize the forward pass (1913) X** 11 06 99 99 00 the first formal intercollegiate football game played (Rutgers 6 - Princeton 4) (1869) X** 11 25 99 99 00 Radio station WTAW of college station, Texas, broadcast the first play-by-play description of a football game (1920) X** 11 28 99 99 00 The first automobile race was held from Chicago to Waukegan through the snow; 6 cars, 55 miles, winner averaged 7 MPH (1895) X** 11 29 99 99 00 1st Army-Navy football game. Score: Navy 25, Army 0. (1890) X** 12 04 99 99 00 Numbers first appear on football uniforms (1908) X** 12 15 99 99 00 James Naismith, a Canadian, invents basketball, while working at the Y.M.C.A. College at Springfield, Massachusetts (1891) X** 12 17 99 99 00 1st professional football game: Chicago Bears vs. NY Giants. (1933) X** 12 26 99 99 00 1st East-West football game at Ewing Park before 25,000 fans. (1925) END_OF_FILE if test 8498 -ne `wc -c <'dates/sports'`; then echo shar: \"'dates/sports'\" unpacked with wrong size! fi # end of 'dates/sports' fi if test -f 'month2ct.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'month2ct.c'\" else echo shar: Extracting \"'month2ct.c'\" \(4022 characters\) sed "s/^X//" >'month2ct.c' <<'END_OF_FILE' X/* X * $Header: month2ct.c,v 2.2 91/02/01 12:20:10 billr Exp $ X */ X/* X * month2ct - convert month schedule files to calentool style files X * X * Author: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * X * Copyright (C) 1989, 1991 Tektronix, Inc. All Rights Reserved X * X * Permission is hereby granted to use and modify this code in source X * or binary form as long as it is not sold for profit and this copyright X * notice remains intact. X */ X X#include "month.h" X#include "ct.h" X#include <stdio.h> X Xstruct appt_entry appt; Xstruct event_rec events; XFILE *fp; Xchar filename[128]; Xchar *dir, *getenv(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X if (argc > 1) X dir = argv[1]; X else { X strcpy(filename, getenv("HOME")); X dir = filename; X } X X if (read_schedule(dir, READ_ONLY)) { X fprintf(stderr, "no reminders read from %s/.month\n", dir); X exit(1); X } X strcpy(filename, getenv("HOME")); X strcat(filename, "/.appointments"); X if ((fp = fopen(filename, "w")) == NULL) { X fprintf(stderr, "can't open .appointments file for writing\n"); X exit(1); X } X write_ct_file(); X} X X/* X * write out the new .appointments file X */ Xwrite_ct_file() X{ X struct event_rec *evt; X int length, oflags, i; X X evt = &events; X fputs(HEADER, fp); X /* first event is empty */ X evt = evt->next_event; X while (evt) { X /* DEBUG X fprintf(stderr,"evt struct:\n mly=%d, yly=%d, evry=%d\n nth=%d, last=%d, nthon=%d\n str=%s\n", X evt->monthly, evt->yearly, evt->every, evt->nth, evt->last, evt->nth_is_on, evt->event_string); X */ X appt.flags = appt.repeat = appt.lookahead = 0; X appt.warn = 10; /* default */ X appt.year = evt->start_date.year - 1900; X appt.month = evt->start_date.month - 1; X appt.day = evt->start_date.day; X strcpy(appt.str, evt->event_string); X if (evt->monthly) X appt.flags |= ALL_MONTHS; X if (evt->yearly) X appt.flags |= ALL_YEARS; X appt.hour = evt->start_time.hour; X appt.minute = evt->start_time.minute; X if (appt.hour > 23 || appt.hour < 0 || appt.minute > 59 || appt.minute < 0) X appt.flags |= A_NOTE; X if (appt.minute < 15) X appt.minute = 0; X else if (appt.minute < 45) X appt.minute = 30; X else { X appt.minute = 0; X appt.hour++; X } X length = evt->duration.hour * 60 + evt->duration.minute; X appt.arrows = length / 30 - 1; X if (appt.arrows < 0) X appt.arrows = 0; X if (evt->anti) X appt.flags |= DELETED; X if (evt->warning.hour >= 24) X appt.lookahead = evt->warning.hour / 24; X else X appt.warn = evt->warning.hour * 60 + evt->warning.minute; X if (evt->until) { X fprintf(stderr, "this appointment runs more than 1 day,\n"); X fprintf(stderr, "modify the calentool entry after conversion:\n"); X fprintf(stderr, "start date (m/d/y): %d/%d/%d, ", X evt->start_date.month, evt->start_date.day, X evt->start_date.year); X fprintf(stderr, "start time: %d:%d, ", evt->start_time.hour, X evt->start_time.minute); X fprintf(stderr, "runs until (m/d/y): %d/%d/%d\n", X evt->until_date.month, evt->until_date.day, X evt->until_date.year); X } X if (evt->every) { X /* event occurs on an every something */ X appt.flags |= REPEAT; X if (evt->last) X appt.repeat = LAST_WEEK; X else if (evt->nth_is_on) X appt.repeat = 1<<(evt->nth_is_on-1); X else X appt.repeat = ALL_WEEKS; X oflags = appt.flags; X /* check for mon-fri */ X if (!evt->smtwtfs[0] && !evt->smtwtfs[6] && X evt->smtwtfs[1] && evt->smtwtfs[2] && X evt->smtwtfs[3] && evt->smtwtfs[4] && X evt->smtwtfs[5]) { X appt.flags |= EVERY_MON_FRI; X if (put_aentry(fp, &appt)) { X fprintf(stderr, X "error writing .appointments file\n"); X return; X } X } else X for (i=0; i<7; i++) { X if (evt->smtwtfs[i]) { X appt.flags = oflags | Setday(i); X if (put_aentry(fp, &appt)) { X fprintf(stderr, X "error writing .appointments file\n"); X return; X } X } X } X } else X if (put_aentry(fp, &appt)) { X fprintf(stderr, "error writing .appointments file\n"); X return; X } X fputs("\n", fp); X evt = evt->next_event; X } X} END_OF_FILE if test 4022 -ne `wc -c <'month2ct.c'`; then echo shar: \"'month2ct.c'\" unpacked with wrong size! fi # end of 'month2ct.c' fi if test -f 'utils.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'utils.c'\" else echo shar: Extracting \"'utils.c'\" \(29701 characters\) sed "s/^X//" >'utils.c' <<'END_OF_FILE' X/* X * $Header: utils.c,v 2.8 91/03/27 16:46:39 billr Exp $ X */ X/* X * utils.c X * X * calentool - a year/month/week/day-at-a-glance calendar for Sun workstations. X * X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com> X * X * Original source Copyright (C) 1987, Sun Microsystems, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify this program in source X * or binary form as long as it is not sold for profit and this copyright X * notice remains intact. X * X * X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM> X * X * Changes and additions Copyright (C) 1988, 1989, 1991 Tektronix, Inc. X * All Rights Reserved X * Permission is hereby granted to use and modify the modifications in source X * or binary form as long as they are not sold for profit and this copyright X * notice remains intact. X * Modified parse_date to allow +nnn and -nnn syntax for dates relative to the X * current date. Peter Marshall <peter.marshall@uwo.ca>. 1989-09-19. X */ X/******************************************** X * * X * Utility routines. * X * * X ********************************************/ X X X X#include "ct.h" X#include <stdio.h> X#ifndef NOTOOL X#include <suntool/sunview.h> X#include <suntool/canvas.h> X#endif /* NOTOOL */ X#include <ctype.h> X#include <sys/types.h> X#include <sys/time.h> X#include <sys/file.h> X#include <sys/stat.h> X#include <sys/errno.h> X X Xextern struct tm today, current; Xextern struct tm First; Xextern int day_is_open, read_only; Xextern int n_slots; Xextern struct dayslot *slots; Xextern char apts_pathname[], tmpapts_pathname[]; Xextern char *progname; Xextern int one_based, version2, new_entry; Xextern char apts_dir[], lib_dir[]; Xextern int include_old, save_old, expire_days; X#ifndef NOTOOL Xextern Frame frame; Xextern Canvas canvas; Xextern Pixwin *main_pixwin; Xextern int mainsw_state; Xextern Pixfont *font, *sfont; Xextern Frame prompt_frame; Xextern int update_interval; Xextern int monday_first, hour24, day_first; X#endif /* NOTOOL */ Xextern int week_ofs; Xextern int errno; X Xchar inbuf[512], strbuf[256], errbuf[128]; Xchar clockstr[32]; Xstatic int include_level = 0; Xstatic int log_to_console; Xchar *daynames[] = {"Sunday","Monday","Tuesday","Wednesday", X "Thursday","Friday","Saturday"}; Xchar *monthnames[] = {"January","February","March","April", X "May","June","July","August", X "September","October","November","December"}; Xchar *smonthnames[] = {"Jan","Feb","Mar","Apr", X "May","Jun","Jul","Aug", X "Sep","Oct","Nov","Dec"}; Xchar *dayname[8] = {"SU", "MO", "TU", "WE", "TH", "FR", "SA", "MF"}; X Xextern char *strcpy(), *strcat(); X X/* X * sets "today" and current time X */ Xvoid Xget_today() X{ X struct tm *tm; X struct timeval tv; X char timstr[16]; X X gettimeofday(&tv, 0); X tm = localtime(&tv.tv_sec); X X today = *tm; X X#ifndef CALENCHECK X if (day_first) X sprintf(clockstr, "%3.3s %d %s %d, ", daynames[today.tm_wday], X today.tm_mday, smonthnames[today.tm_mon], today.tm_year+1900); X else X sprintf(clockstr, "%3.3s %s %d %d, ", daynames[today.tm_wday], X smonthnames[today.tm_mon], today.tm_mday, today.tm_year+1900); X if (update_interval >= 60) X sprintf(timstr, "%02d:%02d", today.tm_hour, today.tm_min); X else X sprintf(timstr, "%02d:%02d:%02d", today.tm_hour, today.tm_min, today.tm_sec); X if (!hour24) { X /* display am/pm for 12-hour time */ X if (today.tm_hour > 12) { X strcat(timstr, "pm"); X timstr[0] = ((today.tm_hour - 12) / 10) + '0'; X timstr[1] = ((today.tm_hour - 12) % 10) + '0'; X } else if (today.tm_hour == 12) { X strcat(timstr, "pm"); X } else { X strcat(timstr, "am"); X } X if (timstr[0] == '0') X timstr[0] = ' '; X } X strcat(clockstr, timstr); X#endif /* CALENCHECK */ X} X X/* X * Reset some values in current tm structure. Year, month and X * day-of-month are valid but day and/or month may be < 0 or X * greater than the maximum value, in which case they are adjusted X * accordingly. Day-of-year and day-of-week are then recalculated. X */ Xvoid Xfix_current_day() X{ X int month, totdays = 0; X struct tm from, to; X X if (current.tm_mon < JAN) { X current.tm_mon = DEC; X current.tm_year--; X } else if (current.tm_mon > DEC) { X current.tm_mon = JAN; X current.tm_year++; X } X if (current.tm_mday < 1) { X current.tm_mon--; X if (current.tm_mon < JAN) { X current.tm_mon = DEC; X current.tm_year--; X } X current.tm_mday += monthlength(current.tm_mon); X } else if (current.tm_mday > monthlength(current.tm_mon)) { X current.tm_mday -= monthlength(current.tm_mon); X current.tm_mon++; X if (current.tm_mon > DEC) { X current.tm_mon = JAN; X current.tm_year++; X } X } X current.tm_yday = day_of_year((double)current.tm_mday, current.tm_mon+1, current.tm_year+1900) - 1; X current.tm_wday = get_day_of_week((double)current.tm_mday, current.tm_mon+1, current.tm_year+1900); X} X X/* X * Compares two sets of year/month/day. Returns -1 if the first is earlier than X * the second, +1 if later, 0 if they are the same. X */ Xymd_compare(day0, day1) Xstruct tm day0, day1; X{ X if (day0.tm_year > day1.tm_year) return(1); X if (day0.tm_year < day1.tm_year) return(-1); X if (day0.tm_mon > day1.tm_mon) return(1); X if (day0.tm_mon < day1.tm_mon) return(-1); X if (day0.tm_mday > day1.tm_mday) return(1); X if (day0.tm_mday < day1.tm_mday) return(-1); X return(0); X} X X/* X * Compares two sets of year/month/day. Returns -1 if the first is earlier than X * the second, +1 if later, 0 if they are the same. Similar to X * ymd_compare() only compares given date to date of an appt entry. X */ Xymd2_compare(day0, aday) Xstruct tm *day0; Xstruct appt_entry *aday; X{ X if (day0->tm_year > aday->year) return(1); X if (day0->tm_year < aday->year) return(-1); X if (day0->tm_mon > aday->month) return(1); X if (day0->tm_mon < aday->month) return(-1); X if (day0->tm_mday > aday->day) return(1); X if (day0->tm_mday < aday->day) return(-1); X return(0); X} X Xint Xmonthlength(month) Xint month; X{ X static int monthlengths[] = {31,28,31,30,31,30,31,31,30,31,30,31}; X X if (month == FEB && (length_of_year(current.tm_year + 1900) == 366)) X return(29); X else X return(monthlengths[month]); X} X X/* X * X * Append data from active timeslots to end of "tmp.appointments" X * file, then copy "tmp.appointments" to "appointments". Note that X * when we opened the current day we filtered "appointments": X * all items that applied to the current day were displayed and X * stored in slots; all others were copied to "tmp.appointments". X * So by now "tmp.appointments" contains no entries for the X * current day. X * As an optimization, if nothing changed in the day then the X * original appointments file is left unchanged. X * X */ X Xclose_day() X{ X int i, j; X FILE *f; X struct stat sbuf; X struct appt_entry *aptr, *optr; X X if (read_only || !new_entry) { X new_entry = 0; X day_is_open = FALSE; X return(0); X } X X#ifndef CALENCHECK X f = fopen(tmpapts_pathname, "a+"); X if (f == NULL) { X err_rpt("can't open temp file for appending", NON_FATAL); X day_is_open = FALSE; X return(1); X } X X for (i=0; i<n_slots; i++) { X if (slots[i].first != NULL) { X aptr = slots[i].first; X if (put_aentry(f, aptr)) X /* write error */ X break; X optr = aptr; X while (aptr = aptr->next) { X free(optr); X if (put_aentry(f, aptr)) X /* write error */ X break; X optr = aptr; X } X free(optr); X } X } X if (ferror(f)) X err_rpt("write on temp file failed", FATAL); X fclose(f); X new_entry = 0; X day_is_open = FALSE; X /* don't rename zero length files */ X stat(tmpapts_pathname, &sbuf); X if (sbuf.st_size == (off_t) 0) X return(1); X xrename(tmpapts_pathname, apts_pathname); X#endif /* CALENCHECK */ X return(0); X} X X/* X * get entry from appointments file X */ Xget_aentry(apts_file, appt, noInclude, noUmkNotes, target) XFILE *apts_file; Xstruct appt_entry *appt; Xint noInclude; Xint noUmkNotes; Xint target; X{ X char *ptr, *str; X char *fgets(), *index(); X char *incl_ptr, incl_buf[128], wday[3]; X int i, lib, parse_options, nodata = 1; X int n, nflag, lrange, hrange; X struct stat sbuf; X static FILE *include[MAX_INCLUDE_NESTING]; X X appt->flags = appt->repeat = appt->lookahead = 0; X appt->sindex = 0; X appt->runlength = 0; X appt->warn = 10; X appt->next = NULL; X /* If noInclude is set then don't follow include files, i.e. X * treat #include directives as comments. This is useful for X * copying the appts file. X */ X while (nodata) { X if (include_level) { X if (fgets(inbuf, 512, include[include_level-1]) == NULL) { X /* end of include file - get next entry X * from previous level of nesting X */ X unwind: X fclose(include[include_level-1]); X include_level--; X } else { X /* don't modify stuff from include files */ X appt->flags |= READONLY; X nodata = 0; /* still data in file */ X } X } else { X if (fgets(inbuf, 512, apts_file) == NULL) X return(EOF); X else X nodata = 0; /* still data in file */ X } X } X ptr = inbuf; X if (noInclude && *ptr == '#') { X appt->flags |= A_COMMENT; X return(0); X } X if (*ptr == '#') { X if (!include_level && (!strcmp(inbuf, OHEADER) || X !strncmp(inbuf, HEADER, 18))) { X /* first line in base file read */ X if (include_old && (First.tm_year <= today.tm_year)) { X /* read in old include file (if it exists) */ X /* prepend directory info */ X sprintf(incl_buf, "%s.%02d", X apts_pathname, First.tm_year); X if (!stat(incl_buf, &sbuf)) { X if ((include[include_level] = fopen(incl_buf, "r")) == NULL) { X strcpy(errbuf, "can't open include file <"); X strcat(errbuf, incl_buf); X strcat(errbuf, "> (ignored)"); X err_rpt(errbuf, NON_FATAL); X } else X include_level++; X } X } X if (!strcmp(inbuf, OHEADER)) X /* substitute new header format */ X strcpy(inbuf, HEADER); X } else if (!strncmp(inbuf, HEADER, 18)) { X /* found a ver 2.2 header - get statistics */ X n = sscanf(inbuf, "%*[^-]- nflag=%d range=%d,%d", X &nflag, &lrange, &hrange); X if (n == 3 && include_level) { X /* proper match found */ X if (noUmkNotes && nflag) X goto unwind; X if (target && (target < lrange || target > hrange)) X goto unwind; X } X } else if (!strncmp(inbuf, "#include", 8)) { X /* include file */ X if (include_level > MAX_INCLUDE_NESTING) { X err_rpt("include files nested too deep (ignored)", NON_FATAL); X appt->flags |= A_COMMENT; X return(0); X } X incl_ptr = strbuf; X if ((ptr = index(inbuf, '"')) == NULL) X X if ((ptr = index(inbuf, '<')) == NULL) { X err_rpt("missing '\"' or '<' in include file spec", NON_FATAL); X appt->flags |= A_COMMENT; X return(0); X } else { X lib = 1; X } X else X lib = 0; X ptr++; X while (*ptr && *ptr != '"' && *ptr != '>') X *incl_ptr++ = *ptr++; X if (! *ptr) { X err_rpt("missing '\"' or '>' in include file spec", NON_FATAL); X appt->flags |= A_COMMENT; X return(0); X } X *incl_ptr = '\0'; X if (strbuf[0] == '/') X /* full pathname provided */ X strcpy(incl_buf, strbuf); X else X /* prepend directory info */ X if (lib) X sprintf(incl_buf, "%s/%s", lib_dir, strbuf); X else X sprintf(incl_buf, "%s/%s", apts_dir, strbuf); X if ((include[include_level] = fopen(incl_buf, "r")) == NULL) { X strcpy(errbuf, "can't open include file <"); X strcat(errbuf, incl_buf); X strcat(errbuf, "> (ignored)"); X err_rpt(errbuf, NON_FATAL); X } else X include_level++; X } X appt->flags |= A_COMMENT; X return(0); X } X while (isspace(*ptr)) X ++ptr; X if (!*ptr) { X /* empty line */ X appt->flags |= A_COMMENT; X return(0); X } X if (*ptr == '*') { X appt->flags |= ALL_YEARS; X appt->year = START_YEAR; X ++ptr; /* point to second '*' */ X ++ptr; /* point to space */ X } else { X appt->year = 0; X while (isdigit(*ptr)) { X appt->year *= 10; X appt->year += *ptr++ - '0'; X } X /* sanity check */ X if (appt->year < 0) { X sprintf(errbuf, "illegal year value [%d] (ignored)", appt->year); X err_rpt(errbuf, NON_FATAL); X return(1); X } X } X while (isspace(*ptr)) X ++ptr; X if (*ptr == '*') { X appt->flags |= ALL_MONTHS; X appt->month = 0; X ++ptr; X } else { X appt->month = (*ptr - '0') * 10; X appt->month += *++ptr - '0'; X if (one_based) (appt->month)--; X /* sanity check */ X if (appt->month < JAN || appt->month > DEC) { X sprintf(errbuf, "illegal month value [%d] (ignored)", appt->month); X err_rpt(errbuf, NON_FATAL); X return(1); X } X } X ++ptr; X while (isspace(*ptr)) X ++ptr; X if (*ptr == '*') { X appt->flags |= ALL_DAYS; X appt->day = 1; X appt->repeat = 1; X ++ptr; X } else if (isdigit(*ptr)) { X appt->day = (*ptr - '0') * 10; X appt->day += *++ptr - '0'; X if (!one_based) (appt->day)++; X /* sanity check */ X if (appt->day < 1 || appt->day > 31) { X sprintf(errbuf, "illegal day value [%d] (ignored)", appt->day); X err_rpt(errbuf, NON_FATAL); X return(1); X } X } else { X /* check for day names */ X wday[0] = islower(*ptr) ? toupper(*ptr) : *ptr; X ++ptr; X wday[1] = islower(*ptr) ? toupper(*ptr) : *ptr; X wday[2] = '\0'; X i = 0; X if (!strcmp(wday, dayname[i++])) X appt->flags |= EVERY_SUN; X else if (!strcmp(wday, dayname[i++])) X appt->flags |= EVERY_MON; X else if (!strcmp(wday, dayname[i++])) X appt->flags |= EVERY_TUE; X else if (!strcmp(wday, dayname[i++])) X appt->flags |= EVERY_WED; X else if (!strcmp(wday, dayname[i++])) X appt->flags |= EVERY_THU; X else if (!strcmp(wday, dayname[i++])) X appt->flags |= EVERY_FRI; X else if (!strcmp(wday, dayname[i++])) X appt->flags |= EVERY_SAT; X else if (!strcmp(wday, dayname[i])) X appt->flags |= EVERY_MON_FRI; X else { X /* sanity check */ X sprintf(errbuf, "illegal day name [%s] (ignored)", wday); X err_rpt(errbuf, NON_FATAL); X return(1); X } X appt->day = 1; X if (appt->flags & EVERY_MON_FRI) { X appt->repeat = 1; X } else { X appt->flags |= REPEAT; X appt->repeat = ALL_WEEKS; /* default to every week */ X } X } X ++ptr; X while (isspace(*ptr)) X ++ptr; X appt->hour = (*ptr - '0') * 10; X appt->hour += *++ptr - '0'; X /* sanity check */ X if (appt->hour < 0 || (appt->hour > 23 && appt->hour != 99)) { X sprintf(errbuf, "illegal hour value [%d] (ignored)", appt->hour); X err_rpt(errbuf, NON_FATAL); X return(1); X } X if ((version2 && appt->hour == 99) || (!version2 && appt->hour == 0)) X appt->flags |= A_NOTE; X ++ptr; X while (isspace(*ptr)) X ++ptr; X appt->minute = (*ptr - '0') * 10; X appt->minute += *++ptr - '0'; X /* sanity check */ X if (appt->minute < 0 || (appt->minute > 59 && appt->minute != 99)) { X /* minutes currently can only be 00 or 30 X * unless it's a note. X */ X sprintf(errbuf, "illegal minute value [%d] (ignored)", appt->minute); X err_rpt(errbuf, NON_FATAL); X return(1); X } X if ((appt->flags & A_NOTE) && version2 && appt->minute == 99) X appt->flags |= MARKED; /* don't show in mon/yr display */ X ++ptr; X while (isspace(*ptr)) X ++ptr; X appt->arrows = (*ptr - '0') * 10; X appt->arrows += *++ptr - '0'; X /* sanity check */ X if (appt->arrows < 0 || appt->arrows > 48) { X sprintf(errbuf, "illegal arrow value [%d] (ignored)", appt->arrows); X err_rpt(errbuf, NON_FATAL); X return(1); X } X ++ptr; X while (isspace(*ptr)) X ++ptr; X /* lookahead and repeat entries are free format, i.e. they */ X /* can occur in any order */ X parse_options = TRUE; X while (parse_options) { X switch (*ptr) { X case '\\': X /* start of string text */ X parse_options = FALSE; X ++ptr; X break; X X case '%': X /* advance warning time (minutes) */ X appt->warn = 0; X while (isdigit(*++ptr)) X appt->warn = appt->warn * 10 + (int)(*ptr - '0'); X if (appt->warn < 0) { X err_rpt("illegal advance warning (ignored)", NON_FATAL); X appt->warn = 10; X } X break; X X case '[': X /* repeating appointment */ X appt->flags |= REPEAT; X if (appt->flags & EVERY_SOMEDAY) { X if ((appt->repeat = do_wk_repeat(&ptr)) < 0) X return(1); X } else { X if ((appt->repeat = do_repeat(&ptr)) < 0) X return(1); X } X break; X X case '<': X /* remind us ahead of time */ X appt->flags |= LOOKAHEAD; X if ((appt->lookahead = do_lookahead(&ptr)) < 0) X return(1); X break; X X case '+': X /* this appointment lasts for n days */ X appt->flags |= RUN; X while (isdigit(*++ptr)) X appt->runlength = appt->runlength * 10 + (int)(*ptr - '0'); X if (appt->runlength < 0) X return(1); X if (!(appt->flags & REPEAT)) { X /* default to run of days */ X appt->flags |= REPEAT; X appt->repeat = 1; X } X break; X X case '#': X /* deleted appointment */ X appt->flags |= DELETED; X ++ptr; X break; X X default: X parse_options = FALSE; X break; X } X while (isspace(*ptr)) X ++ptr; X } X str = strbuf; X while (*ptr && *ptr != '\n') X *str++ = *ptr++; X *str = '\0'; X strcpy(appt->str, strbuf); X if (appt->flags & DELETED) X /* ignore some flags */ X appt->flags &= ~(RUN | REPEAT); X X return(0); X} X X/* parse normal repeated entry field */ Xdo_repeat(ptr) Xchar **ptr; X{ X int repeat = 0; X X while (isdigit(*++*ptr)) X repeat = repeat * 10 + (int)(**ptr - '0'); X if (**ptr != ']') { X err_rpt("bad entry (ignored)", NON_FATAL); X return(-1); X } X /* sanity check */ X if (repeat < 0) { X err_rpt("illegal repeat interval (ignored)", NON_FATAL); X return(-1); X } X ++*ptr; X return(repeat); X} X X/* parse weekly repeated entry field */ Xdo_wk_repeat(ptr) Xchar **ptr; X{ X int repeat = 0; X X while (*++*ptr != ']') { X if (**ptr == ',') X continue; /* get next week */ X if (isdigit(**ptr)) { X repeat |= 0x1<<(**ptr - '1'); X } else if (**ptr == 'L' || **ptr == 'l') { X /* last week in month */ X repeat |= LAST_WEEK; X } else { X /* format error */ X err_rpt("illegal repeat specification (ignored)", NON_FATAL); X return(-1); X } X } X /* sanity check */ X if ((unsigned int)repeat > WEEK_LIMIT) { X err_rpt("illegal weekly repeat (ignored)", NON_FATAL); X return(-1); X } X ++*ptr; X return(repeat); X} X X/* parse lookahead entry field */ Xdo_lookahead(ptr) Xchar **ptr; X{ X int lookahead = 0; X X while (isdigit(*++*ptr)) X lookahead = lookahead * 10 + (int)(**ptr - '0'); X if (**ptr != '>') { X err_rpt("bad entry (ignored)", NON_FATAL); X return(-1); X } X /* sanity check */ X if (lookahead < 0) { X err_rpt("illegal lookahead interval (ignored)", NON_FATAL); X return(-1); X } X ++*ptr; X return(lookahead); X} X X#ifndef CALENCHECK X/* X * put entry into appointments file X */ Xput_aentry(apts_file, appt) XFILE *apts_file; Xstruct appt_entry *appt; X{ X char *to_str(); X X if (read_only) X return(0); X X if (appt->flags & READONLY) X /* don't copy include file entries */ X /* (the include directive is copied as a comment) */ X return(0); X if (appt->flags & A_COMMENT) { X fputs(inbuf, apts_file); X return(ferror(apts_file)); X } X if (appt->flags & ALL_YEARS) X fputs("** ", apts_file); X else if (appt->year > 99) X fprintf(apts_file, "%03d ", appt->year); X else X fprintf(apts_file, "%02d ", appt->year); X if (appt->flags & ALL_MONTHS) X fputs("** ", apts_file); X else X fprintf(apts_file, "%02d ", one_based ? appt->month+1 : appt->month); X if (appt->flags & ALL_DAYS) X fputs("** ", apts_file); X else if (appt->flags & EVERY_SOMEDAY) { X switch (appt->flags & EVERY_SOMEDAY) { X case EVERY_SUN: X fputs("Su ", apts_file); X break; X case EVERY_MON: X fputs("Mo ", apts_file); X break; X case EVERY_TUE: X fputs("Tu ", apts_file); X break; X case EVERY_WED: X fputs("We ", apts_file); X break; X case EVERY_THU: X fputs("Th ", apts_file); X break; X case EVERY_FRI: X fputs("Fr ", apts_file); X break; X case EVERY_SAT: X fputs("Sa ", apts_file); X break; X } X } else if (appt->flags & EVERY_MON_FRI) { X fputs("MF ", apts_file); X } else X fprintf(apts_file, "%02d ", one_based ? appt->day : appt->day-1); X if (appt->flags & A_NOTE) { X appt->hour = 99; X appt->minute = 0; /* assume unmarked note */ X } X if ((appt->flags & MARKED_NOTE) == MARKED_NOTE) X appt->minute = 99; X if (!(appt->flags & (ALL_DAYS|DELETED|EVERY_MON_FRI)) && appt->flags & REPEAT) { X if (appt->flags & EVERY_SOMEDAY) X fprintf(apts_file, "%02d %02d %02d %s ", appt->hour, appt->minute, appt->arrows, to_str(appt->repeat)); X else X fprintf(apts_file, "%02d %02d %02d [%d] ", appt->hour, appt->minute, appt->arrows, appt->repeat); X } else X fprintf(apts_file, "%02d %02d %02d ", appt->hour, appt->minute, appt->arrows); X X if (appt->flags & LOOKAHEAD) X fprintf(apts_file, "<%d> ", appt->lookahead); X if (appt->flags & RUN) X fprintf(apts_file, "+%d ", appt->runlength); X if (appt->warn != 10) X fprintf(apts_file, "%%%d ", appt->warn); X if (appt->flags & DELETED) X fputs("# ", apts_file); X if (isalnum(*(appt->str))) X fprintf(apts_file, "%s\n", appt->str); X else X fprintf(apts_file, "\\%s\n", appt->str); X X /* check for failure (e.g. file system full) */ X return(ferror(apts_file)); X} X Xchar rptstr[10]; X X/* convert repeat bit map to printable string */ Xchar * Xto_str(repeat) Xint repeat; X{ X int i, j = 0; X X if (repeat == ALL_WEEKS) X /* if it's every week, then don't write [] spec */ X rptstr[0] = '\0'; X else { X rptstr[j++] = '['; X for (i=0; i<5; i++) { X if (repeat & (0x1<<i)) { X rptstr[j++] = i+1 + '0'; X rptstr[j++] = ','; X } X } X if (repeat & LAST_WEEK) { X rptstr[j++] = 'L'; X rptstr[j++] = ','; X } X rptstr[j] = '\0'; X rptstr[--j] = ']'; X } X return (rptstr); X} X X/* X * Convert from version 1 appts files to version 2 file format. X */ Xver1to2() X{ X FILE *oappts, *nappts, *fp; X struct appt_entry appt; X int err_flag, save_base; X char save_file[128]; X struct stat stbuf; X X /* X * The main difference is that the ver 2 files are one-based, i.e X * days and months start with 1, rather than 0. Another difference X * is that a hour entry of 99 is used to flag a memo entry, rather X * than 00. This allows for 24-hour appointments. X * Version 2 appts files are marked with a special header line X * defined by the HEADER string (in ct.h). Version 2 files X * also support a "lookahead" reminder service to remind one X * in advance of a future appointment. X * If "save_old" is set, then any appointments for years prior X * to this one are saved in a special file of the form X * ".appointments.YY", where YY is the year. X */ X X if (read_only != 0) { X err_rpt("appts file is read-only, no conversion done", NON_FATAL); X return; X } X X /* open files, etc */ X if ((oappts = fopen(apts_pathname, "r")) == NULL) { X err_rpt("can't open appts file for reading", FATAL); X /* NOT REACHED */ X } X if ((nappts = fopen(tmpapts_pathname, "w")) == NULL) { X err_rpt("can't open temp file for writing", NON_FATAL); X return; X } X /* write new header line */ X fputs(HEADER, nappts); X X /* copy existing entries to the new file */ X save_base = one_based; X while ((err_flag = get_aentry(oappts, &appt, TRUE, 0, 0)) != EOF) { X if (err_flag) X continue; /* ignore badly formatted input */ X if (appt.hour == 0) X appt.flags |= A_NOTE; X one_based = 1; /* force new format output */ X if (save_old && !(appt.flags & ALL_YEARS) && (appt.year < today.tm_year) X && !((appt.flags & REPEAT) && !(appt.flags & EVERY_SOMEDAY)) X && !(appt.flags & A_COMMENT)) { X /* prepend directory info */ X sprintf(save_file, "%s.%02d", X apts_pathname, appt.year); X if (stat(save_file, &stbuf) && errno == ENOENT) { X /* new file*/ X if ((fp = fopen(save_file, "w")) == NULL) X err_rpt("can't open save file, bailing out", FATAL); X fputs(HEADER, fp); X fclose(fp); X } X if ((fp = fopen(save_file, "a+")) == NULL) X err_rpt("can't open save file, bailing out", FATAL); X else { X if (put_aentry(fp, &appt)) X err_rpt("write to save appt file failed, bailing out", FATAL); X fclose(fp); X } X } else { X if (appt.flags & A_COMMENT) X fputs(inbuf, nappts); X else X if (put_aentry(nappts, &appt)) X err_rpt("write to new appt file failed, bailing out", FATAL); X } X one_based = save_base; /* (maybe) force old format input */ X } X fclose(oappts); X fclose(nappts); X xrename(tmpapts_pathname, apts_pathname); X one_based = 1; X version2 = 1; X} X X/* X * parse the date on the given string and reset the "current" X * date to reflect that date. The date may take the form of a X * day name (e.g. Tu, Tue, Tuesday) or a date in m/d/y format X * where the month and/or year may be missing (e.g. 27 = 27th X * of this month, 8/27 = August 27 of this year, 8/27/89 = X * August 27 of 1989. If 'cmdline' is true, then the string X * came from the command line '-d' option. X * If the first character of the date is + or - scan the number and X * use it as an offset in days from the current date. Thus -1 becomes X * yesterday and +1 becomes tomorrow. pbm. X */ Xint Xparse_date(str, cmdline) Xchar *str; Xint cmdline; X{ X char c[4]; X int i, dow = -1, m = -1, d = -1, y = -1; X X if (isdigit(*str)) { X /* must be a m/d/y date */ X /* assume it's a month first */ X m = *str++ - '0'; X if (isdigit(*str)) X m = m*10 + *str++ - '0'; X if (!*str) { X /* no more chars => day only */ X d = m; X m = -1; X } else if (*str++ != '/') { X if (cmdline) X err_rpt("badly formed date for -d option (ignored)", NON_FATAL); X else X err_rpt("badly formed date - please reenter", NON_FATAL); X return(1); X } else { X d = *str++ - '0'; X if (isdigit(*str)) X d = d*10 + *str++ - '0'; X if (*str++ == '/') { X /* year also specified */ X y = *str++ - '0'; X if (isdigit(*str)) { X y = y*10 + *str++ - '0'; X if (*str && isdigit(*str)) X y = y*10 + *str++ - '0'; X if (*str && isdigit(*str)) X y = y*10 + *str++ - '0'; X } X } X } X if (y > 0) { X if (y > 1900) X y -= 1900; X current.tm_year = y; X } X if (day_first) { X if (m > 0) { X current.tm_mon = d - 1; X current.tm_mday = m; X } else if (d > 0) X current.tm_mday = d; X } else { X if (m > 0) { X current.tm_mon = m - 1; X current.tm_mday = d; X } else if (d > 0) X current.tm_mday = d; X } X fix_current_day(); X } else if (*str == '-' || *str == '+') { X /* X * If the argument begins with a + or - assume that it is an X * offset in days from the current date. Use current date if the X * number doesn't scan after the - or +. pbm X */ X if (sscanf(str, "%d", &i) == 1) { X current.tm_mday += i; X fix_current_day(); X } X } else { X /* day of week */ X /* check for day names */ X c[0] = islower(*str) ? toupper(*str) : *str; X ++str; X c[1] = islower(*str) ? toupper(*str) : *str; X c[2] = '\0'; X for (i=0; i<7; i++) { X if (!strcmp(c, dayname[i])) { X dow = i; X break; X } X } X if (dow >= 0) { X /* match found */ X current.tm_mday += dow - current.tm_wday; X fix_current_day(); X } else if (!strncmp(c, "TOM", 3)) { X /* tommorrow */ X current.tm_mday++; X fix_current_day(); X } else if (!strncmp(c, "YES", 3)) { X /* yesterday */ X current.tm_mday--; X fix_current_day(); X } else { X if (cmdline) X err_rpt("badly formed date for -d option (ignored)", NON_FATAL); X else X err_rpt("badly formed date - please reenter", NON_FATAL); X return(1); X } X } X return(0); X} X#endif /* CALENCHECK */ X X/* set error logging flag */ Xerr2console(state) Xint state; X{ X /* X * if TRUE, forces error messages to the console, even X * if the base frame is running X */ X log_to_console = state; X} X X/* X * Error reporting. Try first to put message in a popup frame, then X * the console, then stderr as a last resort. X */ Xerr_rpt(errstr, fatal_flag) Xchar *errstr; Xint fatal_flag; X{ X FILE *f; X int closed; X char *getenv(); X X#ifndef NOTOOL X closed = (int) window_get(frame, FRAME_CLOSED); X if (frame && !log_to_console && !closed) { X /* base frame exists */ X create_prompt_frame(errstr, FALSE); X (void) window_loop(prompt_frame); X window_set(prompt_frame, WIN_SHOW, FALSE, 0); X } else if ((f=fopen("/dev/console", "w")) != NULL) { X#else X if (getenv("WINDOW_PARENT") != NULL && (f=fopen("/dev/console", "w")) != NULL) { X#endif X fprintf(f, "%s: %s\n", progname, errstr); X fclose(f); X } else X fprintf(stderr, "%s: %s\n", progname, errstr); X if (fatal_flag) X exit(1); X} X X#ifndef CALENCHECK X/* Clean-up */ Xcleanup() X{ X if (day_is_open) X close_day(); X X /* create outdated include files (if necessary) */ X if (save_old || expire_days) X expire(expire_days); X X /* delete tmp file */ X if (access(tmpapts_pathname, R_OK) == 0 && unlink(tmpapts_pathname) < 0) X perror(tmpapts_pathname); X} X Xchar sysbuf[512]; X X/* Rename files, copying if necessary */ Xxrename(from, to) Xchar *from, *to; X{ X if (rename(from, to) == -1) { X /* rename sys call fialed, try doing a copy */ X sprintf(sysbuf, "cp %s %s", from, to); X if (system(sysbuf) != 0) X err_rpt("couldn't rename/copy tmp file", NON_FATAL); X } X} X X/* X * Conventional and ISO standard week numbers (week starts with monday) X * Assume if moday_first is set TRUE then ISO format is desired. X */ X Xweek_number() X{ X int week_n, week_d, W, r, day, year, leap; X X /* First day of this week */ X if (monday_first) X week_d = (current.tm_wday?(current.tm_wday-1):6); X else X week_d = current.tm_wday; X current.tm_mday -= week_d; X fix_current_day(); X day = current.tm_yday + 1; X week_n = day / 7 + 1; /* "Raw" week number */ X r = day % 7 - 1; /* No of days in the first week this year */ X X if (!monday_first) { X if (week_n == 53) X week_n = 1; X else if (r > 0 && day > r) X if (++week_n == 53 && (day + 6) > length_of_year(current.tm_year+1900)) X week_n = 1; X } else { X if (r >= 4) week_n++; /* First week has more than three days */ X if (week_n == 53) { /* Week number of last week of year */ X year = current.tm_year + 1900; X leap = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0); X day += 7 - ( leap ? 366 : 365 ); X W = day / 7 + 1; X r = day % 7 - 1; X if (r >= 4) W++; X if (W == 2) week_n = 1; X } X } X current.tm_mday += week_d; X fix_current_day(); X return week_n; X} X#endif /* CALENCHECK */ END_OF_FILE if test 29701 -ne `wc -c <'utils.c'`; then echo shar: \"'utils.c'\" unpacked with wrong size! fi # end of 'utils.c' fi echo shar: End of archive 16 \(of 23\). cp /dev/null ark16isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 23 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.