NeoMutt  2021-10-22-8-g9cb437
Teaching an old dog new tricks
DOXYGEN
enter.c File Reference

GUI ask the user to enter a string. More...

#include "config.h"
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include <wchar.h>
#include <wctype.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "history/lib.h"
#include "menu/lib.h"
#include "pattern/lib.h"
#include "browser.h"
#include "enter_state.h"
#include "init.h"
#include "keymap.h"
#include "mutt_globals.h"
#include "mutt_history.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
#include "opcodes.h"
#include "protos.h"
+ Include dependency graph for enter.c:

Go to the source code of this file.

Macros

#define COMB_CHAR(wc)   (IsWPrint(wc) && !wcwidth(wc))
 

Enumerations

enum  EnterRedrawFlags { ENTER_REDRAW_NONE = 0 , ENTER_REDRAW_INIT , ENTER_REDRAW_LINE }
 Redraw flags for mutt_enter_string_full() More...
 

Functions

static int my_addwch (struct MuttWindow *win, wchar_t wc)
 Display one wide character on screen. More...
 
static void replace_part (struct EnterState *state, size_t from, char *buf)
 Search and replace on a buffer. More...
 
struct EnterStatemutt_enter_state_new (void)
 Create a new EnterState. More...
 
int mutt_enter_string_full (char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, struct Mailbox *m, char ***files, int *numfiles, struct EnterState *state)
 Ask the user for a string. More...
 
void mutt_enter_state_free (struct EnterState **ptr)
 Free an EnterState. More...
 

Detailed Description

GUI ask the user to enter a string.

Authors
  • Michael R. Elkins
  • Edmund Grimley Evans

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file enter.c.

Macro Definition Documentation

◆ COMB_CHAR

#define COMB_CHAR (   wc)    (IsWPrint(wc) && !wcwidth(wc))

Definition at line 67 of file enter.c.

Enumeration Type Documentation

◆ EnterRedrawFlags

Redraw flags for mutt_enter_string_full()

Enumerator
ENTER_REDRAW_NONE 

Nothing to redraw.

ENTER_REDRAW_INIT 

Go to end of line and redraw.

ENTER_REDRAW_LINE 

Redraw entire line.

Definition at line 59 of file enter.c.

60 {
61  ENTER_REDRAW_NONE = 0,
64 };
@ ENTER_REDRAW_NONE
Nothing to redraw.
Definition: enter.c:61
@ ENTER_REDRAW_LINE
Redraw entire line.
Definition: enter.c:63
@ ENTER_REDRAW_INIT
Go to end of line and redraw.
Definition: enter.c:62

Function Documentation

◆ my_addwch()

static int my_addwch ( struct MuttWindow win,
wchar_t  wc 
)
static

Display one wide character on screen.

Parameters
winWindow
wcCharacter to display
Return values
OKSuccess
ERRFailure

Definition at line 76 of file enter.c.

77 {
78  int n = wcwidth(wc);
79  if (IsWPrint(wc) && (n > 0))
80  return mutt_addwch(win, wc);
81  if (!(wc & ~0x7f))
82  return mutt_window_printf(win, "^%c", ((int) wc + 0x40) & 0x7f);
83  if (!(wc & ~0xffff))
84  return mutt_window_printf(win, "\\u%04x", (int) wc);
85  return mutt_window_printf(win, "\\u%08x", (int) wc);
86 }
int mutt_addwch(struct MuttWindow *win, wchar_t wc)
Addwch would be provided by an up-to-date curses library.
Definition: curs_lib.c:687
#define IsWPrint(wc)
Definition: mbyte.h:39
int mutt_window_printf(struct MuttWindow *win, const char *fmt,...)
Write a formatted string to a Window.
Definition: mutt_window.c:423
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ replace_part()

static void replace_part ( struct EnterState state,
size_t  from,
char *  buf 
)
static

Search and replace on a buffer.

Parameters
stateCurrent state of the input buffer
fromStarting point for the replacement
bufReplacement string

Definition at line 94 of file enter.c.

95 {
96  /* Save the suffix */
97  size_t savelen = state->lastchar - state->curpos;
98  wchar_t *savebuf = NULL;
99 
100  if (savelen)
101  {
102  savebuf = mutt_mem_calloc(savelen, sizeof(wchar_t));
103  memcpy(savebuf, state->wbuf + state->curpos, savelen * sizeof(wchar_t));
104  }
105 
106  /* Convert to wide characters */
107  state->curpos = mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, from, buf);
108 
109  if (savelen)
110  {
111  /* Make space for suffix */
112  if (state->curpos + savelen > state->wbuflen)
113  {
114  state->wbuflen = state->curpos + savelen;
115  mutt_mem_realloc(&state->wbuf, state->wbuflen * sizeof(wchar_t));
116  }
117 
118  /* Restore suffix */
119  memcpy(state->wbuf + state->curpos, savebuf, savelen * sizeof(wchar_t));
120  FREE(&savebuf);
121  }
122 
123  state->lastchar = state->curpos + savelen;
124 }
size_t mutt_mb_mbstowcs(wchar_t **pwbuf, size_t *pwbuflen, size_t i, const char *buf)
Convert a string from multibyte to wide characters.
Definition: mbyte.c:294
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
#define FREE(x)
Definition: memory.h:40
size_t curpos
Position of the cursor.
Definition: enter_state.h:37
size_t wbuflen
Length of buffer.
Definition: enter_state.h:35
wchar_t * wbuf
Buffer for the string being entered.
Definition: enter_state.h:34
size_t lastchar
Position of the last character.
Definition: enter_state.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_state_new()

struct EnterState* mutt_enter_state_new ( void  )

Create a new EnterState.

Return values
ptrNew EnterState

Definition at line 130 of file enter.c.

131 {
132  return mutt_mem_calloc(1, sizeof(struct EnterState));
133 }
Keep our place when entering a string.
Definition: enter_state.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_string_full()

int mutt_enter_string_full ( char *  buf,
size_t  buflen,
int  col,
CompletionFlags  flags,
bool  multiple,
struct Mailbox m,
char ***  files,
int *  numfiles,
struct EnterState state 
)

Ask the user for a string.

Parameters
[in]bufBuffer to store the string
[in]buflenBuffer length
[in]colInitial cursor position
[in]flagsFlags, see CompletionFlags
[in]multipleAllow multiple matches
[in]mMailbox
[out]filesList of files selected
[out]numfilesNumber of files selected
[out]stateCurrent state (if function is called repeatedly)
Return values
1Redraw the screen and call the function again
0Selection made
-1Aborted

Definition at line 150 of file enter.c.

153 {
154  struct MuttWindow *win = msgwin_get_window();
155  if (!win)
156  return -1;
157 
158  int width = win->state.cols - col - 1;
159  enum EnterRedrawFlags redraw = ENTER_REDRAW_NONE;
160  bool pass = (flags & MUTT_PASS);
161  bool first = true;
162  int ch;
163  wchar_t *tempbuf = NULL;
164  size_t templen = 0;
165  enum HistoryClass hclass;
166  int rc = 0;
167  mbstate_t mbstate;
168  memset(&mbstate, 0, sizeof(mbstate));
169 
170  if (state->wbuf)
171  {
172  /* Coming back after return 1 */
173  redraw = ENTER_REDRAW_LINE;
174  first = false;
175  }
176  else
177  {
178  /* Initialise wbuf from buf */
179  state->wbuflen = 0;
180  state->lastchar = mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, 0, buf);
181  redraw = ENTER_REDRAW_INIT;
182  }
183 
184  if (flags & MUTT_FILE)
185  hclass = HC_FILE;
186  else if (flags & MUTT_EFILE)
187  hclass = HC_MBOX;
188  else if (flags & MUTT_CMD)
189  hclass = HC_CMD;
190  else if (flags & MUTT_ALIAS)
191  hclass = HC_ALIAS;
192  else if (flags & MUTT_COMMAND)
193  hclass = HC_COMMAND;
194  else if (flags & MUTT_PATTERN)
195  hclass = HC_PATTERN;
196  else
197  hclass = HC_OTHER;
198 
199  while (true)
200  {
201  if (!pass)
202  {
203  if (redraw == ENTER_REDRAW_INIT)
204  {
205  /* Go to end of line */
206  state->curpos = state->lastchar;
207  state->begin = mutt_mb_width_ceiling(
208  state->wbuf, state->lastchar,
209  mutt_mb_wcswidth(state->wbuf, state->lastchar) - width + 1);
210  }
211  if ((state->curpos < state->begin) ||
212  (mutt_mb_wcswidth(state->wbuf + state->begin, state->curpos - state->begin) >= width))
213  {
214  state->begin = mutt_mb_width_ceiling(
215  state->wbuf, state->lastchar,
216  mutt_mb_wcswidth(state->wbuf, state->curpos) - (width / 2));
217  }
218  mutt_window_move(win, col, 0);
219  int w = 0;
220  for (size_t i = state->begin; i < state->lastchar; i++)
221  {
222  w += mutt_mb_wcwidth(state->wbuf[i]);
223  if (w > width)
224  break;
225  my_addwch(win, state->wbuf[i]);
226  }
228  mutt_window_move(win,
229  col + mutt_mb_wcswidth(state->wbuf + state->begin,
230  state->curpos - state->begin),
231  0);
232  }
233  mutt_refresh();
234 
235  ch = km_dokey(MENU_EDITOR);
236  if (ch < 0)
237  {
238  rc = (SigWinch && (ch == -2)) ? 1 : -1;
239  goto bye;
240  }
241 
242  if (ch != OP_NULL)
243  {
244  first = false;
245  if ((ch != OP_EDITOR_COMPLETE) && (ch != OP_EDITOR_COMPLETE_QUERY))
246  state->tabs = 0;
247  redraw = ENTER_REDRAW_LINE;
248  switch (ch)
249  {
250  case OP_EDITOR_HISTORY_UP:
251  state->curpos = state->lastchar;
252  if (mutt_hist_at_scratch(hclass))
253  {
254  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
255  mutt_hist_save_scratch(hclass, buf);
256  }
257  replace_part(state, 0, mutt_hist_prev(hclass));
258  redraw = ENTER_REDRAW_INIT;
259  break;
260 
261  case OP_EDITOR_HISTORY_DOWN:
262  state->curpos = state->lastchar;
263  if (mutt_hist_at_scratch(hclass))
264  {
265  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
266  mutt_hist_save_scratch(hclass, buf);
267  }
268  replace_part(state, 0, mutt_hist_next(hclass));
269  redraw = ENTER_REDRAW_INIT;
270  break;
271 
272  case OP_EDITOR_HISTORY_SEARCH:
273  state->curpos = state->lastchar;
274  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
275  mutt_hist_complete(buf, buflen, hclass);
276  replace_part(state, 0, buf);
277  rc = 1;
278  goto bye;
279  break;
280 
281  case OP_EDITOR_BACKSPACE:
282  if (state->curpos == 0)
283  {
284  // Pressing backspace when no text is in the command prompt should exit the prompt
285  const bool c_abort_backspace =
286  cs_subset_bool(NeoMutt->sub, "abort_backspace");
287  if (c_abort_backspace && (state->lastchar == 0))
288  goto bye;
289  // Pressing backspace with text in the command prompt should just beep
290  mutt_beep(false);
291  }
292  else
293  {
294  size_t i = state->curpos;
295  while ((i > 0) && COMB_CHAR(state->wbuf[i - 1]))
296  i--;
297  if (i > 0)
298  i--;
299  memmove(state->wbuf + i, state->wbuf + state->curpos,
300  (state->lastchar - state->curpos) * sizeof(wchar_t));
301  state->lastchar -= state->curpos - i;
302  state->curpos = i;
303  }
304  break;
305 
306  case OP_EDITOR_BOL:
307  state->curpos = 0;
308  break;
309 
310  case OP_EDITOR_EOL:
311  redraw = ENTER_REDRAW_INIT;
312  break;
313 
314  case OP_EDITOR_KILL_LINE:
315  state->curpos = 0;
316  state->lastchar = 0;
317  break;
318 
319  case OP_EDITOR_KILL_EOL:
320  state->lastchar = state->curpos;
321  break;
322 
323  case OP_EDITOR_BACKWARD_CHAR:
324  if (state->curpos == 0)
325  mutt_beep(false);
326  else
327  {
328  while (state->curpos && COMB_CHAR(state->wbuf[state->curpos - 1]))
329  state->curpos--;
330  if (state->curpos)
331  state->curpos--;
332  }
333  break;
334 
335  case OP_EDITOR_FORWARD_CHAR:
336  if (state->curpos == state->lastchar)
337  mutt_beep(false);
338  else
339  {
340  state->curpos++;
341  while ((state->curpos < state->lastchar) &&
342  COMB_CHAR(state->wbuf[state->curpos]))
343  {
344  state->curpos++;
345  }
346  }
347  break;
348 
349  case OP_EDITOR_BACKWARD_WORD:
350  if (state->curpos == 0)
351  mutt_beep(false);
352  else
353  {
354  while (state->curpos && iswspace(state->wbuf[state->curpos - 1]))
355  state->curpos--;
356  while (state->curpos && !iswspace(state->wbuf[state->curpos - 1]))
357  state->curpos--;
358  }
359  break;
360 
361  case OP_EDITOR_FORWARD_WORD:
362  if (state->curpos == state->lastchar)
363  mutt_beep(false);
364  else
365  {
366  while ((state->curpos < state->lastchar) &&
367  iswspace(state->wbuf[state->curpos]))
368  {
369  state->curpos++;
370  }
371  while ((state->curpos < state->lastchar) &&
372  !iswspace(state->wbuf[state->curpos]))
373  {
374  state->curpos++;
375  }
376  }
377  break;
378 
379  case OP_EDITOR_CAPITALIZE_WORD:
380  case OP_EDITOR_UPCASE_WORD:
381  case OP_EDITOR_DOWNCASE_WORD:
382  if (state->curpos == state->lastchar)
383  {
384  mutt_beep(false);
385  break;
386  }
387  while (state->curpos && !iswspace(state->wbuf[state->curpos]))
388  state->curpos--;
389  while ((state->curpos < state->lastchar) && iswspace(state->wbuf[state->curpos]))
390  state->curpos++;
391  while ((state->curpos < state->lastchar) &&
392  !iswspace(state->wbuf[state->curpos]))
393  {
394  if (ch == OP_EDITOR_DOWNCASE_WORD)
395  state->wbuf[state->curpos] = towlower(state->wbuf[state->curpos]);
396  else
397  {
398  state->wbuf[state->curpos] = towupper(state->wbuf[state->curpos]);
399  if (ch == OP_EDITOR_CAPITALIZE_WORD)
400  ch = OP_EDITOR_DOWNCASE_WORD;
401  }
402  state->curpos++;
403  }
404  break;
405 
406  case OP_EDITOR_DELETE_CHAR:
407  if (state->curpos == state->lastchar)
408  mutt_beep(false);
409  else
410  {
411  size_t i = state->curpos;
412  while ((i < state->lastchar) && COMB_CHAR(state->wbuf[i]))
413  i++;
414  if (i < state->lastchar)
415  i++;
416  while ((i < state->lastchar) && COMB_CHAR(state->wbuf[i]))
417  i++;
418  memmove(state->wbuf + state->curpos, state->wbuf + i,
419  (state->lastchar - i) * sizeof(wchar_t));
420  state->lastchar -= i - state->curpos;
421  }
422  break;
423 
424  case OP_EDITOR_KILL_WORD:
425  /* delete to beginning of word */
426  if (state->curpos != 0)
427  {
428  size_t i = state->curpos;
429  while (i && iswspace(state->wbuf[i - 1]))
430  i--;
431  if (i > 0)
432  {
433  if (iswalnum(state->wbuf[i - 1]))
434  {
435  for (--i; (i > 0) && iswalnum(state->wbuf[i - 1]); i--)
436  ; // do nothing
437  }
438  else
439  i--;
440  }
441  memmove(state->wbuf + i, state->wbuf + state->curpos,
442  (state->lastchar - state->curpos) * sizeof(wchar_t));
443  state->lastchar += i - state->curpos;
444  state->curpos = i;
445  }
446  break;
447 
448  case OP_EDITOR_KILL_EOW:
449  {
450  /* delete to end of word */
451 
452  /* first skip over whitespace */
453  size_t i;
454  for (i = state->curpos; (i < state->lastchar) && iswspace(state->wbuf[i]); i++)
455  ; // do nothing
456 
457  /* if there are any characters left.. */
458  if (i < state->lastchar)
459  {
460  /* if the current character is alphanumeric.. */
461  if (iswalnum(state->wbuf[i]))
462  {
463  /* skip over the rest of the word consistent of only alphanumerics */
464  for (; (i < state->lastchar) && iswalnum(state->wbuf[i]); i++)
465  ; // do nothing
466  }
467  else
468  {
469  /* skip over one non-alphanumeric character */
470  i++;
471  }
472  }
473 
474  memmove(state->wbuf + state->curpos, state->wbuf + i,
475  (state->lastchar - i) * sizeof(wchar_t));
476  state->lastchar += state->curpos - i;
477  break;
478  }
479 
480  case OP_EDITOR_MAILBOX_CYCLE:
481  if (flags & MUTT_EFILE)
482  {
483  first = true; /* clear input if user types a real key later */
484  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
485 
486  struct Buffer *pool = mutt_buffer_pool_get();
487  mutt_buffer_addstr(pool, buf);
488  mutt_mailbox_next(m, pool);
489  mutt_str_copy(buf, mutt_buffer_string(pool), buflen);
491 
492  state->curpos = state->lastchar =
493  mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, 0, buf);
494  break;
495  }
496  else if (!(flags & MUTT_FILE))
497  {
498  goto self_insert;
499  }
500  /* fallthrough */
501 
502  case OP_EDITOR_COMPLETE:
503  case OP_EDITOR_COMPLETE_QUERY:
504  state->tabs++;
505  if (flags & MUTT_CMD)
506  {
507  size_t i;
508  for (i = state->curpos;
509  (i > 0) && !mutt_mb_is_shell_char(state->wbuf[i - 1]); i--)
510  {
511  }
512  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
513  if (tempbuf && (templen == (state->lastchar - i)) &&
514  (memcmp(tempbuf, state->wbuf + i, (state->lastchar - i) * sizeof(wchar_t)) == 0))
515  {
517  m, NULL, NULL);
518  if (buf[0] != '\0')
519  replace_part(state, i, buf);
520  rc = 1;
521  goto bye;
522  }
523  if (mutt_complete(buf, buflen) == 0)
524  {
525  templen = state->lastchar - i;
526  mutt_mem_realloc(&tempbuf, templen * sizeof(wchar_t));
527  }
528  else
529  mutt_beep(false);
530 
531  replace_part(state, i, buf);
532  }
533  else if ((flags & MUTT_ALIAS) && (ch == OP_EDITOR_COMPLETE))
534  {
535  /* invoke the alias-menu to get more addresses */
536  size_t i;
537  for (i = state->curpos;
538  (i > 0) && (state->wbuf[i - 1] != ',') && (state->wbuf[i - 1] != ':'); i--)
539  {
540  }
541  for (; (i < state->lastchar) && (state->wbuf[i] == ' '); i++)
542  ; // do nothing
543 
544  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
545  int rc2 = alias_complete(buf, buflen, NeoMutt->sub);
546  replace_part(state, i, buf);
547  if (rc2 != 1)
548  {
549  rc = 1;
550  goto bye;
551  }
552  break;
553  }
554  else if ((flags & MUTT_LABEL) && (ch == OP_EDITOR_COMPLETE))
555  {
556  size_t i;
557  for (i = state->curpos;
558  (i > 0) && (state->wbuf[i - 1] != ',') && (state->wbuf[i - 1] != ':'); i--)
559  {
560  }
561  for (; (i < state->lastchar) && (state->wbuf[i] == ' '); i++)
562  ; // do nothing
563 
564  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
565  int rc2 = mutt_label_complete(buf, buflen, state->tabs);
566  replace_part(state, i, buf);
567  if (rc2 != 1)
568  {
569  rc = 1;
570  goto bye;
571  }
572  break;
573  }
574  else if ((flags & MUTT_PATTERN) && (ch == OP_EDITOR_COMPLETE))
575  {
576  size_t i = state->curpos;
577  if (i && (state->wbuf[i - 1] == '~'))
578  {
579  if (dlg_select_pattern(buf, buflen))
580  replace_part(state, i - 1, buf);
581  rc = 1;
582  goto bye;
583  }
584  for (; (i > 0) && (state->wbuf[i - 1] != '~'); i--)
585  ; // do nothing
586 
587  if ((i > 0) && (i < state->curpos) && (state->wbuf[i - 1] == '~') &&
588  (state->wbuf[i] == 'y'))
589  {
590  i++;
591  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
592  int rc2 = mutt_label_complete(buf, buflen, state->tabs);
593  replace_part(state, i, buf);
594  if (rc2 != 1)
595  {
596  rc = 1;
597  goto bye;
598  }
599  }
600  else
601  goto self_insert;
602  break;
603  }
604  else if ((flags & MUTT_ALIAS) && (ch == OP_EDITOR_COMPLETE_QUERY))
605  {
606  size_t i = state->curpos;
607  if (i != 0)
608  {
609  for (; (i > 0) && (state->wbuf[i - 1] != ','); i--)
610  ; // do nothing
611 
612  for (; (i < state->curpos) && (state->wbuf[i] == ' '); i++)
613  ; // do nothing
614  }
615 
616  mutt_mb_wcstombs(buf, buflen, state->wbuf + i, state->curpos - i);
617  query_complete(buf, buflen, NeoMutt->sub);
618  replace_part(state, i, buf);
619 
620  rc = 1;
621  goto bye;
622  }
623  else if (flags & MUTT_COMMAND)
624  {
625  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
626  size_t i = strlen(buf);
627  if ((i != 0) && (buf[i - 1] == '=') &&
628  (mutt_var_value_complete(buf, buflen, i) != 0))
629  {
630  state->tabs = 0;
631  }
632  else if (mutt_command_complete(buf, buflen, i, state->tabs) == 0)
633  mutt_beep(false);
634  replace_part(state, 0, buf);
635  }
636  else if (flags & (MUTT_FILE | MUTT_EFILE))
637  {
638  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
639 
640  /* see if the path has changed from the last time */
641  if ((!tempbuf && !state->lastchar) ||
642  (tempbuf && (templen == state->lastchar) &&
643  (memcmp(tempbuf, state->wbuf, state->lastchar * sizeof(wchar_t)) == 0)))
644  {
645  mutt_select_file(buf, buflen,
647  (multiple ? MUTT_SEL_MULTI : MUTT_SEL_NO_FLAGS),
648  m, files, numfiles);
649  if (buf[0] != '\0')
650  {
651  mutt_pretty_mailbox(buf, buflen);
652  if (!pass)
653  mutt_hist_add(hclass, buf, true);
654  rc = 0;
655  goto bye;
656  }
657 
658  /* file selection cancelled */
659  rc = 1;
660  goto bye;
661  }
662 
663  if (mutt_complete(buf, buflen) == 0)
664  {
665  templen = state->lastchar;
666  mutt_mem_realloc(&tempbuf, templen * sizeof(wchar_t));
667  memcpy(tempbuf, state->wbuf, templen * sizeof(wchar_t));
668  }
669  else
670  mutt_beep(false); /* let the user know that nothing matched */
671  replace_part(state, 0, buf);
672  }
673 #ifdef USE_NOTMUCH
674  else if (flags & MUTT_NM_QUERY)
675  {
676  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
677  size_t len = strlen(buf);
678  if (!mutt_nm_query_complete(buf, buflen, len, state->tabs))
679  mutt_beep(false);
680 
681  replace_part(state, 0, buf);
682  }
683  else if (flags & MUTT_NM_TAG)
684  {
685  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->curpos);
686  if (!mutt_nm_tag_complete(buf, buflen, state->tabs))
687  mutt_beep(false);
688 
689  replace_part(state, 0, buf);
690  }
691 #endif
692  else
693  goto self_insert;
694  break;
695 
696  case OP_EDITOR_QUOTE_CHAR:
697  {
698  struct KeyEvent event;
699  do
700  {
701  event = mutt_getch();
702  } while (event.ch == -2); // Timeout
703  if (event.ch >= 0)
704  {
705  LastKey = event.ch;
706  goto self_insert;
707  }
708  break;
709  }
710 
711  case OP_EDITOR_TRANSPOSE_CHARS:
712  if (state->lastchar < 2)
713  mutt_beep(false);
714  else
715  {
716  wchar_t t;
717 
718  if (state->curpos == 0)
719  state->curpos = 2;
720  else if (state->curpos < state->lastchar)
721  state->curpos++;
722 
723  t = state->wbuf[state->curpos - 2];
724  state->wbuf[state->curpos - 2] = state->wbuf[state->curpos - 1];
725  state->wbuf[state->curpos - 1] = t;
726  }
727  break;
728 
729  default:
730  mutt_beep(false);
731  }
732  }
733  else
734  {
735  self_insert:
736  state->tabs = 0;
737  wchar_t wc;
738  /* use the raw keypress */
739  ch = LastKey;
740 
741  /* quietly ignore all other function keys */
742  if (ch & ~0xff)
743  continue;
744 
745  /* gather the octets into a wide character */
746  {
747  char c = ch;
748  size_t k = mbrtowc(&wc, &c, 1, &mbstate);
749  if (k == (size_t) (-2))
750  continue;
751  else if ((k != 0) && (k != 1))
752  {
753  memset(&mbstate, 0, sizeof(mbstate));
754  continue;
755  }
756  }
757 
758  if (first && (flags & MUTT_CLEAR))
759  {
760  first = false;
761  if (IsWPrint(wc)) /* why? */
762  {
763  state->curpos = 0;
764  state->lastchar = 0;
765  }
766  }
767 
768  if ((wc == '\r') || (wc == '\n'))
769  {
770  /* Convert from wide characters */
771  mutt_mb_wcstombs(buf, buflen, state->wbuf, state->lastchar);
772  if (!pass)
773  mutt_hist_add(hclass, buf, true);
774 
775  if (multiple)
776  {
777  char **tfiles = NULL;
778  *numfiles = 1;
779  tfiles = mutt_mem_calloc(*numfiles, sizeof(char *));
780  mutt_expand_path(buf, buflen);
781  tfiles[0] = mutt_str_dup(buf);
782  *files = tfiles;
783  }
784  rc = 0;
785  goto bye;
786  }
787  else if (wc && ((wc < ' ') || IsWPrint(wc))) /* why? */
788  {
789  if (state->lastchar >= state->wbuflen)
790  {
791  state->wbuflen = state->lastchar + 20;
792  mutt_mem_realloc(&state->wbuf, state->wbuflen * sizeof(wchar_t));
793  }
794  memmove(state->wbuf + state->curpos + 1, state->wbuf + state->curpos,
795  (state->lastchar - state->curpos) * sizeof(wchar_t));
796  state->wbuf[state->curpos++] = wc;
797  state->lastchar++;
798  }
799  else
800  {
801  mutt_flushinp();
802  mutt_beep(false);
803  }
804  }
805  }
806 
807 bye:
808 
809  mutt_hist_reset_state(hclass);
810  FREE(&tempbuf);
811  return rc;
812 }
void mutt_select_file(char *file, size_t filelen, SelectFileFlags flags, struct Mailbox *m, char ***files, int *numfiles)
Let the user select a file.
Definition: browser.c:2341
#define MUTT_SEL_FOLDER
Select a local directory.
Definition: browser.h:39
#define MUTT_SEL_MULTI
Multi-selection is enabled.
Definition: browser.h:38
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: browser.h:36
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:225
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_complete(char *buf, size_t buflen)
Attempt to complete a partial pathname.
Definition: complete.c:57
void mutt_flushinp(void)
Empty all the keyboard buffers.
Definition: curs_lib.c:673
struct KeyEvent mutt_getch(void)
Read a character from the input buffer.
Definition: curs_lib.c:195
void mutt_refresh(void)
Force a refresh of the screen.
Definition: curs_lib.c:114
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:104
int alias_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
Alias completion routine.
Definition: dlgalias.c:463
bool dlg_select_pattern(char *buf, size_t buflen)
Show menu to select a Pattern.
Definition: dlgpattern.c:343
int query_complete(char *buf, size_t buflen, struct ConfigSubset *sub)
Perform auto-complete using an Address Query.
Definition: dlgquery.c:694
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:526
#define COMB_CHAR(wc)
Definition: enter.c:67
static int my_addwch(struct MuttWindow *win, wchar_t wc)
Display one wide character on screen.
Definition: enter.c:76
static void replace_part(struct EnterState *state, size_t from, char *buf)
Search and replace on a buffer.
Definition: enter.c:94
EnterRedrawFlags
Redraw flags for mutt_enter_string_full()
Definition: enter.c:60
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
HistoryClass
Type to differentiate different histories.
Definition: lib.h:47
@ HC_MBOX
Mailboxes.
Definition: lib.h:54
@ HC_FILE
Files.
Definition: lib.h:51
@ HC_COMMAND
NeoMutt commands.
Definition: lib.h:50
@ HC_ALIAS
Aliases.
Definition: lib.h:49
@ HC_PATTERN
Patterns.
Definition: lib.h:52
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:53
@ HC_CMD
External commands.
Definition: lib.h:48
void mutt_hist_save_scratch(enum HistoryClass hclass, const char *str)
Save a temporary string to the History.
Definition: history.c:669
char * mutt_hist_next(enum HistoryClass hclass)
Get the next string in a History.
Definition: history.c:529
bool mutt_hist_at_scratch(enum HistoryClass hclass)
Is the current History position at the 'scratch' place?
Definition: history.c:652
void mutt_hist_add(enum HistoryClass hclass, const char *str, bool save)
Add a string to a history.
Definition: history.c:486
void mutt_hist_reset_state(enum HistoryClass hclass)
Move the 'current' position to the end of the History.
Definition: history.c:585
char * mutt_hist_prev(enum HistoryClass hclass)
Get the previous string in a History.
Definition: history.c:557
int mutt_var_value_complete(char *buf, size_t buflen, int pos)
Complete a variable/value.
Definition: init.c:1486
bool mutt_nm_query_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:1376
int mutt_label_complete(char *buf, size_t buflen, int numtabs)
Complete a label name.
Definition: init.c:1312
bool mutt_nm_tag_complete(char *buf, size_t buflen, int numtabs)
Complete to the nearest notmuch tag.
Definition: init.c:1433
int mutt_command_complete(char *buf, size_t buflen, int pos, int numtabs)
Complete a command name.
Definition: init.c:1130
int km_dokey(enum MenuType mtype)
Determine what a keypress should do.
Definition: keymap.c:627
int LastKey
contains the last key the user pressed
Definition: keymap.c:117
void mutt_mb_wcstombs(char *dest, size_t dlen, const wchar_t *src, size_t slen)
Convert a string from wide to multibyte characters.
Definition: mbyte.c:236
bool mutt_mb_is_shell_char(wchar_t ch)
Is character not typically part of a pathname.
Definition: mbyte.c:343
size_t mutt_mb_width_ceiling(const wchar_t *s, size_t n, int w1)
Keep the end of the string on-screen.
Definition: mbyte.c:216
int mutt_mb_wcswidth(const wchar_t *s, size_t n)
Measure the screen width of a string.
Definition: mbyte.c:195
int mutt_mb_wcwidth(wchar_t wc)
Measure the screen width of a character.
Definition: mbyte.c:177
struct MuttWindow * msgwin_get_window(void)
Get the Message Window pointer.
Definition: msgwin.c:251
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:749
#define MUTT_CLEAR
Clear input if printable character is pressed.
Definition: mutt.h:58
#define MUTT_PATTERN
Pattern mode - only used for history classes.
Definition: mutt.h:60
#define MUTT_NM_QUERY
Notmuch query mode.
Definition: mutt.h:62
#define MUTT_EFILE
Do file completion, plus incoming folders.
Definition: mutt.h:55
#define MUTT_LABEL
Do label completion.
Definition: mutt.h:61
#define MUTT_ALIAS
Do alias "completion" by calling up the alias-menu.
Definition: mutt.h:53
#define MUTT_CMD
Do completion on previous word.
Definition: mutt.h:56
#define MUTT_COMMAND
Do command completion.
Definition: mutt.h:59
#define MUTT_PASS
Password mode (no echo)
Definition: mutt.h:57
#define MUTT_NM_TAG
Notmuch tag +/- mode.
Definition: mutt.h:63
#define MUTT_FILE
Do file completion.
Definition: mutt.h:54
SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:74
void mutt_hist_complete(char *buf, size_t buflen, enum HistoryClass hclass)
Complete a string from a history list.
Definition: mutt_history.c:43
struct Mailbox * mutt_mailbox_next(struct Mailbox *m_cur, struct Buffer *s)
Incoming folders completion routine.
Definition: mutt_mailbox.c:384
int mutt_window_move(struct MuttWindow *win, int col, int row)
Move the cursor in a Window.
Definition: mutt_window.c:292
void mutt_window_clrtoeol(struct MuttWindow *win)
Clear to the end of the line.
Definition: mutt_window.c:241
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:122
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
String manipulation buffer.
Definition: buffer.h:34
int tabs
Number of times the user has hit tab.
Definition: enter_state.h:39
An event such as a keypress.
Definition: keymap.h:65
int ch
raw key pressed
Definition: keymap.h:66
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:127
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:60
@ MENU_EDITOR
Text entry area.
Definition: type.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_state_free()

void mutt_enter_state_free ( struct EnterState **  ptr)

Free an EnterState.

Parameters
[out]ptrEnterState to free

Definition at line 818 of file enter.c.

819 {
820  if (!ptr || !*ptr)
821  return;
822 
823  struct EnterState *es = *ptr;
824 
825  FREE(&es->wbuf);
826  FREE(ptr);
827 }
+ Here is the caller graph for this function: