changeset: 6991:7f6ff45a7f59
user:      Kevin McCarthy <ke...@8t8.us>
date:      Wed Apr 05 16:09:31 2017 -0700
link:      http://dev.mutt.org/hg/mutt/rev/7f6ff45a7f59

Remove redraw flag setting after mutt_endwin().

There is no need to set a redraw flag in this case.  The screen will
automatically be properly redrawn on the next refresh().

Remove, lest it get propagated.

changeset: 6992:231fa2eff206
user:      Kevin McCarthy <ke...@8t8.us>
date:      Wed Apr 05 16:09:33 2017 -0700
link:      http://dev.mutt.org/hg/mutt/rev/231fa2eff206

Change km_dokey() to pass SigWinch on for the MENU_EDITOR. (see #3877)

Change _mutt_enter_string() to pass the SigWinch through for
_mutt_get_field() or mutt_enter_string() to handle.

Add a call to mutt_current_menu() in _mutt_get_field() to properly
redisplay the screen in that case.

changeset: 6993:c651b528f958
user:      Kevin McCarthy <ke...@8t8.us>
date:      Wed Apr 05 16:09:34 2017 -0700
link:      http://dev.mutt.org/hg/mutt/rev/c651b528f958

Separate out the compose menu redrawing. (see #3877)

Add a custom_menu_redraw to the menu and change menu_redraw() to call
that instead if set.

changeset: 6994:178bd8b53cab
user:      Kevin McCarthy <ke...@8t8.us>
date:      Wed Apr 05 16:09:35 2017 -0700
link:      http://dev.mutt.org/hg/mutt/rev/178bd8b53cab

Separate out the index menu redrawing. (see #3877)

changeset: 6995:dcc95921c3c5
user:      Kevin McCarthy <ke...@8t8.us>
date:      Wed Apr 05 16:09:36 2017 -0700
link:      http://dev.mutt.org/hg/mutt/rev/dcc95921c3c5

Prepare for pager redraw separation. (see #3877)

Move some of the code inside SigWinch handling into the REDRAW part of
the code.

SigInt is handled by mutt_getch(), so remove the redundant code from
inside the pager.

changeset: 6996:86848e5932b0
user:      Kevin McCarthy <ke...@8t8.us>
date:      Wed Apr 05 16:09:37 2017 -0700
link:      http://dev.mutt.org/hg/mutt/rev/86848e5932b0

Separate out the pager menu redrawing. (see #3877)

The pager relies on REDRAW_SIGWINCH, so add that to _mutt_get_field().

changeset: 6997:303fc058692f
user:      Kevin McCarthy <ke...@8t8.us>
date:      Wed Apr 05 16:09:39 2017 -0700
link:      http://dev.mutt.org/hg/mutt/rev/303fc058692f

Don't create query menu until after initial prompt. (see #3877)

A resize in the prompt will trigger a redraw, but the data won't be
loaded yet, displaying a blank screen instead of the previous menu.
Once the query is done, the data is loaded, but the menu->redraw state
has been changed by the resize.

We could manually flag a redraw, but it makes more sense visually
logically to just create the menu after the query and results are
loaded.

diffs (truncated from 1792 to 950 lines):

diff -r 8b9bbd983b1a -r 303fc058692f compose.c
--- a/compose.c Fri Mar 31 18:15:31 2017 -0700
+++ b/compose.c Wed Apr 05 16:09:39 2017 -0700
@@ -468,6 +468,54 @@
         (unsigned long) menu, 0);
 }
 
+typedef struct
+{
+  HEADER *msg;
+  char *fcc;
+} compose_redraw_data_t;
+
+static void compose_menu_redraw (MUTTMENU *menu)
+{
+  char buf[LONG_STRING];
+  compose_redraw_data_t *rd = menu->redraw_data;
+
+  if (!rd)
+    return;
+
+  if (menu->redraw & REDRAW_FULL)
+  {
+    menu_redraw_full (menu);
+
+    draw_envelope (rd->msg, rd->fcc);
+    menu->offset = HDR_ATTACH;
+    menu->pagelen = MuttIndexWindow->rows - HDR_ATTACH;
+  }
+
+  menu_check_recenter (menu);
+
+  if (menu->redraw & REDRAW_STATUS)
+  {
+    compose_status_line (buf, sizeof (buf), 0, MuttStatusWindow->cols, menu, 
NONULL(ComposeFormat));
+    mutt_window_move (MuttStatusWindow, 0, 0);
+    SETCOLOR (MT_COLOR_STATUS);
+    mutt_paddstr (MuttStatusWindow->cols, buf);
+    NORMAL_COLOR;
+    menu->redraw &= ~REDRAW_STATUS;
+  }
+
+#ifdef USE_SIDEBAR
+  if (menu->redraw & REDRAW_SIDEBAR)
+    menu_redraw_sidebar (menu);
+#endif
+
+  if (menu->redraw & REDRAW_INDEX)
+    menu_redraw_index (menu);
+  else if (menu->redraw & (REDRAW_MOTION | REDRAW_MOTION_RESYNCH))
+    menu_redraw_motion (menu);
+  else if (menu->redraw == REDRAW_CURRENT)
+    menu_redraw_current (menu);
+}
+
 
 /* return values:
  *
@@ -497,6 +545,10 @@
   /* Sort, SortAux could be changed in mutt_index_menu() */
   int oldSort, oldSortAux;
   struct stat st;
+  compose_redraw_data_t rd;
+
+  rd.msg = msg;
+  rd.fcc = fcc;
 
   mutt_attach_init (msg->content);
   idx = mutt_gen_attach_list (msg->content, -1, idx, &idxlen, &idxmax, 0, 1);
@@ -508,17 +560,14 @@
   menu->tag = mutt_tag_attach;
   menu->data = idx;
   menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_COMPOSE, 
ComposeHelp);
+  menu->custom_menu_redraw = compose_menu_redraw;
+  menu->redraw_data = &rd;
   mutt_push_current_menu (menu);
 
   while (loop)
   {
     switch (op = mutt_menuLoop (menu))
     {
-      case OP_REDRAW:
-       draw_envelope (msg, fcc);
-       menu->offset = HDR_ATTACH;
-       menu->pagelen = MuttIndexWindow->rows - HDR_ATTACH;
-       break;
       case OP_COMPOSE_EDIT_FROM:
        edit_address_list (HDR_FROM, &msg->env->from);
         mutt_message_hook (NULL, msg, MUTT_SEND2HOOK);
@@ -1320,17 +1369,6 @@
 #endif
 
     }
-
-    /* Draw formatted compose status line */
-    if (menu->redraw & REDRAW_STATUS) 
-    {
-        compose_status_line (buf, sizeof (buf), 0, MuttStatusWindow->cols, 
menu, NONULL(ComposeFormat));
-       mutt_window_move (MuttStatusWindow, 0, 0);
-       SETCOLOR (MT_COLOR_STATUS);
-       mutt_paddstr (MuttStatusWindow->cols, buf);
-       NORMAL_COLOR;
-       menu->redraw &= ~REDRAW_STATUS;
-    }
   }
 
   mutt_pop_current_menu (menu);
diff -r 8b9bbd983b1a -r 303fc058692f curs_lib.c
--- a/curs_lib.c        Fri Mar 31 18:15:31 2017 -0700
+++ b/curs_lib.c        Wed Apr 05 16:09:39 2017 -0700
@@ -162,6 +162,16 @@
   
   do
   {
+    if (SigWinch)
+    {
+      SigWinch = 0;
+      mutt_resize_screen ();
+      /* mutt_resize_screen sets REDRAW_FULL, but the pager also
+       * requires SIGWINCH. */
+      mutt_set_current_menu_redraw (REDRAW_SIGWINCH);
+      clearok(stdscr, TRUE);
+      mutt_current_menu_redraw ();
+    }
     mutt_window_clearline (MuttMessageWindow, 0);
     SETCOLOR (MT_COLOR_PROMPT);
     addstr ((char *)field); /* cast to get around bad prototypes */
@@ -173,7 +183,7 @@
   while (ret == 1);
   mutt_window_clearline (MuttMessageWindow, 0);
   mutt_free_enter_state (&es);
-  
+
   return (ret);
 }
 
diff -r 8b9bbd983b1a -r 303fc058692f curs_main.c
--- a/curs_main.c       Fri Mar 31 18:15:31 2017 -0700
+++ b/curs_main.c       Wed Apr 05 16:09:39 2017 -0700
@@ -494,6 +494,59 @@
   { NULL,       0 }
 };
 
+static void index_menu_redraw (MUTTMENU *menu)
+{
+  char buf[LONG_STRING];
+
+  if (menu->redraw & REDRAW_FULL)
+  {
+    menu_redraw_full (menu);
+    mutt_show_error ();
+  }
+
+#ifdef USE_SIDEBAR
+  if (menu->redraw & REDRAW_SIDEBAR)
+  {
+    mutt_sb_set_buffystats (Context);
+    menu_redraw_sidebar (menu);
+  }
+#endif
+
+  if (Context && Context->hdrs && !(menu->current >= Context->vcount))
+  {
+    menu_check_recenter (menu);
+
+    if (menu->redraw & REDRAW_INDEX)
+    {
+      menu_redraw_index (menu);
+      menu->redraw |= REDRAW_STATUS;
+    }
+    else if (menu->redraw & (REDRAW_MOTION_RESYNCH | REDRAW_MOTION))
+      menu_redraw_motion (menu);
+    else if (menu->redraw & REDRAW_CURRENT)
+      menu_redraw_current (menu);
+  }
+
+  if (menu->redraw & REDRAW_STATUS)
+  {
+    menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
+    mutt_window_move (MuttStatusWindow, 0, 0);
+    SETCOLOR (MT_COLOR_STATUS);
+    mutt_paddstr (MuttStatusWindow->cols, buf);
+    NORMAL_COLOR;
+    menu->redraw &= ~REDRAW_STATUS;
+    if (option(OPTTSENABLED) && TSSupported)
+    {
+      menu_status_line (buf, sizeof (buf), menu, NONULL (TSStatusFormat));
+      mutt_ts_status(buf);
+      menu_status_line (buf, sizeof (buf), menu, NONULL (TSIconFormat));
+      mutt_ts_icon(buf);
+    }
+  }
+
+  menu->redraw = 0;
+}
+
 /* This function handles the message index window as well as commands returned
  * from the pager (MENU_PAGER).
  */
@@ -519,6 +572,7 @@
   menu->color = index_color;
   menu->current = ci_first_message ();
   menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, 
IndexHelp);
+  menu->custom_menu_redraw = index_menu_redraw;
   mutt_push_current_menu (menu);
 
   if (!attach_msg)
@@ -615,63 +669,19 @@
 
     if (menu->menu == MENU_MAIN)
     {
-      if (menu->redraw & REDRAW_FULL)
-      {
-        menu_redraw_full (menu);
-        mutt_show_error ();
-      }
+      index_menu_redraw (menu);
 
-#ifdef USE_SIDEBAR
-      if (menu->redraw & REDRAW_SIDEBAR)
-      {
-        mutt_sb_set_buffystats (Context);
-        menu_redraw_sidebar (menu);
-      }
-#endif
-      if (Context && Context->hdrs && !(menu->current >= Context->vcount))
-      {
-       menu_check_recenter (menu);
-
-       if (menu->redraw & REDRAW_INDEX)
-       {
-         menu_redraw_index (menu);
-         menu->redraw |= REDRAW_STATUS;
-       }
-       else if (menu->redraw & (REDRAW_MOTION_RESYNCH | REDRAW_MOTION))
-         menu_redraw_motion (menu);
-       else if (menu->redraw & REDRAW_CURRENT)
-         menu_redraw_current (menu);
-      }
-
-      if (menu->redraw & REDRAW_STATUS)
-      {
-       menu_status_line (buf, sizeof (buf), menu, NONULL (Status));
-        mutt_window_move (MuttStatusWindow, 0, 0);
-       SETCOLOR (MT_COLOR_STATUS);
-       mutt_paddstr (MuttStatusWindow->cols, buf);
-       NORMAL_COLOR;
-       menu->redraw &= ~REDRAW_STATUS;
-       if (option(OPTTSENABLED) && TSSupported)
-       {
-         menu_status_line (buf, sizeof (buf), menu, NONULL (TSStatusFormat));
-         mutt_ts_status(buf);
-         menu_status_line (buf, sizeof (buf), menu, NONULL (TSIconFormat));
-         mutt_ts_icon(buf);
-       }
-      }
-
-      menu->redraw = 0;
       if (menu->current < menu->max)
-       menu->oldcurrent = menu->current;
+        menu->oldcurrent = menu->current;
       else
-       menu->oldcurrent = -1;
+        menu->oldcurrent = -1;
 
       if (option (OPTARROWCURSOR))
-       mutt_window_move (MuttIndexWindow, menu->current - menu->top + 
menu->offset, 2);
+        mutt_window_move (MuttIndexWindow, menu->current - menu->top + 
menu->offset, 2);
       else if (option (OPTBRAILLEFRIENDLY))
-       mutt_window_move (MuttIndexWindow, menu->current - menu->top + 
menu->offset, 0);
+        mutt_window_move (MuttIndexWindow, menu->current - menu->top + 
menu->offset, 0);
       else
-       mutt_window_move (MuttIndexWindow, menu->current - menu->top + 
menu->offset,
+        mutt_window_move (MuttIndexWindow, menu->current - menu->top + 
menu->offset,
                           MuttIndexWindow->cols - 1);
       mutt_refresh ();
 
@@ -680,8 +690,6 @@
       {
        mutt_flushinp ();
        mutt_resize_screen ();
-       menu->redraw = REDRAW_FULL;
-       menu->menu = MENU_MAIN;
        SigWinch = 0;
        menu->top = 0; /* so we scroll the right amount */
        /*
diff -r 8b9bbd983b1a -r 303fc058692f enter.c
--- a/enter.c   Fri Mar 31 18:15:31 2017 -0700
+++ b/enter.c   Wed Apr 05 16:09:39 2017 -0700
@@ -203,22 +203,40 @@
   return wcschr(shell_chars, ch) != NULL;
 }
 
-/*
+/* This function is for very basic input, currently used only by the
+ * built-in editor.  It does not handle screen redrawing on resizes
+ * well, because there is no active menu for the built-in editor.
+ * Most callers should prefer mutt_get_field() instead.
+ *
  * Returns:
- *     1 need to redraw the screen and call me again
  *     0 if input was given
  *     -1 if abort.
  */
-
 int  mutt_enter_string(char *buf, size_t buflen, int col, int flags)
 {
   int rv;
   ENTER_STATE *es = mutt_new_enter_state ();
-  rv = _mutt_enter_string (buf, buflen, col, flags, 0, NULL, NULL, es);
+  do
+  {
+    if (SigWinch)
+    {
+      SigWinch = 0;
+      mutt_resize_screen ();
+      clearok(stdscr, TRUE);
+    }
+    rv = _mutt_enter_string (buf, buflen, col, flags, 0, NULL, NULL, es);
+  }
+  while (rv == 1);
   mutt_free_enter_state (&es);
   return rv;
 }
 
+/*
+ * Returns:
+ *      1 need to redraw the screen and call me again
+ *     0 if input was given
+ *     -1 if abort.
+ */
 int _mutt_enter_string (char *buf, size_t buflen, int col,
                        int flags, int multiple, char ***files, int *numfiles,
                        ENTER_STATE *state)
@@ -297,7 +315,7 @@
 
     if ((ch = km_dokey (MENU_EDITOR)) == -1)
     {
-      rv = -1; 
+      rv = SigWinch ? 1 : -1;
       goto bye;
     }
 
@@ -785,7 +803,7 @@
   }
   
   bye:
-  
+
   mutt_reset_history_state (hclass);
   FREE (&tempbuf);
   return rv;
diff -r 8b9bbd983b1a -r 303fc058692f init.c
--- a/init.c    Fri Mar 31 18:15:31 2017 -0700
+++ b/init.c    Wed Apr 05 16:09:39 2017 -0700
@@ -1291,8 +1291,6 @@
     print_attach_list(AttachExclude, '-', "A");
     print_attach_list(InlineAllow,   '+', "I");
     print_attach_list(InlineExclude, '-', "I");
-    mutt_set_menu_redraw_full (MENU_MAIN);
-    mutt_set_menu_redraw_full (MENU_PAGER);
     mutt_any_key_to_continue (NULL);
     return 0;
   }
@@ -1974,7 +1972,6 @@
 
     if (found)
     {
-      mutt_set_current_menu_redraw_full ();
       mutt_any_key_to_continue (NULL);
       return 0;
     }
diff -r 8b9bbd983b1a -r 303fc058692f keymap.c
--- a/keymap.c  Fri Mar 31 18:15:31 2017 -0700
+++ b/keymap.c  Wed Apr 05 16:09:39 2017 -0700
@@ -464,8 +464,8 @@
 #ifdef USE_IMAP
   gotkey:
 #endif
-    /* hide timeouts and window resizes from line editor. */
-    if (menu == MENU_EDITOR && tmp.ch == -2)
+    /* hide timeouts, but not window resizes, from the line editor. */
+    if (menu == MENU_EDITOR && tmp.ch == -2 && !SigWinch)
       continue;
 
     LastKey = tmp.ch;
diff -r 8b9bbd983b1a -r 303fc058692f menu.c
--- a/menu.c    Fri Mar 31 18:15:31 2017 -0700
+++ b/menu.c    Wed Apr 05 16:09:39 2017 -0700
@@ -798,6 +798,22 @@
     mutt_set_current_menu_redraw_full ();
 }
 
+void mutt_current_menu_redraw ()
+{
+  MUTTMENU *current_menu;
+
+  current_menu = get_current_menu ();
+  if (current_menu)
+  {
+    if (menu_redraw (current_menu) == OP_REDRAW)
+    /* On a REDRAW_FULL with a non-customized redraw, menu_redraw()
+     * will return OP_REDRAW to give the calling menu-loop a chance to
+     * customize output.
+     */
+       menu_redraw (current_menu);
+  }
+}
+
 
 #define MUTT_SEARCH_UP   1
 #define MUTT_SEARCH_DOWN 2
@@ -910,6 +926,12 @@
 
 int menu_redraw (MUTTMENU *menu)
 {
+  if (menu->custom_menu_redraw)
+  {
+    menu->custom_menu_redraw (menu);
+    return OP_NULL;
+  }
+
   /* See if all or part of the screen needs to be updated.  */
   if (menu->redraw & REDRAW_FULL)
   {
@@ -1012,7 +1034,6 @@
     if (SigWinch)
     {
       mutt_resize_screen ();
-      menu->redraw = REDRAW_FULL;
       SigWinch = 0;
       clearok(stdscr,TRUE);/*force complete redraw*/
     }
diff -r 8b9bbd983b1a -r 303fc058692f mutt_menu.h
--- a/mutt_menu.h       Fri Mar 31 18:15:31 2017 -0700
+++ b/mutt_menu.h       Wed Apr 05 16:09:39 2017 -0700
@@ -75,6 +75,10 @@
 
   int (*tag) (struct menu_t *, int i, int m);
 
+  /* these are used for custom redrawing callbacks */
+  void (*custom_menu_redraw) (struct menu_t *);
+  void *redraw_data;
+
   /* color pair to be used for the requested element 
    * (default function returns ColorDefs[MT_COLOR_NORMAL])
    */
@@ -125,6 +129,7 @@
 void mutt_set_current_menu_redraw (int);
 void mutt_set_current_menu_redraw_full ();
 void mutt_set_menu_redraw_full (int);
+void mutt_current_menu_redraw (void);
 int mutt_menuLoop (MUTTMENU *);
 
 /* used in both the index and pager index to make an entry. */
diff -r 8b9bbd983b1a -r 303fc058692f pager.c
--- a/pager.c   Fri Mar 31 18:15:31 2017 -0700
+++ b/pager.c   Wed Apr 05 16:09:39 2017 -0700
@@ -1576,6 +1576,307 @@
   OldHdr = NULL;
 }
 
+typedef struct
+{
+  int flags;
+  pager_t *extra;
+  int indexlen;
+  int indicator;                /* the indicator line of the PI */
+  int oldtopline;
+  int lines;
+  int maxLine;
+  int lastLine;
+  int curline;
+  int topline;
+  int force_redraw;
+  int has_types;
+  int hideQuoted;
+  int q_level;
+  struct q_class_t *QuoteList;
+  LOFF_T last_pos;
+  LOFF_T last_offset;
+  mutt_window_t *index_status_window;
+  mutt_window_t *index_window;
+  mutt_window_t *pager_status_window;
+  mutt_window_t *pager_window;
+  MUTTMENU *index;             /* the Pager Index (PI) */
+  regex_t SearchRE;
+  int SearchCompiled;
+  int SearchFlag;
+  int SearchBack;
+  const char *banner;
+  char *helpstr;
+  char *searchbuf;
+  struct line_t *lineInfo;
+  FILE *fp;
+  struct stat sb;
+} pager_redraw_data_t;
+
+static void pager_menu_redraw (MUTTMENU *pager_menu)
+{
+  pager_redraw_data_t *rd = pager_menu->redraw_data;
+  int i, j;
+  char buffer[LONG_STRING];
+
+  if (!rd)
+    return;
+
+  if (pager_menu->redraw & REDRAW_FULL)
+  {
+#if ! (defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM))
+    mutt_reflow_windows ();
+#endif
+    NORMAL_COLOR;
+    /* clear() doesn't optimize screen redraws */
+    move (0, 0);
+    clrtobot ();
+
+    if (IsHeader (rd->extra) && Context->vcount + 1 < PagerIndexLines)
+      rd->indexlen = Context->vcount + 1;
+    else
+      rd->indexlen = PagerIndexLines;
+
+    rd->indicator = rd->indexlen / 3;
+
+    memcpy (rd->pager_window, MuttIndexWindow, sizeof(mutt_window_t));
+    memcpy (rd->pager_status_window, MuttStatusWindow, sizeof(mutt_window_t));
+    rd->index_status_window->rows = rd->index_window->rows = 0;
+
+    if (IsHeader (rd->extra) && PagerIndexLines)
+    {
+      memcpy (rd->index_window, MuttIndexWindow, sizeof(mutt_window_t));
+      rd->index_window->rows = rd->indexlen > 0 ? rd->indexlen - 1 : 0;
+
+      if (option (OPTSTATUSONTOP))
+      {
+        memcpy (rd->index_status_window, MuttStatusWindow, 
sizeof(mutt_window_t));
+
+        memcpy (rd->pager_status_window, MuttIndexWindow, 
sizeof(mutt_window_t));
+        rd->pager_status_window->rows = 1;
+        rd->pager_status_window->row_offset += rd->index_window->rows;
+
+        rd->pager_window->rows -= rd->index_window->rows + 
rd->pager_status_window->rows;
+        rd->pager_window->row_offset += rd->index_window->rows + 
rd->pager_status_window->rows;
+      }
+      else
+      {
+        memcpy (rd->index_status_window, MuttIndexWindow, 
sizeof(mutt_window_t));
+        rd->index_status_window->rows = 1;
+        rd->index_status_window->row_offset += rd->index_window->rows;
+
+        rd->pager_window->rows -= rd->index_window->rows + 
rd->index_status_window->rows;
+        rd->pager_window->row_offset += rd->index_window->rows + 
rd->index_status_window->rows;
+      }
+    }
+
+    if (option (OPTHELP))
+    {
+      SETCOLOR (MT_COLOR_STATUS);
+      mutt_window_move (MuttHelpWindow, 0, 0);
+      mutt_paddstr (MuttHelpWindow->cols, rd->helpstr);
+      NORMAL_COLOR;
+    }
+
+#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
+    if (Resize != NULL)
+    {
+      if ((rd->SearchCompiled = Resize->SearchCompiled))
+      {
+        REGCOMP
+          (&rd->SearchRE, rd->searchbuf, REG_NEWLINE | mutt_which_case 
(rd->searchbuf));
+        rd->SearchFlag = MUTT_SEARCH;
+        rd->SearchBack = Resize->SearchBack;
+      }
+      rd->lines = Resize->line;
+      pager_menu->redraw |= REDRAW_SIGWINCH;
+
+      FREE (&Resize);
+    }
+#endif
+
+    if (IsHeader (rd->extra) && PagerIndexLines)
+    {
+      if (rd->index == NULL)
+      {
+        /* only allocate the space if/when we need the index.
+           Initialise the menu as per the main index */
+        rd->index = mutt_new_menu(MENU_MAIN);
+        rd->index->make_entry = index_make_entry;
+        rd->index->color = index_color;
+        rd->index->max = Context->vcount;
+        rd->index->current = rd->extra->hdr->virtual;
+        rd->index->indexwin = rd->index_window;
+        rd->index->statuswin = rd->index_status_window;
+      }
+
+      NORMAL_COLOR;
+      rd->index->pagelen = rd->index_window->rows;;
+
+      /* some fudge to work out where abouts the indicator should go */
+      if (rd->index->current - rd->indicator < 0)
+        rd->index->top = 0;
+      else if (rd->index->max - rd->index->current < rd->index->pagelen - 
rd->indicator)
+        rd->index->top = rd->index->max - rd->index->pagelen;
+      else
+        rd->index->top = rd->index->current - rd->indicator;
+
+      menu_redraw_index(rd->index);
+    }
+
+    pager_menu->redraw |= REDRAW_BODY | REDRAW_INDEX | REDRAW_STATUS;
+#ifdef USE_SIDEBAR
+    pager_menu->redraw |= REDRAW_SIDEBAR;
+#endif
+    mutt_show_error ();
+  }
+
+  if (pager_menu->redraw & REDRAW_SIGWINCH)
+  {
+    if (!(rd->flags & MUTT_PAGER_RETWINCH))
+    {
+      rd->lines = -1;
+      for (i = 0; i <= rd->topline; i++)
+        if (!rd->lineInfo[i].continuation)
+          rd->lines++;
+      for (i = 0; i < rd->maxLine; i++)
+      {
+        rd->lineInfo[i].offset = 0;
+        rd->lineInfo[i].type = -1;
+        rd->lineInfo[i].continuation = 0;
+        rd->lineInfo[i].chunks = 0;
+        rd->lineInfo[i].search_cnt = -1;
+        rd->lineInfo[i].quote = NULL;
+
+        safe_realloc (&(rd->lineInfo[i].syntax),
+                      sizeof (struct syntax_t));
+        if (rd->SearchCompiled && rd->lineInfo[i].search)
+          FREE (&(rd->lineInfo[i].search));
+      }
+
+      rd->lastLine = 0;
+      rd->topline = 0;
+    }
+    i = -1;
+    j = -1;
+    while (display_line (rd->fp, &rd->last_pos, &rd->lineInfo, ++i, 
&rd->lastLine, &rd->maxLine,
+                         rd->has_types | rd->SearchFlag | (rd->flags & 
MUTT_PAGER_NOWRAP),
+                         &rd->QuoteList, &rd->q_level, &rd->force_redraw,
+                         &rd->SearchRE, rd->pager_window) == 0)
+      if (!rd->lineInfo[i].continuation && ++j == rd->lines)
+      {
+        rd->topline = i;
+        if (!rd->SearchFlag)
+          break;
+      }
+  }
+
+#ifdef USE_SIDEBAR
+  if (pager_menu->redraw & REDRAW_SIDEBAR)
+  {
+    menu_redraw_sidebar (pager_menu);
+  }
+#endif
+
+  if ((pager_menu->redraw & REDRAW_BODY) || rd->topline != rd->oldtopline)
+  {
+    do
+    {
+      mutt_window_move (rd->pager_window, 0, 0);
+      rd->curline = rd->oldtopline = rd->topline;
+      rd->lines = 0;
+      rd->force_redraw = 0;
+
+      while (rd->lines < rd->pager_window->rows &&
+             rd->lineInfo[rd->curline].offset <= rd->sb.st_size - 1)
+      {
+        if (display_line (rd->fp, &rd->last_pos, &rd->lineInfo, rd->curline, 
&rd->lastLine, 
+                          &rd->maxLine,
+                          (rd->flags & MUTT_DISPLAYFLAGS) | rd->hideQuoted | 
rd->SearchFlag | (rd->flags & MUTT_PAGER_NOWRAP),
+                          &rd->QuoteList, &rd->q_level, &rd->force_redraw, 
&rd->SearchRE,
+                          rd->pager_window) > 0)
+          rd->lines++;
+        rd->curline++;
+        mutt_window_move (rd->pager_window, rd->lines, 0);
+      }
+      rd->last_offset = rd->lineInfo[rd->curline].offset;
+    } while (rd->force_redraw);
+
+    SETCOLOR (MT_COLOR_TILDE);
+    while (rd->lines < rd->pager_window->rows)
+    {
+      mutt_window_clrtoeol (rd->pager_window);
+      if (option (OPTTILDE))
+        addch ('~');
+      rd->lines++;
+      mutt_window_move (rd->pager_window, rd->lines, 0);
+    }
+    NORMAL_COLOR;
+
+    /* We are going to update the pager status bar, so it isn't
+     * necessary to reset to normal color now. */
+
+    pager_menu->redraw |= REDRAW_STATUS; /* need to update the % seen */
+  }
+
+  if (pager_menu->redraw & REDRAW_STATUS)
+  {
+    struct hdr_format_info hfi;
+    char pager_progress_str[4];
+
+    hfi.ctx = Context;
+    hfi.pager_progress = pager_progress_str;
+
+    if (rd->last_pos < rd->sb.st_size - 1)
+      snprintf(pager_progress_str, sizeof(pager_progress_str), OFF_T_FMT "%%", 
(100 * rd->last_offset / rd->sb.st_size));
+    else
+      strfcpy(pager_progress_str, (rd->topline == 0) ? "all" : "end", 
sizeof(pager_progress_str));
+
+    /* print out the pager status bar */
+    mutt_window_move (rd->pager_status_window, 0, 0);
+    SETCOLOR (MT_COLOR_STATUS);
+
+    if (IsHeader (rd->extra) || IsMsgAttach (rd->extra))
+    {
+      size_t l1 = rd->pager_status_window->cols * MB_LEN_MAX;
+      size_t l2 = sizeof (buffer);
+      hfi.hdr = (IsHeader (rd->extra)) ? rd->extra->hdr : rd->extra->bdy->hdr;
+      mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, 
rd->pager_status_window->cols, NONULL (PagerFmt), &hfi, MUTT_FORMAT_MAKEPRINT);
+      mutt_paddstr (rd->pager_status_window->cols, buffer);
+    }
+    else
+    {
+      char bn[STRING];
+      snprintf (bn, sizeof (bn), "%s (%s)", rd->banner, pager_progress_str);
+      mutt_paddstr (rd->pager_status_window->cols, bn);
+    }
+    NORMAL_COLOR;
+    if (option(OPTTSENABLED) && TSSupported)
+    {
+      menu_status_line (buffer, sizeof (buffer), rd->index, NONULL 
(TSStatusFormat));
+      mutt_ts_status(buffer);
+      menu_status_line (buffer, sizeof (buffer), rd->index, NONULL 
(TSIconFormat));
+      mutt_ts_icon(buffer);
+    }
+  }
+
+  if ((pager_menu->redraw & REDRAW_INDEX) && rd->index)
+  {
+    /* redraw the pager_index indicator, because the
+     * flags for this message might have changed. */
+    if (rd->index_window->rows > 0)
+      menu_redraw_current (rd->index);
+
+    /* print out the index status bar */
+    menu_status_line (buffer, sizeof (buffer), rd->index, NONULL(Status));
+
+    mutt_window_move (rd->index_status_window, 0, 0);
+    SETCOLOR (MT_COLOR_STATUS);
+    mutt_paddstr (rd->index_status_window->cols, buffer);
+    NORMAL_COLOR;
+  }
+
+  pager_menu->redraw = 0;
+}
 
 /* This pager is actually not so simple as it once was.  It now operates in
    two modes: one for viewing messages and the other for viewing help.  These
@@ -1589,45 +1890,40 @@
   char buffer[LONG_STRING];
   char helpstr[SHORT_STRING*2];
   char tmphelp[SHORT_STRING*2];
-  int maxLine, lastLine = 0;
-  struct line_t *lineInfo;
-  struct q_class_t *QuoteList = NULL;
-  int i, j, ch = 0, rc = -1, hideQuoted = 0, q_level = 0, force_redraw = 0;
-  int lines = 0, curline = 0, topline = 0, oldtopline = 0, err, first = 1;
+  int i, j, ch = 0, rc = -1;
+  int err, first = 1;
   int r = -1, wrapped = 0, searchctx = 0;
-  FILE *fp = NULL;
-  LOFF_T last_pos = 0, last_offset = 0;
   int old_smart_wrap, old_markers;
-  struct stat sb;
-  regex_t SearchRE;
-  int SearchCompiled = 0, SearchFlag = 0, SearchBack = 0;
-  int has_types = (IsHeader(extra) || (flags & MUTT_SHOWCOLOR)) ? MUTT_TYPES : 
0; /* main message or rfc822 attachment */
-
-  mutt_window_t *index_status_window = NULL;
-  mutt_window_t *index_window = NULL;
-  mutt_window_t *pager_status_window = NULL;
-  mutt_window_t *pager_window = NULL;
 
   MUTTMENU *pager_menu = NULL;
-  MUTTMENU *index = NULL;              /* the Pager Index (PI) */
-  int indexlen = PagerIndexLines;      /* indexlen not always == PIL */
-  int indicator = indexlen / 3;        /* the indicator line of the PI */
   int old_PagerIndexLines;             /* some people want to resize it
                                         * while inside the pager... */
 
+  pager_redraw_data_t rd;
+
   if (!(flags & MUTT_SHOWCOLOR))
     flags |= MUTT_SHOWFLAT;
 
-  if ((fp = fopen (fname, "r")) == NULL)
+  memset (&rd, 0, sizeof (rd));
+  rd.banner = banner;
+  rd.flags = flags;
+  rd.extra = extra;
+  rd.indexlen = PagerIndexLines;
+  rd.indicator = rd.indexlen / 3;
+  rd.helpstr = helpstr;
+  rd.searchbuf = searchbuf;
+  rd.has_types = (IsHeader(extra) || (flags & MUTT_SHOWCOLOR)) ? MUTT_TYPES : 
0; /* main message or rfc822 attachment */
+
+  if ((rd.fp = fopen (fname, "r")) == NULL)
   {
     mutt_perror (fname);
     return (-1);
   }
 
-  if (stat (fname, &sb) != 0)
+  if (stat (fname, &rd.sb) != 0)
   {
     mutt_perror (fname);
-    safe_fclose (&fp);
+    safe_fclose (&rd.fp);
     return (-1);
   }
   unlink (fname);
@@ -1640,14 +1936,14 @@
     mutt_set_flag (Context, extra->hdr, MUTT_READ, 1);
   }
 
-  lineInfo = safe_malloc (sizeof (struct line_t) * (maxLine = LINES));
-  for (i = 0 ; i < maxLine ; i++)
+  rd.lineInfo = safe_malloc (sizeof (struct line_t) * (rd.maxLine = LINES));
+  for (i = 0 ; i < rd.maxLine ; i++)
   {
-    memset (&lineInfo[i], 0, sizeof (struct line_t));
-    lineInfo[i].type = -1;
-    lineInfo[i].search_cnt = -1;
-    lineInfo[i].syntax = safe_malloc (sizeof (struct syntax_t));
-    (lineInfo[i].syntax)[0].first = (lineInfo[i].syntax)[0].last = -1;
+    memset (&rd.lineInfo[i], 0, sizeof (struct line_t));
+    rd.lineInfo[i].type = -1;
+    rd.lineInfo[i].search_cnt = -1;
+    rd.lineInfo[i].syntax = safe_malloc (sizeof (struct syntax_t));
+    (rd.lineInfo[i].syntax)[0].first = (rd.lineInfo[i].syntax)[0].last = -1;
   }
 
   mutt_compile_help (helpstr, sizeof (helpstr), MENU_PAGER, PagerHelp);
@@ -1664,246 +1960,21 @@
     snprintf (helpstr, sizeof (helpstr), "%s %s", tmphelp, buffer);
   }
 
-  index_status_window = safe_calloc (sizeof (mutt_window_t), 1);
-  index_window        = safe_calloc (sizeof (mutt_window_t), 1);
-  pager_status_window = safe_calloc (sizeof (mutt_window_t), 1);
-  pager_window        = safe_calloc (sizeof (mutt_window_t), 1);
+  rd.index_status_window = safe_calloc (sizeof (mutt_window_t), 1);
+  rd.index_window        = safe_calloc (sizeof (mutt_window_t), 1);
+  rd.pager_status_window = safe_calloc (sizeof (mutt_window_t), 1);
+  rd.pager_window        = safe_calloc (sizeof (mutt_window_t), 1);
 
   pager_menu = mutt_new_menu (MENU_PAGER);
+  pager_menu->custom_menu_redraw = pager_menu_redraw;
+  pager_menu->redraw_data = &rd;
   mutt_push_current_menu (pager_menu);
 
   while (ch != -1)
   {
     mutt_curs_set (0);
 
-    if (pager_menu->redraw & REDRAW_FULL)
-    {
-#if ! (defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM))
-      mutt_reflow_windows ();
-#endif
-      NORMAL_COLOR;
-      /* clear() doesn't optimize screen redraws */
-      move (0, 0);
-      clrtobot ();
-
-      if (IsHeader (extra) && Context->vcount + 1 < PagerIndexLines)
-       indexlen = Context->vcount + 1;
-      else
-       indexlen = PagerIndexLines;
-
-      indicator = indexlen / 3;
-
-      memcpy (pager_window, MuttIndexWindow, sizeof(mutt_window_t));
-      memcpy (pager_status_window, MuttStatusWindow, sizeof(mutt_window_t));
-      index_status_window->rows = index_window->rows = 0;
-
-      if (IsHeader (extra) && PagerIndexLines)
-      {
-        memcpy (index_window, MuttIndexWindow, sizeof(mutt_window_t));
-        index_window->rows = indexlen > 0 ? indexlen - 1 : 0;
-
-        if (option (OPTSTATUSONTOP))
-        {
-          memcpy (index_status_window, MuttStatusWindow, 
sizeof(mutt_window_t));
-
-          memcpy (pager_status_window, MuttIndexWindow, sizeof(mutt_window_t));
-          pager_status_window->rows = 1;
-          pager_status_window->row_offset += index_window->rows;
-
-          pager_window->rows -= index_window->rows + pager_status_window->rows;
-          pager_window->row_offset += index_window->rows + 
pager_status_window->rows;
-        }
-        else
-        {
-          memcpy (index_status_window, MuttIndexWindow, sizeof(mutt_window_t));
-          index_status_window->rows = 1;
-          index_status_window->row_offset += index_window->rows;
-
-          pager_window->rows -= index_window->rows + index_status_window->rows;
-          pager_window->row_offset += index_window->rows + 
index_status_window->rows;
-        }
-      }
-
-      if (option (OPTHELP))
-      {
-       SETCOLOR (MT_COLOR_STATUS);
-       mutt_window_move (MuttHelpWindow, 0, 0);
-       mutt_paddstr (MuttHelpWindow->cols, helpstr);
-       NORMAL_COLOR;
-      }
-
-#if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM)
-      if (Resize != NULL)
-      {
-       if ((SearchCompiled = Resize->SearchCompiled))
-       {
-         REGCOMP
-           (&SearchRE, searchbuf, REG_NEWLINE | mutt_which_case (searchbuf));
-         SearchFlag = MUTT_SEARCH;
-         SearchBack = Resize->SearchBack;
-       }
-       lines = Resize->line;
-       pager_menu->redraw |= REDRAW_SIGWINCH;
-
-       FREE (&Resize);
-      }
-#endif
-
-      if (IsHeader (extra) && PagerIndexLines)
-      {
-       if (index == NULL)
-       {

Reply via email to