From 6892b596222bdc5b2c0757a8f6cc79bcf2691d1a Mon Sep 17 00:00:00 2001
From: Frederic Culot <calcurse@culot.org>
Date: Sun, 21 Mar 2010 10:17:03 +0000
Subject: Avoid concurrent screen refreshes.

---
 src/calcurse.h |  5 +++-
 src/custom.c   | 18 ++++++-------
 src/help.c     |  4 +--
 src/io.c       | 12 ++++-----
 src/notify.c   |  4 +--
 src/utils.c    | 21 ++++++++-------
 src/wins.c     | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 7 files changed, 107 insertions(+), 37 deletions(-)

(limited to 'src')

diff --git a/src/calcurse.h b/src/calcurse.h
index fa18b56..6085f53 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -1,4 +1,4 @@
-/*	$Id: calcurse.h,v 1.3 2010/03/21 09:21:07 culot Exp $	*/
+/*	$Id: calcurse.h,v 1.4 2010/03/21 10:17:03 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -897,6 +897,9 @@ void vars_init (struct conf *);
 
 /* wins.c */
 extern struct window win[NBWINS];
+int       wins_refresh (void);
+int       wins_wrefresh (WINDOW *);
+int       wins_doupdate (void);
 int       wins_layout (void);
 void      wins_set_layout (int);
 unsigned  wins_sbar_width (void);
diff --git a/src/custom.c b/src/custom.c
index 007c71b..e6d547d 100755
--- a/src/custom.c
+++ b/src/custom.c
@@ -1,4 +1,4 @@
-/*	$calcurse: custom.c,v 1.48 2010/03/21 09:21:07 culot Exp $	*/
+/*	$calcurse: custom.c,v 1.49 2010/03/21 10:17:03 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -250,7 +250,7 @@ custom_load_conf (struct conf *conf, int background)
     {
       status_mesg (mesg_line1, mesg_line2);
       wnoutrefresh (win[STA].p);
-      doupdate ();
+      wins_doupdate ();
       (void)keys_getch (win[STA].p);
     }
   var = CUSTOM_CONF_NOVARIABLE;
@@ -432,7 +432,7 @@ custom_config_bar (void)
   
   wnoutrefresh (win[STA].p);
   wmove (win[STA].p, 0, 0);
-  doupdate ();
+  wins_doupdate ();
 }
 
 static void
@@ -518,7 +518,7 @@ display_layout_config (struct window *lwin, int mark, int cursor,
   layout_selection_bar ();
   wnoutrefresh (win[STA].p);
   wnoutrefresh (lwin->p);
-  doupdate ();
+  wins_doupdate ();
   if (notify_bar ())
     notify_update_bar ();
 }
@@ -552,7 +552,7 @@ custom_layout_config (void)
 	{
 	case KEY_RESIZE:
 	  endwin ();
-	  refresh ();
+	  wins_refresh ();
 	  curs_set (0);
 	  need_reset = 1;
 	  break;
@@ -611,7 +611,7 @@ custom_sidebar_config (void)
   binding_size = sizeof (binding) / sizeof (binding[0]);
 
   keys_display_bindings_bar (win[STA].p, binding, 0, binding_size);
-  doupdate ();
+  wins_doupdate ();
 
   while ((ch = keys_getch (win[STA].p)) != KEY_GENERIC_QUIT)  
     {
@@ -641,7 +641,7 @@ custom_sidebar_config (void)
           wins_update_border ();
           wins_update_panels ();
           keys_display_bindings_bar (win[STA].p, binding, 0, binding_size);
-          doupdate ();
+          wins_doupdate ();
           need_update = 0;
         }
     }
@@ -828,7 +828,7 @@ display_color_config (struct window *cwin, int *mark_fore, int *mark_back,
   color_selection_bar ();
   wnoutrefresh (win[STA].p);
   wnoutrefresh (cwin->p);
-  doupdate ();
+  wins_doupdate ();
   if (notify_bar ())
     notify_update_bar ();
 }
@@ -861,7 +861,7 @@ custom_color_config (void)
 	{
 	case KEY_RESIZE:
 	  endwin ();
-	  refresh ();
+	  wins_refresh ();
 	  curs_set (0);
 	  need_reset = 1;
 	  break;
diff --git a/src/help.c b/src/help.c
index e4f7d48..f3b2209 100755
--- a/src/help.c
+++ b/src/help.c
@@ -1,4 +1,4 @@
-/*	$calcurse: help.c,v 1.43 2010/03/20 10:54:45 culot Exp $	*/
+/*	$calcurse: help.c,v 1.44 2010/03/21 10:17:03 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -185,7 +185,7 @@ static void
 help_wins_reset (struct scrollwin *hwin)
 {
   endwin ();
-  refresh ();
+  wins_refresh ();
   curs_set (0);
   delwin (win[STA].p);
   help_wins_reinit (hwin);
diff --git a/src/io.c b/src/io.c
index 79ca3c0..271f0e6 100755
--- a/src/io.c
+++ b/src/io.c
@@ -1,4 +1,4 @@
-/*	$calcurse: io.c,v 1.82 2010/03/21 09:21:07 culot Exp $	*/
+/*	$calcurse: io.c,v 1.83 2010/03/21 10:17:04 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -194,7 +194,7 @@ progress_bar (progress_bar_t type, int progress)
     mvwaddch (win[STA].p, 1, i, ' ' | A_REVERSE);
   custom_remove_attr (win[STA].p, ATTR_HIGHEST);
   wmove (win[STA].p, 0, 0);
-  wrefresh (win[STA].p);
+  wins_wrefresh (win[STA].p);
   (void)usleep (SLEEPTIME);
 #undef SLEEPTIME
 #undef NBFILES
@@ -805,12 +805,12 @@ display_mark (void)
   
   custom_apply_attr (mwin, ATTR_HIGHEST);
   mvwprintw (mwin, 0, 0, "**");
-  wrefresh (mwin);
+  wins_wrefresh (mwin);
   sleep (DISPLAY_TIME);
   mvwprintw (mwin, 0, 0, "  ");
-  wrefresh (mwin);  
+  wins_wrefresh (mwin);  
   delwin (mwin);
-  doupdate ();
+  wins_doupdate ();
 }
 
 static pthread_mutex_t io_save_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -1677,7 +1677,7 @@ io_export_bar (void)
 
   wnoutrefresh (win[STA].p);
   wmove (win[STA].p, 0, 0);
-  doupdate ();
+  wins_doupdate ();
 }
 
 /* Print a header to describe import log report format. */
