mutt stable branch with some hacks
at master 772 lines 19 kB view raw
1/* 2 * Copyright (C) 1996-2000,2007,2011,2013 Michael R. Elkins <me@mutt.org> 3 * Copyright (C) 2000-2001 Edmund Grimley Evans <edmundo@rano.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 */ 19 20#if HAVE_CONFIG_H 21# include "config.h" 22#endif 23 24#include "mutt.h" 25#include "mutt_menu.h" 26#include "mutt_curses.h" 27#include "keymap.h" 28#include "history.h" 29 30#include <string.h> 31 32/* redraw flags for mutt_enter_string() */ 33enum 34{ 35 MUTT_REDRAW_INIT = 1, /* go to end of line and redraw */ 36 MUTT_REDRAW_LINE /* redraw entire line */ 37}; 38 39static int my_wcwidth (wchar_t wc) 40{ 41 int n = wcwidth (wc); 42 if (IsWPrint (wc) && n > 0) 43 return n; 44 if (!(wc & ~0x7f)) 45 return 2; 46 if (!(wc & ~0xffff)) 47 return 6; 48 return 10; 49} 50 51/* combining mark / non-spacing character */ 52#define COMB_CHAR(wc) (IsWPrint (wc) && !wcwidth (wc)) 53 54static int my_wcswidth (const wchar_t *s, size_t n) 55{ 56 int w = 0; 57 while (n--) 58 w += my_wcwidth (*s++); 59 return w; 60} 61 62static int my_addwch (wchar_t wc) 63{ 64 int n = wcwidth (wc); 65 if (IsWPrint (wc) && n > 0) 66 return mutt_addwch (wc); 67 if (!(wc & ~0x7f)) 68 return printw ("^%c", ((int)wc + 0x40) & 0x7f); 69 if (!(wc & ~0xffff)) 70 return printw ("\\u%04x", (int)wc); 71 return printw ("\\u%08x", (int)wc); 72} 73 74static size_t width_ceiling (const wchar_t *s, size_t n, int w1) 75{ 76 const wchar_t *s0 = s; 77 int w = 0; 78 for (; n; s++, n--) 79 if ((w += my_wcwidth (*s)) > w1) 80 break; 81 return s - s0; 82} 83 84static void my_wcstombs (char *dest, size_t dlen, const wchar_t *src, size_t slen) 85{ 86 mbstate_t st; 87 size_t k; 88 89 /* First convert directly into the destination buffer */ 90 memset (&st, 0, sizeof (st)); 91 for (; slen && dlen >= MB_LEN_MAX; dest += k, dlen -= k, src++, slen--) 92 if ((k = wcrtomb (dest, *src, &st)) == (size_t)(-1)) 93 break; 94 95 /* If this works, we can stop now */ 96 if (dlen >= MB_LEN_MAX) { 97 wcrtomb (dest, 0, &st); 98 return; 99 } 100 101 /* Otherwise convert any remaining data into a local buffer */ 102 { 103 char buf[3 * MB_LEN_MAX]; 104 char *p = buf; 105 106 for (; slen && p - buf < dlen; p += k, src++, slen--) 107 if ((k = wcrtomb (p, *src, &st)) == (size_t)(-1)) 108 break; 109 p += wcrtomb (p, 0, &st); 110 111 /* If it fits into the destination buffer, we can stop now */ 112 if (p - buf <= dlen) { 113 memcpy (dest, buf, p - buf); 114 return; 115 } 116 117 /* Otherwise we truncate the string in an ugly fashion */ 118 memcpy (dest, buf, dlen); 119 dest[dlen - 1] = '\0'; /* assume original dlen > 0 */ 120 } 121} 122 123static size_t my_mbstowcs (wchar_t **pwbuf, size_t *pwbuflen, size_t i, char *buf) 124{ 125 wchar_t wc; 126 mbstate_t st; 127 size_t k; 128 wchar_t *wbuf; 129 size_t wbuflen; 130 131 wbuf = *pwbuf, wbuflen = *pwbuflen; 132 133 while (*buf) 134 { 135 memset (&st, 0, sizeof (st)); 136 for (; (k = mbrtowc (&wc, buf, MB_LEN_MAX, &st)) && 137 k != (size_t)(-1) && k != (size_t)(-2); buf += k) 138 { 139 if (i >= wbuflen) 140 { 141 wbuflen = i + 20; 142 safe_realloc (&wbuf, wbuflen * sizeof (*wbuf)); 143 } 144 wbuf[i++] = wc; 145 } 146 if (*buf && (k == (size_t) -1 || k == (size_t) -2)) 147 { 148 if (i >= wbuflen) 149 { 150 wbuflen = i + 20; 151 safe_realloc (&wbuf, wbuflen * sizeof (*wbuf)); 152 } 153 wbuf[i++] = replacement_char(); 154 buf++; 155 } 156 } 157 *pwbuf = wbuf, *pwbuflen = wbuflen; 158 return i; 159} 160 161/* 162 * Replace part of the wchar_t buffer, from FROM to CURPOS, by BUF. 163 */ 164 165static void replace_part (ENTER_STATE *state, size_t from, char *buf) 166{ 167 /* Save the suffix */ 168 size_t savelen = state->lastchar - state->curpos; 169 wchar_t *savebuf = NULL; 170 171 if (savelen) 172 { 173 savebuf = safe_calloc (savelen, sizeof (wchar_t)); 174 memcpy (savebuf, state->wbuf + state->curpos, savelen * sizeof (wchar_t)); 175 } 176 177 /* Convert to wide characters */ 178 state->curpos = my_mbstowcs (&state->wbuf, &state->wbuflen, from, buf); 179 180 if (savelen) 181 { 182 /* Make space for suffix */ 183 if (state->curpos + savelen > state->wbuflen) 184 { 185 state->wbuflen = state->curpos + savelen; 186 safe_realloc (&state->wbuf, state->wbuflen * sizeof (wchar_t)); 187 } 188 189 /* Restore suffix */ 190 memcpy (state->wbuf + state->curpos, savebuf, savelen * sizeof (wchar_t)); 191 FREE (&savebuf); 192 } 193 194 state->lastchar = state->curpos + savelen; 195} 196 197/* 198 * Return 1 if the character is not typically part of a pathname 199 */ 200static inline int is_shell_char(wchar_t ch) 201{ 202 static const wchar_t shell_chars[] = L"<>&()$?*;{}| "; /* ! not included because it can be part of a pathname in Mutt */ 203 return wcschr(shell_chars, ch) != NULL; 204} 205 206/* 207 * Returns: 208 * 1 need to redraw the screen and call me again 209 * 0 if input was given 210 * -1 if abort. 211 */ 212 213int mutt_enter_string(char *buf, size_t buflen, int col, int flags) 214{ 215 int rv; 216 ENTER_STATE *es = mutt_new_enter_state (); 217 rv = _mutt_enter_string (buf, buflen, col, flags, 0, NULL, NULL, es); 218 mutt_free_enter_state (&es); 219 return rv; 220} 221 222int _mutt_enter_string (char *buf, size_t buflen, int col, 223 int flags, int multiple, char ***files, int *numfiles, 224 ENTER_STATE *state) 225{ 226 int width = MuttMessageWindow->cols - col - 1; 227 int redraw; 228 int pass = (flags & MUTT_PASS); 229 int first = 1; 230 int ch, w, r; 231 size_t i; 232 wchar_t *tempbuf = 0; 233 size_t templen = 0; 234 history_class_t hclass; 235 wchar_t wc; 236 mbstate_t mbstate; 237 238 int rv = 0; 239 memset (&mbstate, 0, sizeof (mbstate)); 240 241 if (state->wbuf) 242 { 243 /* Coming back after return 1 */ 244 redraw = MUTT_REDRAW_LINE; 245 first = 0; 246 } 247 else 248 { 249 /* Initialise wbuf from buf */ 250 state->wbuflen = 0; 251 state->lastchar = my_mbstowcs (&state->wbuf, &state->wbuflen, 0, buf); 252 redraw = MUTT_REDRAW_INIT; 253 } 254 255 if (flags & MUTT_FILE) 256 hclass = HC_FILE; 257 else if (flags & MUTT_EFILE) 258 hclass = HC_MBOX; 259 else if (flags & MUTT_CMD) 260 hclass = HC_CMD; 261 else if (flags & MUTT_ALIAS) 262 hclass = HC_ALIAS; 263 else if (flags & MUTT_COMMAND) 264 hclass = HC_COMMAND; 265 else if (flags & MUTT_PATTERN) 266 hclass = HC_PATTERN; 267 else 268 hclass = HC_OTHER; 269 270 for (;;) 271 { 272 if (redraw && !pass) 273 { 274 if (redraw == MUTT_REDRAW_INIT) 275 { 276 /* Go to end of line */ 277 state->curpos = state->lastchar; 278 state->begin = width_ceiling (state->wbuf, state->lastchar, my_wcswidth (state->wbuf, state->lastchar) - width + 1); 279 } 280 if (state->curpos < state->begin || 281 my_wcswidth (state->wbuf + state->begin, state->curpos - state->begin) >= width) 282 state->begin = width_ceiling (state->wbuf, state->lastchar, my_wcswidth (state->wbuf, state->curpos) - width / 2); 283 mutt_window_move (MuttMessageWindow, 0, col); 284 w = 0; 285 for (i = state->begin; i < state->lastchar; i++) 286 { 287 w += my_wcwidth (state->wbuf[i]); 288 if (w > width) 289 break; 290 my_addwch (state->wbuf[i]); 291 } 292 mutt_window_clrtoeol (MuttMessageWindow); 293 mutt_window_move (MuttMessageWindow, 0, 294 col + my_wcswidth (state->wbuf + state->begin, state->curpos - state->begin)); 295 } 296 mutt_refresh (); 297 298 if ((ch = km_dokey (MENU_EDITOR)) == -1) 299 { 300 rv = -1; 301 goto bye; 302 } 303 304 if (ch != OP_NULL) 305 { 306 first = 0; 307 if (ch != OP_EDITOR_COMPLETE && ch != OP_EDITOR_COMPLETE_QUERY) 308 state->tabs = 0; 309 redraw = MUTT_REDRAW_LINE; 310 switch (ch) 311 { 312 case OP_EDITOR_HISTORY_UP: 313 state->curpos = state->lastchar; 314 if (mutt_history_at_scratch (hclass)) 315 { 316 my_wcstombs (buf, buflen, state->wbuf, state->curpos); 317 mutt_history_save_scratch (hclass, buf); 318 } 319 replace_part (state, 0, mutt_history_prev (hclass)); 320 redraw = MUTT_REDRAW_INIT; 321 break; 322 323 case OP_EDITOR_HISTORY_DOWN: 324 state->curpos = state->lastchar; 325 if (mutt_history_at_scratch (hclass)) 326 { 327 my_wcstombs (buf, buflen, state->wbuf, state->curpos); 328 mutt_history_save_scratch (hclass, buf); 329 } 330 replace_part (state, 0, mutt_history_next (hclass)); 331 redraw = MUTT_REDRAW_INIT; 332 break; 333 334 case OP_EDITOR_BACKSPACE: 335 if (state->curpos == 0) 336 BEEP (); 337 else 338 { 339 i = state->curpos; 340 while (i && COMB_CHAR (state->wbuf[i - 1])) 341 --i; 342 if (i) 343 --i; 344 memmove (state->wbuf + i, state->wbuf + state->curpos, (state->lastchar - state->curpos) * sizeof (wchar_t)); 345 state->lastchar -= state->curpos - i; 346 state->curpos = i; 347 } 348 break; 349 350 case OP_EDITOR_BOL: 351 state->curpos = 0; 352 break; 353 354 case OP_EDITOR_EOL: 355 redraw= MUTT_REDRAW_INIT; 356 break; 357 358 case OP_EDITOR_KILL_LINE: 359 state->curpos = state->lastchar = 0; 360 break; 361 362 case OP_EDITOR_KILL_EOL: 363 state->lastchar = state->curpos; 364 break; 365 366 case OP_EDITOR_BACKWARD_CHAR: 367 if (state->curpos == 0) 368 BEEP (); 369 else 370 { 371 while (state->curpos && COMB_CHAR (state->wbuf[state->curpos - 1])) 372 state->curpos--; 373 if (state->curpos) 374 state->curpos--; 375 } 376 break; 377 378 case OP_EDITOR_FORWARD_CHAR: 379 if (state->curpos == state->lastchar) 380 BEEP (); 381 else 382 { 383 ++state->curpos; 384 while (state->curpos < state->lastchar && COMB_CHAR (state->wbuf[state->curpos])) 385 ++state->curpos; 386 } 387 break; 388 389 case OP_EDITOR_BACKWARD_WORD: 390 if (state->curpos == 0) 391 BEEP (); 392 else 393 { 394 while (state->curpos && iswspace (state->wbuf[state->curpos - 1])) 395 --state->curpos; 396 while (state->curpos && !iswspace (state->wbuf[state->curpos - 1])) 397 --state->curpos; 398 } 399 break; 400 401 case OP_EDITOR_FORWARD_WORD: 402 if (state->curpos == state->lastchar) 403 BEEP (); 404 else 405 { 406 while (state->curpos < state->lastchar && iswspace (state->wbuf[state->curpos])) 407 ++state->curpos; 408 while (state->curpos < state->lastchar && !iswspace (state->wbuf[state->curpos])) 409 ++state->curpos; 410 } 411 break; 412 413 case OP_EDITOR_CAPITALIZE_WORD: 414 case OP_EDITOR_UPCASE_WORD: 415 case OP_EDITOR_DOWNCASE_WORD: 416 if (state->curpos == state->lastchar) 417 { 418 BEEP (); 419 break; 420 } 421 while (state->curpos && !iswspace (state->wbuf[state->curpos])) 422 --state->curpos; 423 while (state->curpos < state->lastchar && iswspace (state->wbuf[state->curpos])) 424 ++state->curpos; 425 while (state->curpos < state->lastchar && !iswspace (state->wbuf[state->curpos])) 426 { 427 if (ch == OP_EDITOR_DOWNCASE_WORD) 428 state->wbuf[state->curpos] = towlower (state->wbuf[state->curpos]); 429 else 430 { 431 state->wbuf[state->curpos] = towupper (state->wbuf[state->curpos]); 432 if (ch == OP_EDITOR_CAPITALIZE_WORD) 433 ch = OP_EDITOR_DOWNCASE_WORD; 434 } 435 state->curpos++; 436 } 437 break; 438 439 case OP_EDITOR_DELETE_CHAR: 440 if (state->curpos == state->lastchar) 441 BEEP (); 442 else 443 { 444 i = state->curpos; 445 while (i < state->lastchar && COMB_CHAR (state->wbuf[i])) 446 ++i; 447 if (i < state->lastchar) 448 ++i; 449 while (i < state->lastchar && COMB_CHAR (state->wbuf[i])) 450 ++i; 451 memmove (state->wbuf + state->curpos, state->wbuf + i, (state->lastchar - i) * sizeof (wchar_t)); 452 state->lastchar -= i - state->curpos; 453 } 454 break; 455 456 case OP_EDITOR_KILL_WORD: 457 /* delete to beginning of word */ 458 if (state->curpos != 0) 459 { 460 i = state->curpos; 461 while (i && iswspace (state->wbuf[i - 1])) 462 --i; 463 if (i) 464 { 465 if (iswalnum (state->wbuf[i - 1])) 466 { 467 for (--i; i && iswalnum (state->wbuf[i - 1]); i--) 468 ; 469 } 470 else 471 --i; 472 } 473 memmove (state->wbuf + i, state->wbuf + state->curpos, 474 (state->lastchar - state->curpos) * sizeof (wchar_t)); 475 state->lastchar += i - state->curpos; 476 state->curpos = i; 477 } 478 break; 479 480 case OP_EDITOR_KILL_EOW: 481 /* delete to end of word */ 482 483 /* first skip over whitespace */ 484 for (i = state->curpos; 485 i < state->lastchar && iswspace (state->wbuf[i]); i++) 486 ; 487 488 /* if there are any characters left.. */ 489 if (i < state->lastchar) 490 { 491 /* if the current character is alphanumeric.. */ 492 if (iswalnum (state->wbuf[i])) 493 { 494 /* skip over the rest of the word consistent of only alphanumerics */ 495 for (; i < state->lastchar && iswalnum (state->wbuf[i]); i++) 496 ; 497 } 498 else 499 { 500 /* skip over one non-alphanumeric character */ 501 ++i; 502 } 503 } 504 505 memmove (state->wbuf + state->curpos, state->wbuf + i, 506 (state->lastchar - i) * sizeof (wchar_t)); 507 state->lastchar += state->curpos - i; 508 break; 509 510 case OP_EDITOR_BUFFY_CYCLE: 511 if (flags & MUTT_EFILE) 512 { 513 first = 1; /* clear input if user types a real key later */ 514 my_wcstombs (buf, buflen, state->wbuf, state->curpos); 515 mutt_buffy (buf, buflen); 516 state->curpos = state->lastchar = my_mbstowcs (&state->wbuf, &state->wbuflen, 0, buf); 517 break; 518 } 519 else if (!(flags & MUTT_FILE)) 520 goto self_insert; 521 /* fall through to completion routine (MUTT_FILE) */ 522 523 case OP_EDITOR_COMPLETE: 524 case OP_EDITOR_COMPLETE_QUERY: 525 state->tabs++; 526 if (flags & MUTT_CMD) 527 { 528 for (i = state->curpos; i && !is_shell_char(state->wbuf[i-1]); i--) 529 ; 530 my_wcstombs (buf, buflen, state->wbuf + i, state->curpos - i); 531 if (tempbuf && templen == state->lastchar - i && 532 !memcmp (tempbuf, state->wbuf + i, (state->lastchar - i) * sizeof (wchar_t))) 533 { 534 mutt_select_file (buf, buflen, (flags & MUTT_EFILE) ? MUTT_SEL_FOLDER : 0); 535 set_option (OPTNEEDREDRAW); 536 if (*buf) 537 replace_part (state, i, buf); 538 rv = 1; 539 goto bye; 540 } 541 if (!mutt_complete (buf, buflen)) 542 { 543 templen = state->lastchar - i; 544 safe_realloc (&tempbuf, templen * sizeof (wchar_t)); 545 } 546 else 547 BEEP (); 548 549 replace_part (state, i, buf); 550 } 551 else if (flags & MUTT_ALIAS && ch == OP_EDITOR_COMPLETE) 552 { 553 /* invoke the alias-menu to get more addresses */ 554 for (i = state->curpos; i && state->wbuf[i-1] != ',' && 555 state->wbuf[i-1] != ':'; i--) 556 ; 557 for (; i < state->lastchar && state->wbuf[i] == ' '; i++) 558 ; 559 my_wcstombs (buf, buflen, state->wbuf + i, state->curpos - i); 560 r = mutt_alias_complete (buf, buflen); 561 replace_part (state, i, buf); 562 if (!r) 563 { 564 rv = 1; 565 goto bye; 566 } 567 break; 568 } 569 else if (flags & MUTT_ALIAS && ch == OP_EDITOR_COMPLETE_QUERY) 570 { 571 /* invoke the query-menu to get more addresses */ 572 if ((i = state->curpos)) 573 { 574 for (; i && state->wbuf[i - 1] != ','; i--) 575 ; 576 for (; i < state->curpos && state->wbuf[i] == ' '; i++) 577 ; 578 } 579 580 my_wcstombs (buf, buflen, state->wbuf + i, state->curpos - i); 581 mutt_query_complete (buf, buflen); 582 replace_part (state, i, buf); 583 584 rv = 1; 585 goto bye; 586 } 587 else if (flags & MUTT_COMMAND) 588 { 589 my_wcstombs (buf, buflen, state->wbuf, state->curpos); 590 i = strlen (buf); 591 if (i && buf[i - 1] == '=' && 592 mutt_var_value_complete (buf, buflen, i)) 593 state->tabs = 0; 594 else if (!mutt_command_complete (buf, buflen, i, state->tabs)) 595 BEEP (); 596 replace_part (state, 0, buf); 597 } 598 else if (flags & (MUTT_FILE | MUTT_EFILE)) 599 { 600 my_wcstombs (buf, buflen, state->wbuf, state->curpos); 601 602 /* see if the path has changed from the last time */ 603 if ((!tempbuf && !state->lastchar) || (tempbuf && templen == state->lastchar && 604 !memcmp (tempbuf, state->wbuf, state->lastchar * sizeof (wchar_t)))) 605 { 606 _mutt_select_file (buf, buflen, 607 ((flags & MUTT_EFILE) ? MUTT_SEL_FOLDER : 0) | (multiple ? MUTT_SEL_MULTI : 0), 608 files, numfiles); 609 set_option (OPTNEEDREDRAW); 610 if (*buf) 611 { 612 mutt_pretty_mailbox (buf, buflen); 613 if (!pass) 614 mutt_history_add (hclass, buf, 1); 615 rv = 0; 616 goto bye; 617 } 618 619 /* file selection cancelled */ 620 rv = 1; 621 goto bye; 622 } 623 624 if (!mutt_complete (buf, buflen)) 625 { 626 templen = state->lastchar; 627 safe_realloc (&tempbuf, templen * sizeof (wchar_t)); 628 memcpy (tempbuf, state->wbuf, templen * sizeof (wchar_t)); 629 } 630 else 631 BEEP (); /* let the user know that nothing matched */ 632 replace_part (state, 0, buf); 633 } 634 else 635 goto self_insert; 636 break; 637 638 case OP_EDITOR_QUOTE_CHAR: 639 { 640 event_t event; 641 /*ADDCH (LastKey);*/ 642 event = mutt_getch (); 643 if (event.ch >= 0) 644 { 645 LastKey = event.ch; 646 goto self_insert; 647 } 648 } 649 650 case OP_EDITOR_TRANSPOSE_CHARS: 651 if (state->lastchar < 2) 652 BEEP (); 653 else 654 { 655 wchar_t t; 656 657 if (state->curpos == 0) 658 state->curpos = 2; 659 else if (state->curpos < state->lastchar) 660 ++state->curpos; 661 662 t = state->wbuf[state->curpos - 2]; 663 state->wbuf[state->curpos - 2] = state->wbuf[state->curpos - 1]; 664 state->wbuf[state->curpos - 1] = t; 665 } 666 break; 667 668 default: 669 BEEP (); 670 } 671 } 672 else 673 { 674 675self_insert: 676 677 state->tabs = 0; 678 /* use the raw keypress */ 679 ch = LastKey; 680 681#ifdef KEY_ENTER 682 /* treat ENTER the same as RETURN */ 683 if (ch == KEY_ENTER) 684 ch = '\r'; 685#endif 686 687 /* quietly ignore all other function keys */ 688 if (ch & ~0xff) 689 continue; 690 691 /* gather the octets into a wide character */ 692 { 693 char c; 694 size_t k; 695 696 c = ch; 697 k = mbrtowc (&wc, &c, 1, &mbstate); 698 if (k == (size_t)(-2)) 699 continue; 700 else if (k && k != 1) 701 { 702 memset (&mbstate, 0, sizeof (mbstate)); 703 continue; 704 } 705 } 706 707 if (first && (flags & MUTT_CLEAR)) 708 { 709 first = 0; 710 if (IsWPrint (wc)) /* why? */ 711 state->curpos = state->lastchar = 0; 712 } 713 714 if (wc == '\r' || wc == '\n') 715 { 716 /* Convert from wide characters */ 717 my_wcstombs (buf, buflen, state->wbuf, state->lastchar); 718 if (!pass) 719 mutt_history_add (hclass, buf, 1); 720 721 if (multiple) 722 { 723 char **tfiles; 724 *numfiles = 1; 725 tfiles = safe_calloc (*numfiles, sizeof (char *)); 726 mutt_expand_path (buf, buflen); 727 tfiles[0] = safe_strdup (buf); 728 *files = tfiles; 729 } 730 rv = 0; 731 goto bye; 732 } 733 else if (wc && (wc < ' ' || IsWPrint (wc))) /* why? */ 734 { 735 if (state->lastchar >= state->wbuflen) 736 { 737 state->wbuflen = state->lastchar + 20; 738 safe_realloc (&state->wbuf, state->wbuflen * sizeof (wchar_t)); 739 } 740 memmove (state->wbuf + state->curpos + 1, state->wbuf + state->curpos, (state->lastchar - state->curpos) * sizeof (wchar_t)); 741 state->wbuf[state->curpos++] = wc; 742 state->lastchar++; 743 } 744 else 745 { 746 mutt_flushinp (); 747 BEEP (); 748 } 749 } 750 } 751 752 bye: 753 754 mutt_reset_history_state (hclass); 755 FREE (&tempbuf); 756 return rv; 757} 758 759void mutt_free_enter_state (ENTER_STATE **esp) 760{ 761 if (!esp) return; 762 763 FREE (&(*esp)->wbuf); 764 FREE (esp); /* __FREE_CHECKED__ */ 765} 766 767/* 768 * TODO: 769 * very narrow screen might crash it 770 * sort out the input side 771 * unprintable chars 772 */