On Tue, Apr 19, 2016 at 12:21:19PM -0700, Kevin J. McCarthy wrote: > 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.
Attaching an updated part-06 patch. Added a reflow when resizeterm is not available. -- Kevin J. McCarthy GPG Fingerprint: 8975 A9B3 3AA3 7910 385C 5308 ADEF 7684 8031 6BDA http://www.8t8.us/configs/gpg-key-transition-statement.txt
# HG changeset patch # User Kevin McCarthy <ke...@8t8.us> # Date 1461362827 25200 # Fri Apr 22 15:07:07 2016 -0700 # Node ID a76985b6f06197c9eb14cbce51070be12bae56ce # Parent 2a3622a1e4ddb6cc281fbd092008585b17372ce5 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. diff --git a/copy.c b/copy.c --- a/copy.c +++ b/copy.c @@ -283,17 +283,18 @@ /* We couldn't do the prefixing when reading because RFC 2047 * decoding may have concatenated lines. */ 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; } } else { if (fputs (headers[x], out) == EOF) diff --git a/mutt_curses.h b/mutt_curses.h --- a/mutt_curses.h +++ b/mutt_curses.h @@ -183,24 +183,24 @@ 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); -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; extern int ColorQuoteUsed; extern int ColorDefs[]; extern COLOR_LINE *ColorHdrList; extern COLOR_LINE *ColorBodyList; extern COLOR_LINE *ColorIndexList; diff --git a/pager.c b/pager.c --- a/pager.c +++ b/pager.c @@ -1087,28 +1087,29 @@ *q = 0; } return b_read; } 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; size_t k; 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)); for (ch = 0, vch = 0; ch < cnt; ch += k, vch += k) { /* Handle ANSI sequences */ while (cnt-ch >= 2 && buf[ch] == '\033' && buf[ch+1] == '[' && @@ -1279,17 +1280,18 @@ * -1 EOF was reached * 0 normal exit, line was not displayed * >0 normal exit, line was displayed */ 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; unsigned char *buf_ptr = buf; int ch, vch, col, cnt, b_read; int buf_ready = 0, change_last = 0; int special; int offset; @@ -1415,17 +1417,18 @@ &buflen, &buf_ready)) < 0) { if (change_last) (*last)--; goto out; } /* 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 */ if (option (OPTWRAP)) { if (cnt < b_read) { if (ch != -1 && buf[0] != ' ' && buf[0] != '\t' && @@ -1462,29 +1465,30 @@ /* if we don't need to display the line we are done */ if (!(flags & M_SHOW)) { rc = 0; goto out; } /* 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 if (col == 0) { NORMAL_COLOR; addch (' '); } #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); /* * Fill the blank space at the end of the line with the prevailing color. * ncurses does an implicit clrtoeol() when you do addch('\n') so we have * to make sure to reset the color *after* that */ if (flags & M_SHOWCOLOR) @@ -1498,17 +1502,17 @@ ATTRSET(def_color); } /* ncurses always wraps lines when you get to the right side of the * screen, but S-Lang seems to only wrap if the next character is *not* * a newline (grr!). */ #ifndef USE_SLANG_CURSES - if (col < COLS) + if (col < pager_window->cols) #endif addch ('\n'); /* * reset the color back to normal. This *must* come after the * addch('\n'), otherwise the color for this line will not be * filled to the right margin. */ @@ -1578,23 +1582,22 @@ 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 & 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 * while inside the pager... */ if (!(flags & M_SHOWCOLOR)) flags |= M_SHOWFLAT; @@ -1639,60 +1642,88 @@ } if (!InHelp) { strfcpy (tmphelp, helpstr, sizeof (tmphelp)); mutt_make_help (buffer, sizeof (buffer), _("Help"), MENU_PAGER, OP_HELP); 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); clrtobot (); if (IsHeader (extra) && Context->vcount + 1 < PagerIndexLines) indexlen = Context->vcount + 1; else indexlen = PagerIndexLines; 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; } #if defined (USE_SLANG_CURSES) || defined (HAVE_RESIZETERM) if (Resize != NULL) { if ((SearchCompiled = Resize->SearchCompiled)) { @@ -1714,22 +1745,21 @@ { /* only allocate the space if/when we need the index. Initialise the menu as per the main index */ index = mutt_new_menu(MENU_MAIN); index->make_entry = index_make_entry; 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) index->top = 0; else if (index->max - index->current < index->pagelen - indicator) index->top = index->max - index->pagelen; else index->top = index->current - indicator; @@ -1742,53 +1772,56 @@ } if (redraw & REDRAW_SIGWINCH) { i = -1; 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; if (!SearchFlag) break; } } 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; /* We are going to update the pager status bar, so it isn't * necessary to reset to normal color now. */ redraw |= REDRAW_STATUS; /* need to update the % seen */ } @@ -1802,32 +1835,32 @@ hfi.pager_progress = pager_progress_str; if (last_pos < sb.st_size - 1) snprintf(pager_progress_str, sizeof(pager_progress_str), OFF_T_FMT "%%", (100 * last_offset / sb.st_size)); else 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) { menu_status_line (buffer, sizeof (buffer), index, NONULL (TSStatusFormat)); mutt_ts_status(buffer); menu_status_line (buffer, sizeof (buffer), index, NONULL (TSIconFormat)); mutt_ts_icon(buffer); @@ -1838,30 +1871,31 @@ { /* redraw the pager_index indicator, because the * flags for this message might have changed. */ menu_redraw_current (index); /* 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; } redraw = 0; if (option(OPTBRAILLEFRIENDLY)) { if (brailleLine!=-1) { 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 && lineInfo[curline].offset < sb.st_size-1) { if (TopLine - topline > lines) topline += lines; else @@ -1972,17 +2006,17 @@ rc = OP_MAIN_NEXT_UNDELETED; ch = -1; } break; 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."); break; case OP_NEXT_LINE: if (lineInfo[curline].offset < sb.st_size-1) { @@ -2009,25 +2043,25 @@ if (topline) topline = 0; else mutt_error _("Top of message is shown."); break; 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; 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)) { /* emulate "less -q" and don't go on to the next message. */ mutt_error _("Bottom of message is shown."); } else { @@ -2038,17 +2072,17 @@ break; case OP_SEARCH_NEXT: case OP_SEARCH_OPPOSITE: if (SearchCompiled) { wrapped = 0; - if (SearchContext > 0 && SearchContext < LINES - 2 - option (OPTHELP) ? 1 : 0) + if (SearchContext > 0 && SearchContext < pager_window->rows) searchctx = SearchContext; else searchctx = 0; search_next: if ((!SearchBack && ch==OP_SEARCH_NEXT) || (SearchBack &&ch==OP_SEARCH_OPPOSITE)) { @@ -2169,17 +2203,17 @@ else { SearchCompiled = 1; /* update the search pointers */ i = 0; 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) { /* searching forward */ for (i = topline; i < lastLine; i++) { if ((!hideQuoted || lineInfo[i].type != MT_COLOR_QUOTED) && @@ -2206,17 +2240,17 @@ { SearchFlag = 0; mutt_error _("Not found."); } else { 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; if (topline - searchctx > 0) topline -= searchctx; } } @@ -2259,30 +2293,30 @@ if (has_types) { int dretval = 0; int new_topline = topline; 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++; if (dretval < 0) { mutt_error _("No more quoted text."); break; } 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++; if (dretval < 0) { mutt_error _("No more unquoted text after quoted text."); break; } @@ -2293,19 +2327,19 @@ case OP_PAGER_BOTTOM: /* move to the end of the file */ if (lineInfo[curline].offset < sb.st_size - 1) { i = curline; /* make sure the types are defined to the end of file */ 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."); break; case OP_REDRAW: clearok (stdscr, TRUE); redraw = REDRAW_FULL; @@ -2494,17 +2528,17 @@ /* try to keep the old position */ topline = 0; lastLine = 0; while (j > 0 && display_line (fp, &last_pos, &lineInfo, topline, &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--; if (j > 0) topline++; } ch = 0; @@ -2819,10 +2853,16 @@ if (SearchCompiled) { regfree (&SearchRE); SearchCompiled = 0; } 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 --- a/rfc3676.c +++ b/rfc3676.c @@ -143,17 +143,17 @@ fst->spaces = 0; } /* Calculate the paragraph width based upon the current quote level. The start * of a quoted line will be ">>> ", so we need to subtract the space required * 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 * guidelines */ if (width > FLOWED_MAX) width = FLOWED_MAX; ++ql; /* When replying, we will add an additional quote level */ }
signature.asc
Description: PGP signature