NeoMutt  2020-11-20
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 "core/neomutt.h"
#include "alias/lib.h"
#include "gui/lib.h"
#include "mutt.h"
#include "history/lib.h"
#include "pattern/lib.h"
#include "browser.h"
#include "context.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 (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 (char *buf, size_t buflen, int col, CompletionFlags flags)
 Ask the user for a string. More...
 
int mutt_enter_string_full (char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, 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 66 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 58 of file enter.c.

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

Function Documentation

◆ my_addwch()

static int my_addwch ( wchar_t  wc)
static

Display one wide character on screen.

Parameters
wcCharacter to display
Return values
OKSuccess
ERRFailure

Definition at line 74 of file enter.c.

75 {
76  int n = wcwidth(wc);
77  if (IsWPrint(wc) && (n > 0))
78  return mutt_addwch(wc);
79  if (!(wc & ~0x7f))
80  return mutt_window_printf("^%c", ((int) wc + 0x40) & 0x7f);
81  if (!(wc & ~0xffff))
82  return mutt_window_printf("\\u%04x", (int) wc);
83  return mutt_window_printf("\\u%08x", (int) wc);
84 }
#define IsWPrint(wc)
Definition: mbyte.h:40
int mutt_window_printf(const char *fmt,...)
Write a formatted string to a Window.
Definition: mutt_window.c:550
int mutt_addwch(wchar_t wc)
addwch would be provided by an up-to-date curses library
Definition: curs_lib.c:1059
+ 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 92 of file enter.c.

93 {
94  /* Save the suffix */
95  size_t savelen = state->lastchar - state->curpos;
96  wchar_t *savebuf = NULL;
97 
98  if (savelen)
99  {
100  savebuf = mutt_mem_calloc(savelen, sizeof(wchar_t));
101  memcpy(savebuf, state->wbuf + state->curpos, savelen * sizeof(wchar_t));
102  }
103 
104  /* Convert to wide characters */
105  state->curpos = mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, from, buf);
106 
107  if (savelen)
108  {
109  /* Make space for suffix */
110  if (state->curpos + savelen > state->wbuflen)
111  {
112  state->wbuflen = state->curpos + savelen;
113  mutt_mem_realloc(&state->wbuf, state->wbuflen * sizeof(wchar_t));
114  }
115 
116  /* Restore suffix */
117  memcpy(state->wbuf + state->curpos, savebuf, savelen * sizeof(wchar_t));
118  FREE(&savebuf);
119  }
120 
121  state->lastchar = state->curpos + savelen;
122 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
wchar_t * wbuf
Definition: enter_state.h:34
size_t wbuflen
Definition: enter_state.h:35
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
size_t curpos
Definition: enter_state.h:37
size_t mutt_mb_mbstowcs(wchar_t **pwbuf, size_t *pwbuflen, size_t i, char *buf)
Convert a string from multibyte to wide characters.
Definition: mbyte.c:295
#define FREE(x)
Definition: memory.h:40
size_t lastchar
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 128 of file enter.c.

129 {
130  return mutt_mem_calloc(1, sizeof(struct EnterState));
131 }
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
Keep our place when entering a string.
Definition: enter_state.h:32
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_string()

int mutt_enter_string ( char *  buf,
size_t  buflen,
int  col,
CompletionFlags  flags 
)

Ask the user for a string.

Parameters
bufBuffer to store the string
buflenBuffer length
colInitial cursor position
flagsFlags, see CompletionFlags
Return values
0if input was given
-1if abort

This function is for very basic input, currently used only by the built-in editor. It does not handle screen redrawing on resizes well, because there is no active menu for the built-in editor. Most callers should prefer mutt_get_field() instead.

Definition at line 147 of file enter.c.

148 {
149  int rc;
150  struct EnterState *es = mutt_enter_state_new();
151  do
152  {
153  if (SigWinch)
154  {
155  SigWinch = 0;
157  clearok(stdscr, true);
158  }
159  rc = mutt_enter_string_full(buf, buflen, col, flags, false, NULL, NULL, es);
160  } while (rc == 1);
162  return rc;
163 }
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:101
int mutt_enter_string_full(char *buf, size_t buflen, int col, CompletionFlags flags, bool multiple, char ***files, int *numfiles, struct EnterState *state)
Ask the user for a string.
Definition: enter.c:179
Keep our place when entering a string.
Definition: enter_state.h:32
void mutt_enter_state_free(struct EnterState **ptr)
Free an EnterState.
Definition: enter.c:841
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:128
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:75
+ Here is the call graph for this function:

◆ mutt_enter_string_full()

int mutt_enter_string_full ( char *  buf,
size_t  buflen,
int  col,
CompletionFlags  flags,
bool  multiple,
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
[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 179 of file enter.c.

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

842 {
843  if (!ptr || !*ptr)
844  return;
845 
846  struct EnterState *es = *ptr;
847 
848  FREE(&es->wbuf);
849  FREE(ptr);
850 }
wchar_t * wbuf
Definition: enter_state.h:34
Keep our place when entering a string.
Definition: enter_state.h:32
#define FREE(x)
Definition: memory.h:40
+ Here is the caller graph for this function: