X-Git-Url: https://git.llucax.com/software/mutt-debian.git/blobdiff_plain/14c29200cb58d3c4a0830265f2433849781858d0..299d2b65f257d19159e3adeaf5d62af7e96e0ec6:/pager.c diff --git a/pager.c b/pager.c index c88b5d4..61fe096 100644 --- a/pager.c +++ b/pager.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1996-2002 Michael R. Elkins + * Copyright (C) 1996-2002,2007 Michael R. Elkins * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,17 +26,10 @@ #include "keymap.h" #include "mutt_menu.h" #include "mapping.h" -#include "sort.h" #include "pager.h" #include "attach.h" #include "mbyte.h" -#include "mx.h" - -#ifdef USE_IMAP -#include "imap_private.h" -#endif - #include "mutt_crypt.h" #include @@ -819,8 +812,14 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last, if (lineInfo[n].type == MT_COLOR_NORMAL || lineInfo[n].type == MT_COLOR_QUOTED) { - i = 0; + size_t nl; + /* don't consider line endings part of the buffer + * for regex matching */ + if ((nl = mutt_strlen (buf)) > 0 && buf[nl-1] == '\n') + buf[nl-1] = 0; + + i = 0; offset = 0; lineInfo[n].chunks = 0; do @@ -870,6 +869,8 @@ resolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last, else offset = (lineInfo[n].syntax)[i].last; } while (found || null_rx); + if (nl > 0) + buf[nl] = '\n'; } } @@ -995,18 +996,18 @@ trim_incomplete_mbyte(unsigned char *buf, size_t len) } static int -fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char *buf, - unsigned char *fmt, size_t blen, int *buf_ready) +fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char **buf, + unsigned char **fmt, size_t *blen, int *buf_ready) { - unsigned char *p; + unsigned char *p, *q; static int b_read; - + int l; + if (*buf_ready == 0) { - buf[blen - 1] = 0; if (offset != *last_pos) fseeko (f, offset, 0); - if (fgets ((char *) buf, blen - 1, f) == NULL) + if ((*buf = (unsigned char *) mutt_read_line ((char *) *buf, blen, f, &l, M_EOL)) == NULL) { fmt[0] = 0; return (-1); @@ -1015,26 +1016,29 @@ fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char *buf, b_read = (int) (*last_pos - offset); *buf_ready = 1; + safe_realloc (fmt, *blen); + /* incomplete mbyte characters trigger a segfault in regex processing for * certain versions of glibc. Trim them if necessary. */ - if (b_read == blen - 2) - b_read -= trim_incomplete_mbyte(buf, b_read); + if (b_read == *blen - 2) + b_read -= trim_incomplete_mbyte(*buf, b_read); /* copy "buf" to "fmt", but without bold and underline controls */ - p = buf; + p = *buf; + q = *fmt; while (*p) { - if (*p == '\010' && (p > buf)) + if (*p == '\010' && (p > *buf)) { if (*(p+1) == '_') /* underline */ p += 2; else if (*(p+1)) /* bold or overstrike */ { - *(fmt-1) = *(p+1); + *(q-1) = *(p+1); p += 2; } else /* ^H */ - *fmt++ = *p++; + *q++ = *p++; } else if (*p == '\033' && *(p+1) == '[' && is_ansi (p + 2)) { @@ -1048,9 +1052,9 @@ fill_buffer (FILE *f, LOFF_T *last_pos, LOFF_T offset, unsigned char *buf, ; } else - *fmt++ = *p++; + *q++ = *p++; } - *fmt = 0; + *q = 0; } return b_read; } @@ -1106,6 +1110,12 @@ static int format_line (struct line_t **lineInfo, int n, unsigned char *buf, if (k == 0) k = 1; + if (Charset_is_utf8 && (wc == 0x200B || wc == 0xFEFF)) + { + dprint (3, (debugfile, "skip zero-width character U+%04X\n", (unsigned short)wc)); + continue; + } + /* Handle backspace */ special = 0; if (IsWPrint (wc)) @@ -1229,7 +1239,8 @@ 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) { - unsigned char buf[LONG_STRING], fmt[LONG_STRING]; + 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; @@ -1237,6 +1248,7 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, int offset; int def_color; int m; + int rc = -1; ansi_attr a = {0,0,0,-1}; regmatch_t pmatch[1]; @@ -1265,11 +1277,11 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, if ((*lineInfo)[n].type == -1) { /* determine the line class */ - if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0) + if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, &buf, &fmt, &buflen, &buf_ready) < 0) { if (change_last) (*last)--; - return (-1); + goto out; } resolve_types ((char *) fmt, (char *) buf, *lineInfo, n, *last, @@ -1294,11 +1306,11 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, if ((flags & M_SHOWCOLOR) && !(*lineInfo)[n].continuation && (*lineInfo)[n].type == MT_COLOR_QUOTED && (*lineInfo)[n].quote == NULL) { - if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0) + if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, &buf, &fmt, &buflen, &buf_ready) < 0) { if (change_last) (*last)--; - return (-1); + goto out; } regexec ((regex_t *) QuoteRegexp.rx, (char *) fmt, 1, pmatch, 0); (*lineInfo)[n].quote = classify_quote (QuoteList, @@ -1309,11 +1321,11 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, if ((flags & M_SEARCH) && !(*lineInfo)[n].continuation && (*lineInfo)[n].search_cnt == -1) { - if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, sizeof (buf), &buf_ready) < 0) + if (fill_buffer (f, last_pos, (*lineInfo)[n].offset, &buf, &fmt, &buflen, &buf_ready) < 0) { if (change_last) (*last)--; - return (-1); + goto out; } offset = 0; @@ -1342,20 +1354,22 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, if (!(flags & M_SHOW) && (*lineInfo)[n+1].offset > 0) { /* we've already scanned this line, so just exit */ - return (0); + rc = 0; + goto out; } if ((flags & M_SHOWCOLOR) && *force_redraw && (*lineInfo)[n+1].offset > 0) { /* no need to try to display this line... */ - return (1); /* fake display */ + rc = 1; + goto out; /* fake display */ } - if ((b_read = fill_buffer (f, last_pos, (*lineInfo)[n].offset, buf, fmt, - sizeof (buf), &buf_ready)) < 0) + if ((b_read = fill_buffer (f, last_pos, (*lineInfo)[n].offset, &buf, &fmt, + &buflen, &buf_ready)) < 0) { if (change_last) (*last)--; - return (-1); + goto out; } /* now chose a good place to break the line */ @@ -1399,7 +1413,10 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, /* if we don't need to display the line we are done */ if (!(flags & M_SHOW)) - return 0; + { + rc = 0; + goto out; + } /* display the line */ format_line (lineInfo, n, buf, flags, &a, cnt, &ch, &vch, &col, &special); @@ -1460,7 +1477,12 @@ display_line (FILE *f, LOFF_T *last_pos, struct line_t **lineInfo, int n, if (!(flags & M_SHOW)) flags = 0; - return (flags); + rc = flags; + +out: + FREE(&buf); + FREE(&fmt); + return rc; } static int @@ -1500,7 +1522,7 @@ static struct mapping_t PagerHelpExtra[] = { int mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) { - static char searchbuf[STRING]; + static char searchbuf[STRING] = ""; char buffer[LONG_STRING]; char helpstr[SHORT_STRING*2]; char tmphelp[SHORT_STRING*2]; @@ -1509,7 +1531,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) 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 r = -1; + int r = -1, wrapped = 0, searchctx = 0; int redraw = REDRAW_FULL; FILE *fp = NULL; LOFF_T last_pos = 0, last_offset = 0; @@ -1543,7 +1565,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) if (stat (fname, &sb) != 0) { mutt_perror (fname); - fclose (fp); + safe_fclose (&fp); return (-1); } unlink (fname); @@ -1584,10 +1606,6 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) { mutt_curs_set (0); -#ifdef USE_IMAP - imap_keepalive (); -#endif - if (redraw & REDRAW_FULL) { SETCOLOR (MT_COLOR_NORMAL); @@ -1654,8 +1672,7 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) { /* only allocate the space if/when we need the index. Initialise the menu as per the main index */ - index = mutt_new_menu(); - index->menu = MENU_MAIN; + index = mutt_new_menu(MENU_MAIN); index->make_entry = index_make_entry; index->color = index_color; index->max = Context->vcount; @@ -1750,21 +1767,21 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) SETCOLOR (MT_COLOR_STATUS); BKGDSET (MT_COLOR_STATUS); CLEARLINE (statusoffset); - if (IsHeader (extra)) + + if (IsHeader (extra) || IsMsgAttach (extra)) { size_t l1 = COLS * MB_LEN_MAX; size_t l2 = sizeof (buffer); - hfi.hdr = extra->hdr; + 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); } - else if (IsMsgAttach (extra)) + else { - size_t l1 = COLS * MB_LEN_MAX; - size_t l2 = sizeof (buffer); - hfi.hdr = extra->bdy->hdr; - mutt_make_string_info (buffer, l1 < l2 ? l1 : l2, NONULL (PagerFmt), &hfi, M_FORMAT_MAKEPRINT); + char bn[STRING]; + snprintf (bn, sizeof (bn), "%s (%s)", banner, pager_progress_str); + mutt_paddstr (COLS, bn); } - mutt_paddstr (COLS, IsHeader (extra) || IsMsgAttach (extra) ? buffer : banner); BKGDSET (MT_COLOR_NORMAL); SETCOLOR (MT_COLOR_NORMAL); } @@ -1969,12 +1986,19 @@ mutt_pager (const char *banner, const char *fname, int flags, pager_t *extra) case OP_SEARCH_OPPOSITE: if (SearchCompiled) { + wrapped = 0; + + if (SearchContext > 0 && SearchContext < LINES - 2 - option (OPTHELP) ? 1 : 0) + searchctx = SearchContext; + else + searchctx = 0; + search_next: if ((!SearchBack && ch==OP_SEARCH_NEXT) || (SearchBack &&ch==OP_SEARCH_OPPOSITE)) { /* searching forward */ - for (i = topline + 1; i < lastLine; i++) + for (i = wrapped ? 0 : topline + searchctx + 1; i < lastLine; i++) { if ((!hideQuoted || lineInfo[i].type != MT_COLOR_QUOTED) && !lineInfo[i].continuation && lineInfo[i].search_cnt > 0) @@ -1983,13 +2007,19 @@ search_next: if (i < lastLine) topline = i; - else + else if (wrapped || !option (OPTWRAPSEARCH)) mutt_error _("Not found."); + else + { + mutt_message _("Search wrapped to top."); + wrapped = 1; + goto search_next; + } } else { /* searching backward */ - for (i = topline - 1; i >= 0; i--) + for (i = wrapped ? lastLine : topline + searchctx - 1; i >= 0; i--) { if ((!hideQuoted || (has_types && lineInfo[i].type != MT_COLOR_QUOTED)) && @@ -1999,12 +2029,23 @@ search_next: if (i >= 0) topline = i; - else + else if (wrapped || !option (OPTWRAPSEARCH)) mutt_error _("Not found."); + else + { + mutt_message _("Search wrapped to bottom."); + wrapped = 1; + goto search_next; + } } if (lineInfo[topline].search_cnt > 0) + { SearchFlag = M_SEARCH; + /* give some context for search results */ + if (topline - searchctx > 0) + topline -= searchctx; + } break; } @@ -2013,9 +2054,10 @@ search_next: case OP_SEARCH: case OP_SEARCH_REVERSE: strfcpy (buffer, searchbuf, sizeof (buffer)); - if (mutt_get_field ((SearchBack ? _("Reverse search: ") : - _("Search: ")), buffer, sizeof (buffer), - M_CLEAR) != 0) + if (mutt_get_field ((ch == OP_SEARCH || ch == OP_SEARCH_NEXT) ? + _("Search for: ") : _("Reverse search for: "), + buffer, sizeof (buffer), + M_CLEAR) != 0) break; if (!strcmp (buffer, searchbuf)) @@ -2028,6 +2070,7 @@ search_next: else ch = OP_SEARCH_OPPOSITE; + wrapped = 0; goto search_next; } } @@ -2111,7 +2154,17 @@ search_next: mutt_error _("Not found."); } else + { SearchFlag = M_SEARCH; + /* give some context for search results */ + if (SearchContext > 0 && SearchContext < LINES - 2 - option (OPTHELP) ? 1 : 0) + searchctx = SearchContext; + else + searchctx = 0; + if (topline - searchctx > 0) + topline -= searchctx; + } + } redraw = REDRAW_BODY; break; @@ -2272,6 +2325,20 @@ search_next: } break; + case OP_MAIN_SET_FLAG: + case OP_MAIN_CLEAR_FLAG: + CHECK_MODE(IsHeader (extra)); + CHECK_READONLY; + + if (mutt_change_flag (extra->hdr, (ch == OP_MAIN_SET_FLAG)) == 0) + redraw |= REDRAW_STATUS | REDRAW_INDEX; + if (extra->hdr->deleted && option (OPTRESOLVE)) + { + ch = -1; + rc = OP_MAIN_NEXT_UNDELETED; + } + break; + case OP_DELETE_THREAD: case OP_DELETE_SUBTHREAD: CHECK_MODE(IsHeader (extra)); @@ -2658,13 +2725,17 @@ search_next: redraw = REDRAW_FULL; break; + case OP_WHAT_KEY: + mutt_what_key (); + break; + default: ch = -1; break; } } - fclose (fp); + safe_fclose (&fp); if (IsHeader (extra)) { Context->msgnotreadyet = -1;