diff --git a/src/notify.c b/src/notify.c
index 1695faf..c36a2be 100755
--- a/src/notify.c
+++ b/src/notify.c
@@ -1,4 +1,4 @@
-/*	$calcurse: notify.c,v 1.49 2010/03/20 10:54:47 culot Exp $	*/
+/*	$calcurse: notify.c,v 1.50 2010/03/21 10:17:04 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -318,7 +318,7 @@ notify_update_bar (void)
 
   wattroff (notify.win, A_UNDERLINE | A_REVERSE);
   custom_remove_attr (notify.win, ATTR_HIGHEST);
-  wrefresh (notify.win);
+  wins_wrefresh (notify.win);
 
   pthread_mutex_unlock (&notify.mutex);
 }
diff --git a/src/utils.c b/src/utils.c
index ce976e6..0015c60 100755
--- a/src/utils.c
+++ b/src/utils.c
@@ -1,4 +1,4 @@
-/*	$calcurse: utils.c,v 1.83 2010/03/20 10:54:49 culot Exp $	*/
+/*	$calcurse: utils.c,v 1.84 2010/03/21 10:17:04 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -57,7 +57,7 @@ exit_calcurse (int status)
     {
       notify_stop_main_thread ();
       clear ();
-      refresh ();
+      wins_refresh ();
       endwin ();
       ui_mode = UI_CMDLINE;
       was_interactive = 1;
@@ -121,10 +121,10 @@ fatalbox (const char *errmsg)
   mvwprintw (errwin, 3, 1, reportmsg);
   mvwprintw (errwin, 5, (WINCOL - strlen (msg)) / 2, "%s", msg);
   custom_remove_attr (errwin, ATTR_HIGHEST);
-  wrefresh (errwin);
+  wins_wrefresh (errwin);
   (void)wgetch (errwin);
   delwin (errwin);
-  doupdate ();
+  wins_doupdate ();
 }
 
 void
@@ -147,10 +147,10 @@ warnbox (const char *msg)
   wins_show (warnwin, label);
   mvwprintw (warnwin, 5, (WINCOL - strlen (displmsg)) / 2, "%s", displmsg);
   custom_remove_attr (warnwin, ATTR_HIGHEST);
-  wrefresh (warnwin);
+  wins_wrefresh (warnwin);
   (void)wgetch (warnwin);
   delwin (warnwin);
-  doupdate ();
+  wins_doupdate ();
 }
 
 /* 
@@ -206,8 +206,7 @@ popup (int pop_row, int pop_col, int pop_y, int pop_x, char *title, char *msg,
     mvwprintw (popup_win, pop_row - 2, pop_col - (strlen (any_key) + 1), "%s",
                any_key);
   custom_remove_attr (popup_win, ATTR_HIGHEST);
-  wrefresh (popup_win);
-  doupdate ();
+  wins_wrefresh (popup_win);
   
   return popup_win;
 }
@@ -409,7 +408,7 @@ getstring (WINDOW *win, char *str, int l, int x, int y)
 
 	}
       showstring (win, y, x, orig, len, newpos);
-      doupdate ();
+      wins_doupdate ();
     }
   *str = 0;
   custom_remove_attr (win, ATTR_HIGHEST);
@@ -726,7 +725,7 @@ item_in_popup (char *saved_a_start, char *saved_a_end, char *msg,
   mvwprintw (pad, 0, margin_left, "%s", msg);
   wmove (win[STA].p, 0, 0);
   pnoutrefresh (pad, 0, 0, margin_top + 2, margin_left, padl, winw);
-  doupdate ();
+  wins_doupdate ();
   (void)wgetch (popup_win);
   delwin (pad);
   delwin (popup_win);
@@ -813,7 +812,7 @@ print_bool_option_incolor (WINDOW *win, unsigned option, int pos_y, int pos_x)
   mvwprintw (win, pos_y, pos_x, "%s", option_value);
   custom_remove_attr (win, color);
   wnoutrefresh (win);
-  doupdate ();
+  wins_doupdate ();
 }
 
 /* 
diff --git a/src/wins.c b/src/wins.c
index 8cdd9da..cfe1050 100755
--- a/src/wins.c
+++ b/src/wins.c
@@ -1,4 +1,4 @@
-/*	$calcurse: wins.c,v 1.31 2010/03/21 09:21:07 culot Exp $	*/
+/*	$calcurse: wins.c,v 1.32 2010/03/21 10:17:04 culot Exp $	*/
 
 /*
  * Calcurse - text-based organizer
@@ -51,6 +51,74 @@ static unsigned sbarwidth;
 static enum win slctd_win;
 static int layout;
 
+/*
+ * The screen_mutex mutex and wins_refresh(), wins_wrefresh(), wins_doupdate()
+ * functions are used to prevent concurrent updates of the screen.
+ * It was observed that the display could get screwed up when mulitple threads
+ * tried to refresh the screen at the same time.
+ *
+ * Note (2010-03-21):
+ * Since recent versions of ncurses (5.7), rudimentary support for threads are
+ * available (use_screen(), use_window() for instance - see curs_threads(3)),
+ * but to remain compatible with earlier versions, it was chosen to rely on a
+ * screen-level mutex instead.
+ */
+static pthread_mutex_t screen_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static unsigned
+screen_acquire (void)
+{
+  if (pthread_mutex_lock (&screen_mutex) != 0)
+    return 0;
+  else
+    return 1;
+}
+
+static void
+screen_release (void)
+{
+  (void)pthread_mutex_unlock (&screen_mutex);
+}
+
+int
+wins_refresh (void)
+{
+  int rc;
+  
+  if (!screen_acquire ())
+    return ERR;
+  rc = refresh ();
+  screen_release ();
+
+  return rc;
+}
+
+int
+wins_wrefresh (WINDOW *win)
+{
+  int rc;
+  
+  if (!win || !screen_acquire ())
+    return ERR;
+  rc = wrefresh (win);
+  screen_release ();
+
+  return rc;
+}
+
+int
+wins_doupdate (void)
+{
+  int rc;
+
+  if (!screen_acquire ())
+    return ERR;
+  rc = doupdate ();
+  screen_release ();
+
+  return rc;
+}
+
 /* Get the current layout. */
 int
 wins_layout (void)
@@ -236,7 +304,7 @@ wins_scrollwin_display (struct scrollwin *sw)
   wnoutrefresh (sw->win.p);
   pnoutrefresh (sw->pad.p, sw->first_visible_line, 0, sw->pad.y, sw->pad.x,
                 sw->win.h - sw->pad.y + 1, sw->win.w - sw->win.x);
-  doupdate ();
+  wins_doupdate ();
 }
 
 void
@@ -520,7 +588,7 @@ wins_update (void)
   if (notify_bar ())
     notify_update_bar ();
   wmove (win[STA].p, 0, 0);
-  doupdate ();
+  wins_doupdate ();
 }
 
 /* Reset the screen, needed when resizing terminal for example. */
@@ -528,7 +596,7 @@ void
 wins_reset (void)
 {
   endwin ();
-  refresh ();
+  wins_refresh ();
   curs_set (0);
   wins_reinit ();
   wins_update ();
@@ -559,13 +627,13 @@ wins_launch_external (const char *file, const char *cmd)
   endwin ();
   ui_mode = UI_CMDLINE;
   clear ();
-  refresh ();
+  wins_refresh ();
   (void)system (p);
   reset_prog_mode ();
   clearok (curscr, TRUE);
   curs_set (0);
   ui_mode = UI_CURSES;
-  refresh ();
+  wins_refresh ();
   if (notify_bar ())
     notify_start_main_thread ();
   mem_free (p);
-- 
cgit v1.2.3-70-g09d2