From a2fe228ebeb7f24573f3bc9bc63b71e91c5350f2 Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Wed, 6 Aug 2008 17:44:34 +0000
Subject: new command line options added (thanks Erik for the patch)

---
 src/args.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++----------
 src/io.c   | 118 +++++++++++++++++++++-----------------
 src/io.h   |   4 +-
 src/vars.h |  16 ++++--
 4 files changed, 237 insertions(+), 91 deletions(-)

(limited to 'src')

diff --git a/src/args.c b/src/args.c
index 0b5395d..c345da7 100755
--- a/src/args.c
+++ b/src/args.c
@@ -1,4 +1,4 @@
-/*	$calcurse: args.c,v 1.34 2008/04/20 12:54:05 culot Exp $	*/
+/*	$calcurse: args.c,v 1.35 2008/08/06 17:44:34 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -48,8 +48,9 @@ static void
 usage ()
 {
   char *arg_usage =
-    _("Usage: calcurse [-h|-v] [-x] [-N] [-an] [-t[num]] [-d date|num] "
-      "[-c file]\n");
+    _("Usage: calcurse [-h|-v] [-x] [-N] [-an] [-t[num]]\n"
+      "                [-d <date>|<num>] [-s[date]] [-r[range]]\n"
+      "                [-c<file> | -D<dir>]\n");
   fputs (arg_usage, stdout);
 }
 
@@ -91,20 +92,30 @@ help_arg ()
       "	print calcurse version and exit.\n"
       "\nFiles:\n"
       "  -c <file>, --calendar <file>\n"
-      "	specify the calendar <file> to use.\n"
+      "	specify the calendar <file> to use (incompatible with '-D').\n"
+      "\n  -D <dir>, --directory <dir>\n"
+      "	specify the data directory to use (incompatible with '-c').\n"
+      "\tIf not specified, the default directory is ~/.calcurse\n"
       "\nNon-interactive:\n"
       "  -a, --appointment\n"
       " 	print events and appointments for current day and exit.\n"
       "\n  -d <date|num>, --day <date|num>\n"
       "	print events and appointments for <date> or <num> upcoming days and"
-      "\n\texit. Possible formats are: 'mm/dd/yyyy' or 'n'.\n"
+      "\n\texit. To specify both a starting date and a range, use the\n"
+      "\t'--startday' and the '--range' option.\n"
       "\n  -n, --next\n"
-      "  	print next appointment within upcoming 24 hours "
+      "	print next appointment within upcoming 24 hours "
       "and exit. Also given\n\tis the remaining time before this "
       "next appointment.\n"
       "\n  -N, --note\n"
       "	when used with the '-a' or '-t' flag, also print note content\n"
       "	if one is associated with the displayed item.\n"
+      "\n  -r[num], --range[=num]\n"
+      "	print events and appointments for the [num] number of days"
+      "\n\tand exit. If no [num] is given, a range of 1 day is considered.\n"
+      "\n  -s[date], --startday[=date]\n"
+      "	print events and appointments from [date] and exit.\n"
+      "\tIf no [date] is given, the current day is considered.\n"
       "\n  -t[num], --todo[=num]\n"
       "	print todo list and exit. If the optional number [num] is given,\n"
       "\tthen only todos having a priority equal to [num] will be returned.\n"
@@ -388,6 +399,40 @@ app_arg (int add_line, date_t *day, long date, int print_note, conf_t *conf)
   return (app_found);
 }
 
+static void
+more_info (void)
+{
+  fputs (_("\nFor more information, type '?' from within Calcurse, "
+           "or read the manpage.\n"), stdout);
+  fputs (_("Mail bug reports and suggestions to "
+           "<calcurse@culot.org>.\n"), stdout);
+}
+
+/* 
+ * For a given date, print appointments for each day
+ * in the chosen interval. app_found and add_line are used
+ * to format the output correctly. 
+ */
+static void
+display_app (struct tm *t, int numdays, int add_line, int print_note,
+             conf_t *conf)
+{
+  int i, app_found;
+  date_t day;
+
+  for (i = 0; i < numdays; i++)
+    {
+      day.dd = t->tm_mday;
+      day.mm = t->tm_mon + 1;
+      day.yyyy = t->tm_year + 1900;
+      app_found = app_arg (add_line, &day, 0, print_note, conf);
+      if (app_found)
+        add_line = 1;
+      t->tm_mday++;
+      mktime (t);
+    }
+}
+
 /*
  * Print appointment for the given date or for the given n upcoming
  * days.
@@ -424,18 +469,7 @@ date_arg (char *ddate, int add_line, int print_note, conf_t *conf)
        */
       timer = time (NULL);
       t = *localtime (&timer);
-
-      for (i = 0; i < numdays; i++)
-	{
-	  day.dd = t.tm_mday;
-	  day.mm = t.tm_mon + 1;
-	  day.yyyy = t.tm_year + 1900;
-	  app_found = app_arg (add_line, &day, 0, print_note, conf);
-	  if (app_found)
-	    add_line = 1;
-	  t.tm_mday++;
-	  mktime (&t);
-	}
+      display_app (&t, numdays, add_line, print_note, conf);
     }
   else
     {				/* a date was entered */
@@ -446,21 +480,81 @@ date_arg (char *ddate, int add_line, int print_note, conf_t *conf)
 	}
       else
 	{
-	  fputs (_("Argument to the '-d' flag is not valid\n"), stdout);
 	  char outstr[BUFSIZ];
+	  fputs (_("Argument to the '-d' flag is not valid\n"), stderr);
 	  snprintf (outstr, BUFSIZ,
 		    "Possible argument format are: '%s' or 'n'\n",
 		    DATEFMT_DESC (conf->input_datefmt));
 	  fputs (_(outstr), stdout);
-	  fputs (_("\nFor more information, type '?' from within Calcurse, "
-                   "or read the manpage.\n"),
-		 stdout);
-	  fputs (_("Mail bug reports and suggestions to "
-                   "<calcurse@culot.org>.\n"), stdout);
+          more_info ();
 	}
     }
 }
 
+/*
+ * Print appointment from the given date 'startday' for the 'range' upcoming
+ * days. 
+ * If no starday is given (NULL), today is considered
+ * If no range is given (NULL), 1 day is considered
+ *
+ * Many thanks to Erik Saule for providing this function.
+ */
+static void
+date_arg_extended (char *startday, char *range, int add_line, int print_note,
+                   conf_t *conf)
+{
+  int i, numdays = 1, error = 0, arg_len = 0;
+  static struct tm t;
+  time_t timer;
+
+  /* 
+   * Check arguments and extract information
+   */
+  if (range != NULL)
+    {
+      arg_len = strlen (range);
+      for (i = 0; i <= arg_len - 1; i++)
+	{
+	  if (!isdigit (range[i]))
+	    error = 1;
+	}
+      if (!error)
+	numdays = atoi (range);
+    }
+  timer = time (NULL);
+  t = *localtime (&timer);
+  if (startday != NULL)
+    {
+      if (parse_date (startday, conf->input_datefmt, (int *)&t.tm_year,
+		      (int *)&t.tm_mon, (int *)&t.tm_mday))
+	{
+	  t.tm_year -= 1900;
+	  t.tm_mon--;
+	  mktime (&t);
+	}
+      else
+	{
+	  error = 1;
+	}
+    }
+  if (!error)
+    {
+      display_app (&t, numdays, add_line, print_note, conf);
+    }
+  else
+    {
+      char outstr[BUFSIZ];
+      fputs (_("Argument is not valid\n"), stderr);
+      snprintf (outstr, BUFSIZ,
+		"Argument format for -s and --startday is: '%s'\n",
+		DATEFMT_DESC (conf->input_datefmt));
+      fputs (_(outstr), stdout);
+      fputs (_("Argument format for -r and --range is: 'n'\n"), stdout);
+      more_info ();
+    }
+}
+
+
 /* 
  * Parse the command-line arguments and call the appropriate
  * routines to handle those arguments. Also initialize the data paths.
@@ -474,9 +568,12 @@ parse_args (int argc, char **argv, conf_t *conf)
   int aflag = 0;    /* -a: print appointments for current day */
   int cflag = 0;    /* -c: specify the calendar file to use */
   int dflag = 0;    /* -d: print appointments for a specified days */
