60 const unsigned int NUM_SIG_LINES = 4;
61 unsigned int count = 0;
63 while ((offset > 0) && (count <= NUM_SIG_LINES))
74 if (count > NUM_SIG_LINES)
100 const int *cnt = (
const int *) m1;
103 if (*cnt < stx->
first)
105 if (*cnt >= stx->
last)
125 static struct AttrColor last_color = { 0 };
133 last_color.
attrs = A_NORMAL;
136 if (lines[line_num].cont_line)
139 if (!cnt && c_markers)
195 matching_chunk = bsearch(&cnt, lines[m].syntax, lines[m].syntax_arr_size,
197 if (matching_chunk && (cnt >= matching_chunk->
first) &&
198 (cnt < matching_chunk->last))
207 matching_chunk = bsearch(&cnt, lines[m].
search, lines[m].search_arr_size,
209 if (matching_chunk && (cnt >= matching_chunk->
first) &&
210 (cnt < matching_chunk->last))
218 if (special & A_BOLD)
223 color.
attrs |= A_BOLD;
225 else if (special & A_UNDERLINE)
230 color.
attrs |= A_UNDERLINE;
263 lines[line_num + 1].
cid = lines[line_num].
cid;
264 (lines[line_num + 1].
syntax)[0].attr_color = (lines[line_num].syntax)[0].attr_color;
268 for (m = line_num; m >= 0; m--)
269 if (!lines[m].cont_line)
272 (lines[line_num + 1].
syntax)[0].first = m;
273 (lines[line_num + 1].
syntax)[0].last = (lines[line_num].cont_line) ?
274 cnt + (lines[line_num].
syntax)[0].last :
286 for (; (p[0] == q[0]) && (q[0] !=
'\0') && (p[0] !=
'\0') && (q[0] !=
'\a') &&
292 return (
int) (*p - *q);
326 bool is_quote =
false;
328 regmatch_t pmatch_internal[1] = { 0 };
331 pmatch = pmatch_internal;
336 regmatch_t smatch[1] = { 0 };
339 if (smatch[0].rm_so > 0)
341 char c = line[smatch[0].rm_so];
342 line[smatch[0].rm_so] = 0;
347 line[smatch[0].rm_so] = c;
370 if ((buflen > 0) && (pat[buflen - 1] ==
'\n'))
373 pat[buflen - 1] =
'\0';
379 struct RegexColorList *head = NULL;
381 bool null_rx =
false;
382 regmatch_t pmatch[1] = { 0 };
401 if (offset >= (buflen - has_nl))
414 if ((regexec(&color_line->
regex, pat + offset, 1, pmatch,
415 ((offset != 0) ? REG_NOTBOL : 0)) != 0))
424 if (pmatch[0].rm_eo == pmatch[0].rm_so)
433 if (lines[line_num].syntax_arr_size == SHRT_MAX)
438 if (++(lines[line_num].syntax_arr_size) > 1)
441 lines[line_num].syntax_arr_size,
struct TextSyntax);
445 memset(ts, 0,
sizeof(*ts));
449 pmatch[0].rm_so += offset;
450 pmatch[0].rm_eo += offset;
452 if (!found || (pmatch[0].rm_so < (lines[line_num].syntax)[i].
first) ||
453 ((pmatch[0].rm_so == (lines[line_num].syntax)[i].
first) &&
454 (pmatch[0].rm_eo > (lines[line_num].syntax)[i].
last)))
457 (lines[line_num].
syntax)[i].
first = pmatch[0].rm_so;
458 (lines[line_num].
syntax)[i].
last = pmatch[0].rm_eo;
460 else if ((pmatch[0].rm_so == (lines[line_num].syntax)[i].
first) &&
461 (pmatch[0].rm_eo == (lines[line_num].syntax)[i].
last))
465 (lines[line_num].
syntax)[i].
first = pmatch[0].rm_so;
466 (lines[line_num].
syntax)[i].
last = pmatch[0].rm_eo;
477 }
while (found || null_rx);
480 pat[buflen - 1] =
'\n';
507 struct Line *lines,
int line_num,
int lines_used,
509 bool *force_redraw,
bool q_classify)
512 regmatch_t pmatch[1] = { 0 };
529 if ((line_num > 0) && ((buf[0] ==
' ') || (buf[0] ==
'\t')))
531 lines[line_num].
cid = lines[line_num - 1].
cid;
532 if (!c_header_color_partial)
534 (lines[line_num].
syntax)[0].attr_color =
535 (lines[line_num - 1].syntax)[0].attr_color;
547 if (!c_header_color_partial)
551 if (regexec(&color_line->
regex, buf, 0, NULL, 0) == 0)
558 lines[line_num].syntax[0].attr_color, &color_line->
attr_color);
559 if (lines[line_num].cont_header)
563 for (j = line_num - 1; j >= 0 && lines[j].
cont_header; j--)
565 lines[j].
cid = lines[line_num].
cid;
571 lines[j].
cid = lines[line_num].
cid;
574 *force_redraw =
true;
594 while ((i < lines_used) && (
check_sig(buf, lines, i - 1) == 0) &&
599 if (lines[i].syntax_arr_size)
610 else if (
check_sig(buf, lines, line_num - 1) == 0)
616 if (q_classify && !lines[line_num].quote)
619 pmatch[0].rm_eo - pmatch[0].rm_so,
620 force_redraw, q_level);
643 if ((nl > 0) && (buf[nl - 1] ==
'\n'))
651 bool null_rx =
false;
661 if (regexec(&color_line->
regex, buf + offset, 1, pmatch,
662 ((offset != 0) ? REG_NOTBOL : 0)) != 0)
667 if (pmatch[0].rm_eo != pmatch[0].rm_so)
671 if (++(lines[line_num].syntax_arr_size) > 1)
674 lines[line_num].syntax_arr_size,
struct TextSyntax);
678 memset(ts, 0,
sizeof(*ts));
682 pmatch[0].rm_so += offset;
683 pmatch[0].rm_eo += offset;
684 if (!found || (pmatch[0].rm_so < (lines[line_num].syntax)[i].
first) ||
685 ((pmatch[0].rm_so == (lines[line_num].syntax)[i].
first) &&
686 (pmatch[0].rm_eo > (lines[line_num].syntax)[i].
last)))
693 (lines[line_num].
syntax)[i].
first = pmatch[0].rm_so;
694 (lines[line_num].
syntax)[i].
last = pmatch[0].rm_eo;
696 else if ((pmatch[0].rm_so == (lines[line_num].syntax)[i].
first) &&
697 (pmatch[0].rm_eo == (lines[line_num].syntax)[i].
last))
701 (lines[line_num].
syntax)[i].
first = pmatch[0].rm_so;
702 (lines[line_num].
syntax)[i].
last = pmatch[0].rm_eo;
717 }
while (found || null_rx);
747 if ((s[0] ==
'\010') && (s > src))
753 else if (s[1] &&
buf_len(dest))
771 else if (strip_markers && (s[0] ==
'\033') && (s[1] ==
']') &&
797static int fill_buffer(FILE *fp, LOFF_T *bytes_read, LOFF_T offset,
unsigned char **buf,
798 unsigned char **fmt,
size_t *blen,
int *buf_ready)
800 static int b_read = 0;
804 if (offset != *bytes_read)
819 *bytes_read = ftello(fp);
820 LOFF_T diff = *bytes_read - offset;
821 b_read = (diff > INT_MAX) ? INT_MAX : (int) diff;
829 *fmt = (
unsigned char *)
buf_strdup(stripped);
855 int cnt,
int *pspace,
int *pvch,
int *pcol,
856 int *pspecial,
int width,
struct AttrColorList *ansi_list)
860 size_t col = c_markers ? (*lines)[line_num].cont_line : 0;
862 int ch, vch, last_special = -1, special = 0, t;
864 mbstate_t mbstate = { 0 };
876 for (ch = 0, vch = 0; ch < cnt; ch += k, vch += k)
879 if (buf[ch] ==
'\033')
885 while ((cnt - ch >= 2) && (buf[ch] ==
'\033') && (buf[ch + 1] ==
']') &&
889 while (buf[ch++] !=
'\a')
898 k = mbrtowc(&wc, (
char *) buf + ch, cnt - ch, &mbstate);
902 memset(&mbstate, 0,
sizeof(mbstate));
904 if ((col + 4) > wrap_cols)
918 if ((wc == 0x200B) || (wc == 0x200C) || (wc == 0xFEFF))
935 mbstate_t mbstate1 = mbstate;
936 size_t k1 = mbrtowc(&wc1, (
char *) buf + ch + k, cnt - ch - k, &mbstate1);
938 (k1 > 0) && (wc1 ==
'\b'))
940 const size_t k2 = mbrtowc(&wc1, (
char *) buf + ch + k + k1,
941 cnt - ch - k - k1, &mbstate1);
950 special |= ((wc ==
'_') && (special & A_UNDERLINE)) ? A_UNDERLINE : A_BOLD;
952 else if ((wc ==
'_') || (wc1 ==
'_'))
954 special |= A_UNDERLINE;
955 wc = (wc1 ==
'_') ? wc : wc1;
966 k1 = mbrtowc(&wc1, (
char *) buf + ch + k, cnt - ch - k, &mbstate1);
971 special || last_special || (ansi->
attrs != A_NORMAL)))
974 last_special = special;
985 if (col + t > wrap_cols)
1002 for (; col < t; col++)
1007 else if ((wc < 0x20) || (wc == 0x7f))
1009 if ((col + 2) > wrap_cols)
1015 else if (wc < 0x100)
1017 if ((col + 4) > wrap_cols)
1025 if ((col + 1) > wrap_cols)
1035 *pspecial = special;
1064 unsigned char *buf = NULL, *fmt = NULL;
1066 unsigned char *buf_ptr = NULL;
1067 int ch, vch, col, cnt, b_read;
1069 bool change_last =
false;
1072 const struct AttrColor *def_color = NULL;
1076 regmatch_t pmatch[1] = { 0 };
1093 memset(&((*
lines)[ch]), 0,
sizeof(
struct Line));
1094 (*lines)[ch].cid = -1;
1095 (*lines)[ch].search_arr_size = -1;
1097 ((*lines)[ch].syntax)[0].
first = -1;
1098 ((*lines)[ch].syntax)[0].last = -1;
1102 struct Line *
const cur_line = &(*lines)[line_num];
1107 if (
fill_buffer(fp, bytes_read, cur_line->
offset, &buf, &fmt, &buflen, &buf_ready) < 0)
1114 if ((cur_line->
cont_line) && (line_num > 0))
1116 struct Line *
const old_line = &(*lines)[line_num - 1];
1117 cur_line->
cid = old_line->
cid;
1124 if ((blen > 11) && (buf[11] ==
'M'))
1126 else if ((blen > 11) && (buf[11] ==
'W'))
1128 else if ((blen > 11) && (buf[11] ==
'E'))
1138 if (cur_line->
cid == -1)
1141 if (
fill_buffer(fp, bytes_read, cur_line->
offset, &buf, &fmt, &buflen, &buf_ready) < 0)
1150 resolve_types(win_pager, (
char *) fmt, (
char *) buf, *lines, line_num, *lines_used,
1159 for (m = line_num + 1;
1160 m < *lines_used && (*lines)[m].offset && (*lines)[m].cont_line; m++)
1162 (*lines)[m].cid = cur_line->
cid;
1169 (!cur_line->
quote || (cur_line->
quote->
quote_n >= c_toggle_quoted_show_levels)))
1183 if (
fill_buffer(fp, bytes_read, cur_line->
offset, &buf, &fmt, &buflen, &buf_ready) < 0)
1194 pmatch[0].rm_eo - pmatch[0].rm_so,
1195 force_redraw, q_level);
1205 if (
fill_buffer(fp, bytes_read, cur_line->
offset, &buf, &fmt, &buflen, &buf_ready) < 0)
1214 while (regexec(search_re, (
char *) fmt + offset, 1, pmatch,
1215 (offset ? REG_NOTBOL : 0)) == 0)
1223 memset(ts, 0,
sizeof(*ts));
1229 pmatch[0].rm_so += offset;
1230 pmatch[0].rm_eo += offset;
1234 if (pmatch[0].rm_eo == pmatch[0].rm_so)
1237 offset = pmatch[0].rm_eo;
1243 if (!(flags &
MUTT_SHOW) && ((*lines)[line_num + 1].offset > 0))
1249 if ((flags &
MUTT_SHOWCOLOR) && *force_redraw && ((*lines)[line_num + 1].offset > 0))
1256 b_read =
fill_buffer(fp, bytes_read, cur_line->
offset, &buf, &fmt, &buflen, &buf_ready);
1265 cnt =
format_line(win_pager, lines, line_num, buf, flags, NULL, b_read, &ch,
1266 &vch, &col, &special, win_pager->
state.
cols, ansi_list);
1267 buf_ptr = buf + cnt;
1278 while (ch && ((buf[ch] ==
' ') || (buf[ch] ==
'\t') || (buf[ch] ==
'\r')))
1284 buf_ptr = buf + cnt;
1290 while ((*buf_ptr ==
' ') || (*buf_ptr ==
'\t'))
1294 if (*buf_ptr ==
'\r')
1296 if (*buf_ptr ==
'\n')
1299 if (((
int) (buf_ptr - buf) < b_read) && !(*lines)[line_num + 1].cont_line)
1300 append_line(*lines, line_num, (
int) (buf_ptr - buf));
1301 (*lines)[line_num + 1].offset = cur_line->
offset + (long) (buf_ptr - buf);
1317 format_line(win_pager, lines, line_num, buf, flags, &ansi, cnt, &ch, &vch,
1318 &col, &special, win_pager->
state.
cols, ansi_list);
1344 def_color = ((*lines)[m].syntax)[0].
attr_color;
1359 if (col < win_pager->state.cols)
int ansi_color_parse(const char *str, struct AnsiColor *ansi, struct AttrColorList *acl, bool dry_run)
Parse a string of ANSI escape sequence.
bool attr_color_match(struct AttrColor *ac1, struct AttrColor *ac2)
Do the colours match?
struct AttrColor attr_color_copy(const struct AttrColor *ac)
Copy a colour.
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Color and attribute parsing.
struct RegexColorList * regex_colors_get_list(enum ColorId cid)
Return the RegexColorList for a Colour ID.
bool simple_color_is_set(enum ColorId cid)
Is the object coloured?
struct AttrColor * simple_color_get(enum ColorId cid)
Get the colour of an object by its ID.
ColorId
List of all coloured objects.
@ MT_COLOR_MARKERS
Pager: markers, line continuation.
@ MT_COLOR_MESSAGE
Informational message.
@ MT_COLOR_QUOTED0
Pager: quoted text, level 0.
@ MT_COLOR_HEADER
Message headers (takes a pattern)
@ MT_COLOR_STRIPE_EVEN
Stripes: even lines of the Help Page.
@ MT_COLOR_ERROR
Error message.
@ MT_COLOR_BOLD
Bold text.
@ MT_COLOR_BODY
Pager: highlight body of message (takes a pattern)
@ MT_COLOR_HDRDEFAULT
Header default colour.
@ MT_COLOR_NORMAL
Plain text.
@ MT_COLOR_ATTACH_HEADERS
MIME attachment test (takes a pattern)
@ MT_COLOR_SEARCH
Pager: search matches.
@ MT_COLOR_ITALIC
Italic text.
@ MT_COLOR_STRIPE_ODD
Stripes: odd lines of the Help Page.
@ MT_COLOR_ATTACHMENT
MIME attachments text (entire line)
@ MT_COLOR_WARNING
Warning messages.
@ MT_COLOR_UNDERLINE
Underlined text.
@ MT_COLOR_SIGNATURE
Pager: signature lines.
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
bool mutt_isspace(int arg)
Wrapper for isspace(3)
int mutt_addwch(struct MuttWindow *win, wchar_t wc)
Addwch would be provided by an up-to-date curses library.
static int format_line(struct MuttWindow *win, struct Line **lines, int line_num, unsigned char *buf, PagerFlags flags, struct AnsiColor *ansi, int cnt, int *pspace, int *pvch, int *pcol, int *pspecial, int width, struct AttrColorList *ansi_list)
Display a line of text in the pager.
static int check_protected_header_marker(const char *p)
Check that the unique marker is present.
bool mutt_is_quote_line(char *line, regmatch_t *pmatch)
Is a line of message text a quote?
static int fill_buffer(FILE *fp, LOFF_T *bytes_read, LOFF_T offset, unsigned char **buf, unsigned char **fmt, size_t *blen, int *buf_ready)
Fill a buffer from a file.
static int check_sig(const char *s, struct Line *info, int offset)
Check for an email signature.
static void match_body_patterns(char *pat, struct Line *lines, int line_num)
Match body patterns, e.g.
void buf_strip_formatting(struct Buffer *dest, const char *src, bool strip_markers)
Removes ANSI and backspace formatting.
static int comp_syntax_t(const void *m1, const void *m2)
Search for a Syntax using bsearch(3)
bool color_is_header(enum ColorId cid)
Colour is for an Email header.
static int check_attachment_marker(const char *p)
Check that the unique marker is present.
static void resolve_color(struct MuttWindow *win, struct Line *lines, int line_num, int cnt, PagerFlags flags, int special, struct AnsiColor *ansi)
Set the colour for a line of text.
static void resolve_types(struct MuttWindow *win, char *buf, char *raw, struct Line *lines, int line_num, int lines_used, struct QuoteStyle **quote_list, int *q_level, bool *force_redraw, bool q_classify)
Determine the style for a line of text.
int display_line(FILE *fp, LOFF_T *bytes_read, struct Line **lines, int line_num, int *lines_used, int *lines_max, PagerFlags flags, struct QuoteStyle **quote_list, int *q_level, bool *force_redraw, regex_t *search_re, struct MuttWindow *win_pager, struct AttrColorList *ansi_list)
Print a line on screen.
static void append_line(struct Line *lines, int line_num, int cnt)
Add a new Line to the array.
static int check_marker(const char *q, const char *p)
Check that the unique marker is present.
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
@ MUTT_RL_EOL
don't strip \n / \r\n
#define mutt_debug(LEVEL,...)
Convenience wrapper for the gui headers.
@ LL_DEBUG3
Log at debug level 3.
@ LL_DEBUG2
Log at debug level 2.
@ LL_DEBUG1
Log at debug level 1.
bool mutt_mb_is_display_corrupting_utf8(wchar_t wc)
Will this character corrupt the display?
#define FREE(x)
Free memory and set the pointer to NULL.
#define MUTT_MEM_CALLOC(n, type)
#define MUTT_MEM_REALLOC(pptr, n, type)
const struct AttrColor * merged_color_overlay(const struct AttrColor *base, const struct AttrColor *over)
Combine two colours.
@ MODULE_ID_PAGER
ModulePager, Pager
bool CharsetIsUtf8
Is the user's current character set utf-8?
wchar_t ReplacementChar
When a Unicode character can't be displayed, use this instead.
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Convenience wrapper for the library headers.
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
Match a regex against a string, with provided options.
const char * state_attachment_marker(void)
Get a unique (per-run) ANSI string to mark PGP messages in an email.
const char * state_protected_header_marker(void)
Get a unique (per-run) ANSI string to mark protected headers in an email.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
const struct AttrColor * mutt_curses_set_normal_backed_color_by_id(enum ColorId cid)
Set the colour and attributes by the Colour ID.
const struct AttrColor * mutt_curses_set_color_by_id(enum ColorId cid)
Set the colour and attributes by the Colour ID.
void mutt_curses_set_color(const struct AttrColor *ac)
Set the colour and attributes for text.
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
void mutt_window_get_coords(struct MuttWindow *win, int *row, int *col)
Get the cursor position in the Window.
int mutt_window_wrap_cols(int width, short wrap)
Calculate the wrap column for a given screen width.
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
int mutt_window_addch(struct MuttWindow *win, int ch)
Write one character to a Window.
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
int ansi_color_seq_length(const char *str)
Is this an ANSI escape sequence?
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
struct QuoteStyle * qstyle_classify(struct QuoteStyle **quote_list, const char *qptr, size_t length, bool *force_redraw, int *q_level)
Find a style for a string.
#define STAILQ_FOREACH(var, head, field)
#define COLOR_QUOTED(cid)
int attrs
Text attributes, e.g. A_BOLD.
const struct AttrColor * attr_color
Curses colour of text.
A curses colour and its attributes.
int attrs
Text attributes, e.g. A_BOLD.
struct CursesColor * curses_color
Underlying Curses colour.
String manipulation buffer.
char * dptr
Current read/write position.
A line of text in the pager.
short search_arr_size
Number of items in search array.
struct TextSyntax * search
Array of search text in the line.
bool cont_line
Continuation of a previous line (wrapped by NeoMutt)
short cid
Default line colour, e.g. MT_COLOR_SIGNATURE.
struct QuoteStyle * quote
Quoting style for this line (pointer into PagerPrivateData->quote_list)
LOFF_T offset
Offset into Email file (PagerPrivateData->fp)
bool cont_header
Continuation of a header line (wrapped by MTA)
short syntax_arr_size
Number of items in syntax array.
struct TextSyntax * syntax
Array of coloured text in the line.
struct WindowState state
Current state of the Window.
void * wdata
Private data.
struct MuttWindow * parent
Parent Window.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
struct AttrColor * attr_color
Colour and attribute of the text.
size_t prefix_len
Length of the prefix string.
int quote_n
The quoteN colour index for this level.
A regular expression and a color to highlight a line.
regex_t regex
Compiled regex.
struct AttrColor attr_color
Colour and attributes to apply.
bool stop_matching
Used by the pager for body patterns, to prevent the color from being retried once it fails.
Cached regular expression.
Highlighting for a piece of text.
const struct AttrColor * attr_color
Curses colour of text.
int last
Last character in line to be coloured (not included)
int first
First character in line to be coloured.
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.