NeoMutt  2019-12-07-60-g0cfa53
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/mutt.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 "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 63 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 55 of file enter.c.

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

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

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

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

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

145 {
146  int rc;
147  struct EnterState *es = mutt_enter_state_new();
148  do
149  {
150  if (SigWinch)
151  {
152  SigWinch = 0;
154  clearok(stdscr, true);
155  }
156  rc = mutt_enter_string_full(buf, buflen, col, flags, false, NULL, NULL, es);
157  } while (rc == 1);
159  return rc;
160 }
void mutt_resize_screen(void)
Update NeoMutt&#39;s opinion about the window size (CURSES)
Definition: resize.c:100
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:176
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:820
struct EnterState * mutt_enter_state_new(void)
Create a new EnterState.
Definition: enter.c:125
+ 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 176 of file enter.c.

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

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