From 746bc982497eee813400d7aa08f838d133486186 Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Wed, 27 Apr 2016 17:56:55 -0700 Subject: [PATCH] Modify the pager to use windows. The pager view is somewhat complex, due to the "mini-index" and the positioning of the index_status vs pager_status changes depending on $status_on_top as well as $pager_index_lines and $help. To make things simpler, it creates four "pager windows": index_status_window, index_window, pager_status_window, pager_window. mutt_term_width() is renamed to mutt_window_wrap_cols() and a mutt_window_t parameter passed in. Also, the pager drawing loop calling display_line() has a mutt_window_move() added to move to the beginning of the next line each time. This is in case the pager_window isn't flush with the left side of the terminal. --- copy.c | 3 +- mutt_curses.h | 8 +-- pager.c | 152 +++++++++++++++++++++++++++++++------------------- rfc3676.c | 2 +- 4 files changed, 103 insertions(+), 62 deletions(-) diff --git a/copy.c b/copy.c index 360c1a42..8e4ffa51 100644 --- a/copy.c +++ b/copy.c @@ -288,7 +288,8 @@ mutt_copy_hdr (FILE *in, FILE *out, LOFF_T off_start, LOFF_T off_end, int flags, if (flags & (CH_DECODE|CH_PREFIX)) { if (mutt_write_one_header (out, 0, headers[x], - flags & CH_PREFIX ? prefix : 0, mutt_term_width (Wrap), flags) == -1) + flags & CH_PREFIX ? prefix : 0, + mutt_window_wrap_cols (MuttIndexWindow, Wrap), flags) == -1) { error = TRUE; break; diff --git a/mutt_curses.h b/mutt_curses.h index 2d2fb280..1156c4ac 100644 --- a/mutt_curses.h +++ b/mutt_curses.h @@ -189,14 +189,14 @@ 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) +static inline int mutt_window_wrap_cols(mutt_window_t *win, short wrap) { if (wrap < 0) - return COLS > -wrap ? COLS + wrap : COLS; + return win->cols > -wrap ? win->cols + wrap : win->cols; else if (wrap) - return wrap < COLS ? wrap : COLS; + return wrap < win->cols ? wrap : win->cols; else - return COLS; + return win->cols; } extern int *ColorQuote; diff --git a/pager.c b/pager.c index bc74578f..50e36b75 100644 --- a/pager.c +++ b/pager.c @@ -1092,7 +1092,8 @@ fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char **buf, static int format_line (struct line_t **lineInfo, int n, unsigned char *buf, int flags, ansi_attr *pa, int cnt, - int *pspace, int *pvch, int *pcol, int *pspecial) + int *pspace, int *pvch, int *pcol, int *pspecial, + mutt_window_t *pager_window) { int space = -1; /* index of the last space or TAB */ int col = option (OPTMARKERS) ? (*lineInfo)[n].continuation : 0; @@ -1100,10 +1101,10 @@ static int format_line (struct line_t **lineInfo, int n, unsigned char *buf, int ch, vch, last_special = -1, special = 0, t; wchar_t wc; mbstate_t mbstate; - int wrap_cols = mutt_term_width ((flags & M_PAGER_NOWRAP) ? 0 : Wrap); + int wrap_cols = mutt_window_wrap_cols (pager_window, (flags & M_PAGER_NOWRAP) ? 0 : Wrap); if (check_attachment_marker ((char *)buf) == 0) - wrap_cols = COLS; + wrap_cols = pager_window->cols; /* FIXME: this should come from lineInfo */ memset(&mbstate, 0, sizeof(mbstate)); @@ -1284,7 +1285,8 @@ static int format_line (struct line_t **lineInfo, int n, unsigned char *buf, static int display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, int *last, int *max, int flags, struct q_class_t **QuoteList, - int *q_level, int *force_redraw, regex_t *SearchRE) + int *q_level, int *force_redraw, regex_t *SearchRE, + mutt_window_t *pager_window) { unsigned char *buf = NULL, *fmt = NULL; size_t buflen = 0; @@ -1420,7 +1422,8 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, } /* now chose a good place to break the line */ - cnt = format_line (lineInfo, n, buf, flags, 0, b_read, &ch, &vch, &col, &special); + cnt = format_line (lineInfo, n, buf, flags, 0, b_read, &ch, &vch, &col, &special, + pager_window); buf_ptr = buf + cnt; /* move the break point only if smart_wrap is set */ @@ -1467,7 +1470,8 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, } /* display the line */ - format_line (lineInfo, n, buf, flags, &a, cnt, &ch, &vch, &col, &special); + format_line (lineInfo, n, buf, flags, &a, cnt, &ch, &vch, &col, &special, + pager_window); /* avoid a bug in ncurses... */ #ifndef USE_SLANG_CURSES @@ -1479,7 +1483,7 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, #endif /* end the last color pattern (needed by S-Lang) */ - if (special || (col != COLS && (flags & (M_SHOWCOLOR | M_SEARCH)))) + if (special || (col != pager_window->cols && (flags & (M_SHOWCOLOR | M_SEARCH)))) resolve_color (*lineInfo, n, vch, flags, 0, &a); /* @@ -1503,7 +1507,7 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, * a newline (grr!). */ #ifndef USE_SLANG_CURSES - if (col < COLS) + if (col < pager_window->cols) #endif addch ('\n'); @@ -1583,13 +1587,12 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) int SearchCompiled = 0, SearchFlag = 0, SearchBack = 0; int has_types = (IsHeader(extra) || (flags & M_SHOWCOLOR)) ? M_TYPES : 0; /* main message or rfc822 attachment */ - int bodyoffset = 1; /* offset of first line of real text */ - int statusoffset = 0; /* offset for the status bar */ - int helpoffset = LINES - 2; /* offset for the help bar. */ - int bodylen = LINES - 2 - bodyoffset; /* length of displayable area */ + 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 *index = NULL; /* the Pager Index (PI) */ - int indexoffset = 0; /* offset for the 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 @@ -1644,12 +1647,20 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) 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); + while (ch != -1) { mutt_curs_set (0); if (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); @@ -1662,32 +1673,52 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) indicator = indexlen / 3; + if (IsHeader (extra) && PagerIndexLines) + { + memcpy (index_window, MuttIndexWindow, sizeof(mutt_window_t)); + index_window->rows = indexlen > 0 ? indexlen - 1 : 0; + } + else + index_status_window->rows = index_window->rows = 0; + if (option (OPTSTATUSONTOP)) { - indexoffset = 0; - statusoffset = IsHeader (extra) ? indexlen : 0; - bodyoffset = statusoffset + 1; - helpoffset = LINES - 2; - bodylen = helpoffset - bodyoffset; - if (!option (OPTHELP)) - bodylen++; + if (IsHeader (extra) && PagerIndexLines) + { + 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; + } + else + memcpy (pager_status_window, MuttStatusWindow, sizeof(mutt_window_t)); + + memcpy (pager_window, MuttIndexWindow, sizeof(mutt_window_t)); + pager_window->rows -= index_window->rows + pager_status_window->rows; + pager_window->row_offset += index_window->rows + pager_status_window->rows; } else { - helpoffset = 0; - indexoffset = 1; - statusoffset = LINES - 2; - if (!option (OPTHELP)) - indexoffset = 0; - bodyoffset = indexoffset + (IsHeader (extra) ? indexlen : 0); - bodylen = statusoffset - bodyoffset; + if (IsHeader (extra) && PagerIndexLines) + { + memcpy (index_status_window, MuttIndexWindow, sizeof(mutt_window_t)); + index_status_window->rows = 1; + index_status_window->row_offset += index_window->rows; + } + + memcpy (pager_status_window, MuttStatusWindow, sizeof(mutt_window_t)); + + memcpy (pager_window, MuttIndexWindow, sizeof(mutt_window_t)); + 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); - move (helpoffset, 0); - mutt_paddstr (COLS, helpstr); + mutt_window_move (MuttHelpWindow, 0, 0); + mutt_paddstr (MuttHelpWindow->cols, helpstr); NORMAL_COLOR; } @@ -1719,12 +1750,11 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) index->color = index_color; index->max = Context->vcount; index->current = extra->hdr->virtual; + index->indexwin = index_window; } NORMAL_COLOR; - index->offset = indexoffset + (option (OPTSTATUSONTOP) ? 1 : 0); - - index->pagelen = indexlen - 1; + index->pagelen = index_window->rows;; /* some fudge to work out where abouts the indicator should go */ if (index->current - indicator < 0) @@ -1747,7 +1777,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) j = -1; while (display_line (fp, &last_pos, &lineInfo, ++i, &lastLine, &maxLine, has_types | SearchFlag | (flags & M_PAGER_NOWRAP), &QuoteList, &q_level, &force_redraw, - &SearchRE) == 0) + &SearchRE, pager_window) == 0) if (!lineInfo[i].continuation && ++j == lines) { topline = i; @@ -1759,31 +1789,34 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) if ((redraw & REDRAW_BODY) || topline != oldtopline) { do { - move (bodyoffset, 0); + mutt_window_move (pager_window, 0, 0); curline = oldtopline = topline; lines = 0; force_redraw = 0; - while (lines < bodylen && lineInfo[curline].offset <= sb.st_size - 1) + while (lines < pager_window->rows && lineInfo[curline].offset <= sb.st_size - 1) { if (display_line (fp, &last_pos, &lineInfo, curline, &lastLine, &maxLine, (flags & M_DISPLAYFLAGS) | hideQuoted | SearchFlag | (flags & M_PAGER_NOWRAP), - &QuoteList, &q_level, &force_redraw, &SearchRE) > 0) + &QuoteList, &q_level, &force_redraw, &SearchRE, + pager_window) > 0) lines++; curline++; + mutt_window_move (pager_window, lines, 0); } last_offset = lineInfo[curline].offset; } while (force_redraw); SETCOLOR (MT_COLOR_TILDE); - while (lines < bodylen) + while (lines < pager_window->rows) { - clrtoeol (); + mutt_window_clrtoeol (pager_window); if (option (OPTTILDE)) addch ('~'); addch ('\n'); lines++; + mutt_window_move (pager_window, lines, 0); } NORMAL_COLOR; @@ -1807,22 +1840,22 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) strfcpy(pager_progress_str, (topline == 0) ? "all" : "end", sizeof(pager_progress_str)); /* print out the pager status bar */ - move (statusoffset, 0); + mutt_window_move (pager_status_window, 0, 0); SETCOLOR (MT_COLOR_STATUS); if (IsHeader (extra) || IsMsgAttach (extra)) { - size_t l1 = COLS * MB_LEN_MAX; + size_t l1 = pager_status_window->cols * MB_LEN_MAX; size_t l2 = sizeof (buffer); hfi.hdr = (IsHeader (extra)) ? extra->hdr : extra->bdy->hdr; mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, NONULL (PagerFmt), &hfi, M_FORMAT_MAKEPRINT); - mutt_paddstr (COLS, buffer); + mutt_paddstr (pager_status_window->cols, buffer); } else { char bn[STRING]; snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str); - mutt_paddstr (COLS, bn); + mutt_paddstr (pager_status_window->cols, bn); } NORMAL_COLOR; if (option(OPTTSENABLED) && TSSupported) @@ -1843,9 +1876,9 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) /* print out the index status bar */ menu_status_line (buffer, sizeof (buffer), index, NONULL(Status)); - move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), 0); + mutt_window_move (index_status_window, 0, 0); SETCOLOR (MT_COLOR_STATUS); - mutt_paddstr (COLS, buffer); + mutt_paddstr (index_status_window->cols, buffer); NORMAL_COLOR; } @@ -1856,7 +1889,8 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) move(brailleLine+1, 0); brailleLine = -1; } - } else move (statusoffset, COLS-1); + } else + mutt_window_move (pager_status_window, 0, pager_status_window->cols-1); mutt_refresh (); if (IsHeader (extra) && OldHdr == extra->hdr && TopLine != topline @@ -1977,7 +2011,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) case OP_PREV_PAGE: if (topline != 0) { - topline = upNLines (bodylen-PagerContext, lineInfo, topline, hideQuoted); + topline = upNLines (pager_window->rows-PagerContext, lineInfo, topline, hideQuoted); } else mutt_error _("Top of message is shown."); @@ -2014,7 +2048,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) case OP_HALF_UP: if (topline) - topline = upNLines (bodylen/2, lineInfo, topline, hideQuoted); + topline = upNLines (pager_window->rows/2, lineInfo, topline, hideQuoted); else mutt_error _("Top of message is shown."); break; @@ -2022,7 +2056,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) case OP_HALF_DOWN: if (lineInfo[curline].offset < sb.st_size-1) { - topline = upNLines (bodylen/2, lineInfo, curline, hideQuoted); + topline = upNLines (pager_window->rows/2, lineInfo, curline, hideQuoted); } else if (option (OPTPAGERSTOP)) { @@ -2043,7 +2077,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) { wrapped = 0; - if (SearchContext > 0 && SearchContext < LINES - 2 - option (OPTHELP) ? 1 : 0) + if (SearchContext > 0 && SearchContext < pager_window->rows) searchctx = SearchContext; else searchctx = 0; @@ -2174,7 +2208,7 @@ search_next: while (display_line (fp, &last_pos, &lineInfo, i, &lastLine, &maxLine, M_SEARCH | (flags & M_PAGER_NSKIP) | (flags & M_PAGER_NOWRAP), &QuoteList, &q_level, - &force_redraw, &SearchRE) == 0) + &force_redraw, &SearchRE, pager_window) == 0) i++; if (!SearchBack) @@ -2211,7 +2245,7 @@ search_next: { SearchFlag = M_SEARCH; /* give some context for search results */ - if (SearchContext > 0 && SearchContext < LINES - 2 - option (OPTHELP) ? 1 : 0) + if (SearchContext > 0 && SearchContext < pager_window->rows) searchctx = SearchContext; else searchctx = 0; @@ -2264,7 +2298,7 @@ search_next: while ((new_topline < lastLine || (0 == (dretval = display_line (fp, &last_pos, &lineInfo, new_topline, &lastLine, &maxLine, M_TYPES | (flags & M_PAGER_NOWRAP), - &QuoteList, &q_level, &force_redraw, &SearchRE)))) + &QuoteList, &q_level, &force_redraw, &SearchRE, pager_window)))) && lineInfo[new_topline].type != MT_COLOR_QUOTED) new_topline++; @@ -2277,7 +2311,7 @@ search_next: while ((new_topline < lastLine || (0 == (dretval = display_line (fp, &last_pos, &lineInfo, new_topline, &lastLine, &maxLine, M_TYPES | (flags & M_PAGER_NOWRAP), - &QuoteList, &q_level, &force_redraw, &SearchRE)))) + &QuoteList, &q_level, &force_redraw, &SearchRE, pager_window)))) && lineInfo[new_topline].type == MT_COLOR_QUOTED) new_topline++; @@ -2298,9 +2332,9 @@ search_next: while (display_line (fp, &last_pos, &lineInfo, i, &lastLine, &maxLine, has_types | (flags & M_PAGER_NOWRAP), &QuoteList, &q_level, &force_redraw, - &SearchRE) == 0) + &SearchRE, pager_window) == 0) i++; - topline = upNLines (bodylen, lineInfo, lastLine, hideQuoted); + topline = upNLines (pager_window->rows, lineInfo, lastLine, hideQuoted); } else mutt_error _("Bottom of message is shown."); @@ -2499,7 +2533,7 @@ search_next: &lastLine, &maxLine, (has_types ? M_TYPES : 0) | (flags & M_PAGER_NOWRAP), &QuoteList, &q_level, &force_redraw, - &SearchRE) == 0) + &SearchRE, pager_window) == 0) { if (! lineInfo[topline].continuation) j--; @@ -2824,5 +2858,11 @@ search_next: FREE (&lineInfo); if (index) mutt_menuDestroy(&index); + + FREE (&index_status_window); + FREE (&index_window); + FREE (&pager_status_window); + FREE (&pager_window); + return (rc != -1 ? rc : 0); } diff --git a/rfc3676.c b/rfc3676.c index dd67f741..5ce9ffdf 100644 --- a/rfc3676.c +++ b/rfc3676.c @@ -148,7 +148,7 @@ static void flush_par (STATE *s, flowed_state_t *fst) * for the prefix from the terminal width. */ static int quote_width (STATE *s, int ql) { - int width = mutt_term_width (ReflowWrap); + int width = mutt_window_wrap_cols (MuttIndexWindow, ReflowWrap); if (option(OPTTEXTFLOWED) && (s->flags & M_REPLYING)) { /* When replying, force a wrap at FLOWED_MAX to comply with RFC3676 -- 2.40.0