+  int Dflag = 0;    /* -D: specify data directory to use */
   int hflag = 0;    /* -h: print help text */
   int nflag = 0;    /* -n: print next appointment */
   int Nflag = 0;    /* -N: also print note content with apps and todos */
+  int rflag = 0;    /* -r: specify the range of days to consider */
+  int sflag = 0;    /* -s: specify the first day to consider */
   int tflag = 0;    /* -t: print todo list */
   int vflag = 0;    /* -v: print version number */
   int xflag = 0;    /* -x: export data to iCalendar format */
@@ -484,17 +581,21 @@ parse_args (int argc, char **argv, conf_t *conf)
   int tnum = 0;
   int non_interactive = 0, multiple_flag = 0, load_data = 0;
   int no_file = 1;
-  char *ddate = "", *cfile = NULL;
+  char *ddate = "", *cfile = NULL, *range = NULL, *startday = NULL;
+  char *datadir = NULL;
 
-  static char *optstr = "hvnNaxt::d:c:";
+  static char *optstr = "hvnNaxt::d:c:r:s:D:";
 
   struct option longopts[] = {
     {"appointment", no_argument, NULL, 'a'},
     {"calendar", required_argument, NULL, 'c'},
     {"day", required_argument, NULL, 'd'},
+    {"directory", required_argument, NULL, 'D'},
     {"help", no_argument, NULL, 'h'},
     {"next", no_argument, NULL, 'n'},
     {"note", no_argument, NULL, 'N'},
+    {"range", required_argument, NULL, 'r'},
+    {"startday", required_argument, NULL, 's'},
     {"todo", optional_argument, NULL, 't'},
     {"version", no_argument, NULL, 'v'},
     {"export", no_argument, NULL, 'x'},
@@ -522,6 +623,10 @@ parse_args (int argc, char **argv, conf_t *conf)
 	  load_data++;
 	  ddate = optarg;
 	  break;
+        case 'D':
+          Dflag = 1;
+          datadir = optarg;
+          break;
 	case 'h':
 	  hflag = 1;
 	  break;
@@ -533,6 +638,18 @@ parse_args (int argc, char **argv, conf_t *conf)
 	case 'N':
 	  Nflag = 1;
 	  break;
+        case 'r':
+          rflag = 1;
+          multiple_flag++;
+          load_data++;
+          range = optarg;
+          break;
+        case 's':
+          sflag = 1;
+          multiple_flag++;
+          load_data++;
+          startday = optarg;
+          break;
 	case 't':
 	  tflag = 1;
 	  multiple_flag++;
@@ -577,6 +694,14 @@ parse_args (int argc, char **argv, conf_t *conf)
       return (EXIT_FAILURE);
       /* Incorrect arguments */
     }
+  else if (Dflag && cflag)
+    {
+      fputs (_("Options '-D' and '-c' cannot be used at the same time\n"),
+               stderr);
+      usage ();
+      usage_try ();
+      return (EXIT_FAILURE);
+    }
   else
     {
       if (unknown_flag)
@@ -597,9 +722,9 @@ parse_args (int argc, char **argv, conf_t *conf)
 	{
 	  if (load_data)
 	    {
-	      io_init (cfile);
+	      io_init (cfile, datadir);
 	      no_file = io_check_data_files ();
-	      if (dflag || aflag || nflag || xflag)
+	      if (dflag || aflag || nflag || xflag || rflag || sflag)
 		io_load_app ();
 	    }
 	  if (xflag)
@@ -620,12 +745,15 @@ parse_args (int argc, char **argv, conf_t *conf)
 	      next_arg ();
 	      non_interactive = 1;
 	    }
-	  if (dflag)
+	  if (dflag || rflag || sflag)
 	    {
 	      notify_init_vars ();
 	      vars_init (conf);
 	      custom_load_conf (conf, 0);
-	      date_arg (ddate, add_line, Nflag, conf);
+              if (dflag)
+                date_arg (ddate, add_line, Nflag, conf);
+              if (rflag || sflag)
+                date_arg_extended (startday, range, add_line, Nflag, conf);
 	      non_interactive = 1;
 	    }
 	  else if (aflag)
@@ -642,7 +770,7 @@ parse_args (int argc, char **argv, conf_t *conf)
       else
 	{
 	  non_interactive = 0;
-	  io_init (cfile);
+	  io_init (cfile, datadir);
 	  no_file = io_check_data_files ();
 	}
       return (non_interactive);
diff --git a/src/io.c b/src/io.c
index 07efe6f..792a243 100755
--- a/src/io.c
+++ b/src/io.c
@@ -1,4 +1,4 @@
-/*	$calcurse: io.c,v 1.29 2008/04/12 21:14:03 culot Exp $	*/
+/*	$calcurse: io.c,v 1.30 2008/08/06 17:44:34 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -328,72 +328,86 @@ io_export_todo (FILE *stream)
 }
 
 /* 
- * Initialization of data paths. The argument cfile is the variable
+ * Initialization of data paths. The cfile argument is the variable
  * which contains the calendar file. If none is given, then the default
  * one (~/.calcurse/apts) is taken. If the one given does not exist, it
  * is created.
+ * The datadir argument can be use to specify an alternative data root dir.
  */
 void
-io_init (char *cfile)
+io_init (char *cfile, char *datadir)
 {
   FILE *data_file;
   char *home;
   char apts_file[BUFSIZ] = "";
   int ch;
 
-  home = getenv ("HOME");
-  if (home == NULL)
+  if (datadir != NULL)
     {
-      home = ".";
-    }
-  snprintf (path_dir, BUFSIZ, "%s/" DIR_NAME, home);
-  snprintf (path_todo, BUFSIZ, "%s/" TODO_PATH, home);
-  snprintf (path_conf, BUFSIZ, "%s/" CONF_PATH, home);
-  snprintf (path_notes, BUFSIZ, "%s/" NOTES_DIR, home);
-  if (cfile == NULL)
-    {
-      snprintf (path_apts, BUFSIZ, "%s/" APTS_PATH, home);
+      home = datadir;
+      snprintf (path_dir, BUFSIZ, "%s", home);
+      snprintf (path_todo, BUFSIZ, "%s/" TODO_PATH_NAME, home);
+      snprintf (path_conf, BUFSIZ, "%s/" CONF_PATH_NAME, home);
+      snprintf (path_notes, BUFSIZ, "%s/" NOTES_DIR_NAME, home);
+      snprintf (path_apts, BUFSIZ, "%s/" APTS_PATH_NAME, home);
     }
   else
     {
-      snprintf (apts_file, BUFSIZ, "%s", cfile);
-      strncpy (path_apts, apts_file, BUFSIZ);
-      /* check if the file exists, otherwise create it */
-      data_file = fopen (path_apts, "r");
-      if (data_file == NULL)
-	{
-	  printf (_("%s does not exist, create it now [y or n] ? "), path_apts);
-	  ch = getchar ();
-	  switch (ch)
-	    {
-	    case 'N':
-	    case 'n':
-	      printf (_("aborting...\n"));
-	      exit (EXIT_FAILURE);
-	      break;
-
-	    case 'Y':
-	    case 'y':
-	      data_file = fopen (path_apts, "w");
-	      if (data_file == NULL)
-		{
-		  perror (path_apts);
-		  exit (EXIT_FAILURE);
-		}
-	      else
-		{
-		  printf (_("%s successfully created\n"), path_apts);
-		  printf (_("starting interactive mode...\n"));
-		}
-	      break;
-
-	    default:
-	      printf (_("aborting...\n"));
-	      exit (EXIT_FAILURE);
-	      break;
-	    }
-	}
-      fclose (data_file);
+      home = getenv ("HOME");
+      if (home == NULL)
+        {
+          home = ".";
+        }
+      snprintf (path_dir, BUFSIZ, "%s", home);
+      snprintf (path_todo, BUFSIZ, "%s/" TODO_PATH, home);
+      snprintf (path_conf, BUFSIZ, "%s/" CONF_PATH, home);
+      snprintf (path_notes, BUFSIZ, "%s/" NOTES_DIR, home);
+      if (cfile == NULL)
+        {
+          snprintf (path_apts, BUFSIZ, "%s/" APTS_PATH, home);
+        }
+      else
+        {
+          snprintf (apts_file, BUFSIZ, "%s", cfile);
+          strncpy (path_apts, apts_file, BUFSIZ);
+          /* check if the file exists, otherwise create it */
+          data_file = fopen (path_apts, "r");
+          if (data_file == NULL)
+            {
+              printf (_("%s does not exist, create it now [y or n] ? "),
+                      path_apts);
+              ch = getchar ();
+              switch (ch)
+                {
+                case 'N':
+                case 'n':
+                  printf (_("aborting...\n"));
+                  exit (EXIT_FAILURE);
+                  break;
+
+                case 'Y':
+                case 'y':
+                  data_file = fopen (path_apts, "w");
+                  if (data_file == NULL)
+                    {
+                      perror (path_apts);
+                      exit (EXIT_FAILURE);
+                    }
+                  else
+                    {
+                      printf (_("%s successfully created\n"), path_apts);
+                      printf (_("starting interactive mode...\n"));
+                    }
+                  break;
+
+                default:
+                  printf (_("aborting...\n"));
+                  exit (EXIT_FAILURE);
+                  break;
+                }
+            }
+          fclose (data_file);
+        }
     }
 }
 
diff --git a/src/io.h b/src/io.h
index ebaa193..7578c11 100755
--- a/src/io.h
+++ b/src/io.h
@@ -1,4 +1,4 @@
-/*	$calcurse: io.h,v 1.9 2008/04/12 21:14:03 culot Exp $	*/
+/*	$calcurse: io.h,v 1.10 2008/08/06 17:44:34 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -37,7 +37,7 @@ typedef enum
 }
 export_mode_t;
 
-void io_init (char *);
+void io_init (char *, char *);
 void io_extract_data (char *, const char *, int);
 void io_save_cal (conf_t *);
 void io_load_app (void);
diff --git a/src/vars.h b/src/vars.h
index 6b06705..ba00cb4 100755
--- a/src/vars.h
+++ b/src/vars.h
@@ -1,4 +1,4 @@
-/*	$calcurse: vars.h,v 1.22 2008/04/12 21:14:03 culot Exp $	*/
+/*	$calcurse: vars.h,v 1.23 2008/08/06 17:44:34 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -31,11 +31,15 @@
 #include <pthread.h>
 #include <stdbool.h>
 
-#define DIR_NAME	".calcurse"
-#define TODO_PATH 	".calcurse/todo"
-#define APTS_PATH	".calcurse/apts"
-#define CONF_PATH	".calcurse/conf"
-#define NOTES_DIR	".calcurse/notes/"
+#define DIR_NAME         ".calcurse/"
+#define TODO_PATH_NAME   "todo"
+#define APTS_PATH_NAME   "apts"
+#define CONF_PATH_NAME   "conf"
+#define NOTES_DIR_NAME   "notes/"
+#define TODO_PATH        DIR_NAME TODO_PATH_NAME
+#define APTS_PATH        DIR_NAME APTS_PATH_NAME
+#define CONF_PATH        DIR_NAME CONF_PATH_NAME
+#define NOTES_DIR        DIR_NAME NOTES_DIR_NAME
 
 #define CTRL(x)         ((x) & 0x1f)
 #define ESCAPE		27
-- 
cgit v1.2.3-70-g09d2