aboutsummaryrefslogtreecommitdiffstats
path: root/calendar
diff options
context:
space:
mode:
authorArturo Espinosa <unammx@src.gnome.org>1998-04-19 08:19:48 +0800
committerArturo Espinosa <unammx@src.gnome.org>1998-04-19 08:19:48 +0800
commit64a3522acac1f96115f6d8aaee15dcb1d5812f5a (patch)
tree639108aa317ae9e8f8057d2f02c03253540a93f3 /calendar
parent24f0de634028297d3647779cffa082f8ff6a230a (diff)
downloadgsoc2013-evolution-64a3522acac1f96115f6d8aaee15dcb1d5812f5a.tar
gsoc2013-evolution-64a3522acac1f96115f6d8aaee15dcb1d5812f5a.tar.gz
gsoc2013-evolution-64a3522acac1f96115f6d8aaee15dcb1d5812f5a.tar.bz2
gsoc2013-evolution-64a3522acac1f96115f6d8aaee15dcb1d5812f5a.tar.lz
gsoc2013-evolution-64a3522acac1f96115f6d8aaee15dcb1d5812f5a.tar.xz
gsoc2013-evolution-64a3522acac1f96115f6d8aaee15dcb1d5812f5a.tar.zst
gsoc2013-evolution-64a3522acac1f96115f6d8aaee15dcb1d5812f5a.zip
Update spanish translation for the Calendar.
Update spanish translation for the Calendar. Added command line handling to the calendar program. You can now display your appointments for any given date from the command line wihtout running X. Added CVS's `getdate'. This is a date parser for a bunch of formats. Internationalized getdate. You can even type date descriptions in your native language. Miguel. svn path=/trunk/; revision=159
Diffstat (limited to 'calendar')
-rw-r--r--calendar/ChangeLog12
-rw-r--r--calendar/Makefile.am12
-rw-r--r--calendar/getdate.y1001
-rw-r--r--calendar/gnome-cal.html42
-rw-r--r--calendar/gui/Makefile.am12
-rw-r--r--calendar/gui/getdate.y1001
-rw-r--r--calendar/gui/gnome-cal.html42
-rw-r--r--calendar/gui/main.c133
-rw-r--r--calendar/gui/topic.dat2
-rw-r--r--calendar/main.c133
-rw-r--r--calendar/timeutil.h1
-rw-r--r--calendar/topic.dat2
12 files changed, 2377 insertions, 16 deletions
diff --git a/calendar/ChangeLog b/calendar/ChangeLog
index 5d7959c4ae..8450a82bed 100644
--- a/calendar/ChangeLog
+++ b/calendar/ChangeLog
@@ -1,5 +1,17 @@
1998-04-18 Miguel de Icaza <miguel@nuclecu.unam.mx>
+ * gnome-cal.html: Added small documentation.
+
+ * main.c: Add more icons to the menus; Rename some menubar
+ entries; Add `new' icon to the toolbar.
+ (dump_events): Added argument handling and dumping of events from
+ the command line. Extremely cool.
+
+ * getdate.y: Taken from the CVS source code. Used for date
+ parsing in the command line.
+
+ Internationalized getdate.y. Wee! It even works with spanish.
+
* calobj.c (ical_object_to_vobject): Add Quoted printable property
to items containing new lines.
(duration): Use unsigned integers, to work around buggy calendar
diff --git a/calendar/Makefile.am b/calendar/Makefile.am
index 9728a02d4b..15e7bf5f95 100644
--- a/calendar/Makefile.am
+++ b/calendar/Makefile.am
@@ -1,4 +1,5 @@
SUBDIRS = versit
+help_base = $(datadir)/gnome/help/cal
INCLUDES = \
-I$(includedir) \
@@ -23,6 +24,7 @@ gnomecal_SOURCES = \
gncal-week-view.h \
gncal-year-view.c \
gncal-year-view.h \
+ getdate.y \
gnome-cal.c \
gnome-cal.h \
main.c \
@@ -64,9 +66,17 @@ LINK_FLAGS = \
gnomecal_LDADD = $(LINK_FLAGS)
EXTRA_DIST = \
- gncal.desktop
+ gncal.desktop \
+ topic.dat \
+ gnome-cal.html
+
Productivitydir = $(datadir)/apps/Productivity
Productivity_DATA = gncal.desktop
+install-data-local:
+ $(mkinstalldirs) $(help_base)/C
+ $(INSTALL_DATA) $(srcdir)/topic.dat $(help_base)/C/topic.dat
+ $(INSTALL_DATA) $(srcdir)/gnome-cal.html $(help_base)/C/gnome-cal.html
+ cd $(help_base)/C; ln -sf gnome-cal.html index.html \ No newline at end of file
diff --git a/calendar/getdate.y b/calendar/getdate.y
new file mode 100644
index 0000000000..6df71bddda
--- /dev/null
+++ b/calendar/getdate.y
@@ -0,0 +1,1001 @@
+%{
+/*
+** Originally) written by Steven M. Bellovin <smb@research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+** send any email to Rich.
+**
+** This grammar has 10 shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#include <config.h>
+#include <gnome.h>
+
+/* Since the code of getdate.y is not included in the Emacs executable
+ itself, there is no need to #define static in this file. Even if
+ the code were included in the Emacs executable, it probably
+ wouldn't do any harm to #undef it here; this will only cause
+ problems if we try to write to a static variable, which I don't
+ think this code needs to do. */
+#ifdef emacs
+#undef static
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* The code at the top of get_date which figures out the offset of the
+ current time zone checks various CPP symbols to see if special
+ tricks are need, but defaults to using the gettimeofday system call.
+ Include <sys/time.h> if that will be used. */
+
+#if defined(vms)
+
+#include <types.h>
+#include <time.h>
+
+#else
+
+#include <sys/types.h>
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef timezone
+#undef timezone /* needed for sgi */
+#endif
+
+#if defined(HAVE_SYS_TIMEB_H)
+#include <sys/timeb.h>
+#else
+/*
+** We use the obsolete `struct timeb' as part of our interface!
+** Since the system doesn't have it, we define it here;
+** our callers must do likewise.
+*/
+struct timeb {
+ time_t time; /* Seconds since the epoch */
+ unsigned short millitm; /* Field not used */
+ short timezone; /* Minutes west of GMT */
+ short dstflag; /* Field not used */
+};
+#endif /* defined(HAVE_SYS_TIMEB_H) */
+
+#endif /* defined(vms) */
+
+#if defined (STDC_HEADERS) || defined (USG)
+#include <string.h>
+#endif
+
+/* Some old versions of bison generate parsers that use bcopy.
+ That loses on systems that don't provide the function, so we have
+ to redefine it here. */
+#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
+#define bcopy(from, to, len) memcpy ((to), (from), (len))
+#endif
+
+#if defined (STDC_HEADERS)
+#include <stdlib.h>
+#endif
+
+/* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
+ releases):
+
+ We don't want to mess with all the portability hassles of alloca.
+ In particular, most (all?) versions of bison will use alloca in
+ their parser. If bison works on your system (e.g. it should work
+ with gcc), then go ahead and use it, but the more general solution
+ is to use byacc instead of bison, which should generate a portable
+ parser. I played with adding "#define alloca dont_use_alloca", to
+ give an error if the parser generator uses alloca (and thus detect
+ unportable getdate.c's), but that seems to cause as many problems
+ as it solves. */
+
+extern struct tm *gmtime();
+extern struct tm *localtime();
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+static int yylex ();
+static int yyerror ();
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+
+/*
+** An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+ char *name;
+ int type;
+ time_t value;
+} TABLE;
+
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+ MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static MERIDIAN yyMeridian;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+%}
+
+%union {
+ time_t Number;
+ enum _MERIDIAN Meridian;
+}
+
+%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
+%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
+
+%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
+%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%type <Meridian> tMERIDIAN o_merid
+
+%%
+
+spec : /* NULL */
+ | spec item
+ ;
+
+item : time {
+ yyHaveTime++;
+ }
+ | zone {
+ yyHaveZone++;
+ }
+ | date {
+ yyHaveDate++;
+ }
+ | day {
+ yyHaveDay++;
+ }
+ | rel {
+ yyHaveRel++;
+ }
+ | number
+ ;
+
+time : tUNUMBER tMERIDIAN {
+ yyHour = $1;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = $2;
+ }
+ | tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = 0;
+ yyMeridian = $4;
+ }
+ | tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = $6;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+ }
+ ;
+
+zone : tZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSToff;
+ }
+ | tDAYZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ |
+ tZONE tDST {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ ;
+
+day : tDAY {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tDAY ',' {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tUNUMBER tDAY {
+ yyDayOrdinal = $1;
+ yyDayNumber = $2;
+ }
+ ;
+
+date : tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ }
+ | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ }
+ | tUNUMBER tSNUMBER tSNUMBER {
+ /* ISO 8601 format. yyyy-mm-dd. */
+ yyYear = $1;
+ yyMonth = -$2;
+ yyDay = -$3;
+ }
+ | tUNUMBER tMONTH tSNUMBER {
+ /* e.g. 17-JUN-1992. */
+ yyDay = $1;
+ yyMonth = $2;
+ yyYear = -$3;
+ }
+ | tMONTH tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ }
+ | tMONTH tUNUMBER ',' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ yyYear = $4;
+ }
+ | tUNUMBER tMONTH {
+ yyMonth = $2;
+ yyDay = $1;
+ }
+ | tUNUMBER tMONTH tUNUMBER {
+ yyMonth = $2;
+ yyDay = $1;
+ yyYear = $3;
+ }
+ ;
+
+rel : relunit tAGO {
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ }
+ | relunit
+ ;
+
+relunit : tUNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tSNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tMINUTE_UNIT {
+ yyRelSeconds += $1 * 60L;
+ }
+ | tSNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tUNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tSEC_UNIT {
+ yyRelSeconds++;
+ }
+ | tSNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tUNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tMONTH_UNIT {
+ yyRelMonth += $1;
+ }
+ ;
+
+number : tUNUMBER {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = $1;
+ else {
+ if($1>10000) {
+ yyHaveDate++;
+ yyDay= ($1)%100;
+ yyMonth= ($1/100)%100;
+ yyYear = $1/10000;
+ }
+ else {
+ yyHaveTime++;
+ if ($1 < 100) {
+ yyHour = $1;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = $1 / 100;
+ yyMinutes = $1 % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
+ }
+ }
+ }
+ ;
+
+o_merid : /* NULL */ {
+ $$ = MER24;
+ }
+ | tMERIDIAN {
+ $$ = $1;
+ }
+ ;
+
+%%
+
+/* Month and day table. */
+static TABLE const MonthDayTable[] = {
+ { N_("january"), tMONTH, 1 },
+ { N_("february"), tMONTH, 2 },
+ { N_("march"), tMONTH, 3 },
+ { N_("april"), tMONTH, 4 },
+ { N_("may"), tMONTH, 5 },
+ { N_("june"), tMONTH, 6 },
+ { N_("july"), tMONTH, 7 },
+ { N_("august"), tMONTH, 8 },
+ { N_("september"), tMONTH, 9 },
+ { N_("sept"), tMONTH, 9 },
+ { N_("october"), tMONTH, 10 },
+ { N_("november"), tMONTH, 11 },
+ { N_("december"), tMONTH, 12 },
+ { N_("sunday"), tDAY, 0 },
+ { N_("monday"), tDAY, 1 },
+ { N_("tuesday"), tDAY, 2 },
+ { N_("tues"), tDAY, 2 },
+ { N_("wednesday"), tDAY, 3 },
+ { N_("wednes"), tDAY, 3 },
+ { N_("thursday"), tDAY, 4 },
+ { N_("thur"), tDAY, 4 },
+ { N_("thurs"), tDAY, 4 },
+ { N_("friday"), tDAY, 5 },
+ { N_("saturday"), tDAY, 6 },
+ { NULL }
+};
+
+/* Time units table. */
+static TABLE const UnitsTable[] = {
+ { N_("year"), tMONTH_UNIT, 12 },
+ { N_("month"), tMONTH_UNIT, 1 },
+ { N_("fortnight"), tMINUTE_UNIT, 14 * 24 * 60 },
+ { N_("week"), tMINUTE_UNIT, 7 * 24 * 60 },
+ { N_("day"), tMINUTE_UNIT, 1 * 24 * 60 },
+ { N_("hour"), tMINUTE_UNIT, 60 },
+ { N_("minute"), tMINUTE_UNIT, 1 },
+ { N_("min"), tMINUTE_UNIT, 1 },
+ { N_("second"), tSEC_UNIT, 1 },
+ { N_("sec"), tSEC_UNIT, 1 },
+ { NULL }
+};
+
+/* Assorted relative-time words. */
+static TABLE const OtherTable[] = {
+ { N_("tomorrow"), tMINUTE_UNIT, 1 * 24 * 60 },
+ { N_("yesterday"), tMINUTE_UNIT, -1 * 24 * 60 },
+ { N_("today"), tMINUTE_UNIT, 0 },
+ { N_("now"), tMINUTE_UNIT, 0 },
+ { N_("last"), tUNUMBER, -1 },
+ { N_("this"), tMINUTE_UNIT, 0 },
+ { N_("next"), tUNUMBER, 2 },
+ { N_("first"), tUNUMBER, 1 },
+/* { N_("second"), tUNUMBER, 2 }, */
+ { N_("third"), tUNUMBER, 3 },
+ { N_("fourth"), tUNUMBER, 4 },
+ { N_("fifth"), tUNUMBER, 5 },
+ { N_("sixth"), tUNUMBER, 6 },
+ { N_("seventh"), tUNUMBER, 7 },
+ { N_("eighth"), tUNUMBER, 8 },
+ { N_("ninth"), tUNUMBER, 9 },
+ { N_("tenth"), tUNUMBER, 10 },
+ { N_("eleventh"), tUNUMBER, 11 },
+ { N_("twelfth"), tUNUMBER, 12 },
+ { N_("ago"), tAGO, 1 },
+ { NULL }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE const TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+#endif
+#if 0
+ { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
+ { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR(1) }, /* Central European */
+ { "met", tZONE, -HOUR(1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+#if 0
+ { "it", tZONE, -HOUR(3.5) },/* Iran */
+#endif
+ { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+#if 0
+ { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
+#endif
+ { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Stanard, and SST is
+ * also Swedish Summer. */
+ { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
+ { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+#if 0
+ { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+ { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
+#if 0
+ { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ { NULL }
+};
+
+/* Military timezone table. */
+static TABLE const MilitaryTable[] = {
+ { "a", tZONE, HOUR( 1) },
+ { "b", tZONE, HOUR( 2) },
+ { "c", tZONE, HOUR( 3) },
+ { "d", tZONE, HOUR( 4) },
+ { "e", tZONE, HOUR( 5) },
+ { "f", tZONE, HOUR( 6) },
+ { "g", tZONE, HOUR( 7) },
+ { "h", tZONE, HOUR( 8) },
+ { "i", tZONE, HOUR( 9) },
+ { "k", tZONE, HOUR( 10) },
+ { "l", tZONE, HOUR( 11) },
+ { "m", tZONE, HOUR( 12) },
+ { "n", tZONE, HOUR(- 1) },
+ { "o", tZONE, HOUR(- 2) },
+ { "p", tZONE, HOUR(- 3) },
+ { "q", tZONE, HOUR(- 4) },
+ { "r", tZONE, HOUR(- 5) },
+ { "s", tZONE, HOUR(- 6) },
+ { "t", tZONE, HOUR(- 7) },
+ { "u", tZONE, HOUR(- 8) },
+ { "v", tZONE, HOUR(- 9) },
+ { "w", tZONE, HOUR(-10) },
+ { "x", tZONE, HOUR(-11) },
+ { "y", tZONE, HOUR(-12) },
+ { "z", tZONE, HOUR( 0) },
+ { NULL }
+};
+
+
+
+
+/* ARGSUSED */
+static int
+yyerror(s)
+ char *s;
+{
+ return 0;
+}
+
+
+static time_t
+ToSeconds(Hours, Minutes, Seconds, Meridian)
+ time_t Hours;
+ time_t Minutes;
+ time_t Seconds;
+ MERIDIAN Meridian;
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ switch (Meridian) {
+ case MER24:
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERam:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERpm:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+ default:
+ abort ();
+ }
+ /* NOTREACHED */
+}
+
+
+static time_t
+Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
+ time_t Month;
+ time_t Day;
+ time_t Year;
+ time_t Hours;
+ time_t Minutes;
+ time_t Seconds;
+ MERIDIAN Meridian;
+ DSTMODE DSTmode;
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 0)
+ Year = -Year;
+ if (Year < 100)
+ Year += 1900;
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ if (Year < EPOCH || Year > 1999
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[(int)--Month])
+ return -1;
+
+ for (Julian = Day - 1, i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(Start, Future)
+ time_t Start;
+ time_t Future;
+{
+ time_t StartDay;
+ time_t FutureDay;
+
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(Start, DayOrdinal, DayNumber)
+ time_t Start;
+ time_t DayOrdinal;
+ time_t DayNumber;
+{
+ struct tm *tm;
+ time_t now;
+
+ now = Start;
+ tm = localtime(&now);
+ now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(Start, RelMonth)
+ time_t Start;
+ time_t RelMonth;
+{
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm->tm_mday, Year,
+ (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+ MER24, DSTmaybe));
+}
+
+
+static int
+LookupWord(buff)
+ char *buff;
+{
+ register char *p;
+ register char *q;
+ register const TABLE *tp;
+ int i;
+ int abbrev;
+
+ /* Make it lowercase. */
+ for (p = buff; *p; p++)
+ if (isupper(*p))
+ *p = tolower(*p);
+
+ if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+ yylval.Meridian = MERam;
+ return tMERIDIAN;
+ }
+ if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+ yylval.Meridian = MERpm;
+ return tMERIDIAN;
+ }
+
+ /* See if we have an abbreviation for a month. */
+ if (strlen(buff) == 3)
+ abbrev = 1;
+ else if (strlen(buff) == 4 && buff[3] == '.') {
+ abbrev = 1;
+ buff[3] = '\0';
+ }
+ else
+ abbrev = 0;
+
+ for (tp = MonthDayTable; tp->name; tp++) {
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ else if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ if (strcmp(buff, "dst") == 0)
+ return tDST;
+
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Strip off any plural and try the units table again. */
+ i = strlen(buff) - 1;
+ if (buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ buff[i] = 's'; /* Put back for "this" in OtherTable. */
+ }
+
+ for (tp = OtherTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Military timezones. */
+ if (buff[1] == '\0' && isalpha(*buff)) {
+ for (tp = MilitaryTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ /* Drop out any periods and try the timezone table again. */
+ for (i = 0, p = q = buff; *q; q++)
+ if (*q != '.')
+ *p++ = *q;
+ else
+ i++;
+ *p = '\0';
+ if (i)
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ return tID;
+}
+
+
+static int
+yylex()
+{
+ register char c;
+ register char *p;
+ char buff[20];
+ int Count;
+ int sign;
+
+ for ( ; ; ) {
+ while (isspace(*yyInput))
+ yyInput++;
+
+ if (isdigit(c = *yyInput) || c == '-' || c == '+') {
+ if (c == '-' || c == '+') {
+ sign = c == '-' ? -1 : 1;
+ if (!isdigit(*++yyInput))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ for (yylval.Number = 0; isdigit(c = *yyInput++); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ if (sign < 0)
+ yylval.Number = -yylval.Number;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ if (isalpha(c)) {
+ for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
+ if (p < &buff[sizeof buff - 1])
+ *p++ = c;
+ *p = '\0';
+ yyInput--;
+ return LookupWord(buff);
+ }
+ if (c != '(')
+ return *yyInput++;
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm (a, b)
+ struct tm *a, *b;
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+
+time_t
+get_date(p, now)
+ char *p;
+ struct timeb *now;
+{
+ struct tm *tm, gmt;
+ struct timeb ftz;
+ time_t Start;
+ time_t tod;
+ time_t nowtime;
+
+ yyInput = p;
+ if (now == NULL) {
+ now = &ftz;
+ (void)time (&nowtime);
+
+ if (! (tm = gmtime (&nowtime)))
+ return -1;
+ gmt = *tm; /* Make a copy, in case localtime modifies *tm. */
+
+ if (! (tm = localtime (&nowtime)))
+ return -1;
+
+ ftz.timezone = difftm (&gmt, tm) / 60;
+ if(tm->tm_isdst)
+ ftz.timezone += 60;
+ }
+ else
+ {
+ nowtime = now->time;
+ }
+
+ tm = localtime(&nowtime);
+ yyYear = tm->tm_year;
+ yyMonth = tm->tm_mon + 1;
+ yyDay = tm->tm_mday;
+ yyTimezone = now->timezone;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = MER24;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+ yyMeridian, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ }
+ else {
+ Start = nowtime;
+ if (!yyHaveRel)
+ Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's distinguishable
+ * from the error return value. (Alternately could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#if defined(TEST)
+
+/* ARGSUSED */
+int
+main(ac, av)
+ int ac;
+ char *av[];
+{
+ char buff[128];
+ time_t d;
+
+ (void)printf("Enter date, or blank line to exit.\n\t> ");
+ (void)fflush(stdout);
+ while (gets(buff) && buff[0]) {
+ d = get_date(buff, (struct timeb *)NULL);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("%s", ctime(&d));
+ (void)printf("\t> ");
+ (void)fflush(stdout);
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
diff --git a/calendar/gnome-cal.html b/calendar/gnome-cal.html
new file mode 100644
index 0000000000..eeb8d4e25e
--- /dev/null
+++ b/calendar/gnome-cal.html
@@ -0,0 +1,42 @@
+<!-- Some simple instructions on how to use the help browser -->
+<BODY>
+<!-- <TITLE>GNOME Calendar Documentation</TITLE> -->
+<H2> GNOME Calendar Documentation </H2>
+<p>
+The GNOME calendar program is the calendaring program of the GNOME
+system. It uses the vCalendar standard for transfering calendar
+information (and is also the on-disk format used).
+
+<p>
+
+<a name="cmdline">
+<h2>Command line options</h2>
+
+Several options are available on the command line, they are:
+<ul>
+ <li><tt>--events</tt> Displays the events for the date
+ specified (or today, if no date is specified).
+
+ <li><tt>--from DATE</tt> Define the beginning of the range for
+ the event display, or the startup day on the calenday views.
+ By default, the event will span the whole day specified in
+ DATE.
+
+ <li><tt>--to DATE</tt> Define the range end for the event
+ display. If this is not specified, it will default to the end
+ of the day specified by the <tt>--from</tt> option.
+
+ <li><tt>--file FILE</tt> Set the calendar to the FILE
+ specified on the command line.
+</ul>
+
+<p>
+
+DATE is interpreted as being in the local time- zone, unless a
+specific timezone is specified. Examples of valid date specifications
+include: "1 month ago", "2 hours ago", "400000 seconds ago", "last
+year", "last Monday", "yesterday", "a fortnight ago", "3/31/92
+10:00:07 PST", "January 23, 1987 10:05pm", "22:00 GMT".
+
+</BODY>
+
diff --git a/calendar/gui/Makefile.am b/calendar/gui/Makefile.am
index 9728a02d4b..15e7bf5f95 100644
--- a/calendar/gui/Makefile.am
+++ b/calendar/gui/Makefile.am
@@ -1,4 +1,5 @@
SUBDIRS = versit
+help_base = $(datadir)/gnome/help/cal
INCLUDES = \
-I$(includedir) \
@@ -23,6 +24,7 @@ gnomecal_SOURCES = \
gncal-week-view.h \
gncal-year-view.c \
gncal-year-view.h \
+ getdate.y \
gnome-cal.c \
gnome-cal.h \
main.c \
@@ -64,9 +66,17 @@ LINK_FLAGS = \
gnomecal_LDADD = $(LINK_FLAGS)
EXTRA_DIST = \
- gncal.desktop
+ gncal.desktop \
+ topic.dat \
+ gnome-cal.html
+
Productivitydir = $(datadir)/apps/Productivity
Productivity_DATA = gncal.desktop
+install-data-local:
+ $(mkinstalldirs) $(help_base)/C
+ $(INSTALL_DATA) $(srcdir)/topic.dat $(help_base)/C/topic.dat
+ $(INSTALL_DATA) $(srcdir)/gnome-cal.html $(help_base)/C/gnome-cal.html
+ cd $(help_base)/C; ln -sf gnome-cal.html index.html \ No newline at end of file
diff --git a/calendar/gui/getdate.y b/calendar/gui/getdate.y
new file mode 100644
index 0000000000..6df71bddda
--- /dev/null
+++ b/calendar/gui/getdate.y
@@ -0,0 +1,1001 @@
+%{
+/*
+** Originally) written by Steven M. Bellovin <smb@research.att.com> while
+** at the University of North Carolina at Chapel Hill. Later tweaked by
+** a couple of people on Usenet. Completely overhauled by Rich $alz
+** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
+** send any email to Rich.
+**
+** This grammar has 10 shift/reduce conflicts.
+**
+** This code is in the public domain and has no copyright.
+*/
+/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
+/* SUPPRESS 288 on yyerrlab *//* Label unused */
+
+#include <config.h>
+#include <gnome.h>
+
+/* Since the code of getdate.y is not included in the Emacs executable
+ itself, there is no need to #define static in this file. Even if
+ the code were included in the Emacs executable, it probably
+ wouldn't do any harm to #undef it here; this will only cause
+ problems if we try to write to a static variable, which I don't
+ think this code needs to do. */
+#ifdef emacs
+#undef static
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+/* The code at the top of get_date which figures out the offset of the
+ current time zone checks various CPP symbols to see if special
+ tricks are need, but defaults to using the gettimeofday system call.
+ Include <sys/time.h> if that will be used. */
+
+#if defined(vms)
+
+#include <types.h>
+#include <time.h>
+
+#else
+
+#include <sys/types.h>
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef timezone
+#undef timezone /* needed for sgi */
+#endif
+
+#if defined(HAVE_SYS_TIMEB_H)
+#include <sys/timeb.h>
+#else
+/*
+** We use the obsolete `struct timeb' as part of our interface!
+** Since the system doesn't have it, we define it here;
+** our callers must do likewise.
+*/
+struct timeb {
+ time_t time; /* Seconds since the epoch */
+ unsigned short millitm; /* Field not used */
+ short timezone; /* Minutes west of GMT */
+ short dstflag; /* Field not used */
+};
+#endif /* defined(HAVE_SYS_TIMEB_H) */
+
+#endif /* defined(vms) */
+
+#if defined (STDC_HEADERS) || defined (USG)
+#include <string.h>
+#endif
+
+/* Some old versions of bison generate parsers that use bcopy.
+ That loses on systems that don't provide the function, so we have
+ to redefine it here. */
+#if !defined (HAVE_BCOPY) && defined (HAVE_MEMCPY) && !defined (bcopy)
+#define bcopy(from, to, len) memcpy ((to), (from), (len))
+#endif
+
+#if defined (STDC_HEADERS)
+#include <stdlib.h>
+#endif
+
+/* NOTES on rebuilding getdate.c (particularly for inclusion in CVS
+ releases):
+
+ We don't want to mess with all the portability hassles of alloca.
+ In particular, most (all?) versions of bison will use alloca in
+ their parser. If bison works on your system (e.g. it should work
+ with gcc), then go ahead and use it, but the more general solution
+ is to use byacc instead of bison, which should generate a portable
+ parser. I played with adding "#define alloca dont_use_alloca", to
+ give an error if the parser generator uses alloca (and thus detect
+ unportable getdate.c's), but that seems to cause as many problems
+ as it solves. */
+
+extern struct tm *gmtime();
+extern struct tm *localtime();
+
+#define yyparse getdate_yyparse
+#define yylex getdate_yylex
+#define yyerror getdate_yyerror
+
+static int yylex ();
+static int yyerror ();
+
+#define EPOCH 1970
+#define HOUR(x) ((time_t)(x) * 60)
+#define SECSPERDAY (24L * 60L * 60L)
+
+
+/*
+** An entry in the lexical lookup table.
+*/
+typedef struct _TABLE {
+ char *name;
+ int type;
+ time_t value;
+} TABLE;
+
+
+/*
+** Daylight-savings mode: on, off, or not yet known.
+*/
+typedef enum _DSTMODE {
+ DSTon, DSToff, DSTmaybe
+} DSTMODE;
+
+/*
+** Meridian: am, pm, or 24-hour style.
+*/
+typedef enum _MERIDIAN {
+ MERam, MERpm, MER24
+} MERIDIAN;
+
+
+/*
+** Global variables. We could get rid of most of these by using a good
+** union as the yacc stack. (This routine was originally written before
+** yacc had the %union construct.) Maybe someday; right now we only use
+** the %union very rarely.
+*/
+static char *yyInput;
+static DSTMODE yyDSTmode;
+static time_t yyDayOrdinal;
+static time_t yyDayNumber;
+static int yyHaveDate;
+static int yyHaveDay;
+static int yyHaveRel;
+static int yyHaveTime;
+static int yyHaveZone;
+static time_t yyTimezone;
+static time_t yyDay;
+static time_t yyHour;
+static time_t yyMinutes;
+static time_t yyMonth;
+static time_t yySeconds;
+static time_t yyYear;
+static MERIDIAN yyMeridian;
+static time_t yyRelMonth;
+static time_t yyRelSeconds;
+
+%}
+
+%union {
+ time_t Number;
+ enum _MERIDIAN Meridian;
+}
+
+%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
+%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST
+
+%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
+%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%type <Meridian> tMERIDIAN o_merid
+
+%%
+
+spec : /* NULL */
+ | spec item
+ ;
+
+item : time {
+ yyHaveTime++;
+ }
+ | zone {
+ yyHaveZone++;
+ }
+ | date {
+ yyHaveDate++;
+ }
+ | day {
+ yyHaveDay++;
+ }
+ | rel {
+ yyHaveRel++;
+ }
+ | number
+ ;
+
+time : tUNUMBER tMERIDIAN {
+ yyHour = $1;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = $2;
+ }
+ | tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = 0;
+ yyMeridian = $4;
+ }
+ | tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = $6;
+ }
+ | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
+ yyHour = $1;
+ yyMinutes = $3;
+ yySeconds = $5;
+ yyMeridian = MER24;
+ yyDSTmode = DSToff;
+ yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
+ }
+ ;
+
+zone : tZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSToff;
+ }
+ | tDAYZONE {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ |
+ tZONE tDST {
+ yyTimezone = $1;
+ yyDSTmode = DSTon;
+ }
+ ;
+
+day : tDAY {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tDAY ',' {
+ yyDayOrdinal = 1;
+ yyDayNumber = $1;
+ }
+ | tUNUMBER tDAY {
+ yyDayOrdinal = $1;
+ yyDayNumber = $2;
+ }
+ ;
+
+date : tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ }
+ | tUNUMBER '/' tUNUMBER '/' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $3;
+ yyYear = $5;
+ }
+ | tUNUMBER tSNUMBER tSNUMBER {
+ /* ISO 8601 format. yyyy-mm-dd. */
+ yyYear = $1;
+ yyMonth = -$2;
+ yyDay = -$3;
+ }
+ | tUNUMBER tMONTH tSNUMBER {
+ /* e.g. 17-JUN-1992. */
+ yyDay = $1;
+ yyMonth = $2;
+ yyYear = -$3;
+ }
+ | tMONTH tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ }
+ | tMONTH tUNUMBER ',' tUNUMBER {
+ yyMonth = $1;
+ yyDay = $2;
+ yyYear = $4;
+ }
+ | tUNUMBER tMONTH {
+ yyMonth = $2;
+ yyDay = $1;
+ }
+ | tUNUMBER tMONTH tUNUMBER {
+ yyMonth = $2;
+ yyDay = $1;
+ yyYear = $3;
+ }
+ ;
+
+rel : relunit tAGO {
+ yyRelSeconds = -yyRelSeconds;
+ yyRelMonth = -yyRelMonth;
+ }
+ | relunit
+ ;
+
+relunit : tUNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tSNUMBER tMINUTE_UNIT {
+ yyRelSeconds += $1 * $2 * 60L;
+ }
+ | tMINUTE_UNIT {
+ yyRelSeconds += $1 * 60L;
+ }
+ | tSNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tUNUMBER tSEC_UNIT {
+ yyRelSeconds += $1;
+ }
+ | tSEC_UNIT {
+ yyRelSeconds++;
+ }
+ | tSNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tUNUMBER tMONTH_UNIT {
+ yyRelMonth += $1 * $2;
+ }
+ | tMONTH_UNIT {
+ yyRelMonth += $1;
+ }
+ ;
+
+number : tUNUMBER {
+ if (yyHaveTime && yyHaveDate && !yyHaveRel)
+ yyYear = $1;
+ else {
+ if($1>10000) {
+ yyHaveDate++;
+ yyDay= ($1)%100;
+ yyMonth= ($1/100)%100;
+ yyYear = $1/10000;
+ }
+ else {
+ yyHaveTime++;
+ if ($1 < 100) {
+ yyHour = $1;
+ yyMinutes = 0;
+ }
+ else {
+ yyHour = $1 / 100;
+ yyMinutes = $1 % 100;
+ }
+ yySeconds = 0;
+ yyMeridian = MER24;
+ }
+ }
+ }
+ ;
+
+o_merid : /* NULL */ {
+ $$ = MER24;
+ }
+ | tMERIDIAN {
+ $$ = $1;
+ }
+ ;
+
+%%
+
+/* Month and day table. */
+static TABLE const MonthDayTable[] = {
+ { N_("january"), tMONTH, 1 },
+ { N_("february"), tMONTH, 2 },
+ { N_("march"), tMONTH, 3 },
+ { N_("april"), tMONTH, 4 },
+ { N_("may"), tMONTH, 5 },
+ { N_("june"), tMONTH, 6 },
+ { N_("july"), tMONTH, 7 },
+ { N_("august"), tMONTH, 8 },
+ { N_("september"), tMONTH, 9 },
+ { N_("sept"), tMONTH, 9 },
+ { N_("october"), tMONTH, 10 },
+ { N_("november"), tMONTH, 11 },
+ { N_("december"), tMONTH, 12 },
+ { N_("sunday"), tDAY, 0 },
+ { N_("monday"), tDAY, 1 },
+ { N_("tuesday"), tDAY, 2 },
+ { N_("tues"), tDAY, 2 },
+ { N_("wednesday"), tDAY, 3 },
+ { N_("wednes"), tDAY, 3 },
+ { N_("thursday"), tDAY, 4 },
+ { N_("thur"), tDAY, 4 },
+ { N_("thurs"), tDAY, 4 },
+ { N_("friday"), tDAY, 5 },
+ { N_("saturday"), tDAY, 6 },
+ { NULL }
+};
+
+/* Time units table. */
+static TABLE const UnitsTable[] = {
+ { N_("year"), tMONTH_UNIT, 12 },
+ { N_("month"), tMONTH_UNIT, 1 },
+ { N_("fortnight"), tMINUTE_UNIT, 14 * 24 * 60 },
+ { N_("week"), tMINUTE_UNIT, 7 * 24 * 60 },
+ { N_("day"), tMINUTE_UNIT, 1 * 24 * 60 },
+ { N_("hour"), tMINUTE_UNIT, 60 },
+ { N_("minute"), tMINUTE_UNIT, 1 },
+ { N_("min"), tMINUTE_UNIT, 1 },
+ { N_("second"), tSEC_UNIT, 1 },
+ { N_("sec"), tSEC_UNIT, 1 },
+ { NULL }
+};
+
+/* Assorted relative-time words. */
+static TABLE const OtherTable[] = {
+ { N_("tomorrow"), tMINUTE_UNIT, 1 * 24 * 60 },
+ { N_("yesterday"), tMINUTE_UNIT, -1 * 24 * 60 },
+ { N_("today"), tMINUTE_UNIT, 0 },
+ { N_("now"), tMINUTE_UNIT, 0 },
+ { N_("last"), tUNUMBER, -1 },
+ { N_("this"), tMINUTE_UNIT, 0 },
+ { N_("next"), tUNUMBER, 2 },
+ { N_("first"), tUNUMBER, 1 },
+/* { N_("second"), tUNUMBER, 2 }, */
+ { N_("third"), tUNUMBER, 3 },
+ { N_("fourth"), tUNUMBER, 4 },
+ { N_("fifth"), tUNUMBER, 5 },
+ { N_("sixth"), tUNUMBER, 6 },
+ { N_("seventh"), tUNUMBER, 7 },
+ { N_("eighth"), tUNUMBER, 8 },
+ { N_("ninth"), tUNUMBER, 9 },
+ { N_("tenth"), tUNUMBER, 10 },
+ { N_("eleventh"), tUNUMBER, 11 },
+ { N_("twelfth"), tUNUMBER, 12 },
+ { N_("ago"), tAGO, 1 },
+ { NULL }
+};
+
+/* The timezone table. */
+/* Some of these are commented out because a time_t can't store a float. */
+static TABLE const TimezoneTable[] = {
+ { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
+ { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
+ { "utc", tZONE, HOUR( 0) },
+ { "wet", tZONE, HOUR( 0) }, /* Western European */
+ { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
+ { "wat", tZONE, HOUR( 1) }, /* West Africa */
+ { "at", tZONE, HOUR( 2) }, /* Azores */
+#if 0
+ /* For completeness. BST is also British Summer, and GST is
+ * also Guam Standard. */
+ { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
+ { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
+#endif
+#if 0
+ { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
+ { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
+ { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
+#endif
+ { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
+ { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
+ { "est", tZONE, HOUR( 5) }, /* Eastern Standard */
+ { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
+ { "cst", tZONE, HOUR( 6) }, /* Central Standard */
+ { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
+ { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
+ { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
+ { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
+ { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
+ { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
+ { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
+ { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
+ { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */
+ { "cat", tZONE, HOUR(10) }, /* Central Alaska */
+ { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */
+ { "nt", tZONE, HOUR(11) }, /* Nome */
+ { "idlw", tZONE, HOUR(12) }, /* International Date Line West */
+ { "cet", tZONE, -HOUR(1) }, /* Central European */
+ { "met", tZONE, -HOUR(1) }, /* Middle European */
+ { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */
+ { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */
+ { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */
+ { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */
+ { "fwt", tZONE, -HOUR(1) }, /* French Winter */
+ { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */
+ { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */
+ { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */
+#if 0
+ { "it", tZONE, -HOUR(3.5) },/* Iran */
+#endif
+ { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */
+ { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */
+#if 0
+ { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */
+#endif
+ { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */
+#if 0
+ /* For completeness. NST is also Newfoundland Stanard, and SST is
+ * also Swedish Summer. */
+ { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */
+ { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */
+#endif /* 0 */
+ { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */
+ { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */
+#if 0
+ { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */
+#endif
+ { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */
+ { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */
+#if 0
+ { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */
+ { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */
+#endif
+ { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */
+ { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */
+ { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */
+ { "nzt", tZONE, -HOUR(12) }, /* New Zealand */
+ { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */
+ { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */
+ { "idle", tZONE, -HOUR(12) }, /* International Date Line East */
+ { NULL }
+};
+
+/* Military timezone table. */
+static TABLE const MilitaryTable[] = {
+ { "a", tZONE, HOUR( 1) },
+ { "b", tZONE, HOUR( 2) },
+ { "c", tZONE, HOUR( 3) },
+ { "d", tZONE, HOUR( 4) },
+ { "e", tZONE, HOUR( 5) },
+ { "f", tZONE, HOUR( 6) },
+ { "g", tZONE, HOUR( 7) },
+ { "h", tZONE, HOUR( 8) },
+ { "i", tZONE, HOUR( 9) },
+ { "k", tZONE, HOUR( 10) },
+ { "l", tZONE, HOUR( 11) },
+ { "m", tZONE, HOUR( 12) },
+ { "n", tZONE, HOUR(- 1) },
+ { "o", tZONE, HOUR(- 2) },
+ { "p", tZONE, HOUR(- 3) },
+ { "q", tZONE, HOUR(- 4) },
+ { "r", tZONE, HOUR(- 5) },
+ { "s", tZONE, HOUR(- 6) },
+ { "t", tZONE, HOUR(- 7) },
+ { "u", tZONE, HOUR(- 8) },
+ { "v", tZONE, HOUR(- 9) },
+ { "w", tZONE, HOUR(-10) },
+ { "x", tZONE, HOUR(-11) },
+ { "y", tZONE, HOUR(-12) },
+ { "z", tZONE, HOUR( 0) },
+ { NULL }
+};
+
+
+
+
+/* ARGSUSED */
+static int
+yyerror(s)
+ char *s;
+{
+ return 0;
+}
+
+
+static time_t
+ToSeconds(Hours, Minutes, Seconds, Meridian)
+ time_t Hours;
+ time_t Minutes;
+ time_t Seconds;
+ MERIDIAN Meridian;
+{
+ if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
+ return -1;
+ switch (Meridian) {
+ case MER24:
+ if (Hours < 0 || Hours > 23)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERam:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ return (Hours * 60L + Minutes) * 60L + Seconds;
+ case MERpm:
+ if (Hours < 1 || Hours > 12)
+ return -1;
+ return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
+ default:
+ abort ();
+ }
+ /* NOTREACHED */
+}
+
+
+static time_t
+Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
+ time_t Month;
+ time_t Day;
+ time_t Year;
+ time_t Hours;
+ time_t Minutes;
+ time_t Seconds;
+ MERIDIAN Meridian;
+ DSTMODE DSTmode;
+{
+ static int DaysInMonth[12] = {
+ 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ time_t tod;
+ time_t Julian;
+ int i;
+
+ if (Year < 0)
+ Year = -Year;
+ if (Year < 100)
+ Year += 1900;
+ DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
+ ? 29 : 28;
+ if (Year < EPOCH || Year > 1999
+ || Month < 1 || Month > 12
+ /* Lint fluff: "conversion from long may lose accuracy" */
+ || Day < 1 || Day > DaysInMonth[(int)--Month])
+ return -1;
+
+ for (Julian = Day - 1, i = 0; i < Month; i++)
+ Julian += DaysInMonth[i];
+ for (i = EPOCH; i < Year; i++)
+ Julian += 365 + (i % 4 == 0);
+ Julian *= SECSPERDAY;
+ Julian += yyTimezone * 60L;
+ if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
+ return -1;
+ Julian += tod;
+ if (DSTmode == DSTon
+ || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
+ Julian -= 60 * 60;
+ return Julian;
+}
+
+
+static time_t
+DSTcorrect(Start, Future)
+ time_t Start;
+ time_t Future;
+{
+ time_t StartDay;
+ time_t FutureDay;
+
+ StartDay = (localtime(&Start)->tm_hour + 1) % 24;
+ FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
+ return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
+}
+
+
+static time_t
+RelativeDate(Start, DayOrdinal, DayNumber)
+ time_t Start;
+ time_t DayOrdinal;
+ time_t DayNumber;
+{
+ struct tm *tm;
+ time_t now;
+
+ now = Start;
+ tm = localtime(&now);
+ now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
+ now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
+ return DSTcorrect(Start, now);
+}
+
+
+static time_t
+RelativeMonth(Start, RelMonth)
+ time_t Start;
+ time_t RelMonth;
+{
+ struct tm *tm;
+ time_t Month;
+ time_t Year;
+
+ if (RelMonth == 0)
+ return 0;
+ tm = localtime(&Start);
+ Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
+ Year = Month / 12;
+ Month = Month % 12 + 1;
+ return DSTcorrect(Start,
+ Convert(Month, (time_t)tm->tm_mday, Year,
+ (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
+ MER24, DSTmaybe));
+}
+
+
+static int
+LookupWord(buff)
+ char *buff;
+{
+ register char *p;
+ register char *q;
+ register const TABLE *tp;
+ int i;
+ int abbrev;
+
+ /* Make it lowercase. */
+ for (p = buff; *p; p++)
+ if (isupper(*p))
+ *p = tolower(*p);
+
+ if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
+ yylval.Meridian = MERam;
+ return tMERIDIAN;
+ }
+ if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
+ yylval.Meridian = MERpm;
+ return tMERIDIAN;
+ }
+
+ /* See if we have an abbreviation for a month. */
+ if (strlen(buff) == 3)
+ abbrev = 1;
+ else if (strlen(buff) == 4 && buff[3] == '.') {
+ abbrev = 1;
+ buff[3] = '\0';
+ }
+ else
+ abbrev = 0;
+
+ for (tp = MonthDayTable; tp->name; tp++) {
+ if (abbrev) {
+ if (strncmp(buff, tp->name, 3) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+ else if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ if (strcmp(buff, "dst") == 0)
+ return tDST;
+
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Strip off any plural and try the units table again. */
+ i = strlen(buff) - 1;
+ if (buff[i] == 's') {
+ buff[i] = '\0';
+ for (tp = UnitsTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ buff[i] = 's'; /* Put back for "this" in OtherTable. */
+ }
+
+ for (tp = OtherTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ /* Military timezones. */
+ if (buff[1] == '\0' && isalpha(*buff)) {
+ for (tp = MilitaryTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+ }
+
+ /* Drop out any periods and try the timezone table again. */
+ for (i = 0, p = q = buff; *q; q++)
+ if (*q != '.')
+ *p++ = *q;
+ else
+ i++;
+ *p = '\0';
+ if (i)
+ for (tp = TimezoneTable; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval.Number = tp->value;
+ return tp->type;
+ }
+
+ return tID;
+}
+
+
+static int
+yylex()
+{
+ register char c;
+ register char *p;
+ char buff[20];
+ int Count;
+ int sign;
+
+ for ( ; ; ) {
+ while (isspace(*yyInput))
+ yyInput++;
+
+ if (isdigit(c = *yyInput) || c == '-' || c == '+') {
+ if (c == '-' || c == '+') {
+ sign = c == '-' ? -1 : 1;
+ if (!isdigit(*++yyInput))
+ /* skip the '-' sign */
+ continue;
+ }
+ else
+ sign = 0;
+ for (yylval.Number = 0; isdigit(c = *yyInput++); )
+ yylval.Number = 10 * yylval.Number + c - '0';
+ yyInput--;
+ if (sign < 0)
+ yylval.Number = -yylval.Number;
+ return sign ? tSNUMBER : tUNUMBER;
+ }
+ if (isalpha(c)) {
+ for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
+ if (p < &buff[sizeof buff - 1])
+ *p++ = c;
+ *p = '\0';
+ yyInput--;
+ return LookupWord(buff);
+ }
+ if (c != '(')
+ return *yyInput++;
+ Count = 0;
+ do {
+ c = *yyInput++;
+ if (c == '\0')
+ return c;
+ if (c == '(')
+ Count++;
+ else if (c == ')')
+ Count--;
+ } while (Count > 0);
+ }
+}
+
+#define TM_YEAR_ORIGIN 1900
+
+/* Yield A - B, measured in seconds. */
+static long
+difftm (a, b)
+ struct tm *a, *b;
+{
+ int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
+ int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
+ int days = (
+ /* difference in day of year */
+ a->tm_yday - b->tm_yday
+ /* + intervening leap days */
+ + ((ay >> 2) - (by >> 2))
+ - (ay/100 - by/100)
+ + ((ay/100 >> 2) - (by/100 >> 2))
+ /* + difference in years * 365 */
+ + (long)(ay-by) * 365
+ );
+ return (60*(60*(24*days + (a->tm_hour - b->tm_hour))
+ + (a->tm_min - b->tm_min))
+ + (a->tm_sec - b->tm_sec));
+}
+
+time_t
+get_date(p, now)
+ char *p;
+ struct timeb *now;
+{
+ struct tm *tm, gmt;
+ struct timeb ftz;
+ time_t Start;
+ time_t tod;
+ time_t nowtime;
+
+ yyInput = p;
+ if (now == NULL) {
+ now = &ftz;
+ (void)time (&nowtime);
+
+ if (! (tm = gmtime (&nowtime)))
+ return -1;
+ gmt = *tm; /* Make a copy, in case localtime modifies *tm. */
+
+ if (! (tm = localtime (&nowtime)))
+ return -1;
+
+ ftz.timezone = difftm (&gmt, tm) / 60;
+ if(tm->tm_isdst)
+ ftz.timezone += 60;
+ }
+ else
+ {
+ nowtime = now->time;
+ }
+
+ tm = localtime(&nowtime);
+ yyYear = tm->tm_year;
+ yyMonth = tm->tm_mon + 1;
+ yyDay = tm->tm_mday;
+ yyTimezone = now->timezone;
+ yyDSTmode = DSTmaybe;
+ yyHour = 0;
+ yyMinutes = 0;
+ yySeconds = 0;
+ yyMeridian = MER24;
+ yyRelSeconds = 0;
+ yyRelMonth = 0;
+ yyHaveDate = 0;
+ yyHaveDay = 0;
+ yyHaveRel = 0;
+ yyHaveTime = 0;
+ yyHaveZone = 0;
+
+ if (yyparse()
+ || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
+ return -1;
+
+ if (yyHaveDate || yyHaveTime || yyHaveDay) {
+ Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
+ yyMeridian, yyDSTmode);
+ if (Start < 0)
+ return -1;
+ }
+ else {
+ Start = nowtime;
+ if (!yyHaveRel)
+ Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
+ }
+
+ Start += yyRelSeconds;
+ Start += RelativeMonth(Start, yyRelMonth);
+
+ if (yyHaveDay && !yyHaveDate) {
+ tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
+ Start += tod;
+ }
+
+ /* Have to do *something* with a legitimate -1 so it's distinguishable
+ * from the error return value. (Alternately could set errno on error.) */
+ return Start == -1 ? 0 : Start;
+}
+
+
+#if defined(TEST)
+
+/* ARGSUSED */
+int
+main(ac, av)
+ int ac;
+ char *av[];
+{
+ char buff[128];
+ time_t d;
+
+ (void)printf("Enter date, or blank line to exit.\n\t> ");
+ (void)fflush(stdout);
+ while (gets(buff) && buff[0]) {
+ d = get_date(buff, (struct timeb *)NULL);
+ if (d == -1)
+ (void)printf("Bad format - couldn't convert.\n");
+ else
+ (void)printf("%s", ctime(&d));
+ (void)printf("\t> ");
+ (void)fflush(stdout);
+ }
+ exit(0);
+ /* NOTREACHED */
+}
+#endif /* defined(TEST) */
diff --git a/calendar/gui/gnome-cal.html b/calendar/gui/gnome-cal.html
new file mode 100644
index 0000000000..eeb8d4e25e
--- /dev/null
+++ b/calendar/gui/gnome-cal.html
@@ -0,0 +1,42 @@
+<!-- Some simple instructions on how to use the help browser -->
+<BODY>
+<!-- <TITLE>GNOME Calendar Documentation</TITLE> -->
+<H2> GNOME Calendar Documentation </H2>
+<p>
+The GNOME calendar program is the calendaring program of the GNOME
+system. It uses the vCalendar standard for transfering calendar
+information (and is also the on-disk format used).
+
+<p>
+
+<a name="cmdline">
+<h2>Command line options</h2>
+
+Several options are available on the command line, they are:
+<ul>
+ <li><tt>--events</tt> Displays the events for the date
+ specified (or today, if no date is specified).
+
+ <li><tt>--from DATE</tt> Define the beginning of the range for
+ the event display, or the startup day on the calenday views.
+ By default, the event will span the whole day specified in
+ DATE.
+
+ <li><tt>--to DATE</tt> Define the range end for the event
+ display. If this is not specified, it will default to the end
+ of the day specified by the <tt>--from</tt> option.
+
+ <li><tt>--file FILE</tt> Set the calendar to the FILE
+ specified on the command line.
+</ul>
+
+<p>
+
+DATE is interpreted as being in the local time- zone, unless a
+specific timezone is specified. Examples of valid date specifications
+include: "1 month ago", "2 hours ago", "400000 seconds ago", "last
+year", "last Monday", "yesterday", "a fortnight ago", "3/31/92
+10:00:07 PST", "January 23, 1987 10:05pm", "22:00 GMT".
+
+</BODY>
+
diff --git a/calendar/gui/main.c b/calendar/gui/main.c
index cc7a0ecd85..3a657ef05e 100644
--- a/calendar/gui/main.c
+++ b/calendar/gui/main.c
@@ -40,6 +40,14 @@ GList *all_calendars = NULL;
static void new_calendar (char *full_name, char *calendar_file);
+/* For dumping part of a calendar */
+static time_t from_t, to_t;
+
+/* File to load instead of the user default's file */
+static char *load_file;
+
+/* If set, show events for the specified date and quit */
+static int show_events;
void
init_username (void)
@@ -263,7 +271,8 @@ save_calendar_cmd (GtkWidget *widget, void *data)
}
GnomeUIInfo gnome_cal_file_menu [] = {
- { GNOME_APP_UI_ITEM, N_("New calendar"), NULL, new_calendar_cmd },
+ { GNOME_APP_UI_ITEM, N_("New calendar"), NULL, new_calendar_cmd, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_NEW },
{ GNOME_APP_UI_ITEM, N_("Open calendar..."), NULL, open_calendar_cmd, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_OPEN },
@@ -304,6 +313,9 @@ GnomeUIInfo gnome_cal_menu [] = {
};
GnomeUIInfo gnome_toolbar [] = {
+ { GNOME_APP_UI_ITEM, N_("New"), NULL, display_objedit, 0, 0,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_NEW },\
+
{ GNOME_APP_UI_ITEM, N_("Prev"), NULL, previous_clicked, 0, 0,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BACK },
@@ -342,12 +354,11 @@ new_calendar (char *full_name, char *calendar_file)
g_free (title);
setup_menu (toplevel);
- if (calendar_file && g_file_exists (calendar_file)) {
- printf ("Trying to load %s\n", calendar_file);
+ if (calendar_file && g_file_exists (calendar_file))
gnome_calendar_load (GNOME_CALENDAR (toplevel), calendar_file);
- } else {
+ else
GNOME_CALENDAR (toplevel)->cal->filename = g_strdup (calendar_file);
- }
+
gtk_signal_connect (GTK_OBJECT (toplevel), "delete_event",
GTK_SIGNAL_FUNC(calendar_close_event), toplevel);
@@ -356,6 +367,113 @@ new_calendar (char *full_name, char *calendar_file)
gtk_widget_show (toplevel);
}
+static void
+process_dates (void)
+{
+ if (!from_t)
+ from_t = time_start_of_day (time (NULL));
+
+ if (!to_t || to_t < from_t)
+ to_t = time_add_day (from_t, 1);
+}
+
+static struct argp_option argp_options [] = {
+ { "events", 'e', NULL, 0, N_("Show events and quit"), 0 },
+ { "from ", 'f', N_("FROM"), 0, N_("Specifies start date [for --events]"), 1 },
+ { "file", 'F', N_("FILE"), 0, N_("File to load calendar from"), 1 },
+ { "to", 't', N_("TO"), 0, N_("Specifies ending date [for --events]"), 1 },
+ { NULL, 0, NULL, 0, NULL, 0 },
+};
+
+int
+same_day (struct tm *a, struct tm *b)
+{
+ return (a->tm_mday == b->tm_mday &&
+ a->tm_mon == b->tm_mon &&
+ a->tm_year == b->tm_year);
+}
+
+void
+dump_events (void)
+{
+ Calendar *cal;
+ GList *l;
+ char *s;
+ time_t now = time (NULL);
+ struct tm today = *localtime (&now);
+
+ process_dates ();
+ init_calendar ();
+
+ cal = calendar_new (full_name);
+ s = calendar_load (cal, load_file ? load_file : user_calendar_file);
+ if (s){
+ printf ("error: %s\n", s);
+ exit (1);
+ }
+ l = calendar_get_events_in_range (cal, from_t, to_t);
+ for (; l; l = l->next){
+ char start [80], end [80];
+ CalendarObject *co = l->data;
+ struct tm ts, te;
+ char *format;
+
+ ts = *localtime (&co->ev_start);
+ te = *localtime (&co->ev_end);
+
+ if (same_day (&today, &ts))
+ format = "%H:%M";
+ else
+ format = "%A %d, %H:%M";
+ strftime (start, sizeof (start), format, &ts);
+
+ if (!same_day (&ts, &te))
+ format = "%A %d, %H:%M";
+ strftime (end, sizeof (start), format, &te);
+
+ printf ("%s -- %s\n", start, end);
+ printf (" %s\n", co->ico->summary);
+ }
+ calendar_destroy_event_list (l);
+ calendar_destroy (cal);
+ exit (0);
+}
+
+static error_t
+parse_an_arg (int key, char *arg, struct argp_state *state)
+{
+ switch (key){
+ case 'f':
+ from_t = get_date (arg, NULL);
+ break;
+
+ case 't':
+ to_t = get_date (arg, NULL);
+ break;
+
+ case 'F':
+ load_file = arg;
+ break;
+
+ case 'e':
+ show_events = 1;
+ break;
+
+ case ARGP_KEY_END:
+ if (show_events)
+ dump_events ();
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+static struct argp parser =
+{
+ argp_options, parse_an_arg, NULL, NULL, NULL, NULL, NULL
+};
+
int
main(int argc, char *argv[])
{
@@ -366,12 +484,13 @@ main(int argc, char *argv[])
bindtextdomain(PACKAGE, GNOMELOCALEDIR);
textdomain(PACKAGE);
- gnome_init ("gncal", NULL, argc, argv, 0, NULL);
+ gnome_init ("gncal", &parser, argc, argv, 0, NULL);
+ process_dates ();
alarm_init ();
init_calendar ();
- new_calendar (full_name, user_calendar_file);
+ new_calendar (full_name, load_file ? load_file : user_calendar_file);
gtk_main ();
return 0;
}
diff --git a/calendar/gui/topic.dat b/calendar/gui/topic.dat
new file mode 100644
index 0000000000..edc7813b26
--- /dev/null
+++ b/calendar/gui/topic.dat
@@ -0,0 +1,2 @@
+gnome-cal.html Manual
+gnome-cal.html#cmdline Command line options \ No newline at end of file
diff --git a/calendar/main.c b/calendar/main.c
index cc7a0ecd85..3a657ef05e 100644
--- a/calendar/main.c
+++ b/calendar/main.c
@@ -40,6 +40,14 @@ GList *all_calendars = NULL;
static void new_calendar (char *full_name, char *calendar_file);
+/* For dumping part of a calendar */
+static time_t from_t, to_t;
+
+/* File to load instead of the user default's file */
+static char *load_file;
+
+/* If set, show events for the specified date and quit */
+static int show_events;
void
init_username (void)
@@ -263,7 +271,8 @@ save_calendar_cmd (GtkWidget *widget, void *data)
}
GnomeUIInfo gnome_cal_file_menu [] = {
- { GNOME_APP_UI_ITEM, N_("New calendar"), NULL, new_calendar_cmd },
+ { GNOME_APP_UI_ITEM, N_("New calendar"), NULL, new_calendar_cmd, NULL, NULL,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_NEW },
{ GNOME_APP_UI_ITEM, N_("Open calendar..."), NULL, open_calendar_cmd, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_OPEN },
@@ -304,6 +313,9 @@ GnomeUIInfo gnome_cal_menu [] = {
};
GnomeUIInfo gnome_toolbar [] = {
+ { GNOME_APP_UI_ITEM, N_("New"), NULL, display_objedit, 0, 0,
+ GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_PIXMAP_NEW },\
+
{ GNOME_APP_UI_ITEM, N_("Prev"), NULL, previous_clicked, 0, 0,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_BACK },
@@ -342,12 +354,11 @@ new_calendar (char *full_name, char *calendar_file)
g_free (title);
setup_menu (toplevel);
- if (calendar_file && g_file_exists (calendar_file)) {
- printf ("Trying to load %s\n", calendar_file);
+ if (calendar_file && g_file_exists (calendar_file))
gnome_calendar_load (GNOME_CALENDAR (toplevel), calendar_file);
- } else {
+ else
GNOME_CALENDAR (toplevel)->cal->filename = g_strdup (calendar_file);
- }
+
gtk_signal_connect (GTK_OBJECT (toplevel), "delete_event",
GTK_SIGNAL_FUNC(calendar_close_event), toplevel);
@@ -356,6 +367,113 @@ new_calendar (char *full_name, char *calendar_file)
gtk_widget_show (toplevel);
}
+static void
+process_dates (void)
+{
+ if (!from_t)
+ from_t = time_start_of_day (time (NULL));
+
+ if (!to_t || to_t < from_t)
+ to_t = time_add_day (from_t, 1);
+}
+
+static struct argp_option argp_options [] = {
+ { "events", 'e', NULL, 0, N_("Show events and quit"), 0 },
+ { "from ", 'f', N_("FROM"), 0, N_("Specifies start date [for --events]"), 1 },
+ { "file", 'F', N_("FILE"), 0, N_("File to load calendar from"), 1 },
+ { "to", 't', N_("TO"), 0, N_("Specifies ending date [for --events]"), 1 },
+ { NULL, 0, NULL, 0, NULL, 0 },
+};
+
+int
+same_day (struct tm *a, struct tm *b)
+{
+ return (a->tm_mday == b->tm_mday &&
+ a->tm_mon == b->tm_mon &&
+ a->tm_year == b->tm_year);
+}
+
+void
+dump_events (void)
+{
+ Calendar *cal;
+ GList *l;
+ char *s;
+ time_t now = time (NULL);
+ struct tm today = *localtime (&now);
+
+ process_dates ();
+ init_calendar ();
+
+ cal = calendar_new (full_name);
+ s = calendar_load (cal, load_file ? load_file : user_calendar_file);
+ if (s){
+ printf ("error: %s\n", s);
+ exit (1);
+ }
+ l = calendar_get_events_in_range (cal, from_t, to_t);
+ for (; l; l = l->next){
+ char start [80], end [80];
+ CalendarObject *co = l->data;
+ struct tm ts, te;
+ char *format;
+
+ ts = *localtime (&co->ev_start);
+ te = *localtime (&co->ev_end);
+
+ if (same_day (&today, &ts))
+ format = "%H:%M";
+ else
+ format = "%A %d, %H:%M";
+ strftime (start, sizeof (start), format, &ts);
+
+ if (!same_day (&ts, &te))
+ format = "%A %d, %H:%M";
+ strftime (end, sizeof (start), format, &te);
+
+ printf ("%s -- %s\n", start, end);
+ printf (" %s\n", co->ico->summary);
+ }
+ calendar_destroy_event_list (l);
+ calendar_destroy (cal);
+ exit (0);
+}
+
+static error_t
+parse_an_arg (int key, char *arg, struct argp_state *state)
+{
+ switch (key){
+ case 'f':
+ from_t = get_date (arg, NULL);
+ break;
+
+ case 't':
+ to_t = get_date (arg, NULL);
+ break;
+
+ case 'F':
+ load_file = arg;
+ break;
+
+ case 'e':
+ show_events = 1;
+ break;
+
+ case ARGP_KEY_END:
+ if (show_events)
+ dump_events ();
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+static struct argp parser =
+{
+ argp_options, parse_an_arg, NULL, NULL, NULL, NULL, NULL
+};
+
int
main(int argc, char *argv[])
{
@@ -366,12 +484,13 @@ main(int argc, char *argv[])
bindtextdomain(PACKAGE, GNOMELOCALEDIR);
textdomain(PACKAGE);
- gnome_init ("gncal", NULL, argc, argv, 0, NULL);
+ gnome_init ("gncal", &parser, argc, argv, 0, NULL);
+ process_dates ();
alarm_init ();
init_calendar ();
- new_calendar (full_name, user_calendar_file);
+ new_calendar (full_name, load_file ? load_file : user_calendar_file);
gtk_main ();
return 0;
}
diff --git a/calendar/timeutil.h b/calendar/timeutil.h
index df2862b37f..8bced60f39 100644
--- a/calendar/timeutil.h
+++ b/calendar/timeutil.h
@@ -35,6 +35,7 @@ time_t time_day_hour (time_t t, int hour);
time_t time_year_begin (int year);
time_t time_year_end (int year);
time_t time_week_begin (time_t t);
+time_t parse_date (char *str);
void print_time_t (time_t t);
diff --git a/calendar/topic.dat b/calendar/topic.dat
new file mode 100644
index 0000000000..edc7813b26
--- /dev/null
+++ b/calendar/topic.dat
@@ -0,0 +1,2 @@
+gnome-cal.html Manual
+gnome-cal.html#cmdline Command line options \ No newline at end of file