NeoMutt  2020-06-26-89-g172cd3
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 "alias/lib.h"
#include "gui/lib.h"
#include "mutt.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 "history/lib.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 64 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 56 of file enter.c.

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

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 72 of file enter.c.

73 {
74  int n = wcwidth(wc);
75  if (IsWPrint(wc) && (n > 0))
76  return mutt_addwch(wc);
77  if (!(wc & ~0x7f))
78  return mutt_window_printf("^%c", ((int) wc + 0x40) & 0x7f);
79  if (!(wc & ~0xffff))
80  return mutt_window_printf("\\u%04x", (int) wc);
81  return mutt_window_printf("\\u%08x", (int) wc);
82 }
#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:546
int n
Definition: acutest.h:492
int mutt_addwch(wchar_t wc)
addwch would be provided by an up-to-date curses library
Definition: curs_lib.c:1056
+ 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 90 of file enter.c.

91 {
92  /* Save the suffix */
93  size_t savelen = state->lastchar - state->curpos;
94  wchar_t *savebuf = NULL;
95 
96  if (savelen)
97  {
98  savebuf = mutt_mem_calloc(savelen, sizeof(wchar_t));
99  memcpy(savebuf, state->wbuf + state->curpos, savelen * sizeof(wchar_t));
100  }
101 
102  /* Convert to wide characters */
103  state->curpos = mutt_mb_mbstowcs(&state->wbuf, &state->wbuflen, from, buf);
104 
105  if (savelen)
106  {
107  /* Make space for suffix */
108  if (state->curpos + savelen > state->wbuflen)
109  {
110  state->wbuflen = state->curpos + savelen;
111  mutt_mem_realloc(&state->wbuf, state->wbuflen * sizeof(wchar_t));
112  }
113 
114  /* Restore suffix */
115  memcpy(state->wbuf + state->curpos, savebuf, savelen * sizeof(wchar_t));
116  FREE(&savebuf);
117  }
118 
119  state->lastchar = state->curpos + savelen;
120 }
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 126 of file enter.c.

127 {
128  return mutt_mem_calloc(1, sizeof(struct EnterState));
129 }
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 145 of file enter.c.

146 {
147  int rc;
148  struct EnterState *es = mutt_enter_state_new();
149  do
150  {
151  if (SigWinch)
152  {
153  SigWinch = 0;
155  clearok(stdscr, true);
156  }
157  rc = mutt_enter_string_full(buf, buflen, col, flags, false, NULL, NULL, es);
158  } while (rc == 1);
160  return rc;
161 }
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:177
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:832
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:126
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: mutt_globals.h:76
+ 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 177 of file enter.c.

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

833 {
834  if (!ptr || !*ptr)
835  return;
836 
837  struct EnterState *es = *ptr;
838 
839  FREE(&es->wbuf);
840  FREE(ptr);
841 }
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: