]> granicus.if.org Git - mutt/commitdiff
Add window structures to use for screen layout.
authorKevin McCarthy <kevin@8t8.us>
Thu, 28 Apr 2016 00:56:49 +0000 (17:56 -0700)
committerKevin McCarthy <kevin@8t8.us>
Thu, 28 Apr 2016 00:56:49 +0000 (17:56 -0700)
This is a series of 11 patches, centralizing Mutt screen drawing
inside windows (mutt_window_t structures).

Currently, the screen drawing and cursor positioning logic is
distributed all over the code, resulting in many files having the same
logic of where the help, status, message windows are.  Additionally,
the code directly uses move and mvadd*/mvprint* functions, which means
if the layouts are changed, the row/column computation logic needs to
be changed all over the place.

The patch creates a (very simple) mutt_window_t structure and
functions for moving, addch/str/printw, along with clearing the line.
The windows keep track of where they are on the screen, allowing the
Mutt code to simply position elements relative to the window.

During curses initalization, and when the window is resized, the
window sizes and positions and recomputed.  Also, a new option flags,
R_REFLOW is added for options that need to force a reflow when they are changed.

Thanks to Richard Russon for pointing out the slang compilation issue.

curs_lib.c
init.c
init.h
main.c
mutt_curses.h
resize.c

index ee1464cacbf8ce132b18a81a77a159319eaa1d5f..8bd4465a4d2a64e7964feffba48952b22a70d71e 100644 (file)
@@ -63,6 +63,14 @@ static size_t UngetCount = 0;
 static size_t UngetLen = 0;
 static event_t *UngetKeyEvents;
 
+mutt_window_t *MuttHelpWindow = NULL;
+mutt_window_t *MuttIndexWindow = NULL;
+mutt_window_t *MuttStatusWindow = NULL;
+mutt_window_t *MuttMessageWindow = NULL;
+#ifdef USE_SIDEBAR
+mutt_window_t *MuttSidebarWindow = NULL;
+#endif
+
 void mutt_refresh (void)
 {
   /* don't refresh when we are waiting for a child. */
@@ -479,6 +487,152 @@ out:
     mutt_clear_error ();
 }
 
+void mutt_init_windows ()
+{
+  MuttHelpWindow = safe_calloc (sizeof (mutt_window_t), 1);
+  MuttIndexWindow = safe_calloc (sizeof (mutt_window_t), 1);
+  MuttStatusWindow = safe_calloc (sizeof (mutt_window_t), 1);
+  MuttMessageWindow = safe_calloc (sizeof (mutt_window_t), 1);
+#ifdef USE_SIDEBAR
+  MuttSidebarWindow = safe_calloc (sizeof (mutt_window_t), 1);
+#endif
+
+  mutt_reflow_windows ();
+}
+
+void mutt_free_windows ()
+{
+  FREE (&MuttHelpWindow);
+  FREE (&MuttIndexWindow);
+  FREE (&MuttStatusWindow);
+  FREE (&MuttMessageWindow);
+#ifdef USE_SIDEBAR
+  FREE (&MuttSidebarWindow);
+#endif
+}
+
+void mutt_reflow_windows (void)
+{
+  if (option (OPTNOCURSES))
+    return;
+
+  dprint (2, (debugfile, "In mutt_reflow_windows\n"));
+
+  MuttStatusWindow->rows = 1;
+  MuttStatusWindow->cols = COLS;
+  MuttStatusWindow->row_offset = option (OPTSTATUSONTOP) ? 0 : LINES - 2;
+  MuttStatusWindow->col_offset = 0;
+
+  memcpy (MuttHelpWindow, MuttStatusWindow, sizeof (mutt_window_t));
+  if (! option (OPTHELP))
+    MuttHelpWindow->rows = 0;
+  else
+    MuttHelpWindow->row_offset = option (OPTSTATUSONTOP) ? LINES - 2 : 0;
+
+  memcpy (MuttMessageWindow, MuttStatusWindow, sizeof (mutt_window_t));
+  MuttMessageWindow->row_offset = LINES - 1;
+
+  memcpy (MuttIndexWindow, MuttStatusWindow, sizeof (mutt_window_t));
+  MuttIndexWindow->rows = LINES - MuttStatusWindow->rows - MuttHelpWindow->rows -
+                          MuttMessageWindow->rows;
+  MuttIndexWindow->row_offset = option (OPTSTATUSONTOP) ? MuttStatusWindow->rows :
+                                                          MuttHelpWindow->rows;
+
+#ifdef USE_SIDEBAR
+  if (option (OPTSIDEBAR))
+  {
+    memcpy (MuttSidebarWindow, MuttIndexWindow, sizeof (mutt_window_t));
+    MuttSidebarWindow->cols = SidebarWidth;
+
+    MuttIndexWindow->cols -= SidebarWidth;
+    MuttIndexWindow->col_offset += SidebarWidth;
+  }
+#endif
+}
+
+int mutt_window_move (mutt_window_t *win, int row, int col)
+{
+  return move (win->row_offset + row, win->col_offset + col);
+}
+
+int mutt_window_mvaddch (mutt_window_t *win, int row, int col, const chtype ch)
+{
+  return mvaddch (win->row_offset + row, win->col_offset + col, ch);
+}
+
+int mutt_window_mvaddstr (mutt_window_t *win, int row, int col, const char *str)
+{
+  return mvaddstr (win->row_offset + row, win->col_offset + col, str);
+}
+
+#ifdef USE_SLANG_CURSES
+static int vw_printw (SLcurses_Window_Type *win, const char *fmt, va_list ap)
+{
+  char buf[LONG_STRING];
+
+  (void) SLvsnprintf (buf, sizeof (buf), (char *)fmt, ap);
+  SLcurses_waddnstr (win, buf, -1);
+  return 0;
+}
+#endif
+
+int mutt_window_mvprintw (mutt_window_t *win, int row, int col, const char *fmt, ...)
+{
+  va_list ap;
+  int rv;
+
+  if ((rv = mutt_window_move (win, row, col) != ERR))
+  {
+    va_start (ap, fmt);
+    rv = vw_printw (stdscr, fmt, ap);
+    va_end (ap);
+  }
+
+  return rv;
+}
+
+/* Assumes the cursor has already been positioned within the
+ * window.
+ */
+void mutt_window_clrtoeol (mutt_window_t *win)
+{
+  int row, col, curcol;
+
+  if (win->col_offset + win->cols == COLS)
+    clrtoeol ();
+  else
+  {
+    getyx (stdscr, row, col);
+    curcol = col;
+    while (curcol < win->col_offset + win->cols)
+    {
+      addch (' ');
+      curcol++;
+    }
+    move (row, col);
+  }
+}
+
+void mutt_window_clearline (mutt_window_t *win, int row)
+{
+  mutt_window_move (win, row, 0);
+  mutt_window_clrtoeol (win);
+}
+
+/* Assumes the current position is inside the window.
+ * Otherwise it will happily return negative or values outside
+ * the window boundaries
+ */
+void mutt_window_getyx (mutt_window_t *win, int *y, int *x)
+{
+  int row, col;
+
+  getyx (stdscr, row, col);
+  *y = row - win->row_offset;
+  *x = col - win->col_offset;
+}
+
+
 void mutt_show_error (void)
 {
   if (option (OPTKEEPQUIET))
diff --git a/init.c b/init.c
index 69e2f765e5f2b384fcb25fda84502d42693e75cb..209cf578f3ec2784fa07583bda23b25742eb451f 100644 (file)
--- a/init.c
+++ b/init.c
@@ -1611,6 +1611,8 @@ static void mutt_restore_default (struct option_t *p)
     set_option (OPTRESORTINIT);
   if (p->flags & R_TREE)
     set_option (OPTREDRAWTREE);
+  if (p->flags & R_REFLOW)
+    mutt_reflow_windows ();
 }
 
 static size_t escape_string (char *dst, size_t len, const char* src)
@@ -2226,6 +2228,8 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err)
         set_option (OPTRESORTINIT);
       if (MuttVars[idx].flags & R_TREE)
         set_option (OPTREDRAWTREE);
+      if (MuttVars[idx].flags & R_REFLOW)
+        mutt_reflow_windows ();
     }
   }
   return (r);
diff --git a/init.h b/init.h
index 5a12ec0d06b7267b630e858b8393704ff85fb5cd..d3dea7fb69597fc9a0e3ed469445c6a5b77235e4 100644 (file)
--- a/init.h
+++ b/init.h
@@ -61,6 +61,7 @@
 #define R_RESORT_SUB   (1<<3)  /* resort subthreads */
 #define R_RESORT_INIT  (1<<4)  /* resort from scratch */
 #define R_TREE         (1<<5)  /* redraw the thread tree */
+#define R_REFLOW        (1<<6)  /* reflow window layout */
 #define R_BOTH         (R_INDEX | R_PAGER)
 #define R_RESORT_BOTH  (R_RESORT | R_RESORT_SUB)
 
@@ -977,7 +978,7 @@ struct option_t MuttVars[] = {
   */
 #endif /* HAVE_GDBM || HAVE_DB4 */
 #endif /* USE_HCACHE */
-  { "help",            DT_BOOL, R_BOTH, OPTHELP, 1 },
+  { "help",            DT_BOOL, R_BOTH|R_REFLOW, OPTHELP, 1 },
   /*
   ** .pp
   ** When \fIset\fP, help lines describing the bindings for the major functions
@@ -3287,7 +3288,7 @@ struct option_t MuttVars[] = {
   ** will replace any dots in the expansion by underscores. This might be helpful
   ** with IMAP folders that don't like dots in folder names.
   */
-  { "status_on_top",   DT_BOOL, R_BOTH, OPTSTATUSONTOP, 0 },
+  { "status_on_top",   DT_BOOL, R_BOTH|R_REFLOW, OPTSTATUSONTOP, 0 },
   /*
   ** .pp
   ** Setting this variable causes the ``status bar'' to be displayed on
diff --git a/main.c b/main.c
index d0a11281d3ce4616254ff20879488f5ef4a9f3e5..82fd46defe20fa4776d198144163b8f0a48a81ad 100644 (file)
--- a/main.c
+++ b/main.c
@@ -547,6 +547,7 @@ static void start_curses (void)
   meta (stdscr, TRUE);
 #endif
 init_extended_keys();
+  mutt_init_windows ();
 }
 
 #define M_IGNORE  (1<<0)       /* -z */
@@ -859,6 +860,7 @@ int main (int argc, char **argv)
     if (!option (OPTNOCURSES))
       mutt_flushinp ();
     ci_send_message (SENDPOSTPONED, NULL, NULL, NULL, NULL);
+    mutt_free_windows ();
     mutt_endwin (NULL);
   }
   else if (subject || msg || sendflags || draftFile || includeFile || attach ||
@@ -1148,7 +1150,10 @@ int main (int argc, char **argv)
     }
 
     if (!option (OPTNOCURSES))
+    {
+      mutt_free_windows ();
       mutt_endwin (NULL);
+    }
 
     if (rv)
       exit(1);
@@ -1217,6 +1222,7 @@ int main (int argc, char **argv)
     mutt_sasl_done ();
 #endif
     mutt_free_opts ();
+    mutt_free_windows ();
     mutt_endwin (Errorbuf);
   }
 
index 93d9aeaac216dee7c4a2e66facabacb60f3d1567..0f6608c7f14413fc8aa2f7c14838f79edd441d92 100644 (file)
@@ -161,6 +161,35 @@ void mutt_progress_init (progress_t* progress, const char *msg,
  * was initialized with positive size, otherwise no percentage is shown */
 void mutt_progress_update (progress_t* progress, long pos, int percent);
 
+/* Windows for different parts of the screen */
+typedef struct
+{
+  int rows;
+  int cols;
+  int row_offset;
+  int col_offset;
+} mutt_window_t;
+
+extern mutt_window_t *MuttHelpWindow;
+extern mutt_window_t *MuttIndexWindow;
+extern mutt_window_t *MuttStatusWindow;
+extern mutt_window_t *MuttMessageWindow;
+#ifdef USE_SIDEBAR
+extern mutt_window_t *MuttSidebarWindow;
+#endif
+
+void mutt_init_windows (void);
+void mutt_free_windows (void);
+void mutt_reflow_windows (void);
+int mutt_window_move (mutt_window_t *, int row, int col);
+int mutt_window_mvaddch (mutt_window_t *, int row, int col, const chtype ch);
+int mutt_window_mvaddstr (mutt_window_t *, int row, int col, const char *str);
+int mutt_window_mvprintw (mutt_window_t *, int row, int col, const char *fmt, ...);
+void mutt_window_clrtoeol (mutt_window_t *);
+void mutt_window_clearline (mutt_window_t *, int row);
+void mutt_window_getyx (mutt_window_t *, int *y, int *x);
+
+
 static inline int mutt_term_width(short wrap)
 {
   if (wrap < 0)
index f9c26b427b093c10d2f62a931a4602be1f5c4688..2e77d2186380c16bf311409ac531d3d13758ecd2 100644 (file)
--- a/resize.c
+++ b/resize.c
@@ -76,4 +76,5 @@ void mutt_resize_screen (void)
 #else
   resizeterm (SLtt_Screen_Rows, SLtt_Screen_Cols);
 #endif
+  mutt_reflow_windows ();
 }