📄 handler.c
字号:
} else { stte->buffer[stte->buff_used++] = c; } } else { stte->buffer[stte->buff_used++] = c; } stte->word_len++; }}static void enriched_puts (char *s, struct enriched_state *stte){ char *c; if (stte->buff_len < stte->buff_used + mutt_strlen(s)) { stte->buff_len += LONG_STRING; safe_realloc (&stte->buffer, stte->buff_len + 1); } c = s; while (*c) { stte->buffer[stte->buff_used++] = *c; c++; }}static void enriched_set_flags (const char *tag, struct enriched_state *stte){ const char *tagptr = tag; int i, j; if (*tagptr == '/') tagptr++; for (i = 0, j = -1; EnrichedTags[i].tag_name; i++) if (ascii_strcasecmp (EnrichedTags[i].tag_name,tagptr) == 0) { j = EnrichedTags[i].index; break; } if (j != -1) { if (j == RICH_CENTER || j == RICH_FLUSHLEFT || j == RICH_FLUSHRIGHT) enriched_flush (stte, 1); if (*tag == '/') { if (stte->tag_level[j]) /* make sure not to go negative */ stte->tag_level[j]--; if ((stte->s->flags & M_DISPLAY) && j == RICH_PARAM && stte->tag_level[RICH_COLOR]) { stte->param[stte->param_used] = '\0'; if (!ascii_strcasecmp(stte->param, "black")) { enriched_puts("\033[30m", stte); } else if (!ascii_strcasecmp(stte->param, "red")) { enriched_puts("\033[31m", stte); } else if (!ascii_strcasecmp(stte->param, "green")) { enriched_puts("\033[32m", stte); } else if (!ascii_strcasecmp(stte->param, "yellow")) { enriched_puts("\033[33m", stte); } else if (!ascii_strcasecmp(stte->param, "blue")) { enriched_puts("\033[34m", stte); } else if (!ascii_strcasecmp(stte->param, "magenta")) { enriched_puts("\033[35m", stte); } else if (!ascii_strcasecmp(stte->param, "cyan")) { enriched_puts("\033[36m", stte); } else if (!ascii_strcasecmp(stte->param, "white")) { enriched_puts("\033[37m", stte); } } if ((stte->s->flags & M_DISPLAY) && j == RICH_COLOR) { enriched_puts("\033[0m", stte); } /* flush parameter buffer when closing the tag */ if (j == RICH_PARAM) { stte->param_used = 0; stte->param[0] = '\0'; } } else stte->tag_level[j]++; if (j == RICH_EXCERPT) enriched_flush(stte, 1); }}int text_enriched_handler (BODY *a, STATE *s){ enum { TEXT, LANGLE, TAG, BOGUS_TAG, NEWLINE, ST_EOF, DONE } state = TEXT; long bytes = a->length; struct enriched_state stte; int c = 0; int tag_len = 0; char tag[LONG_STRING + 1]; memset (&stte, 0, sizeof (stte)); stte.s = s; stte.WrapMargin = ((s->flags & M_DISPLAY) ? (COLS-4) : ((COLS-4)<72)?(COLS-4):72); stte.line_max = stte.WrapMargin * 4; stte.line = (char *) safe_calloc (1, stte.line_max + 1); stte.param = (char *) safe_calloc (1, STRING); stte.param_len = STRING; stte.param_used = 0; if (s->prefix) { state_puts (s->prefix, s); stte.indent_len += mutt_strlen (s->prefix); } while (state != DONE) { if (state != ST_EOF) { if (!bytes || (c = fgetc (s->fpin)) == EOF) state = ST_EOF; else bytes--; } switch (state) { case TEXT : switch (c) { case '<' : state = LANGLE; break; case '\n' : if (stte.tag_level[RICH_NOFILL]) { enriched_flush (&stte, 1); } else { enriched_putc (' ', &stte); state = NEWLINE; } break; default: enriched_putc (c, &stte); } break; case LANGLE : if (c == '<') { enriched_putc (c, &stte); state = TEXT; break; } else { tag_len = 0; state = TAG; } /* Yes, fall through (it wasn't a <<, so this char is first in TAG) */ case TAG : if (c == '>') { tag[tag_len] = '\0'; enriched_set_flags (tag, &stte); state = TEXT; } else if (tag_len < LONG_STRING) /* ignore overly long tags */ tag[tag_len++] = c; else state = BOGUS_TAG; break; case BOGUS_TAG : if (c == '>') state = TEXT; break; case NEWLINE : if (c == '\n') enriched_flush (&stte, 1); else { ungetc (c, s->fpin); bytes++; state = TEXT; } break; case ST_EOF : enriched_putc ('\0', &stte); enriched_flush (&stte, 1); state = DONE; break; case DONE: /* not reached, but gcc complains if this is absent */ break; } } state_putc ('\n', s); /* add a final newline */ FREE (&(stte.buffer)); FREE (&(stte.line)); FREE (&(stte.param)); return 0;} /* * An implementation of RFC 2646. * * NOTE: This still has to be made UTF-8 aware. * */#define FLOWED_MAX 77static void flowed_quote (STATE *s, int level){ int i; if (s->prefix) { if (option (OPTTEXTFLOWED)) level++; else state_puts (s->prefix, s); } for (i = 0; i < level; i++) state_putc ('>', s);}static int flowed_maybe_quoted (char *cont){ return regexec ((regex_t *) QuoteRegexp.rx, cont, 0, NULL, 0) == 0;}static void flowed_stuff (STATE *s, char *cont, int level){ if (!option (OPTTEXTFLOWED) && !(s->flags & M_DISPLAY)) return; if (s->flags & M_DISPLAY) { /* * Hack: If we are in the beginning of the line and there is * some text on the line which looks like it's quoted, turn off * ANSI colors, so quote coloring doesn't affect this line. */ if (*cont && !level && !mutt_strcmp (Pager, "builtin") && flowed_maybe_quoted (cont)) state_puts ("\033[0m",s); } else if ((!(s->flags & M_PRINTING)) && ((*cont == ' ') || (*cont == '>') || (!level && !mutt_strncmp (cont, "From ", 5)))) state_putc (' ', s);}static char *flowed_skip_indent (char *prefix, char *cont){ for (; *cont == ' ' || *cont == '\t'; cont++) *prefix++ = *cont; *prefix = '\0'; return cont;}static int flowed_visual_strlen (char *l, int i){ int j; for (j = 0; *l; l++) { if (*l == '\t') j += 8 - ((i + j) % 8); else j++; } return j;}static int text_plain_flowed_handler (BODY *a, STATE *s){ char line[LONG_STRING]; char indent[LONG_STRING]; int quoted = -1; int last_quoted; int full = 1; int last_full; int col = 0, tmpcol; int i_add = 0; int add = 0; int soft = 0; int l, rl; int flowed_max; int bytes = a->length; int actually_wrap = 0; char *cont = NULL; char *tail = NULL; char *lc = NULL; char *t; *indent = '\0'; if (s->prefix) add = 1; if ((flowed_max = FLOWED_MAX) > COLS - 3) flowed_max = COLS - 3; if (flowed_max > COLS - WrapMargin) flowed_max = COLS - WrapMargin; if (flowed_max <= 0) flowed_max = COLS; while (bytes > 0 && fgets (line, sizeof (line), s->fpin)) { bytes -= strlen (line); tail = NULL; last_full = full; /* * If the last line wasn't fully read, this is the * tail of some line. */ actually_wrap = !last_full; if ((t = strrchr (line, '\r')) || (t = strrchr (line, '\n'))) { *t = '\0'; full = 1; } else if ((t = strrchr (line, ' ')) || (t = strrchr (line, '\t'))) { /* * Bad: We have a line of more than LONG_STRING characters. * (Which SHOULD NOT happen, since lines SHOULD be <= 79 * characters long.) * * Try to simulate a soft line break at a word boundary. * Handle the rest of the line next time. * * Give up when we have a single word which is longer than * LONG_STRING characters. It will just be split into parts, * with a hard line break in between. */ full = 0; l = strlen (t + 1); t[0] = ' '; t[1] = '\0'; if (l) { fseek (s->fpin, -l, SEEK_CUR); bytes += l; } } else full = 0; last_quoted = quoted; if (last_full) { /* * We are in the beginning of a new line. Determine quote level * and indentation prefix */ for (quoted = 0; line[quoted] == '>'; quoted++) ; cont = line + quoted; /* undo space stuffing */ if (*cont == ' ') cont++; /* If there is an indentation, record it. */ cont = flowed_skip_indent (indent, cont); i_add = flowed_visual_strlen (indent, quoted + add); } else { /* * This is just the tail of some over-long line. Keep * indentation and quote levels. Don't unstuff. */ cont = line; } /* If we have a change in quoting depth, wrap. */ if (col && last_quoted != quoted && last_quoted >= 0) { state_putc ('\n', s); col = 0; } do { if (tail) cont = tail; SKIPWS (cont); tail = NULL; soft = 0; /* try to find a point for word wrapping */ retry_wrap: l = flowed_visual_strlen (cont, quoted + i_add + add + col); rl = mutt_strlen (cont); if (quoted + i_add + add + col + l > flowed_max) { actually_wrap = 1; for (tmpcol = quoted + i_add + add + col, t = cont; *t && tmpcol < flowed_max; t++) { if (*t == ' ' || *t == '\t') tail = t; if (*t == '\t') tmpcol = (tmpcol & ~7) + 8; else tmpcol++; } if (tail) { *tail++ = '\0'; soft = 2; } } /* We seem to be desperate. Get me a new line, and retry. */ if (!tail && (quoted + add + col + i_add + l > flowed_max) && col) { state_putc ('\n', s); col = 0; goto retry_wrap; } /* Detect soft line breaks. */ if (!soft && ascii_strcmp (cont, "-- ")) { lc = strrchr (cont, ' '); if (lc && lc[1] == '\0') soft = 1; } /* * If we are in the beginning of an output line, do quoting * and stuffing. * * We have to temporarily assemble the line since display * stuffing (i.e., turning off quote coloring) may depend on * the line's actual content. You never know what people put * into their regular expressions. */ if (!col) { char tmp[LONG_STRING]; snprintf (tmp, sizeof (tmp), "%s%s", indent, cont); flowed_quote (s, quoted); flowed_stuff (s, tmp, quoted + add); state_puts (indent, s); } /* output the text */ state_puts (cont, s); col += flowed_visual_strlen (cont, quoted + i_add + add + col); /* possibly indicate a soft line break */ if (soft == 2) { state_putc (' ', s); col++; } /* * Wrap if this display line corresponds to a * text line. Don't wrap if we changed the line. */ if (!soft || (!actually_wrap && full)) { state_putc ('\n', s); col = 0; } } while (tail); } if (col) state_putc ('\n', s); return 0;}#define TXTHTML 1#define TXTPLAIN 2#define TXTENRICHED 3static int alternative_handler (BODY *a, STATE *s){ BODY *choice = NULL; BODY *b; LIST *t; char buf[STRING]; int type = 0; int mustfree = 0; int rc = 0; if (a->encoding == ENCBASE64 || a->encoding == ENCQUOTEDPRINTABLE || a->encoding == ENCUUENCODED) { struct stat st; mustfree = 1; fstat (fileno (s->fpin), &st); b = mutt_new_body (); b->length = (long) st.st_size; b->parts = mutt_parse_multipart (s->fpin, mutt_get_parameter ("boundary", a->parameter), (long) st.st_size, ascii_strcasecmp ("digest", a->subtype) == 0); } else b = a; a = b; /* First, search list of prefered types */ t = AlternativeOrderList; while (t && !choice) { char *c; int btlen; /* length of basetype */ int wild; /* do we have a wildcard to match all subtypes? */ c = strchr (t->data, '/'); if (c) { wild = (c[1] == '*' && c[2] == 0); btlen = c - t->data; } else { wild = 1; btlen = mutt_strlen (t->data); } if (a && a->parts) b = a->parts; else b = a; while (b) { const char *bt = TYPE(b); if (!ascii_strncasecmp (bt, t->data, btlen) && bt[btlen] == 0) { /* the basetype matches */ if (wild || !ascii_strcasecmp (t->data + btlen + 1, b->subtype)) { choice = b; } } b = b->next; } t = t->next; } /* Next, look for an autoviewable type */ if (!choice) { if (a && a->parts) b = a->parts; else b = a; while (b) { snprintf (buf, sizeof (buf), "%s/%s", TYPE (b), b->subtype); if (mutt_is_autoview (b, buf)) { rfc1524_entry *entry = rfc1524_new_entry (); if (rfc1524_mailcap_lookup (b, buf, entry, M_AUTOVIEW)) { choice = b; } rfc1524_free_entry (&entry); } b = b->next; } } /* Then, look for a text entry */ if (!choice) { if (a && a->parts) b = a->parts; else b = a; while (b) { if (b->type == TYPETEXT) { if (! ascii_strcasecmp ("plain", b->subtype) && type <= TXTPLAIN) { choice = b; type = TXTPLAIN; } else if (! ascii_strcasecmp ("enriched", b->subtype) && type <= TXTENRICHED) { choice = b; type = TXTENRICHED; } else if (! ascii_strcasecmp ("html", b->subtype) && type <= TXTHTML)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -