NeoMutt  2020-08-21-74-g346364
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 "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 65 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 57 of file enter.c.

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

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

74 {
75  int n = wcwidth(wc);
76  if (IsWPrint(wc) && (n > 0))
77  return mutt_addwch(wc);
78  if (!(wc & ~0x7f))
79  return mutt_window_printf("^%c", ((int) wc + 0x40) & 0x7f);
80  if (!(wc & ~0xffff))
81  return mutt_window_printf("\\u%04x", (int) wc);
82  return mutt_window_printf("\\u%08x", (int) wc);
83 }
#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:560
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 91 of file enter.c.

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

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

147 {
148  int rc;
149  struct EnterState *es = mutt_enter_state_new();
150  do
151  {
152  if (SigWinch)
153  {
154  SigWinch = 0;
156  clearok(stdscr, true);
157  }
158  rc = mutt_enter_string_full(buf, buflen, col, flags, false, NULL, NULL, es);
159  } while (rc == 1);
161  return rc;
162 }
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:178
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:840
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:127
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 178 of file enter.c.

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

841 {
842  if (!ptr || !*ptr)
843  return;
844 
845  struct EnterState *es = *ptr;
846 
847  FREE(&es->wbuf);
848  FREE(ptr);
849 }
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: