📄 pager.c
字号:
if (tmp == NULL) { /* add a node above q_list */ tmp = (struct q_class_t *) safe_calloc (1, sizeof (struct q_class_t)); tmp->prefix = (char *) safe_calloc (1, length + 1); strncpy (tmp->prefix, qptr, length); tmp->length = length; /* replace q_list by tmp */ if (q_list->next) { tmp->next = q_list->next; q_list->next->prev = tmp; } if (q_list->prev) { tmp->prev = q_list->prev; q_list->prev->next = tmp; } /* make q_list a child of tmp */ tmp->down = q_list; tmp->up = q_list->up; q_list->up = tmp; if (tmp->up->down == q_list) tmp->up->down = tmp; /* q_list has no siblings */ q_list->next = NULL; q_list->prev = NULL; index = q_list->index; /* tmp should be the return class too */ class = tmp; /* next class to test */ q_list = tmp->next; } else { /* found another branch for which tmp is a shorter prefix */ /* save the next sibling for later */ save = q_list->next; /* unlink q_list from the top level list */ if (q_list->next) q_list->next->prev = q_list->prev; if (q_list->prev) q_list->prev->next = q_list->next; /* at this point, we have a tmp->down; link q_list to it */ ptr = tmp->down; while (ptr->next) ptr = ptr->next; ptr->next = q_list; q_list->next = NULL; q_list->prev = ptr; q_list->up = tmp; index = q_list->index; /* next class to test */ q_list = save; } /* we found a shorter prefix, so we need a redraw */ *force_redraw = 1; continue; } else { q_list = q_list->next; continue; } } else { /* longer than the current prefix: try subclassing it */ if (tmp == NULL && mutt_strncmp (tail_qptr, (q_list->prefix) + offset, q_list->length - offset) == 0) { /* still a subclass: go down one level */ ptr = q_list; offset = q_list->length; q_list = q_list->down; tail_lng = length - offset; tail_qptr = (char *) qptr + offset; continue; } else { /* nope, try the next prefix */ q_list = q_list->next; continue; } } } /* still not found so far: add it as a sibling to the current node */ if (class == NULL) { tmp = (struct q_class_t *) safe_calloc (1, sizeof (struct q_class_t)); tmp->prefix = (char *) safe_calloc (1, length + 1); strncpy (tmp->prefix, qptr, length); tmp->length = length; if (ptr->down) { tmp->next = ptr->down; ptr->down->prev = tmp; } ptr->down = tmp; tmp->up = ptr; new_class_color (tmp, q_level); return tmp; } else { if (index != -1) shift_class_colors (*QuoteList, tmp, index, q_level); return class; } } else { /* nope, try the next prefix */ q_list = q_list->next; continue; } } } if (class == NULL) { /* not found so far: add it as a top level class */ class = (struct q_class_t *) safe_calloc (1, sizeof (struct q_class_t)); class->prefix = (char *) safe_calloc (1, length + 1); strncpy (class->prefix, qptr, length); class->length = length; new_class_color (class, q_level); if (*QuoteList) { class->next = *QuoteList; (*QuoteList)->prev = class; } *QuoteList = class; } if (index != -1) shift_class_colors (*QuoteList, tmp, index, q_level); return class;}static int brailleLine = -1;static int brailleCol = -1;static int check_attachment_marker (char *);static voidresolve_types (char *buf, char *raw, struct line_t *lineInfo, int n, int last, struct q_class_t **QuoteList, int *q_level, int *force_redraw, int q_classify){ COLOR_LINE *color_line; regmatch_t pmatch[1], smatch[1]; int found, offset, null_rx, i; if (n == 0 || ISHEADER (lineInfo[n-1].type)) { if (buf[0] == '\n') { lineInfo[n].type = MT_COLOR_NORMAL; getyx(stdscr, brailleLine, brailleCol); } else if (n > 0 && (buf[0] == ' ' || buf[0] == '\t')) { lineInfo[n].type = lineInfo[n-1].type; /* wrapped line */ (lineInfo[n].syntax)[0].color = (lineInfo[n-1].syntax)[0].color; } else { lineInfo[n].type = MT_COLOR_HDEFAULT; color_line = ColorHdrList; while (color_line) { if (REGEXEC (color_line->rx, buf) == 0) { lineInfo[n].type = MT_COLOR_HEADER; lineInfo[n].syntax[0].color = color_line->pair; break; } color_line = color_line->next; } } } else if (mutt_strncmp ("\033[0m", raw, 4) == 0) /* a little hack... */ lineInfo[n].type = MT_COLOR_NORMAL;#if 0 else if (mutt_strncmp ("[-- ", buf, 4) == 0) lineInfo[n].type = MT_COLOR_ATTACHMENT;#else else if (check_attachment_marker ((char *) raw) == 0) lineInfo[n].type = MT_COLOR_ATTACHMENT;#endif else if (mutt_strcmp ("-- \n", buf) == 0 || mutt_strcmp ("-- \r\n", buf) == 0) { i = n + 1; lineInfo[n].type = MT_COLOR_SIGNATURE; while (i < last && check_sig (buf, lineInfo, i - 1) == 0 && (lineInfo[i].type == MT_COLOR_NORMAL || lineInfo[i].type == MT_COLOR_QUOTED || lineInfo[i].type == MT_COLOR_HEADER)) { /* oops... */ if (lineInfo[i].chunks) { lineInfo[i].chunks = 0; safe_realloc (&(lineInfo[n].syntax), sizeof (struct syntax_t)); } lineInfo[i++].type = MT_COLOR_SIGNATURE; } } else if (check_sig (buf, lineInfo, n - 1) == 0) lineInfo[n].type = MT_COLOR_SIGNATURE; else if (regexec ((regex_t *) QuoteRegexp.rx, buf, 1, pmatch, 0) == 0) { if (regexec ((regex_t *) Smileys.rx, buf, 1, smatch, 0) == 0) { if (smatch[0].rm_so > 0) { char c; /* hack to avoid making an extra copy of buf */ c = buf[smatch[0].rm_so]; buf[smatch[0].rm_so] = 0; if (regexec ((regex_t *) QuoteRegexp.rx, buf, 1, pmatch, 0) == 0) { if (q_classify && lineInfo[n].quote == NULL) lineInfo[n].quote = classify_quote (QuoteList, buf + pmatch[0].rm_so, pmatch[0].rm_eo - pmatch[0].rm_so, force_redraw, q_level); lineInfo[n].type = MT_COLOR_QUOTED; } else lineInfo[n].type = MT_COLOR_NORMAL; buf[smatch[0].rm_so] = c; } else lineInfo[n].type = MT_COLOR_NORMAL; } else { if (q_classify && lineInfo[n].quote == NULL) lineInfo[n].quote = classify_quote (QuoteList, buf + pmatch[0].rm_so, pmatch[0].rm_eo - pmatch[0].rm_so, force_redraw, q_level); lineInfo[n].type = MT_COLOR_QUOTED; } } else lineInfo[n].type = MT_COLOR_NORMAL; /* body patterns */ if (lineInfo[n].type == MT_COLOR_NORMAL || lineInfo[n].type == MT_COLOR_QUOTED) { i = 0; offset = 0; lineInfo[n].chunks = 0; do { if (!buf[offset]) break; found = 0; null_rx = 0; color_line = ColorBodyList; while (color_line) { if (regexec (&color_line->rx, buf + offset, 1, pmatch, (offset ? REG_NOTBOL : 0)) == 0) { if (pmatch[0].rm_eo != pmatch[0].rm_so) { if (!found) { if (++(lineInfo[n].chunks) > 1) safe_realloc (&(lineInfo[n].syntax), (lineInfo[n].chunks) * sizeof (struct syntax_t)); } i = lineInfo[n].chunks - 1; pmatch[0].rm_so += offset; pmatch[0].rm_eo += offset; if (!found || pmatch[0].rm_so < (lineInfo[n].syntax)[i].first || (pmatch[0].rm_so == (lineInfo[n].syntax)[i].first && pmatch[0].rm_eo > (lineInfo[n].syntax)[i].last)) { (lineInfo[n].syntax)[i].color = color_line->pair; (lineInfo[n].syntax)[i].first = pmatch[0].rm_so; (lineInfo[n].syntax)[i].last = pmatch[0].rm_eo; } found = 1; null_rx = 0; } else null_rx = 1; /* empty regexp; don't add it, but keep looking */ } color_line = color_line->next; } if (null_rx) offset++; /* avoid degenerate cases */ else offset = (lineInfo[n].syntax)[i].last; } while (found || null_rx); }}static int is_ansi (unsigned char *buf){ while (*buf && (isdigit(*buf) || *buf == ';')) buf++; return (*buf == 'm');}static int check_attachment_marker (char *p){ char *q = AttachmentMarker; for (;*p == *q && *q && *p && *q != '\a' && *p != '\a'; p++, q++) ; return (int) (*p - *q);}static int grok_ansi(unsigned char *buf, int pos, ansi_attr *a){ int x = pos; while (isdigit(buf[x]) || buf[x] == ';') x++; /* Character Attributes */ if (option (OPTALLOWANSI) && a != NULL && buf[x] == 'm') { if (pos == x) {#ifdef HAVE_COLOR if (a->pair != -1) mutt_free_color (a->fg, a->bg);#endif a->attr = ANSI_OFF; a->pair = -1; } while (pos < x) { if (buf[pos] == '1' && (pos+1 == x || buf[pos+1] == ';')) { a->attr |= ANSI_BOLD; pos += 2; } else if (buf[pos] == '4' && (pos+1 == x || buf[pos+1] == ';')) { a->attr |= ANSI_UNDERLINE; pos += 2; } else if (buf[pos] == '5' && (pos+1 == x || buf[pos+1] == ';')) { a->attr |= ANSI_BLINK; pos += 2; } else if (buf[pos] == '7' && (pos+1 == x || buf[pos+1] == ';')) { a->attr |= ANSI_REVERSE; pos += 2; } else if (buf[pos] == '0' && (pos+1 == x || buf[pos+1] == ';')) {#ifdef HAVE_COLOR if (a->pair != -1) mutt_free_color(a->fg,a->bg);#endif a->attr = ANSI_OFF; a->pair = -1; pos += 2; } else if (buf[pos] == '3' && isdigit(buf[pos+1])) {#ifdef HAVE_COLOR if (a->pair != -1) mutt_free_color(a->fg,a->bg);#endif a->pair = -1; a->attr |= ANSI_COLOR; a->fg = buf[pos+1] - '0'; pos += 3; } else if (buf[pos] == '4' && isdigit(buf[pos+1])) {#ifdef HAVE_COLOR if (a->pair != -1) mutt_free_color(a->fg,a->bg);#endif a->pair = -1; a->attr |= ANSI_COLOR; a->bg = buf[pos+1] - '0'; pos += 3; } else { while (pos < x && buf[pos] != ';') pos++; pos++; } } } pos = x; return pos;}/* trim tail of buf so that it contains complete multibyte characters */static inttrim_incomplete_mbyte(unsigned char *buf, size_t len){ mbstate_t mbstate; size_t k; memset (&mbstate, 0, sizeof (mbstate)); for (; len > 0; buf += k, len -= k) { k = mbrtowc (NULL, (char *) buf, len, &mbstate); if (k == -2) break; else if (k == -1 || k == 0) k = 1; } *buf = '\0'; return len;}static intfill_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; static int b_read; if (*buf_ready == 0) { buf[blen - 1] = 0; if (offset != *last_pos) fseeko (f, offset, 0); if (fgets ((char *) buf, blen - 1, f) == NULL) { fmt[0] = 0; return (-1); } *last_pos = ftello (f); b_read = (int) (*last_pos - offset); *buf_ready = 1; /* 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); /* copy "buf" to "fmt", but without bold and underline controls */ p = buf; while (*p) { if (*p == '\010' && (p > buf)) { if (*(p+1) == '_') /* underline */ p += 2; else if (*(p+1)) /* bold or overstrike */ { *(fmt-1) = *(p+1); p += 2; } else /* ^H */ *fmt++ = *p++; } else if (*p == '\033' && *(p+1) == '[' && is_ansi (p + 2)) { while (*p++ != 'm') /* skip ANSI sequence */ ; } else if (*p == '\033' && *(p+1) == ']' && check_attachment_marker ((char *) p) == 0) { dprint (2, (debugfile, "fill_buffer: Seen attachment marker.\n")); while (*p++ != '\a') /* skip pseudo-ANSI sequence */ ; } else *fmt++ = *p++; } *fmt = 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 space = -1; /* index of the last space or TAB */ int col = option (OPTMARKERS) ? (*lineInfo)[n].continuation : 0; int ch, vch, k, last_special = -1, special = 0, t; wchar_t wc; mbstate_t mbstate; int wrap_cols = COLS - WrapMargin; if (wrap_cols <= 0) wrap_cols = 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] == '[' && is_ansi (buf+ch+2)) ch = grok_ansi (buf, ch+2, pa) + 1; while (cnt-ch >= 2 && buf[ch] == '\033' && buf[ch+1] == ']' && check_attachment_marker ((char *) buf+ch) == 0) { while (buf[ch++] != '\a') if (ch >= cnt)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -