📄 muttlib.c
字号:
wlen += count; col += count; } if (len + wlen > destlen) len = destlen - wlen; memcpy (wptr, buf, len); wptr += len; wlen += len; col += mutt_strwidth (buf); } break; /* skip rest of input */ } else if (ch == '|') { /* pad to EOL */ ch = *src++; if (destlen > COLS) destlen = COLS; if (destlen > wlen) { count = destlen - wlen; memset (wptr, ch, count); wptr += count; } break; /* skip rest of input */ } else { short tolower = 0; short nodots = 0; while (ch == '_' || ch == ':') { if (ch == '_') tolower = 1; else if (ch == ':') nodots = 1; ch = *src++; } /* use callback function to handle this case */ src = callback (buf, sizeof (buf), ch, src, prefix, ifstring, elsestring, data, flags); if (tolower) mutt_strlower (buf); if (nodots) { char *p = buf; for (; *p; p++) if (*p == '.') *p = '_'; } if ((len = mutt_strlen (buf)) + wlen > destlen) len = (destlen - wlen > 0) ? (destlen - wlen) : 0; memcpy (wptr, buf, len); wptr += len; wlen += len; col += mutt_strwidth (buf); } } else if (*src == '\\') { if (!*++src) break; switch (*src) { case 'n': *wptr = '\n'; break; case 't': *wptr = '\t'; break; case 'r': *wptr = '\r'; break; case 'f': *wptr = '\f'; break; case 'v': *wptr = '\v'; break; default: *wptr = *src; break; } src++; wptr++; wlen++; col++; } else { *wptr++ = *src++; wlen++; col++; } } *wptr = 0;#if 0 if (flags & M_FORMAT_MAKEPRINT) { /* Make sure that the string is printable by changing all non-printable chars to dots, or spaces for non-printable whitespace */ for (cp = dest ; *cp ; cp++) if (!IsPrint (*cp) && !((flags & M_FORMAT_TREE) && (*cp <= M_TREE_MAX))) *cp = isspace ((unsigned char) *cp) ? ' ' : '.'; }#endif}/* This function allows the user to specify a command to read stdout from in place of a normal file. If the last character in the string is a pipe (|), then we assume it is a commmand to run instead of a normal file. */FILE *mutt_open_read (const char *path, pid_t *thepid){ FILE *f; struct stat s; int len = mutt_strlen (path); if (path[len - 1] == '|') { /* read from a pipe */ char *s = safe_strdup (path); s[len - 1] = 0; mutt_endwin (NULL); *thepid = mutt_create_filter (s, NULL, &f, NULL); FREE (&s); } else { if (stat (path, &s) < 0) return (NULL); if (S_ISDIR (s.st_mode)) { errno = EINVAL; return (NULL); } f = fopen (path, "r"); *thepid = -1; } return (f);}/* returns 0 if OK to proceed, -1 to abort, 1 to retry */int mutt_save_confirm (const char *s, struct stat *st){ char tmp[_POSIX_PATH_MAX]; int ret = 0; int rc; int magic = 0; magic = mx_get_magic (s);#ifdef USE_POP if (magic == M_POP) { mutt_error _("Can't save message to POP mailbox."); return 1; }#endif if (magic > 0 && !mx_access (s, W_OK)) { if (option (OPTCONFIRMAPPEND)) { snprintf (tmp, sizeof (tmp), _("Append messages to %s?"), s); if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO) ret = 1; else if (rc == -1) ret = -1; } } if (stat (s, st) != -1) { if (magic == -1) { mutt_error (_("%s is not a mailbox!"), s); return 1; } } else#ifdef USE_IMAP if (magic != M_IMAP)#endif /* execute the block unconditionally if we don't use imap */ { st->st_mtime = 0; st->st_atime = 0; if (errno == ENOENT) { if (option (OPTCONFIRMCREATE)) { snprintf (tmp, sizeof (tmp), _("Create %s?"), s); if ((rc = mutt_yesorno (tmp, M_YES)) == M_NO) ret = 1; else if (rc == -1) ret = -1; } } else { mutt_perror (s); return 1; } } CLEARLINE (LINES-1); return (ret);}void state_prefix_putc (char c, STATE *s){ if (s->flags & M_PENDINGPREFIX) { state_reset_prefix (s); if (s->prefix) state_puts (s->prefix, s); } state_putc (c, s); if (c == '\n') state_set_prefix (s);}int state_printf (STATE *s, const char *fmt, ...){ int rv; va_list ap; va_start (ap, fmt); rv = vfprintf (s->fpout, fmt, ap); va_end (ap); return rv;}void state_mark_attach (STATE *s){ if ((s->flags & M_DISPLAY) && !mutt_strcmp (Pager, "builtin")) state_puts (AttachmentMarker, s);}void state_attach_puts (const char *t, STATE *s){ if (*t != '\n') state_mark_attach (s); while (*t) { state_putc (*t, s); if (*t++ == '\n' && *t) if (*t != '\n') state_mark_attach (s); }}void mutt_display_sanitize (char *s){ for (; *s; s++) { if (!IsPrint (*s)) *s = '?'; }} void mutt_sleep (short s){ if (SleepTime > s) sleep (SleepTime); else if (s) sleep (s);}/* * Creates and initializes a BUFFER*. If passed an existing BUFFER*, * just initializes. Frees anything already in the buffer. * * Disregards the 'destroy' flag, which seems reserved for caller. * This is bad, but there's no apparent protocol for it. */BUFFER * mutt_buffer_init(BUFFER *b){ if (!b) { b = safe_malloc(sizeof(BUFFER)); if (!b) return NULL; } else { FREE(&b->data); } memset(b, 0, sizeof(BUFFER)); return b;}/* * Creates and initializes a BUFFER*. If passed an existing BUFFER*, * just initializes. Frees anything already in the buffer. Copies in * the seed string. * * Disregards the 'destroy' flag, which seems reserved for caller. * This is bad, but there's no apparent protocol for it. */BUFFER * mutt_buffer_from(BUFFER *b, char *seed){ if (!seed) return NULL; b = mutt_buffer_init(b); b->data = safe_strdup (seed); b->dsize = mutt_strlen (seed); b->dptr = (char *) b->data + b->dsize; return b;}int mutt_buffer_printf (BUFFER* buf, const char* fmt, ...){ va_list ap, ap_retry; int len, blen, doff; va_start (ap, fmt); va_copy (ap_retry, ap); doff = buf->dptr - buf->data; blen = buf->dsize - doff; /* solaris 9 vsnprintf barfs when blen is 0 */ if (!blen) { blen = 128; buf->dsize += blen; safe_realloc (&buf->data, buf->dsize); buf->dptr = buf->data + doff; } if ((len = vsnprintf (buf->dptr, blen, fmt, ap)) >= blen) { blen = ++len - blen; if (blen < 128) blen = 128; buf->dsize += blen; safe_realloc (&buf->data, buf->dsize); buf->dptr = buf->data + doff; len = vsnprintf (buf->dptr, len, fmt, ap_retry); va_end (ap_retry); } if (len > 0) buf->dptr += len; va_end (ap); return len;}void mutt_buffer_addstr (BUFFER* buf, const char* s){ mutt_buffer_add (buf, s, mutt_strlen (s));}void mutt_buffer_addch (BUFFER* buf, char c){ mutt_buffer_add (buf, &c, 1);}void mutt_buffer_free (BUFFER **p){ if (!p || !*p) return; FREE(&(*p)->data); /* dptr is just an offset to data and shouldn't be freed */ FREE(p); /* __FREE_CHECKED__ */}/* dynamically grows a BUFFER to accomodate s, in increments of 128 bytes. * Always one byte bigger than necessary for the null terminator, and * the buffer is always null-terminated */void mutt_buffer_add (BUFFER* buf, const char* s, size_t len){ size_t offset; if (buf->dptr + len + 1 > buf->data + buf->dsize) { offset = buf->dptr - buf->data; buf->dsize += len < 128 ? 128 : len + 1; safe_realloc ((void**) &buf->data, buf->dsize); buf->dptr = buf->data + offset; } memcpy (buf->dptr, s, len); buf->dptr += len; *(buf->dptr) = '\0';}/* Decrease a file's modification time by 1 second */time_t mutt_decrease_mtime (const char *f, struct stat *st){ struct utimbuf utim; struct stat _st; time_t mtime; if (!st) { if (stat (f, &_st) == -1) return -1; st = &_st; } if ((mtime = st->st_mtime) == time (NULL)) { mtime -= 1; utim.actime = mtime; utim.modtime = mtime; utime (f, &utim); } return mtime;}const char *mutt_make_version (void){ static char vstring[STRING]; snprintf (vstring, sizeof (vstring), "Mutt %s (%s)", MUTT_VERSION, ReleaseDate); return vstring;}REGEXP *mutt_compile_regexp (const char *s, int flags){ REGEXP *pp = safe_calloc (sizeof (REGEXP), 1); pp->pattern = safe_strdup (s); pp->rx = safe_calloc (sizeof (regex_t), 1); if (REGCOMP (pp->rx, NONULL(s), flags) != 0) mutt_free_regexp (&pp); return pp;}void mutt_free_regexp (REGEXP **pp){ FREE (&(*pp)->pattern); regfree ((*pp)->rx); FREE (&(*pp)->rx); FREE (pp); /* __FREE_CHECKED__ */}void mutt_free_rx_list (RX_LIST **list){ RX_LIST *p; if (!list) return; while (*list) { p = *list; *list = (*list)->next; mutt_free_regexp (&p->rx); FREE (&p); }}void mutt_free_spam_list (SPAM_LIST **list){ SPAM_LIST *p; if (!list) return; while (*list) { p = *list; *list = (*list)->next; mutt_free_regexp (&p->rx); FREE (&p->template); FREE (&p); }}int mutt_match_rx_list (const char *s, RX_LIST *l){ if (!s) return 0; for (; l; l = l->next) { if (regexec (l->rx->rx, s, (size_t) 0, (regmatch_t *) 0, (int) 0) == 0) { dprint (5, (debugfile, "mutt_match_rx_list: %s matches %s\n", s, l->rx->pattern)); return 1; } } return 0;}int mutt_match_spam_list (const char *s, SPAM_LIST *l, char *text, int x){ static regmatch_t *pmatch = NULL; static int nmatch = 0; int i, n, tlen; char *p; if (!s) return 0; tlen = 0; for (; l; l = l->next) { /* If this pattern needs more matches, expand pmatch. */ if (l->nmatch > nmatch) { safe_realloc (&pmatch, l->nmatch * sizeof(regmatch_t)); nmatch = l->nmatch; } /* Does this pattern match? */ if (regexec (l->rx->rx, s, (size_t) l->nmatch, (regmatch_t *) pmatch, (int) 0) == 0) { dprint (5, (debugfile, "mutt_match_spam_list: %s matches %s\n", s, l->rx->pattern)); dprint (5, (debugfile, "mutt_match_spam_list: %d subs\n", (int)l->rx->rx->re_nsub)); /* Copy template into text, with substitutions. */ for (p = l->template; *p;) { if (*p == '%') { n = atoi(++p); /* find pmatch index */ while (isdigit((unsigned char)*p)) ++p; /* skip subst token */ for (i = pmatch[n].rm_so; (i < pmatch[n].rm_eo) && (tlen < x); i++) text[tlen++] = s[i]; } else { text[tlen++] = *p++; } } text[tlen] = '\0'; dprint (5, (debugfile, "mutt_match_spam_list: \"%s\"\n", text)); return 1; } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -