/** * mutt_unget_string - Return a string to the input buffer * @param s String to return * * This puts events into the `UngetKeyEvents` buffer */ void mutt_unget_string(const char *s) { const char *p = s + mutt_str_strlen(s) - 1; while (p >= s) { mutt_unget_event((unsigned char) *p--, 0); } }
/** * mutt_getch - Read a character from the input buffer * @retval obj Event to process * * The priority for reading events is: * 1. UngetKeyEvents buffer * 2. MacroEvents buffer * 3. Keyboard * * This function can return: * - Error `{ -1, OP_NULL }` * - Timeout `{ -2, OP_NULL }` */ struct Event mutt_getch(void) { int ch; struct Event err = { -1, OP_NULL }, ret; struct Event timeout = { -2, OP_NULL }; if (UngetCount) return UngetKeyEvents[--UngetCount]; if (!OptIgnoreMacroEvents && MacroBufferCount) return MacroEvents[--MacroBufferCount]; SigInt = 0; mutt_sig_allow_interrupt(1); #ifdef KEY_RESIZE /* ncurses 4.2 sends this when the screen is resized */ ch = KEY_RESIZE; while (ch == KEY_RESIZE) #endif /* KEY_RESIZE */ #ifdef USE_INOTIFY ch = mutt_monitor_getch(); #else ch = getch(); #endif /* USE_INOTIFY */ mutt_sig_allow_interrupt(0); if (SigInt) { mutt_query_exit(); return err; } /* either timeout, a sigwinch (if timeout is set), or the terminal * has been lost */ if (ch == ERR) { if (!isatty(0)) mutt_exit(1); return timeout; } if ((ch & 0x80) && C_MetaKey) { /* send ALT-x as ESC-x */ ch &= ~0x80; mutt_unget_event(ch, 0); ret.ch = '\033'; ret.op = 0; return ret; } ret.ch = ch; ret.op = 0; return (ch == ctrl('G')) ? err : ret; }
/** * mutt_enter_fname_full - Ask the user to select a file * @param[in] prompt Prompt * @param[in] buf Buffer for the result * @param[in] buflen Length of the buffer * @param[in] mailbox If true, select mailboxes * @param[in] multiple Allow multiple selections * @param[out] files List of files selected * @param[out] numfiles Number of files selected * @param[in] flags Flags, see #SelectFileFlags * @retval 0 Success * @retval -1 Error */ int mutt_enter_fname_full(const char *prompt, char *buf, size_t buflen, bool mailbox, bool multiple, char ***files, int *numfiles, SelectFileFlags flags) { struct Event ch; SETCOLOR(MT_COLOR_PROMPT); mutt_window_mvaddstr(MuttMessageWindow, 0, 0, (char *) prompt); addstr(_(" ('?' for list): ")); NORMAL_COLOR; if (buf[0] != '\0') addstr(buf); mutt_window_clrtoeol(MuttMessageWindow); mutt_refresh(); do { ch = mutt_getch(); } while (ch.ch == -2); if (ch.ch < 0) { mutt_window_clearline(MuttMessageWindow, 0); return -1; } else if (ch.ch == '?') { mutt_refresh(); buf[0] = '\0'; if (!flags) flags = MUTT_SEL_FOLDER; if (multiple) flags |= MUTT_SEL_MULTI; if (mailbox) flags |= MUTT_SEL_MAILBOX; mutt_select_file(buf, buflen, flags, files, numfiles); } else { char *pc = mutt_mem_malloc(mutt_str_strlen(prompt) + 3); sprintf(pc, "%s: ", prompt); mutt_unget_event(ch.op ? 0 : ch.ch, ch.op ? ch.op : 0); if (mutt_get_field_full(pc, buf, buflen, (mailbox ? MUTT_EFILE : MUTT_FILE) | MUTT_CLEAR, multiple, files, numfiles) != 0) { buf[0] = '\0'; } FREE(&pc); } return 0; }
int mutt_display_message (HEADER *cur) { char tempfile[_POSIX_PATH_MAX], buf[LONG_STRING]; int rc = 0, builtin = 0; int cmflags = M_CM_DECODE | M_CM_DISPLAY | M_CM_CHARCONV; FILE *fpout = NULL; FILE *fpfilterout = NULL; pid_t filterpid = -1; int res; snprintf (buf, sizeof (buf), "%s/%s", TYPE (cur->content), cur->content->subtype); mutt_parse_mime_message (Context, cur); mutt_message_hook (Context, cur, M_MESSAGEHOOK); /* see if crypto is needed for this message. if so, we should exit curses */ if (WithCrypto && cur->security) { if (cur->security & ENCRYPT) { if (cur->security & APPLICATION_SMIME) crypt_smime_getkeys (cur->env); if(!crypt_valid_passphrase(cur->security)) return 0; cmflags |= M_CM_VERIFY; } else if (cur->security & SIGN) { /* find out whether or not the verify signature */ if (query_quadoption (OPT_VERIFYSIG, _("Verify PGP signature?")) == M_YES) { cmflags |= M_CM_VERIFY; } } } if (cmflags & M_CM_VERIFY || cur->security & ENCRYPT) { if (cur->security & APPLICATION_PGP) { if (cur->env->from) crypt_pgp_invoke_getkeys (cur->env->from); crypt_invoke_message (APPLICATION_PGP); } if (cur->security & APPLICATION_SMIME) crypt_invoke_message (APPLICATION_SMIME); } mutt_mktemp (tempfile, sizeof (tempfile)); if ((fpout = safe_fopen (tempfile, "w")) == NULL) { mutt_error _("Could not create temporary file!"); return (0); } if (DisplayFilter && *DisplayFilter) { fpfilterout = fpout; fpout = NULL; /* mutt_endwin (NULL); */ filterpid = mutt_create_filter_fd (DisplayFilter, &fpout, NULL, NULL, -1, fileno(fpfilterout), -1); if (filterpid < 0) { mutt_error (_("Cannot create display filter")); safe_fclose (&fpfilterout); unlink (tempfile); return 0; } } if (!Pager || mutt_strcmp (Pager, "builtin") == 0) builtin = 1; else { struct hdr_format_info hfi; hfi.ctx = Context; hfi.pager_progress = ExtPagerProgress; hfi.hdr = cur; mutt_make_string_info (buf, sizeof (buf), NONULL(PagerFmt), &hfi, M_FORMAT_MAKEPRINT); fputs (buf, fpout); fputs ("\n\n", fpout); } res = mutt_copy_message (fpout, Context, cur, cmflags, (option (OPTWEED) ? (CH_WEED | CH_REORDER) : 0) | CH_DECODE | CH_FROM | CH_DISPLAY); if ((safe_fclose (&fpout) != 0 && errno != EPIPE) || res < 0) { mutt_error (_("Could not copy message")); if (fpfilterout != NULL) { mutt_wait_filter (filterpid); safe_fclose (&fpfilterout); } mutt_unlink (tempfile); return 0; } if (fpfilterout != NULL && mutt_wait_filter (filterpid) != 0) mutt_any_key_to_continue (NULL); safe_fclose (&fpfilterout); /* XXX - check result? */ if (WithCrypto) { /* update crypto information for this message */ cur->security &= ~(GOODSIGN|BADSIGN); cur->security |= crypt_query (cur->content); /* Remove color cache for this message, in case there are color patterns for both ~g and ~V */ cur->pair = 0; } if (builtin) { pager_t info; if (WithCrypto && (cur->security & APPLICATION_SMIME) && (cmflags & M_CM_VERIFY)) { if (cur->security & GOODSIGN) { if (!crypt_smime_verify_sender(cur)) mutt_message ( _("S/MIME signature successfully verified.")); else mutt_error ( _("S/MIME certificate owner does not match sender.")); } else if (cur->security & PARTSIGN) mutt_message (_("Warning: Part of this message has not been signed.")); else if (cur->security & SIGN || cur->security & BADSIGN) mutt_error ( _("S/MIME signature could NOT be verified.")); } if (WithCrypto && (cur->security & APPLICATION_PGP) && (cmflags & M_CM_VERIFY)) { if (cur->security & GOODSIGN) mutt_message (_("PGP signature successfully verified.")); else if (cur->security & PARTSIGN) mutt_message (_("Warning: Part of this message has not been signed.")); else if (cur->security & SIGN) mutt_message (_("PGP signature could NOT be verified.")); } /* Invoke the builtin pager */ memset (&info, 0, sizeof (pager_t)); info.hdr = cur; info.ctx = Context; rc = mutt_pager (NULL, tempfile, M_PAGER_MESSAGE, &info); } else { int r; mutt_endwin (NULL); snprintf (buf, sizeof (buf), "%s %s", NONULL(Pager), tempfile); if ((r = mutt_system (buf)) == -1) mutt_error (_("Error running \"%s\"!"), buf); unlink (tempfile); if (!option (OPTNOCURSES)) keypad (stdscr, TRUE); if (r != -1) mutt_set_flag (Context, cur, M_READ, 1); if (r != -1 && option (OPTPROMPTAFTER)) { mutt_unget_event (mutt_any_key_to_continue _("Command: "), 0); rc = km_dokey (MENU_PAGER); } else rc = 0; } return rc; }