NeoMutt  2020-03-20-65-g141838
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 "gui/lib.h"
#include "mutt.h"
#include "alias.h"
#include "browser.h"
#include "context.h"
#include "enter_state.h"
#include "globals.h"
#include "init.h"
#include "keymap.h"
#include "mutt_history.h"
#include "mutt_mailbox.h"
#include "muttlib.h"
#include "opcodes.h"
#include "protos.h"
#include "query.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:458
int n
Definition: acutest.h:477
int mutt_addwch(wchar_t wc)
addwch would be provided by an up-to-date curses library
Definition: curs_lib.c:1037
+ 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
WHERE SIG_ATOMIC_VOLATILE_T SigWinch
true after SIGWINCH is received
Definition: globals.h:80
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:821
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:126
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_string_full()

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

822 {
823  if (!ptr || !*ptr)
824  return;
825 
826  struct EnterState *es = *ptr;
827 
828  FREE(&es->wbuf);
829  FREE(ptr);
830 }
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: