From 2cfafe8a89f446b58bc1d026f100c01c0d7cf1a9 Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Mon, 24 Aug 2009 18:59:16 +0000
Subject: Work on implementing the weekly calendar view.

---
 ChangeLog      |   9 +++
 src/calcurse.c |  12 +++-
 src/calendar.c | 198 ++++++++++++++++++++++++++++++++++++++++++---------------
 src/calendar.h |   4 +-
 4 files changed, 168 insertions(+), 55 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4dfc97e..54fa054 100755
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2009-08-24  Frederic Culot  <frederic@culot.org>
+
+	* src/calendar.c (calendar_view_next, calendar_view_prev)
+	(calendar_get_wday, draw_monthly_view, draw_weekly_view): new
+	functions to implement a weekly view inside calendar panel
+
+	* src/calcurse.c: key bindings added to switch between weekly and
+	monthly calendar views
+	
 2009-08-22  Frederic Culot  <frederic@culot.org>
 
 	* === Released 2.7 ===
diff --git a/src/calcurse.c b/src/calcurse.c
index 051008d..ee9ac7d 100755
--- a/src/calcurse.c
+++ b/src/calcurse.c
@@ -1,4 +1,4 @@
-/*	$calcurse: calcurse.c,v 1.85 2009/07/26 20:38:35 culot Exp $	*/
+/*	$calcurse: calcurse.c,v 1.86 2009/08/24 18:59:17 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -526,6 +526,16 @@ main (int argc, char **argv)
 	      calendar_move (WEEK_END);
 	    }
           break;
+
+        case KEY_GENERIC_SCROLL_UP:
+          if (wins_slctd () == CAL)
+            calendar_view_prev ();
+          break;
+
+        case KEY_GENERIC_SCROLL_DOWN:
+          if (wins_slctd () == CAL)
+            calendar_view_next ();
+          break;
           
         case KEY_GENERIC_QUIT:          
 	  if (conf.auto_save)
diff --git a/src/calendar.c b/src/calendar.c
index c626888..19e7f8e 100755
--- a/src/calendar.c
+++ b/src/calendar.c
@@ -1,4 +1,4 @@
-/*	$calcurse: calendar.c,v 1.25 2009/07/12 16:21:59 culot Exp $	*/
+/*	$calcurse: calendar.c,v 1.26 2009/08/24 18:59:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -68,11 +68,38 @@
 
 #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
 
+enum {
+  CAL_MONTH_VIEW,
+  CAL_WEEK_VIEW,
+  CAL_VIEWS
+};
+
 static date_t today, slctd_day;
-static unsigned week_begins_on_monday;
+static unsigned calendar_view, week_begins_on_monday;
 static pthread_mutex_t date_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_t calendar_t_date;
 
+static void draw_monthly_view (WINDOW *, date_t *, unsigned);
+static void draw_weekly_view (WINDOW *, date_t *, unsigned);
+static void (*draw_calendar[CAL_VIEWS]) (WINDOW *, date_t *, unsigned) =
+  {draw_monthly_view, draw_weekly_view};
+
+/* Switch between calendar views (monthly view is selected by default). */
+void
+calendar_view_next (void)
+{
+  calendar_view++;
+  if (calendar_view == CAL_VIEWS)
+    calendar_view = 0;
+}
+
+void
+calendar_view_prev (void)
+{
+  if (calendar_view == 0)
+    calendar_view = CAL_VIEWS;
+  calendar_view--;
+}
 
 /* Thread needed to update current date in calendar. */
 /* ARGSUSED0 */
@@ -188,6 +215,21 @@ calendar_get_slctd_day_sec (void)
   return (date2sec (slctd_day, 0, 0));
 }
 
+static int
+calendar_get_wday (date_t *date)
+{
+  struct tm t;
+
+  (void)memset (&t, 0, sizeof (struct tm));
+  t.tm_mday = date->dd;
+  t.tm_mon = date->mm - 1;
+  t.tm_year = date->yyyy - 1900;
+
+  (void)mktime (&t);
+
+  return t.tm_wday;
+}
+
 static int
 isBissextile (unsigned year)
 {
@@ -221,25 +263,40 @@ ymd_to_scalar (unsigned year, unsigned month, unsigned day)
   return (scalar);
 }
 
-/* Function used to display the calendar panel. */
-void
-calendar_update_panel (WINDOW *cwin)
+/* 
+ * Used to change date by adding a certain amount of days or weeks.
+ * Returns 0 on success, 1 otherwise.
+ */
+static int
+date_change (struct tm *date, int delta_month, int delta_day)
 {
-  date_t current_day, check_day;
+  struct tm t;
+
+  t = *date;
+  t.tm_mon += delta_month;
+  t.tm_mday += delta_day;
+
+  if (mktime (&t) == -1)
+    return (1);
+  else
+    {
+      *date = t;
+      return (0);
+    }
+}
+
+/* Draw the monthly view inside calendar panel. */
+static void
+draw_monthly_view (WINDOW *cwin, date_t *current_day, unsigned sunday_first)
+{
+  date_t check_day;
   int c_day, c_day_1, day_1_sav, numdays, j;
   unsigned yr, mo;
   int ofs_x, ofs_y;
   int item_this_day = 0;
-  int title_lines = 3;
-  int sunday_first = 0;
 
-  /* inits */
-  calendar_store_current_date (&current_day);
-  erase_window_part (cwin, 1, title_lines, CALWIDTH - 2, CALHEIGHT - 2);
   mo = slctd_day.mm;
   yr = slctd_day.yyyy;
-  if (!calendar_week_begins_on_monday ())
-    sunday_first = 1;
 
   /* offset for centering calendar in window */
   ofs_y = 2 + (CALHEIGHT - 9) / 2;
@@ -265,7 +322,7 @@ calendar_update_panel (WINDOW *cwin)
 
   /* print the days, with regards to the first day of the week */
   custom_apply_attr (cwin, ATTR_HIGHEST);
-  for (j = 0; j < 7; j++)
+  for (j = 0; j < WEEKINDAYS; j++)
     {
       mvwprintw (cwin, ofs_y, ofs_x + 4 * j, "%s",
 		 _(daynames[1 + j - sunday_first]));
@@ -291,19 +348,17 @@ calendar_update_panel (WINDOW *cwin)
 	}
 
       /* This is today, so print it in yellow. */
-      if (c_day == current_day.dd && current_day.mm == slctd_day.mm
-	  && current_day.yyyy == slctd_day.yyyy
-	  && current_day.dd != slctd_day.dd)
+      if (c_day == current_day->dd
+          && current_day->mm == slctd_day.mm
+          && current_day->yyyy == slctd_day.yyyy
+          && current_day->dd != slctd_day.dd)
 	{
 	  custom_apply_attr (cwin, ATTR_LOWEST);
 	  mvwprintw (cwin, ofs_y + 1,
 		     ofs_x + day_1_sav + 4 * c_day + 1, "%2d", c_day);
 	  custom_remove_attr (cwin, ATTR_LOWEST);
 	}
-      else if (c_day == slctd_day.dd &&
-	       ((current_day.dd != slctd_day.dd)
-		|| (current_day.mm != slctd_day.mm)
-		|| (current_day.yyyy != slctd_day.yyyy)))
+      else if (c_day == slctd_day.dd)
 	{
 	  /* This is the selected day, print it according to user's theme. */
 	  custom_apply_attr (cwin, ATTR_HIGHEST);
@@ -311,16 +366,6 @@ calendar_update_panel (WINDOW *cwin)
                      c_day);
 	  custom_remove_attr (cwin, ATTR_HIGHEST);
 	}
-      else if (c_day == slctd_day.dd && current_day.dd == slctd_day.dd
-	       && current_day.mm == slctd_day.mm
-	       && current_day.yyyy == slctd_day.yyyy)
-	{
-	  /* today is the selected day */
-	  custom_apply_attr (cwin, ATTR_HIGHEST);
-	  mvwprintw (cwin, ofs_y + 1, ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
-                     c_day);
-	  custom_remove_attr (cwin, ATTR_HIGHEST);
-	}
       else if (item_this_day)
 	{
 	  custom_apply_attr (cwin, ATTR_LOW);
@@ -333,6 +378,75 @@ calendar_update_panel (WINDOW *cwin)
 	mvwprintw (cwin, ofs_y + 1, ofs_x + day_1_sav + 4 * c_day + 1, "%2d",
                    c_day);
     }
+}
+
+/* Draw the weekly view inside calendar panel. */
+static void
+draw_weekly_view (WINDOW *cwin, date_t *current_day, unsigned sunday_first)
+{
+  int j, c_wday, days_to_remove;
+  struct tm t;
+
+  /* Fill in a tm structure with the first day of the selected week. */
+  c_wday = calendar_get_wday (&slctd_day);
+  if (sunday_first)
+    days_to_remove = c_wday;
+  else
+    days_to_remove = c_wday == 0 ? WEEKINDAYS - 1 : c_wday - 1;
+  
+  (void)memset (&t, 0, sizeof (struct tm));
+  t.tm_mday = slctd_day.dd;
+  t.tm_mon = slctd_day.mm - 1;
+  t.tm_year = slctd_day.yyyy - 1900;
+  (void)mktime (&t);
+  (void)date_change (&t, 0, -days_to_remove);
+
+  /* Now draw calendar view. */
+  for (j = 0; j < WEEKINDAYS; j++)
+    {
+      unsigned attr;
+      
+      /* print the day names, with regards to the first day of the week */
+      custom_apply_attr (cwin, ATTR_HIGHEST);      
+      mvwprintw (cwin, 3, 1 + 4 * j, "%s",
+		 _(daynames[1 + j - sunday_first]));
+      custom_remove_attr (cwin, ATTR_HIGHEST);
+      
+      /* Print the day numbers with appropriate decoration. */
+      if (t.tm_mday == current_day->dd
+          && current_day->mm == slctd_day.mm
+          && current_day->yyyy == slctd_day.yyyy
+          && current_day->dd != slctd_day.dd)
+        attr = ATTR_LOWEST;               /* today, but not selected */
+      else if (t.tm_mday == slctd_day.dd)
+        attr = ATTR_HIGHEST;              /* selected day */
+      else
+        attr = 0;
+
+      if (attr)
+        custom_apply_attr (cwin, attr);
+      mvwprintw (cwin, 4, 2 + 4 * j, "%02d", t.tm_mday);
+      if (attr)
+        custom_remove_attr (cwin, attr);
+      
+      /* get next day */
+      (void)date_change (&t, 0, 1);
+    }
+}
+
+/* Function used to display the calendar panel. */
+void
+calendar_update_panel (WINDOW *cwin)
+{
+  date_t current_day;
+  unsigned sunday_first;
+
+  calendar_store_current_date (&current_day);
+  erase_window_part (cwin, 1, 3, CALWIDTH - 2, CALHEIGHT - 2);
+  sunday_first = calendar_week_begins_on_monday () ? 0 : 1;
+
+  draw_calendar[calendar_view] (cwin, &current_day, sunday_first);
+
   wnoutrefresh (cwin);
 }
 
@@ -404,28 +518,6 @@ calendar_change_day (int datefmt)
   return;
 }
 
-/* 
- * Used to change date by adding a certain amount of days or weeks.
- * Returns 0 on success, 1 otherwise.
- */
-static int
-date_change (struct tm *date, int delta_month, int delta_day)
-{
-  struct tm t;
-
-  t = *date;
-  t.tm_mon += delta_month;
-  t.tm_mday += delta_day;
-
-  if (mktime (&t) == -1)
-    return (1);
-  else
-    {
-      *date = t;
-      return (0);
-    }
-}
-
 void
 calendar_move (move_t move)
 {
diff --git a/src/calendar.h b/src/calendar.h
index 406eed6..0269f55 100755
--- a/src/calendar.h
+++ b/src/calendar.h
@@ -1,4 +1,4 @@
-/*	$calcurse: calendar.h,v 1.15 2009/07/12 16:21:59 culot Exp $	*/
+/*	$calcurse: calendar.h,v 1.16 2009/08/24 18:59:18 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -102,6 +102,8 @@ typedef enum
 }
 move_t;
 
+void       calendar_view_next (void);
+void       calendar_view_prev (void);
 void       calendar_start_date_thread (void);
 void       calendar_stop_date_thread (void);
 void       calendar_set_current_date (void);
-- 
cgit v1.2.3-70-g09d2