1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 * See README.txt for an overview of the Vim source code. 8 */ 9 10 /* 11 * message.c: functions for displaying messages on the command line 12 */ 13 14 #define MESSAGE_FILE // don't include prototype for smsg() 15 #define USING_FLOAT_STUFF 16 17 #include "vim.h" 18 19 static void add_msg_hist(char_u *s, int len, int attr); 20 static void hit_return_msg(void); 21 static void msg_home_replace_attr(char_u *fname, int attr); 22 static void msg_puts_attr_len(char *str, int maxlen, int attr); 23 static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse); 24 static void msg_scroll_up(void); 25 static void inc_msg_scrolled(void); 26 static void store_sb_text(char_u **sb_str, char_u *s, int attr, int *sb_col, int finish); 27 static void t_puts(int *t_col, char_u *t_s, char_u *s, int attr); 28 static void msg_puts_printf(char_u *str, int maxlen); 29 static int do_more_prompt(int typed_char); 30 static void msg_screen_putchar(int c, int attr); 31 static void msg_moremsg(int full); 32 static int msg_check_screen(void); 33 static void redir_write(char_u *s, int maxlen); 34 #ifdef FEAT_CON_DIALOG 35 static char_u *msg_show_console_dialog(char_u *message, char_u *buttons, int dfltbutton); 36 static int confirm_msg_used = FALSE; // displaying confirm_msg 37 static char_u *confirm_msg = NULL; // ":confirm" message 38 static char_u *confirm_msg_tail; // tail of confirm_msg 39 static void display_confirm_msg(void); 40 #endif 41 #ifdef FEAT_JOB_CHANNEL 42 static int emsg_to_channel_log = FALSE; 43 #endif 44 45 struct msg_hist 46 { 47 struct msg_hist *next; 48 char_u *msg; 49 int attr; 50 }; 51 52 static struct msg_hist *first_msg_hist = NULL; 53 static struct msg_hist *last_msg_hist = NULL; 54 static int msg_hist_len = 0; 55 56 static FILE *verbose_fd = NULL; 57 static int verbose_did_open = FALSE; 58 59 /* 60 * When writing messages to the screen, there are many different situations. 61 * A number of variables is used to remember the current state: 62 * msg_didany TRUE when messages were written since the last time the 63 * user reacted to a prompt. 64 * Reset: After hitting a key for the hit-return prompt, 65 * hitting <CR> for the command line or input(). 66 * Set: When any message is written to the screen. 67 * msg_didout TRUE when something was written to the current line. 68 * Reset: When advancing to the next line, when the current 69 * text can be overwritten. 70 * Set: When any message is written to the screen. 71 * msg_nowait No extra delay for the last drawn message. 72 * Used in normal_cmd() before the mode message is drawn. 73 * emsg_on_display There was an error message recently. Indicates that there 74 * should be a delay before redrawing. 75 * msg_scroll The next message should not overwrite the current one. 76 * msg_scrolled How many lines the screen has been scrolled (because of 77 * messages). Used in update_screen() to scroll the screen 78 * back. Incremented each time the screen scrolls a line. 79 * msg_scrolled_ign TRUE when msg_scrolled is non-zero and msg_puts_attr() 80 * writes something without scrolling should not make 81 * need_wait_return to be set. This is a hack to make ":ts" 82 * work without an extra prompt. 83 * lines_left Number of lines available for messages before the 84 * more-prompt is to be given. -1 when not set. 85 * need_wait_return TRUE when the hit-return prompt is needed. 86 * Reset: After giving the hit-return prompt, when the user 87 * has answered some other prompt. 88 * Set: When the ruler or typeahead display is overwritten, 89 * scrolling the screen for some message. 90 * keep_msg Message to be displayed after redrawing the screen, in 91 * main_loop(). 92 * This is an allocated string or NULL when not used. 93 */ 94 95 /* 96 * msg(s) - displays the string 's' on the status line 97 * When terminal not initialized (yet) mch_errmsg(..) is used. 98 * return TRUE if wait_return not called 99 */ 100 int 101 msg(char *s) 102 { 103 return msg_attr_keep(s, 0, FALSE); 104 } 105 106 /* 107 * Like msg() but keep it silent when 'verbosefile' is set. 108 */ 109 int 110 verb_msg(char *s) 111 { 112 int n; 113 114 verbose_enter(); 115 n = msg_attr_keep(s, 0, FALSE); 116 verbose_leave(); 117 118 return n; 119 } 120 121 int 122 msg_attr(char *s, int attr) 123 { 124 return msg_attr_keep(s, attr, FALSE); 125 } 126 127 int 128 msg_attr_keep( 129 char *s, 130 int attr, 131 int keep) // TRUE: set keep_msg if it doesn't scroll 132 { 133 static int entered = 0; 134 int retval; 135 char_u *buf = NULL; 136 137 // Skip messages not matching ":filter pattern". 138 // Don't filter when there is an error. 139 if (!emsg_on_display && message_filtered((char_u *)s)) 140 return TRUE; 141 142 #ifdef FEAT_EVAL 143 if (attr == 0) 144 set_vim_var_string(VV_STATUSMSG, (char_u *)s, -1); 145 #endif 146 147 /* 148 * It is possible that displaying a messages causes a problem (e.g., 149 * when redrawing the window), which causes another message, etc.. To 150 * break this loop, limit the recursiveness to 3 levels. 151 */ 152 if (entered >= 3) 153 return TRUE; 154 ++entered; 155 156 // Add message to history (unless it's a repeated kept message or a 157 // truncated message) 158 if ((char_u *)s != keep_msg 159 || (*s != '<' 160 && last_msg_hist != NULL 161 && last_msg_hist->msg != NULL 162 && STRCMP(s, last_msg_hist->msg))) 163 add_msg_hist((char_u *)s, -1, attr); 164 165 #ifdef FEAT_JOB_CHANNEL 166 if (emsg_to_channel_log) 167 // Write message in the channel log. 168 ch_log(NULL, "ERROR: %s", (char *)s); 169 #endif 170 171 // Truncate the message if needed. 172 msg_start(); 173 buf = msg_strtrunc((char_u *)s, FALSE); 174 if (buf != NULL) 175 s = (char *)buf; 176 177 msg_outtrans_attr((char_u *)s, attr); 178 msg_clr_eos(); 179 retval = msg_end(); 180 181 if (keep && retval && vim_strsize((char_u *)s) 182 < (int)(Rows - cmdline_row - 1) * Columns + sc_col) 183 set_keep_msg((char_u *)s, 0); 184 185 vim_free(buf); 186 --entered; 187 return retval; 188 } 189 190 /* 191 * Truncate a string such that it can be printed without causing a scroll. 192 * Returns an allocated string or NULL when no truncating is done. 193 */ 194 char_u * 195 msg_strtrunc( 196 char_u *s, 197 int force) // always truncate 198 { 199 char_u *buf = NULL; 200 int len; 201 int room; 202 203 // May truncate message to avoid a hit-return prompt 204 if ((!msg_scroll && !need_wait_return && shortmess(SHM_TRUNCALL) 205 && !exmode_active && msg_silent == 0) || force) 206 { 207 len = vim_strsize(s); 208 if (msg_scrolled != 0) 209 // Use all the columns. 210 room = (int)(Rows - msg_row) * Columns - 1; 211 else 212 // Use up to 'showcmd' column. 213 room = (int)(Rows - msg_row - 1) * Columns + sc_col - 1; 214 if (len > room && room > 0) 215 { 216 if (enc_utf8) 217 // may have up to 18 bytes per cell (6 per char, up to two 218 // composing chars) 219 len = (room + 2) * 18; 220 else if (enc_dbcs == DBCS_JPNU) 221 // may have up to 2 bytes per cell for euc-jp 222 len = (room + 2) * 2; 223 else 224 len = room + 2; 225 buf = alloc(len); 226 if (buf != NULL) 227 trunc_string(s, buf, room, len); 228 } 229 } 230 return buf; 231 } 232 233 /* 234 * Truncate a string "s" to "buf" with cell width "room". 235 * "s" and "buf" may be equal. 236 */ 237 void 238 trunc_string( 239 char_u *s, 240 char_u *buf, 241 int room_in, 242 int buflen) 243 { 244 size_t room = room_in - 3; // "..." takes 3 chars 245 size_t half; 246 size_t len = 0; 247 int e; 248 int i; 249 int n; 250 251 if (room_in < 3) 252 room = 0; 253 half = room / 2; 254 255 // First part: Start of the string. 256 for (e = 0; len < half && e < buflen; ++e) 257 { 258 if (s[e] == NUL) 259 { 260 // text fits without truncating! 261 buf[e] = NUL; 262 return; 263 } 264 n = ptr2cells(s + e); 265 if (len + n > half) 266 break; 267 len += n; 268 buf[e] = s[e]; 269 if (has_mbyte) 270 for (n = (*mb_ptr2len)(s + e); --n > 0; ) 271 { 272 if (++e == buflen) 273 break; 274 buf[e] = s[e]; 275 } 276 } 277 278 // Last part: End of the string. 279 i = e; 280 if (enc_dbcs != 0) 281 { 282 // For DBCS going backwards in a string is slow, but 283 // computing the cell width isn't too slow: go forward 284 // until the rest fits. 285 n = vim_strsize(s + i); 286 while (len + n > room) 287 { 288 n -= ptr2cells(s + i); 289 i += (*mb_ptr2len)(s + i); 290 } 291 } 292 else if (enc_utf8) 293 { 294 // For UTF-8 we can go backwards easily. 295 half = i = (int)STRLEN(s); 296 for (;;) 297 { 298 do 299 half = half - utf_head_off(s, s + half - 1) - 1; 300 while (half > 0 && utf_iscomposing(utf_ptr2char(s + half))); 301 n = ptr2cells(s + half); 302 if (len + n > room || half == 0) 303 break; 304 len += n; 305 i = (int)half; 306 } 307 } 308 else 309 { 310 for (i = (int)STRLEN(s); 311 i - 1 >= 0 && len + (n = ptr2cells(s + i - 1)) <= room; --i) 312 len += n; 313 } 314 315 316 if (i <= e + 3) 317 { 318 // text fits without truncating 319 if (s != buf) 320 { 321 len = STRLEN(s); 322 if (len >= (size_t)buflen) 323 len = buflen - 1; 324 len = len - e + 1; 325 if (len < 1) 326 buf[e - 1] = NUL; 327 else 328 mch_memmove(buf + e, s + e, len); 329 } 330 } 331 else if (e + 3 < buflen) 332 { 333 // set the middle and copy the last part 334 mch_memmove(buf + e, "...", (size_t)3); 335 len = STRLEN(s + i) + 1; 336 if (len >= (size_t)buflen - e - 3) 337 len = buflen - e - 3 - 1; 338 mch_memmove(buf + e + 3, s + i, len); 339 buf[e + 3 + len - 1] = NUL; 340 } 341 else 342 { 343 // can't fit in the "...", just truncate it 344 buf[e - 1] = NUL; 345 } 346 } 347 348 /* 349 * Automatic prototype generation does not understand this function. 350 * Note: Caller of smsg() and smsg_attr() must check the resulting string is 351 * shorter than IOSIZE!!! 352 */ 353 #ifndef PROTO 354 355 int vim_snprintf(char *str, size_t str_m, const char *fmt, ...); 356 357 int 358 smsg(const char *s, ...) 359 { 360 if (IObuff == NULL) 361 { 362 // Very early in initialisation and already something wrong, just 363 // give the raw message so the user at least gets a hint. 364 return msg((char *)s); 365 } 366 else 367 { 368 va_list arglist; 369 370 va_start(arglist, s); 371 vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist); 372 va_end(arglist); 373 return msg((char *)IObuff); 374 } 375 } 376 377 int 378 smsg_attr(int attr, const char *s, ...) 379 { 380 if (IObuff == NULL) 381 { 382 // Very early in initialisation and already something wrong, just 383 // give the raw message so the user at least gets a hint. 384 return msg_attr((char *)s, attr); 385 } 386 else 387 { 388 va_list arglist; 389 390 va_start(arglist, s); 391 vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist); 392 va_end(arglist); 393 return msg_attr((char *)IObuff, attr); 394 } 395 } 396 397 int 398 smsg_attr_keep(int attr, const char *s, ...) 399 { 400 if (IObuff == NULL) 401 { 402 // Very early in initialisation and already something wrong, just 403 // give the raw message so the user at least gets a hint. 404 return msg_attr_keep((char *)s, attr, TRUE); 405 } 406 else 407 { 408 va_list arglist; 409 410 va_start(arglist, s); 411 vim_vsnprintf((char *)IObuff, IOSIZE, s, arglist); 412 va_end(arglist); 413 return msg_attr_keep((char *)IObuff, attr, TRUE); 414 } 415 } 416 417 #endif 418 419 /* 420 * Remember the last sourcing name/lnum used in an error message, so that it 421 * isn't printed each time when it didn't change. 422 */ 423 static int last_sourcing_lnum = 0; 424 static char_u *last_sourcing_name = NULL; 425 426 /* 427 * Reset the last used sourcing name/lnum. Makes sure it is displayed again 428 * for the next error message; 429 */ 430 void 431 reset_last_sourcing(void) 432 { 433 VIM_CLEAR(last_sourcing_name); 434 last_sourcing_lnum = 0; 435 } 436 437 /* 438 * Return TRUE if "SOURCING_NAME" differs from "last_sourcing_name". 439 */ 440 static int 441 other_sourcing_name(void) 442 { 443 if (SOURCING_NAME != NULL) 444 { 445 if (last_sourcing_name != NULL) 446 return STRCMP(SOURCING_NAME, last_sourcing_name) != 0; 447 return TRUE; 448 } 449 return FALSE; 450 } 451 452 /* 453 * Get the message about the source, as used for an error message. 454 * Returns an allocated string with room for one more character. 455 * Returns NULL when no message is to be given. 456 */ 457 static char_u * 458 get_emsg_source(void) 459 { 460 char_u *Buf, *p; 461 462 if (SOURCING_NAME != NULL && other_sourcing_name()) 463 { 464 char_u *sname = estack_sfile(); 465 char_u *tofree = sname; 466 467 if (sname == NULL) 468 sname = SOURCING_NAME; 469 470 p = (char_u *)_("Error detected while processing %s:"); 471 Buf = alloc(STRLEN(sname) + STRLEN(p)); 472 if (Buf != NULL) 473 sprintf((char *)Buf, (char *)p, sname); 474 vim_free(tofree); 475 return Buf; 476 } 477 return NULL; 478 } 479 480 /* 481 * Get the message about the source lnum, as used for an error message. 482 * Returns an allocated string with room for one more character. 483 * Returns NULL when no message is to be given. 484 */ 485 static char_u * 486 get_emsg_lnum(void) 487 { 488 char_u *Buf, *p; 489 490 // lnum is 0 when executing a command from the command line 491 // argument, we don't want a line number then 492 if (SOURCING_NAME != NULL 493 && (other_sourcing_name() || SOURCING_LNUM != last_sourcing_lnum) 494 && SOURCING_LNUM != 0) 495 { 496 p = (char_u *)_("line %4ld:"); 497 Buf = alloc(STRLEN(p) + 20); 498 if (Buf != NULL) 499 sprintf((char *)Buf, (char *)p, (long)SOURCING_LNUM); 500 return Buf; 501 } 502 return NULL; 503 } 504 505 /* 506 * Display name and line number for the source of an error. 507 * Remember the file name and line number, so that for the next error the info 508 * is only displayed if it changed. 509 */ 510 void 511 msg_source(int attr) 512 { 513 char_u *p; 514 515 ++no_wait_return; 516 p = get_emsg_source(); 517 if (p != NULL) 518 { 519 msg_attr((char *)p, attr); 520 vim_free(p); 521 } 522 p = get_emsg_lnum(); 523 if (p != NULL) 524 { 525 msg_attr((char *)p, HL_ATTR(HLF_N)); 526 vim_free(p); 527 last_sourcing_lnum = SOURCING_LNUM; // only once for each line 528 } 529 530 // remember the last sourcing name printed, also when it's empty 531 if (SOURCING_NAME == NULL || other_sourcing_name()) 532 { 533 vim_free(last_sourcing_name); 534 if (SOURCING_NAME == NULL) 535 last_sourcing_name = NULL; 536 else 537 last_sourcing_name = vim_strsave(SOURCING_NAME); 538 } 539 --no_wait_return; 540 } 541 542 /* 543 * Return TRUE if not giving error messages right now: 544 * If "emsg_off" is set: no error messages at the moment. 545 * If "msg" is in 'debug': do error message but without side effects. 546 * If "emsg_skip" is set: never do error messages. 547 */ 548 static int 549 emsg_not_now(void) 550 { 551 if ((emsg_off > 0 && vim_strchr(p_debug, 'm') == NULL 552 && vim_strchr(p_debug, 't') == NULL) 553 #ifdef FEAT_EVAL 554 || emsg_skip > 0 555 #endif 556 ) 557 return TRUE; 558 return FALSE; 559 } 560 561 #if defined(FEAT_EVAL) || defined(PROTO) 562 static garray_T ignore_error_list = GA_EMPTY; 563 564 void 565 ignore_error_for_testing(char_u *error) 566 { 567 if (ignore_error_list.ga_itemsize == 0) 568 ga_init2(&ignore_error_list, sizeof(char_u *), 1); 569 570 if (STRCMP("RESET", error) == 0) 571 ga_clear_strings(&ignore_error_list); 572 else 573 ga_add_string(&ignore_error_list, error); 574 } 575 576 static int 577 ignore_error(char_u *msg) 578 { 579 int i; 580 581 for (i = 0; i < ignore_error_list.ga_len; ++i) 582 if (strstr((char *)msg, 583 (char *)((char_u **)(ignore_error_list.ga_data))[i]) != NULL) 584 return TRUE; 585 return FALSE; 586 } 587 #endif 588 589 #if !defined(HAVE_STRERROR) || defined(PROTO) 590 /* 591 * Replacement for perror() that behaves more or less like emsg() was called. 592 * v:errmsg will be set and called_emsg will be incremented. 593 */ 594 void 595 do_perror(char *msg) 596 { 597 perror(msg); 598 ++emsg_silent; 599 emsg(msg); 600 --emsg_silent; 601 } 602 #endif 603 604 /* 605 * emsg_core() - display an error message 606 * 607 * Rings the bell, if appropriate, and calls message() to do the real work 608 * When terminal not initialized (yet) mch_errmsg(..) is used. 609 * 610 * Return TRUE if wait_return not called. 611 * Note: caller must check 'emsg_not_now()' before calling this. 612 */ 613 static int 614 emsg_core(char_u *s) 615 { 616 int attr; 617 char_u *p; 618 int r; 619 #ifdef FEAT_EVAL 620 int ignore = FALSE; 621 int severe; 622 #endif 623 624 #ifdef FEAT_EVAL 625 // When testing some errors are turned into a normal message. 626 if (ignore_error(s)) 627 // don't call msg() if it results in a dialog 628 return msg_use_printf() ? FALSE : msg((char *)s); 629 #endif 630 631 ++called_emsg; 632 633 #ifdef FEAT_EVAL 634 // If "emsg_severe" is TRUE: When an error exception is to be thrown, 635 // prefer this message over previous messages for the same command. 636 severe = emsg_severe; 637 emsg_severe = FALSE; 638 #endif 639 640 if (!emsg_off || vim_strchr(p_debug, 't') != NULL) 641 { 642 #ifdef FEAT_EVAL 643 /* 644 * Cause a throw of an error exception if appropriate. Don't display 645 * the error message in this case. (If no matching catch clause will 646 * be found, the message will be displayed later on.) "ignore" is set 647 * when the message should be ignored completely (used for the 648 * interrupt message). 649 */ 650 if (cause_errthrow(s, severe, &ignore) == TRUE) 651 { 652 if (!ignore) 653 ++did_emsg; 654 return TRUE; 655 } 656 657 // set "v:errmsg", also when using ":silent! cmd" 658 set_vim_var_string(VV_ERRMSG, s, -1); 659 #endif 660 661 /* 662 * When using ":silent! cmd" ignore error messages. 663 * But do write it to the redirection file. 664 */ 665 if (emsg_silent != 0) 666 { 667 if (emsg_noredir == 0) 668 { 669 msg_start(); 670 p = get_emsg_source(); 671 if (p != NULL) 672 { 673 STRCAT(p, "\n"); 674 redir_write(p, -1); 675 vim_free(p); 676 } 677 p = get_emsg_lnum(); 678 if (p != NULL) 679 { 680 STRCAT(p, "\n"); 681 redir_write(p, -1); 682 vim_free(p); 683 } 684 redir_write(s, -1); 685 } 686 #ifdef FEAT_JOB_CHANNEL 687 ch_log(NULL, "ERROR silent: %s", (char *)s); 688 #endif 689 return TRUE; 690 } 691 692 ex_exitval = 1; 693 694 // Reset msg_silent, an error causes messages to be switched back on. 695 msg_silent = 0; 696 cmd_silent = FALSE; 697 698 if (global_busy) // break :global command 699 ++global_busy; 700 701 if (p_eb) 702 beep_flush(); // also includes flush_buffers() 703 else 704 flush_buffers(FLUSH_MINIMAL); // flush internal buffers 705 ++did_emsg; // flag for DoOneCmd() 706 #ifdef FEAT_EVAL 707 did_uncaught_emsg = TRUE; 708 #endif 709 } 710 711 emsg_on_display = TRUE; // remember there is an error message 712 ++msg_scroll; // don't overwrite a previous message 713 attr = HL_ATTR(HLF_E); // set highlight mode for error messages 714 if (msg_scrolled != 0) 715 need_wait_return = TRUE; // needed in case emsg() is called after 716 // wait_return has reset need_wait_return 717 // and a redraw is expected because 718 // msg_scrolled is non-zero 719 720 #ifdef FEAT_JOB_CHANNEL 721 emsg_to_channel_log = TRUE; 722 #endif 723 /* 724 * Display name and line number for the source of the error. 725 */ 726 msg_source(attr); 727 728 /* 729 * Display the error message itself. 730 */ 731 msg_nowait = FALSE; // wait for this msg 732 r = msg_attr((char *)s, attr); 733 734 #ifdef FEAT_JOB_CHANNEL 735 emsg_to_channel_log = FALSE; 736 #endif 737 return r; 738 } 739 740 /* 741 * Print an error message. 742 */ 743 int 744 emsg(char *s) 745 { 746 // Skip this if not giving error messages at the moment. 747 if (!emsg_not_now()) 748 return emsg_core((char_u *)s); 749 return TRUE; // no error messages at the moment 750 } 751 752 #ifndef PROTO // manual proto with __attribute__ 753 /* 754 * Print an error message with format string and variable arguments. 755 * Note: caller must not pass 'IObuff' as 1st argument. 756 */ 757 int 758 semsg(const char *s, ...) 759 { 760 // Skip this if not giving error messages at the moment. 761 if (!emsg_not_now()) 762 { 763 if (IObuff == NULL) 764 { 765 // Very early in initialisation and already something wrong, just 766 // give the raw message so the user at least gets a hint. 767 return emsg_core((char_u *)s); 768 } 769 else 770 { 771 va_list ap; 772 773 va_start(ap, s); 774 vim_vsnprintf((char *)IObuff, IOSIZE, s, ap); 775 va_end(ap); 776 return emsg_core(IObuff); 777 } 778 } 779 return TRUE; // no error messages at the moment 780 } 781 #endif 782 783 /* 784 * Same as emsg(...), but abort on error when ABORT_ON_INTERNAL_ERROR is 785 * defined. It is used for internal errors only, so that they can be 786 * detected when fuzzing vim. 787 */ 788 void 789 iemsg(char *s) 790 { 791 if (!emsg_not_now()) 792 emsg_core((char_u *)s); 793 #ifdef ABORT_ON_INTERNAL_ERROR 794 abort(); 795 #endif 796 } 797 798 #ifndef PROTO // manual proto with __attribute__ 799 /* 800 * Same as semsg(...) but abort on error when ABORT_ON_INTERNAL_ERROR is 801 * defined. It is used for internal errors only, so that they can be 802 * detected when fuzzing vim. 803 * Note: caller must not pass 'IObuff' as 1st argument. 804 */ 805 void 806 siemsg(const char *s, ...) 807 { 808 if (!emsg_not_now()) 809 { 810 if (IObuff == NULL) 811 { 812 // Very early in initialisation and already something wrong, just 813 // give the raw message so the user at least gets a hint. 814 emsg_core((char_u *)s); 815 } 816 else 817 { 818 va_list ap; 819 820 va_start(ap, s); 821 vim_vsnprintf((char *)IObuff, IOSIZE, s, ap); 822 va_end(ap); 823 emsg_core(IObuff); 824 } 825 } 826 # ifdef ABORT_ON_INTERNAL_ERROR 827 abort(); 828 # endif 829 } 830 #endif 831 832 /* 833 * Give an "Internal error" message. 834 */ 835 void 836 internal_error(char *where) 837 { 838 siemsg(_(e_intern2), where); 839 } 840 841 /* 842 * Like internal_error() but do not call abort(), to avoid tests using 843 * test_unknown() and test_void() causing Vim to exit. 844 */ 845 void 846 internal_error_no_abort(char *where) 847 { 848 semsg(_(e_intern2), where); 849 } 850 851 // emsg3() and emsgn() are in misc2.c to avoid warnings for the prototypes. 852 853 void 854 emsg_invreg(int name) 855 { 856 semsg(_("E354: Invalid register name: '%s'"), transchar(name)); 857 } 858 859 /* 860 * Give an error message which contains %s for "name[len]". 861 */ 862 void 863 emsg_namelen(char *msg, char_u *name, int len) 864 { 865 char_u *copy = vim_strnsave((char_u *)name, len); 866 867 semsg(msg, copy == NULL ? "NULL" : (char *)copy); 868 } 869 870 /* 871 * Like msg(), but truncate to a single line if p_shm contains 't', or when 872 * "force" is TRUE. This truncates in another way as for normal messages. 873 * Careful: The string may be changed by msg_may_trunc()! 874 * Returns a pointer to the printed message, if wait_return() not called. 875 */ 876 char * 877 msg_trunc_attr(char *s, int force, int attr) 878 { 879 int n; 880 char *ts; 881 882 // Add message to history before truncating 883 add_msg_hist((char_u *)s, -1, attr); 884 885 ts = (char *)msg_may_trunc(force, (char_u *)s); 886 887 msg_hist_off = TRUE; 888 n = msg_attr(ts, attr); 889 msg_hist_off = FALSE; 890 891 if (n) 892 return ts; 893 return NULL; 894 } 895 896 /* 897 * Check if message "s" should be truncated at the start (for filenames). 898 * Return a pointer to where the truncated message starts. 899 * Note: May change the message by replacing a character with '<'. 900 */ 901 char_u * 902 msg_may_trunc(int force, char_u *s) 903 { 904 int n; 905 int room; 906 907 room = (int)(Rows - cmdline_row - 1) * Columns + sc_col - 1; 908 if ((force || (shortmess(SHM_TRUNC) && !exmode_active)) 909 && (n = (int)STRLEN(s) - room) > 0) 910 { 911 if (has_mbyte) 912 { 913 int size = vim_strsize(s); 914 915 // There may be room anyway when there are multibyte chars. 916 if (size <= room) 917 return s; 918 919 for (n = 0; size >= room; ) 920 { 921 size -= (*mb_ptr2cells)(s + n); 922 n += (*mb_ptr2len)(s + n); 923 } 924 --n; 925 } 926 s += n; 927 *s = '<'; 928 } 929 return s; 930 } 931 932 static void 933 add_msg_hist( 934 char_u *s, 935 int len, // -1 for undetermined length 936 int attr) 937 { 938 struct msg_hist *p; 939 940 if (msg_hist_off || msg_silent != 0) 941 return; 942 943 // Don't let the message history get too big 944 while (msg_hist_len > MAX_MSG_HIST_LEN) 945 (void)delete_first_msg(); 946 947 // allocate an entry and add the message at the end of the history 948 p = ALLOC_ONE(struct msg_hist); 949 if (p != NULL) 950 { 951 if (len < 0) 952 len = (int)STRLEN(s); 953 // remove leading and trailing newlines 954 while (len > 0 && *s == '\n') 955 { 956 ++s; 957 --len; 958 } 959 while (len > 0 && s[len - 1] == '\n') 960 --len; 961 p->msg = vim_strnsave(s, len); 962 p->next = NULL; 963 p->attr = attr; 964 if (last_msg_hist != NULL) 965 last_msg_hist->next = p; 966 last_msg_hist = p; 967 if (first_msg_hist == NULL) 968 first_msg_hist = last_msg_hist; 969 ++msg_hist_len; 970 } 971 } 972 973 /* 974 * Delete the first (oldest) message from the history. 975 * Returns FAIL if there are no messages. 976 */ 977 int 978 delete_first_msg(void) 979 { 980 struct msg_hist *p; 981 982 if (msg_hist_len <= 0) 983 return FAIL; 984 p = first_msg_hist; 985 first_msg_hist = p->next; 986 if (first_msg_hist == NULL) 987 last_msg_hist = NULL; // history is empty 988 vim_free(p->msg); 989 vim_free(p); 990 --msg_hist_len; 991 return OK; 992 } 993 994 /* 995 * ":messages" command. 996 */ 997 void 998 ex_messages(exarg_T *eap) 999 { 1000 struct msg_hist *p; 1001 char_u *s; 1002 int c = 0; 1003 1004 if (STRCMP(eap->arg, "clear") == 0) 1005 { 1006 int keep = eap->addr_count == 0 ? 0 : eap->line2; 1007 1008 while (msg_hist_len > keep) 1009 (void)delete_first_msg(); 1010 return; 1011 } 1012 1013 if (*eap->arg != NUL) 1014 { 1015 emsg(_(e_invarg)); 1016 return; 1017 } 1018 1019 msg_hist_off = TRUE; 1020 1021 p = first_msg_hist; 1022 if (eap->addr_count != 0) 1023 { 1024 // Count total messages 1025 for (; p != NULL && !got_int; p = p->next) 1026 c++; 1027 1028 c -= eap->line2; 1029 1030 // Skip without number of messages specified 1031 for (p = first_msg_hist; p != NULL && !got_int && c > 0; 1032 p = p->next, c--); 1033 } 1034 1035 if (p == first_msg_hist) 1036 { 1037 s = mch_getenv((char_u *)"LANG"); 1038 if (s != NULL && *s != NUL) 1039 // The next comment is extracted by xgettext and put in po file for 1040 // translators to read. 1041 msg_attr( 1042 // Translator: Please replace the name and email address 1043 // with the appropriate text for your translation. 1044 _("Messages maintainer: Bram Moolenaar <[email protected]>"), 1045 HL_ATTR(HLF_T)); 1046 } 1047 1048 // Display what was not skipped. 1049 for (; p != NULL && !got_int; p = p->next) 1050 if (p->msg != NULL) 1051 msg_attr((char *)p->msg, p->attr); 1052 1053 msg_hist_off = FALSE; 1054 } 1055 1056 #if defined(FEAT_CON_DIALOG) || defined(FIND_REPLACE_DIALOG) || defined(PROTO) 1057 /* 1058 * Call this after prompting the user. This will avoid a hit-return message 1059 * and a delay. 1060 */ 1061 void 1062 msg_end_prompt(void) 1063 { 1064 need_wait_return = FALSE; 1065 emsg_on_display = FALSE; 1066 cmdline_row = msg_row; 1067 msg_col = 0; 1068 msg_clr_eos(); 1069 lines_left = -1; 1070 } 1071 #endif 1072 1073 /* 1074 * Wait for the user to hit a key (normally Enter). 1075 * If "redraw" is TRUE, clear and redraw the screen. 1076 * If "redraw" is FALSE, just redraw the screen. 1077 * If "redraw" is -1, don't redraw at all. 1078 */ 1079 void 1080 wait_return(int redraw) 1081 { 1082 int c; 1083 int oldState; 1084 int tmpState; 1085 int had_got_int; 1086 int save_reg_recording; 1087 FILE *save_scriptout; 1088 1089 if (redraw == TRUE) 1090 must_redraw = CLEAR; 1091 1092 // If using ":silent cmd", don't wait for a return. Also don't set 1093 // need_wait_return to do it later. 1094 if (msg_silent != 0) 1095 return; 1096 1097 /* 1098 * When inside vgetc(), we can't wait for a typed character at all. 1099 * With the global command (and some others) we only need one return at 1100 * the end. Adjust cmdline_row to avoid the next message overwriting the 1101 * last one. 1102 */ 1103 if (vgetc_busy > 0) 1104 return; 1105 need_wait_return = TRUE; 1106 if (no_wait_return) 1107 { 1108 if (!exmode_active) 1109 cmdline_row = msg_row; 1110 return; 1111 } 1112 1113 redir_off = TRUE; // don't redirect this message 1114 oldState = State; 1115 if (quit_more) 1116 { 1117 c = CAR; // just pretend CR was hit 1118 quit_more = FALSE; 1119 got_int = FALSE; 1120 } 1121 else if (exmode_active) 1122 { 1123 msg_puts(" "); // make sure the cursor is on the right line 1124 c = CAR; // no need for a return in ex mode 1125 got_int = FALSE; 1126 } 1127 else 1128 { 1129 // Make sure the hit-return prompt is on screen when 'guioptions' was 1130 // just changed. 1131 screenalloc(FALSE); 1132 1133 State = HITRETURN; 1134 setmouse(); 1135 #ifdef USE_ON_FLY_SCROLL 1136 dont_scroll = TRUE; // disallow scrolling here 1137 #endif 1138 cmdline_row = msg_row; 1139 1140 // Avoid the sequence that the user types ":" at the hit-return prompt 1141 // to start an Ex command, but the file-changed dialog gets in the 1142 // way. 1143 if (need_check_timestamps) 1144 check_timestamps(FALSE); 1145 1146 hit_return_msg(); 1147 1148 do 1149 { 1150 // Remember "got_int", if it is set vgetc() probably returns a 1151 // CTRL-C, but we need to loop then. 1152 had_got_int = got_int; 1153 1154 // Don't do mappings here, we put the character back in the 1155 // typeahead buffer. 1156 ++no_mapping; 1157 ++allow_keys; 1158 1159 // Temporarily disable Recording. If Recording is active, the 1160 // character will be recorded later, since it will be added to the 1161 // typebuf after the loop 1162 save_reg_recording = reg_recording; 1163 save_scriptout = scriptout; 1164 reg_recording = 0; 1165 scriptout = NULL; 1166 c = safe_vgetc(); 1167 if (had_got_int && !global_busy) 1168 got_int = FALSE; 1169 --no_mapping; 1170 --allow_keys; 1171 reg_recording = save_reg_recording; 1172 scriptout = save_scriptout; 1173 1174 #ifdef FEAT_CLIPBOARD 1175 // Strange way to allow copying (yanking) a modeless selection at 1176 // the hit-enter prompt. Use CTRL-Y, because the same is used in 1177 // Cmdline-mode and it's harmless when there is no selection. 1178 if (c == Ctrl_Y && clip_star.state == SELECT_DONE) 1179 { 1180 clip_copy_modeless_selection(TRUE); 1181 c = K_IGNORE; 1182 } 1183 #endif 1184 1185 /* 1186 * Allow scrolling back in the messages. 1187 * Also accept scroll-down commands when messages fill the screen, 1188 * to avoid that typing one 'j' too many makes the messages 1189 * disappear. 1190 */ 1191 if (p_more && !p_cp) 1192 { 1193 if (c == 'b' || c == 'k' || c == 'u' || c == 'g' 1194 || c == K_UP || c == K_PAGEUP) 1195 { 1196 if (msg_scrolled > Rows) 1197 // scroll back to show older messages 1198 do_more_prompt(c); 1199 else 1200 { 1201 msg_didout = FALSE; 1202 c = K_IGNORE; 1203 msg_col = 1204 #ifdef FEAT_RIGHTLEFT 1205 cmdmsg_rl ? Columns - 1 : 1206 #endif 1207 0; 1208 } 1209 if (quit_more) 1210 { 1211 c = CAR; // just pretend CR was hit 1212 quit_more = FALSE; 1213 got_int = FALSE; 1214 } 1215 else if (c != K_IGNORE) 1216 { 1217 c = K_IGNORE; 1218 hit_return_msg(); 1219 } 1220 } 1221 else if (msg_scrolled > Rows - 2 1222 && (c == 'j' || c == 'd' || c == 'f' 1223 || c == K_DOWN || c == K_PAGEDOWN)) 1224 c = K_IGNORE; 1225 } 1226 } while ((had_got_int && c == Ctrl_C) 1227 || c == K_IGNORE 1228 #ifdef FEAT_GUI 1229 || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR 1230 #endif 1231 || c == K_LEFTDRAG || c == K_LEFTRELEASE 1232 || c == K_MIDDLEDRAG || c == K_MIDDLERELEASE 1233 || c == K_RIGHTDRAG || c == K_RIGHTRELEASE 1234 || c == K_MOUSELEFT || c == K_MOUSERIGHT 1235 || c == K_MOUSEDOWN || c == K_MOUSEUP 1236 || c == K_MOUSEMOVE 1237 || (!mouse_has(MOUSE_RETURN) 1238 && mouse_row < msg_row 1239 && (c == K_LEFTMOUSE 1240 || c == K_MIDDLEMOUSE 1241 || c == K_RIGHTMOUSE 1242 || c == K_X1MOUSE 1243 || c == K_X2MOUSE)) 1244 ); 1245 ui_breakcheck(); 1246 /* 1247 * Avoid that the mouse-up event causes visual mode to start. 1248 */ 1249 if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE 1250 || c == K_X1MOUSE || c == K_X2MOUSE) 1251 (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0); 1252 else if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C) 1253 { 1254 // Put the character back in the typeahead buffer. Don't use the 1255 // stuff buffer, because lmaps wouldn't work. 1256 ins_char_typebuf(c); 1257 do_redraw = TRUE; // need a redraw even though there is 1258 // typeahead 1259 } 1260 } 1261 redir_off = FALSE; 1262 1263 /* 1264 * If the user hits ':', '?' or '/' we get a command line from the next 1265 * line. 1266 */ 1267 if (c == ':' || c == '?' || c == '/') 1268 { 1269 if (!exmode_active) 1270 cmdline_row = msg_row; 1271 skip_redraw = TRUE; // skip redraw once 1272 do_redraw = FALSE; 1273 #ifdef FEAT_TERMINAL 1274 skip_term_loop = TRUE; 1275 #endif 1276 } 1277 1278 /* 1279 * If the window size changed set_shellsize() will redraw the screen. 1280 * Otherwise the screen is only redrawn if 'redraw' is set and no ':' 1281 * typed. 1282 */ 1283 tmpState = State; 1284 State = oldState; // restore State before set_shellsize 1285 setmouse(); 1286 msg_check(); 1287 1288 #if defined(UNIX) || defined(VMS) 1289 /* 1290 * When switching screens, we need to output an extra newline on exit. 1291 */ 1292 if (swapping_screen() && !termcap_active) 1293 newline_on_exit = TRUE; 1294 #endif 1295 1296 need_wait_return = FALSE; 1297 did_wait_return = TRUE; 1298 emsg_on_display = FALSE; // can delete error message now 1299 lines_left = -1; // reset lines_left at next msg_start() 1300 reset_last_sourcing(); 1301 if (keep_msg != NULL && vim_strsize(keep_msg) >= 1302 (Rows - cmdline_row - 1) * Columns + sc_col) 1303 VIM_CLEAR(keep_msg); // don't redisplay message, it's too long 1304 1305 if (tmpState == SETWSIZE) // got resize event while in vgetc() 1306 { 1307 starttermcap(); // start termcap before redrawing 1308 shell_resized(); 1309 } 1310 else if (!skip_redraw 1311 && (redraw == TRUE || (msg_scrolled != 0 && redraw != -1))) 1312 { 1313 starttermcap(); // start termcap before redrawing 1314 redraw_later(VALID); 1315 } 1316 } 1317 1318 /* 1319 * Write the hit-return prompt. 1320 */ 1321 static void 1322 hit_return_msg(void) 1323 { 1324 int save_p_more = p_more; 1325 1326 p_more = FALSE; // don't want see this message when scrolling back 1327 if (msg_didout) // start on a new line 1328 msg_putchar('\n'); 1329 if (got_int) 1330 msg_puts(_("Interrupt: ")); 1331 1332 msg_puts_attr(_("Press ENTER or type command to continue"), HL_ATTR(HLF_R)); 1333 if (!msg_use_printf()) 1334 msg_clr_eos(); 1335 p_more = save_p_more; 1336 } 1337 1338 /* 1339 * Set "keep_msg" to "s". Free the old value and check for NULL pointer. 1340 */ 1341 void 1342 set_keep_msg(char_u *s, int attr) 1343 { 1344 vim_free(keep_msg); 1345 if (s != NULL && msg_silent == 0) 1346 keep_msg = vim_strsave(s); 1347 else 1348 keep_msg = NULL; 1349 keep_msg_more = FALSE; 1350 keep_msg_attr = attr; 1351 } 1352 1353 #if defined(FEAT_TERMRESPONSE) || defined(PROTO) 1354 /* 1355 * If there currently is a message being displayed, set "keep_msg" to it, so 1356 * that it will be displayed again after redraw. 1357 */ 1358 void 1359 set_keep_msg_from_hist(void) 1360 { 1361 if (keep_msg == NULL && last_msg_hist != NULL && msg_scrolled == 0 1362 && (State & NORMAL)) 1363 set_keep_msg(last_msg_hist->msg, last_msg_hist->attr); 1364 } 1365 #endif 1366 1367 /* 1368 * Prepare for outputting characters in the command line. 1369 */ 1370 void 1371 msg_start(void) 1372 { 1373 int did_return = FALSE; 1374 1375 if (!msg_silent) 1376 VIM_CLEAR(keep_msg); 1377 1378 #ifdef FEAT_EVAL 1379 if (need_clr_eos) 1380 { 1381 // Halfway an ":echo" command and getting an (error) message: clear 1382 // any text from the command. 1383 need_clr_eos = FALSE; 1384 msg_clr_eos(); 1385 } 1386 #endif 1387 1388 if (!msg_scroll && full_screen) // overwrite last message 1389 { 1390 msg_row = cmdline_row; 1391 msg_col = 1392 #ifdef FEAT_RIGHTLEFT 1393 cmdmsg_rl ? Columns - 1 : 1394 #endif 1395 0; 1396 } 1397 else if (msg_didout) // start message on next line 1398 { 1399 msg_putchar('\n'); 1400 did_return = TRUE; 1401 if (exmode_active != EXMODE_NORMAL) 1402 cmdline_row = msg_row; 1403 } 1404 if (!msg_didany || lines_left < 0) 1405 msg_starthere(); 1406 if (msg_silent == 0) 1407 { 1408 msg_didout = FALSE; // no output on current line yet 1409 cursor_off(); 1410 } 1411 1412 // when redirecting, may need to start a new line. 1413 if (!did_return) 1414 redir_write((char_u *)"\n", -1); 1415 } 1416 1417 /* 1418 * Note that the current msg position is where messages start. 1419 */ 1420 void 1421 msg_starthere(void) 1422 { 1423 lines_left = cmdline_row; 1424 msg_didany = FALSE; 1425 } 1426 1427 void 1428 msg_putchar(int c) 1429 { 1430 msg_putchar_attr(c, 0); 1431 } 1432 1433 void 1434 msg_putchar_attr(int c, int attr) 1435 { 1436 char_u buf[MB_MAXBYTES + 1]; 1437 1438 if (IS_SPECIAL(c)) 1439 { 1440 buf[0] = K_SPECIAL; 1441 buf[1] = K_SECOND(c); 1442 buf[2] = K_THIRD(c); 1443 buf[3] = NUL; 1444 } 1445 else 1446 buf[(*mb_char2bytes)(c, buf)] = NUL; 1447 msg_puts_attr((char *)buf, attr); 1448 } 1449 1450 void 1451 msg_outnum(long n) 1452 { 1453 char buf[20]; 1454 1455 sprintf(buf, "%ld", n); 1456 msg_puts(buf); 1457 } 1458 1459 void 1460 msg_home_replace(char_u *fname) 1461 { 1462 msg_home_replace_attr(fname, 0); 1463 } 1464 1465 #if defined(FEAT_FIND_ID) || defined(PROTO) 1466 void 1467 msg_home_replace_hl(char_u *fname) 1468 { 1469 msg_home_replace_attr(fname, HL_ATTR(HLF_D)); 1470 } 1471 #endif 1472 1473 static void 1474 msg_home_replace_attr(char_u *fname, int attr) 1475 { 1476 char_u *name; 1477 1478 name = home_replace_save(NULL, fname); 1479 if (name != NULL) 1480 msg_outtrans_attr(name, attr); 1481 vim_free(name); 1482 } 1483 1484 /* 1485 * Output 'len' characters in 'str' (including NULs) with translation 1486 * if 'len' is -1, output up to a NUL character. 1487 * Use attributes 'attr'. 1488 * Return the number of characters it takes on the screen. 1489 */ 1490 int 1491 msg_outtrans(char_u *str) 1492 { 1493 return msg_outtrans_attr(str, 0); 1494 } 1495 1496 int 1497 msg_outtrans_attr(char_u *str, int attr) 1498 { 1499 return msg_outtrans_len_attr(str, (int)STRLEN(str), attr); 1500 } 1501 1502 int 1503 msg_outtrans_len(char_u *str, int len) 1504 { 1505 return msg_outtrans_len_attr(str, len, 0); 1506 } 1507 1508 /* 1509 * Output one character at "p". Return pointer to the next character. 1510 * Handles multi-byte characters. 1511 */ 1512 char_u * 1513 msg_outtrans_one(char_u *p, int attr) 1514 { 1515 int l; 1516 1517 if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) 1518 { 1519 msg_outtrans_len_attr(p, l, attr); 1520 return p + l; 1521 } 1522 msg_puts_attr((char *)transchar_byte(*p), attr); 1523 return p + 1; 1524 } 1525 1526 int 1527 msg_outtrans_len_attr(char_u *msgstr, int len, int attr) 1528 { 1529 int retval = 0; 1530 char_u *str = msgstr; 1531 char_u *plain_start = msgstr; 1532 char_u *s; 1533 int mb_l; 1534 int c; 1535 1536 // if MSG_HIST flag set, add message to history 1537 if (attr & MSG_HIST) 1538 { 1539 add_msg_hist(str, len, attr); 1540 attr &= ~MSG_HIST; 1541 } 1542 1543 // If the string starts with a composing character first draw a space on 1544 // which the composing char can be drawn. 1545 if (enc_utf8 && utf_iscomposing(utf_ptr2char(msgstr))) 1546 msg_puts_attr(" ", attr); 1547 1548 /* 1549 * Go over the string. Special characters are translated and printed. 1550 * Normal characters are printed several at a time. 1551 */ 1552 while (--len >= 0) 1553 { 1554 if (enc_utf8) 1555 // Don't include composing chars after the end. 1556 mb_l = utfc_ptr2len_len(str, len + 1); 1557 else if (has_mbyte) 1558 mb_l = (*mb_ptr2len)(str); 1559 else 1560 mb_l = 1; 1561 if (has_mbyte && mb_l > 1) 1562 { 1563 c = (*mb_ptr2char)(str); 1564 if (vim_isprintc(c)) 1565 // printable multi-byte char: count the cells. 1566 retval += (*mb_ptr2cells)(str); 1567 else 1568 { 1569 // unprintable multi-byte char: print the printable chars so 1570 // far and the translation of the unprintable char. 1571 if (str > plain_start) 1572 msg_puts_attr_len((char *)plain_start, 1573 (int)(str - plain_start), attr); 1574 plain_start = str + mb_l; 1575 msg_puts_attr((char *)transchar(c), 1576 attr == 0 ? HL_ATTR(HLF_8) : attr); 1577 retval += char2cells(c); 1578 } 1579 len -= mb_l - 1; 1580 str += mb_l; 1581 } 1582 else 1583 { 1584 s = transchar_byte(*str); 1585 if (s[1] != NUL) 1586 { 1587 // unprintable char: print the printable chars so far and the 1588 // translation of the unprintable char. 1589 if (str > plain_start) 1590 msg_puts_attr_len((char *)plain_start, 1591 (int)(str - plain_start), attr); 1592 plain_start = str + 1; 1593 msg_puts_attr((char *)s, attr == 0 ? HL_ATTR(HLF_8) : attr); 1594 retval += (int)STRLEN(s); 1595 } 1596 else 1597 ++retval; 1598 ++str; 1599 } 1600 } 1601 1602 if (str > plain_start) 1603 // print the printable chars at the end 1604 msg_puts_attr_len((char *)plain_start, (int)(str - plain_start), attr); 1605 1606 return retval; 1607 } 1608 1609 #if defined(FEAT_QUICKFIX) || defined(PROTO) 1610 void 1611 msg_make(char_u *arg) 1612 { 1613 int i; 1614 static char_u *str = (char_u *)"eeffoc", *rs = (char_u *)"Plon#dqg#vxjduB"; 1615 1616 arg = skipwhite(arg); 1617 for (i = 5; *arg && i >= 0; --i) 1618 if (*arg++ != str[i]) 1619 break; 1620 if (i < 0) 1621 { 1622 msg_putchar('\n'); 1623 for (i = 0; rs[i]; ++i) 1624 msg_putchar(rs[i] - 3); 1625 } 1626 } 1627 #endif 1628 1629 /* 1630 * Output the string 'str' up to a NUL character. 1631 * Return the number of characters it takes on the screen. 1632 * 1633 * If K_SPECIAL is encountered, then it is taken in conjunction with the 1634 * following character and shown as <F1>, <S-Up> etc. Any other character 1635 * which is not printable shown in <> form. 1636 * If 'from' is TRUE (lhs of a mapping), a space is shown as <Space>. 1637 * If a character is displayed in one of these special ways, is also 1638 * highlighted (its highlight name is '8' in the p_hl variable). 1639 * Otherwise characters are not highlighted. 1640 * This function is used to show mappings, where we want to see how to type 1641 * the character/string -- webb 1642 */ 1643 int 1644 msg_outtrans_special( 1645 char_u *strstart, 1646 int from, // TRUE for lhs of a mapping 1647 int maxlen) // screen columns, 0 for unlimited 1648 { 1649 char_u *str = strstart; 1650 int retval = 0; 1651 char *text; 1652 int attr; 1653 int len; 1654 1655 attr = HL_ATTR(HLF_8); 1656 while (*str != NUL) 1657 { 1658 // Leading and trailing spaces need to be displayed in <> form. 1659 if ((str == strstart || str[1] == NUL) && *str == ' ') 1660 { 1661 text = "<Space>"; 1662 ++str; 1663 } 1664 else 1665 text = (char *)str2special(&str, from); 1666 len = vim_strsize((char_u *)text); 1667 if (maxlen > 0 && retval + len >= maxlen) 1668 break; 1669 // Highlight special keys 1670 msg_puts_attr(text, len > 1 1671 && (*mb_ptr2len)((char_u *)text) <= 1 ? attr : 0); 1672 retval += len; 1673 } 1674 return retval; 1675 } 1676 1677 #if defined(FEAT_EVAL) || defined(PROTO) 1678 /* 1679 * Return the lhs or rhs of a mapping, with the key codes turned into printable 1680 * strings, in an allocated string. 1681 */ 1682 char_u * 1683 str2special_save( 1684 char_u *str, 1685 int is_lhs) // TRUE for lhs, FALSE for rhs 1686 { 1687 garray_T ga; 1688 char_u *p = str; 1689 1690 ga_init2(&ga, 1, 40); 1691 while (*p != NUL) 1692 ga_concat(&ga, str2special(&p, is_lhs)); 1693 ga_append(&ga, NUL); 1694 return (char_u *)ga.ga_data; 1695 } 1696 #endif 1697 1698 /* 1699 * Return the printable string for the key codes at "*sp". 1700 * Used for translating the lhs or rhs of a mapping to printable chars. 1701 * Advances "sp" to the next code. 1702 */ 1703 char_u * 1704 str2special( 1705 char_u **sp, 1706 int from) // TRUE for lhs of mapping 1707 { 1708 int c; 1709 static char_u buf[7]; 1710 char_u *str = *sp; 1711 int modifiers = 0; 1712 int special = FALSE; 1713 1714 if (has_mbyte) 1715 { 1716 char_u *p; 1717 1718 // Try to un-escape a multi-byte character. Return the un-escaped 1719 // string if it is a multi-byte character. 1720 p = mb_unescape(sp); 1721 if (p != NULL) 1722 return p; 1723 } 1724 1725 c = *str; 1726 if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) 1727 { 1728 if (str[1] == KS_MODIFIER) 1729 { 1730 modifiers = str[2]; 1731 str += 3; 1732 c = *str; 1733 } 1734 if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) 1735 { 1736 c = TO_SPECIAL(str[1], str[2]); 1737 str += 2; 1738 } 1739 if (IS_SPECIAL(c) || modifiers) // special key 1740 special = TRUE; 1741 } 1742 1743 if (has_mbyte && !IS_SPECIAL(c)) 1744 { 1745 int len = (*mb_ptr2len)(str); 1746 1747 // For multi-byte characters check for an illegal byte. 1748 if (has_mbyte && MB_BYTE2LEN(*str) > len) 1749 { 1750 transchar_nonprint(buf, c); 1751 *sp = str + 1; 1752 return buf; 1753 } 1754 // Since 'special' is TRUE the multi-byte character 'c' will be 1755 // processed by get_special_key_name() 1756 c = (*mb_ptr2char)(str); 1757 *sp = str + len; 1758 } 1759 else 1760 *sp = str + 1; 1761 1762 // Make unprintable characters in <> form, also <M-Space> and <Tab>. 1763 // Use <Space> only for lhs of a mapping. 1764 if (special || char2cells(c) > 1 || (from && c == ' ')) 1765 return get_special_key_name(c, modifiers); 1766 buf[0] = c; 1767 buf[1] = NUL; 1768 return buf; 1769 } 1770 1771 /* 1772 * Translate a key sequence into special key names. 1773 */ 1774 void 1775 str2specialbuf(char_u *sp, char_u *buf, int len) 1776 { 1777 char_u *s; 1778 1779 *buf = NUL; 1780 while (*sp) 1781 { 1782 s = str2special(&sp, FALSE); 1783 if ((int)(STRLEN(s) + STRLEN(buf)) < len) 1784 STRCAT(buf, s); 1785 } 1786 } 1787 1788 /* 1789 * print line for :print or :list command 1790 */ 1791 void 1792 msg_prt_line(char_u *s, int list) 1793 { 1794 int c; 1795 int col = 0; 1796 int n_extra = 0; 1797 int c_extra = 0; 1798 int c_final = 0; 1799 char_u *p_extra = NULL; // init to make SASC shut up 1800 int n; 1801 int attr = 0; 1802 char_u *trail = NULL; 1803 int l; 1804 char_u buf[MB_MAXBYTES + 1]; 1805 1806 if (curwin->w_p_list) 1807 list = TRUE; 1808 1809 // find start of trailing whitespace 1810 if (list && lcs_trail) 1811 { 1812 trail = s + STRLEN(s); 1813 while (trail > s && VIM_ISWHITE(trail[-1])) 1814 --trail; 1815 } 1816 1817 // output a space for an empty line, otherwise the line will be 1818 // overwritten 1819 if (*s == NUL && !(list && lcs_eol != NUL)) 1820 msg_putchar(' '); 1821 1822 while (!got_int) 1823 { 1824 if (n_extra > 0) 1825 { 1826 --n_extra; 1827 if (n_extra == 0 && c_final) 1828 c = c_final; 1829 else if (c_extra) 1830 c = c_extra; 1831 else 1832 c = *p_extra++; 1833 } 1834 else if (has_mbyte && (l = (*mb_ptr2len)(s)) > 1) 1835 { 1836 col += (*mb_ptr2cells)(s); 1837 if (lcs_nbsp != NUL && list 1838 && (mb_ptr2char(s) == 160 1839 || mb_ptr2char(s) == 0x202f)) 1840 { 1841 mb_char2bytes(lcs_nbsp, buf); 1842 buf[(*mb_ptr2len)(buf)] = NUL; 1843 } 1844 else 1845 { 1846 mch_memmove(buf, s, (size_t)l); 1847 buf[l] = NUL; 1848 } 1849 msg_puts((char *)buf); 1850 s += l; 1851 continue; 1852 } 1853 else 1854 { 1855 attr = 0; 1856 c = *s++; 1857 if (c == TAB && (!list || lcs_tab1)) 1858 { 1859 // tab amount depends on current column 1860 #ifdef FEAT_VARTABS 1861 n_extra = tabstop_padding(col, curbuf->b_p_ts, 1862 curbuf->b_p_vts_array) - 1; 1863 #else 1864 n_extra = curbuf->b_p_ts - col % curbuf->b_p_ts - 1; 1865 #endif 1866 if (!list) 1867 { 1868 c = ' '; 1869 c_extra = ' '; 1870 c_final = NUL; 1871 } 1872 else 1873 { 1874 c = (n_extra == 0 && lcs_tab3) ? lcs_tab3 : lcs_tab1; 1875 c_extra = lcs_tab2; 1876 c_final = lcs_tab3; 1877 attr = HL_ATTR(HLF_8); 1878 } 1879 } 1880 else if (c == 160 && list && lcs_nbsp != NUL) 1881 { 1882 c = lcs_nbsp; 1883 attr = HL_ATTR(HLF_8); 1884 } 1885 else if (c == NUL && list && lcs_eol != NUL) 1886 { 1887 p_extra = (char_u *)""; 1888 c_extra = NUL; 1889 c_final = NUL; 1890 n_extra = 1; 1891 c = lcs_eol; 1892 attr = HL_ATTR(HLF_AT); 1893 --s; 1894 } 1895 else if (c != NUL && (n = byte2cells(c)) > 1) 1896 { 1897 n_extra = n - 1; 1898 p_extra = transchar_byte(c); 1899 c_extra = NUL; 1900 c_final = NUL; 1901 c = *p_extra++; 1902 // Use special coloring to be able to distinguish <hex> from 1903 // the same in plain text. 1904 attr = HL_ATTR(HLF_8); 1905 } 1906 else if (c == ' ' && trail != NULL && s > trail) 1907 { 1908 c = lcs_trail; 1909 attr = HL_ATTR(HLF_8); 1910 } 1911 else if (c == ' ' && list && lcs_space != NUL) 1912 { 1913 c = lcs_space; 1914 attr = HL_ATTR(HLF_8); 1915 } 1916 } 1917 1918 if (c == NUL) 1919 break; 1920 1921 msg_putchar_attr(c, attr); 1922 col++; 1923 } 1924 msg_clr_eos(); 1925 } 1926 1927 /* 1928 * Use screen_puts() to output one multi-byte character. 1929 * Return the pointer "s" advanced to the next character. 1930 */ 1931 static char_u * 1932 screen_puts_mbyte(char_u *s, int l, int attr) 1933 { 1934 int cw; 1935 1936 msg_didout = TRUE; // remember that line is not empty 1937 cw = (*mb_ptr2cells)(s); 1938 if (cw > 1 && ( 1939 #ifdef FEAT_RIGHTLEFT 1940 cmdmsg_rl ? msg_col <= 1 : 1941 #endif 1942 msg_col == Columns - 1)) 1943 { 1944 // Doesn't fit, print a highlighted '>' to fill it up. 1945 msg_screen_putchar('>', HL_ATTR(HLF_AT)); 1946 return s; 1947 } 1948 1949 screen_puts_len(s, l, msg_row, msg_col, attr); 1950 #ifdef FEAT_RIGHTLEFT 1951 if (cmdmsg_rl) 1952 { 1953 msg_col -= cw; 1954 if (msg_col == 0) 1955 { 1956 msg_col = Columns; 1957 ++msg_row; 1958 } 1959 } 1960 else 1961 #endif 1962 { 1963 msg_col += cw; 1964 if (msg_col >= Columns) 1965 { 1966 msg_col = 0; 1967 ++msg_row; 1968 } 1969 } 1970 return s + l; 1971 } 1972 1973 /* 1974 * Output a string to the screen at position msg_row, msg_col. 1975 * Update msg_row and msg_col for the next message. 1976 */ 1977 void 1978 msg_puts(char *s) 1979 { 1980 msg_puts_attr(s, 0); 1981 } 1982 1983 void 1984 msg_puts_title(char *s) 1985 { 1986 msg_puts_attr(s, HL_ATTR(HLF_T)); 1987 } 1988 1989 /* 1990 * Show a message in such a way that it always fits in the line. Cut out a 1991 * part in the middle and replace it with "..." when necessary. 1992 * Does not handle multi-byte characters! 1993 */ 1994 static void 1995 msg_outtrans_long_len_attr(char_u *longstr, int len, int attr) 1996 { 1997 int slen = len; 1998 int room; 1999 2000 room = Columns - msg_col; 2001 if (len > room && room >= 20) 2002 { 2003 slen = (room - 3) / 2; 2004 msg_outtrans_len_attr(longstr, slen, attr); 2005 msg_puts_attr("...", HL_ATTR(HLF_8)); 2006 } 2007 msg_outtrans_len_attr(longstr + len - slen, slen, attr); 2008 } 2009 2010 void 2011 msg_outtrans_long_attr(char_u *longstr, int attr) 2012 { 2013 msg_outtrans_long_len_attr(longstr, (int)STRLEN(longstr), attr); 2014 } 2015 2016 /* 2017 * Basic function for writing a message with highlight attributes. 2018 */ 2019 void 2020 msg_puts_attr(char *s, int attr) 2021 { 2022 msg_puts_attr_len(s, -1, attr); 2023 } 2024 2025 /* 2026 * Like msg_puts_attr(), but with a maximum length "maxlen" (in bytes). 2027 * When "maxlen" is -1 there is no maximum length. 2028 * When "maxlen" is >= 0 the message is not put in the history. 2029 */ 2030 static void 2031 msg_puts_attr_len(char *str, int maxlen, int attr) 2032 { 2033 /* 2034 * If redirection is on, also write to the redirection file. 2035 */ 2036 redir_write((char_u *)str, maxlen); 2037 2038 /* 2039 * Don't print anything when using ":silent cmd". 2040 */ 2041 if (msg_silent != 0) 2042 return; 2043 2044 // if MSG_HIST flag set, add message to history 2045 if ((attr & MSG_HIST) && maxlen < 0) 2046 { 2047 add_msg_hist((char_u *)str, -1, attr); 2048 attr &= ~MSG_HIST; 2049 } 2050 2051 // When writing something to the screen after it has scrolled, requires a 2052 // wait-return prompt later. Needed when scrolling, resetting 2053 // need_wait_return after some prompt, and then outputting something 2054 // without scrolling 2055 // Not needed when only using CR to move the cursor. 2056 if (msg_scrolled != 0 && !msg_scrolled_ign && STRCMP(str, "\r") != 0) 2057 need_wait_return = TRUE; 2058 msg_didany = TRUE; // remember that something was outputted 2059 2060 /* 2061 * If there is no valid screen, use fprintf so we can see error messages. 2062 * If termcap is not active, we may be writing in an alternate console 2063 * window, cursor positioning may not work correctly (window size may be 2064 * different, e.g. for Win32 console) or we just don't know where the 2065 * cursor is. 2066 */ 2067 if (msg_use_printf()) 2068 msg_puts_printf((char_u *)str, maxlen); 2069 else 2070 msg_puts_display((char_u *)str, maxlen, attr, FALSE); 2071 } 2072 2073 /* 2074 * The display part of msg_puts_attr_len(). 2075 * May be called recursively to display scroll-back text. 2076 */ 2077 static void 2078 msg_puts_display( 2079 char_u *str, 2080 int maxlen, 2081 int attr, 2082 int recurse) 2083 { 2084 char_u *s = str; 2085 char_u *t_s = str; // string from "t_s" to "s" is still todo 2086 int t_col = 0; // screen cells todo, 0 when "t_s" not used 2087 int l; 2088 int cw; 2089 char_u *sb_str = str; 2090 int sb_col = msg_col; 2091 int wrap; 2092 int did_last_char; 2093 2094 did_wait_return = FALSE; 2095 while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL) 2096 { 2097 /* 2098 * We are at the end of the screen line when: 2099 * - When outputting a newline. 2100 * - When outputting a character in the last column. 2101 */ 2102 if (!recurse && msg_row >= Rows - 1 && (*s == '\n' || ( 2103 #ifdef FEAT_RIGHTLEFT 2104 cmdmsg_rl 2105 ? ( 2106 msg_col <= 1 2107 || (*s == TAB && msg_col <= 7) 2108 || (has_mbyte && (*mb_ptr2cells)(s) > 1 && msg_col <= 2)) 2109 : 2110 #endif 2111 ((*s != '\r' && msg_col + t_col >= Columns - 1) 2112 || (*s == TAB && msg_col + t_col >= ((Columns - 1) & ~7)) 2113 || (has_mbyte && (*mb_ptr2cells)(s) > 1 2114 && msg_col + t_col >= Columns - 2))))) 2115 { 2116 /* 2117 * The screen is scrolled up when at the last row (some terminals 2118 * scroll automatically, some don't. To avoid problems we scroll 2119 * ourselves). 2120 */ 2121 if (t_col > 0) 2122 // output postponed text 2123 t_puts(&t_col, t_s, s, attr); 2124 2125 // When no more prompt and no more room, truncate here 2126 if (msg_no_more && lines_left == 0) 2127 break; 2128 2129 // Scroll the screen up one line. 2130 msg_scroll_up(); 2131 2132 msg_row = Rows - 2; 2133 if (msg_col >= Columns) // can happen after screen resize 2134 msg_col = Columns - 1; 2135 2136 // Display char in last column before showing more-prompt. 2137 if (*s >= ' ' 2138 #ifdef FEAT_RIGHTLEFT 2139 && !cmdmsg_rl 2140 #endif 2141 ) 2142 { 2143 if (has_mbyte) 2144 { 2145 if (enc_utf8 && maxlen >= 0) 2146 // avoid including composing chars after the end 2147 l = utfc_ptr2len_len(s, (int)((str + maxlen) - s)); 2148 else 2149 l = (*mb_ptr2len)(s); 2150 s = screen_puts_mbyte(s, l, attr); 2151 } 2152 else 2153 msg_screen_putchar(*s++, attr); 2154 did_last_char = TRUE; 2155 } 2156 else 2157 did_last_char = FALSE; 2158 2159 if (p_more) 2160 // store text for scrolling back 2161 store_sb_text(&sb_str, s, attr, &sb_col, TRUE); 2162 2163 inc_msg_scrolled(); 2164 need_wait_return = TRUE; // may need wait_return in main() 2165 redraw_cmdline = TRUE; 2166 if (cmdline_row > 0 && !exmode_active) 2167 --cmdline_row; 2168 2169 /* 2170 * If screen is completely filled and 'more' is set then wait 2171 * for a character. 2172 */ 2173 if (lines_left > 0) 2174 --lines_left; 2175 if (p_more && lines_left == 0 && State != HITRETURN 2176 && !msg_no_more && !exmode_active) 2177 { 2178 #ifdef FEAT_CON_DIALOG 2179 if (do_more_prompt(NUL)) 2180 s = confirm_msg_tail; 2181 #else 2182 (void)do_more_prompt(NUL); 2183 #endif 2184 if (quit_more) 2185 return; 2186 } 2187 2188 // When we displayed a char in last column need to check if there 2189 // is still more. 2190 if (did_last_char) 2191 continue; 2192 } 2193 2194 wrap = *s == '\n' 2195 || msg_col + t_col >= Columns 2196 || (has_mbyte && (*mb_ptr2cells)(s) > 1 2197 && msg_col + t_col >= Columns - 1); 2198 if (t_col > 0 && (wrap || *s == '\r' || *s == '\b' 2199 || *s == '\t' || *s == BELL)) 2200 // output any postponed text 2201 t_puts(&t_col, t_s, s, attr); 2202 2203 if (wrap && p_more && !recurse) 2204 // store text for scrolling back 2205 store_sb_text(&sb_str, s, attr, &sb_col, TRUE); 2206 2207 if (*s == '\n') // go to next line 2208 { 2209 msg_didout = FALSE; // remember that line is empty 2210 #ifdef FEAT_RIGHTLEFT 2211 if (cmdmsg_rl) 2212 msg_col = Columns - 1; 2213 else 2214 #endif 2215 msg_col = 0; 2216 if (++msg_row >= Rows) // safety check 2217 msg_row = Rows - 1; 2218 } 2219 else if (*s == '\r') // go to column 0 2220 { 2221 msg_col = 0; 2222 } 2223 else if (*s == '\b') // go to previous char 2224 { 2225 if (msg_col) 2226 --msg_col; 2227 } 2228 else if (*s == TAB) // translate Tab into spaces 2229 { 2230 do 2231 msg_screen_putchar(' ', attr); 2232 while (msg_col & 7); 2233 } 2234 else if (*s == BELL) // beep (from ":sh") 2235 vim_beep(BO_SH); 2236 else 2237 { 2238 if (has_mbyte) 2239 { 2240 cw = (*mb_ptr2cells)(s); 2241 if (enc_utf8 && maxlen >= 0) 2242 // avoid including composing chars after the end 2243 l = utfc_ptr2len_len(s, (int)((str + maxlen) - s)); 2244 else 2245 l = (*mb_ptr2len)(s); 2246 } 2247 else 2248 { 2249 cw = 1; 2250 l = 1; 2251 } 2252 2253 // When drawing from right to left or when a double-wide character 2254 // doesn't fit, draw a single character here. Otherwise collect 2255 // characters and draw them all at once later. 2256 if ( 2257 # ifdef FEAT_RIGHTLEFT 2258 cmdmsg_rl || 2259 # endif 2260 (cw > 1 && msg_col + t_col >= Columns - 1)) 2261 { 2262 if (l > 1) 2263 s = screen_puts_mbyte(s, l, attr) - 1; 2264 else 2265 msg_screen_putchar(*s, attr); 2266 } 2267 else 2268 { 2269 // postpone this character until later 2270 if (t_col == 0) 2271 t_s = s; 2272 t_col += cw; 2273 s += l - 1; 2274 } 2275 } 2276 ++s; 2277 } 2278 2279 // output any postponed text 2280 if (t_col > 0) 2281 t_puts(&t_col, t_s, s, attr); 2282 if (p_more && !recurse) 2283 store_sb_text(&sb_str, s, attr, &sb_col, FALSE); 2284 2285 msg_check(); 2286 } 2287 2288 /* 2289 * Return TRUE when ":filter pattern" was used and "msg" does not match 2290 * "pattern". 2291 */ 2292 int 2293 message_filtered(char_u *msg) 2294 { 2295 int match; 2296 2297 if (cmdmod.filter_regmatch.regprog == NULL) 2298 return FALSE; 2299 match = vim_regexec(&cmdmod.filter_regmatch, msg, (colnr_T)0); 2300 return cmdmod.filter_force ? match : !match; 2301 } 2302 2303 /* 2304 * Scroll the screen up one line for displaying the next message line. 2305 */ 2306 static void 2307 msg_scroll_up(void) 2308 { 2309 #ifdef FEAT_GUI 2310 // Remove the cursor before scrolling, ScreenLines[] is going 2311 // to become invalid. 2312 if (gui.in_use) 2313 gui_undraw_cursor(); 2314 #endif 2315 // scrolling up always works 2316 mch_disable_flush(); 2317 screen_del_lines(0, 0, 1, (int)Rows, TRUE, 0, NULL); 2318 mch_enable_flush(); 2319 2320 if (!can_clear((char_u *)" ")) 2321 { 2322 // Scrolling up doesn't result in the right background. Set the 2323 // background here. It's not efficient, but avoids that we have to do 2324 // it all over the code. 2325 screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); 2326 2327 // Also clear the last char of the last but one line if it was not 2328 // cleared before to avoid a scroll-up. 2329 if (ScreenAttrs[LineOffset[Rows - 2] + Columns - 1] == (sattr_T)-1) 2330 screen_fill((int)Rows - 2, (int)Rows - 1, 2331 (int)Columns - 1, (int)Columns, ' ', ' ', 0); 2332 } 2333 } 2334 2335 /* 2336 * Increment "msg_scrolled". 2337 */ 2338 static void 2339 inc_msg_scrolled(void) 2340 { 2341 #ifdef FEAT_EVAL 2342 if (*get_vim_var_str(VV_SCROLLSTART) == NUL) 2343 { 2344 char_u *p = SOURCING_NAME; 2345 char_u *tofree = NULL; 2346 int len; 2347 2348 // v:scrollstart is empty, set it to the script/function name and line 2349 // number 2350 if (p == NULL) 2351 p = (char_u *)_("Unknown"); 2352 else 2353 { 2354 len = (int)STRLEN(p) + 40; 2355 tofree = alloc(len); 2356 if (tofree != NULL) 2357 { 2358 vim_snprintf((char *)tofree, len, _("%s line %ld"), 2359 p, (long)SOURCING_LNUM); 2360 p = tofree; 2361 } 2362 } 2363 set_vim_var_string(VV_SCROLLSTART, p, -1); 2364 vim_free(tofree); 2365 } 2366 #endif 2367 ++msg_scrolled; 2368 if (must_redraw < VALID) 2369 must_redraw = VALID; 2370 } 2371 2372 /* 2373 * To be able to scroll back at the "more" and "hit-enter" prompts we need to 2374 * store the displayed text and remember where screen lines start. 2375 */ 2376 typedef struct msgchunk_S msgchunk_T; 2377 struct msgchunk_S 2378 { 2379 msgchunk_T *sb_next; 2380 msgchunk_T *sb_prev; 2381 char sb_eol; // TRUE when line ends after this text 2382 int sb_msg_col; // column in which text starts 2383 int sb_attr; // text attributes 2384 char_u sb_text[1]; // text to be displayed, actually longer 2385 }; 2386 2387 static msgchunk_T *last_msgchunk = NULL; // last displayed text 2388 2389 static msgchunk_T *msg_sb_start(msgchunk_T *mps); 2390 2391 typedef enum { 2392 SB_CLEAR_NONE = 0, 2393 SB_CLEAR_ALL, 2394 SB_CLEAR_CMDLINE_BUSY, 2395 SB_CLEAR_CMDLINE_DONE 2396 } sb_clear_T; 2397 2398 // When to clear text on next msg. 2399 static sb_clear_T do_clear_sb_text = SB_CLEAR_NONE; 2400 2401 /* 2402 * Store part of a printed message for displaying when scrolling back. 2403 */ 2404 static void 2405 store_sb_text( 2406 char_u **sb_str, // start of string 2407 char_u *s, // just after string 2408 int attr, 2409 int *sb_col, 2410 int finish) // line ends 2411 { 2412 msgchunk_T *mp; 2413 2414 if (do_clear_sb_text == SB_CLEAR_ALL 2415 || do_clear_sb_text == SB_CLEAR_CMDLINE_DONE) 2416 { 2417 clear_sb_text(do_clear_sb_text == SB_CLEAR_ALL); 2418 do_clear_sb_text = SB_CLEAR_NONE; 2419 } 2420 2421 if (s > *sb_str) 2422 { 2423 mp = alloc(sizeof(msgchunk_T) + (s - *sb_str)); 2424 if (mp != NULL) 2425 { 2426 mp->sb_eol = finish; 2427 mp->sb_msg_col = *sb_col; 2428 mp->sb_attr = attr; 2429 vim_strncpy(mp->sb_text, *sb_str, s - *sb_str); 2430 2431 if (last_msgchunk == NULL) 2432 { 2433 last_msgchunk = mp; 2434 mp->sb_prev = NULL; 2435 } 2436 else 2437 { 2438 mp->sb_prev = last_msgchunk; 2439 last_msgchunk->sb_next = mp; 2440 last_msgchunk = mp; 2441 } 2442 mp->sb_next = NULL; 2443 } 2444 } 2445 else if (finish && last_msgchunk != NULL) 2446 last_msgchunk->sb_eol = TRUE; 2447 2448 *sb_str = s; 2449 *sb_col = 0; 2450 } 2451 2452 /* 2453 * Finished showing messages, clear the scroll-back text on the next message. 2454 */ 2455 void 2456 may_clear_sb_text(void) 2457 { 2458 do_clear_sb_text = SB_CLEAR_ALL; 2459 } 2460 2461 /* 2462 * Starting to edit the command line, do not clear messages now. 2463 */ 2464 void 2465 sb_text_start_cmdline(void) 2466 { 2467 do_clear_sb_text = SB_CLEAR_CMDLINE_BUSY; 2468 msg_sb_eol(); 2469 } 2470 2471 /* 2472 * Ending to edit the command line. Clear old lines but the last one later. 2473 */ 2474 void 2475 sb_text_end_cmdline(void) 2476 { 2477 do_clear_sb_text = SB_CLEAR_CMDLINE_DONE; 2478 } 2479 2480 /* 2481 * Clear any text remembered for scrolling back. 2482 * When "all" is FALSE keep the last line. 2483 * Called when redrawing the screen. 2484 */ 2485 void 2486 clear_sb_text(int all) 2487 { 2488 msgchunk_T *mp; 2489 msgchunk_T **lastp; 2490 2491 if (all) 2492 lastp = &last_msgchunk; 2493 else 2494 { 2495 if (last_msgchunk == NULL) 2496 return; 2497 lastp = &last_msgchunk->sb_prev; 2498 } 2499 2500 while (*lastp != NULL) 2501 { 2502 mp = (*lastp)->sb_prev; 2503 vim_free(*lastp); 2504 *lastp = mp; 2505 } 2506 } 2507 2508 /* 2509 * "g<" command. 2510 */ 2511 void 2512 show_sb_text(void) 2513 { 2514 msgchunk_T *mp; 2515 2516 // Only show something if there is more than one line, otherwise it looks 2517 // weird, typing a command without output results in one line. 2518 mp = msg_sb_start(last_msgchunk); 2519 if (mp == NULL || mp->sb_prev == NULL) 2520 vim_beep(BO_MESS); 2521 else 2522 { 2523 do_more_prompt('G'); 2524 wait_return(FALSE); 2525 } 2526 } 2527 2528 /* 2529 * Move to the start of screen line in already displayed text. 2530 */ 2531 static msgchunk_T * 2532 msg_sb_start(msgchunk_T *mps) 2533 { 2534 msgchunk_T *mp = mps; 2535 2536 while (mp != NULL && mp->sb_prev != NULL && !mp->sb_prev->sb_eol) 2537 mp = mp->sb_prev; 2538 return mp; 2539 } 2540 2541 /* 2542 * Mark the last message chunk as finishing the line. 2543 */ 2544 void 2545 msg_sb_eol(void) 2546 { 2547 if (last_msgchunk != NULL) 2548 last_msgchunk->sb_eol = TRUE; 2549 } 2550 2551 /* 2552 * Display a screen line from previously displayed text at row "row". 2553 * Returns a pointer to the text for the next line (can be NULL). 2554 */ 2555 static msgchunk_T * 2556 disp_sb_line(int row, msgchunk_T *smp) 2557 { 2558 msgchunk_T *mp = smp; 2559 char_u *p; 2560 2561 for (;;) 2562 { 2563 msg_row = row; 2564 msg_col = mp->sb_msg_col; 2565 p = mp->sb_text; 2566 if (*p == '\n') // don't display the line break 2567 ++p; 2568 msg_puts_display(p, -1, mp->sb_attr, TRUE); 2569 if (mp->sb_eol || mp->sb_next == NULL) 2570 break; 2571 mp = mp->sb_next; 2572 } 2573 return mp->sb_next; 2574 } 2575 2576 /* 2577 * Output any postponed text for msg_puts_attr_len(). 2578 */ 2579 static void 2580 t_puts( 2581 int *t_col, 2582 char_u *t_s, 2583 char_u *s, 2584 int attr) 2585 { 2586 // output postponed text 2587 msg_didout = TRUE; // remember that line is not empty 2588 screen_puts_len(t_s, (int)(s - t_s), msg_row, msg_col, attr); 2589 msg_col += *t_col; 2590 *t_col = 0; 2591 // If the string starts with a composing character don't increment the 2592 // column position for it. 2593 if (enc_utf8 && utf_iscomposing(utf_ptr2char(t_s))) 2594 --msg_col; 2595 if (msg_col >= Columns) 2596 { 2597 msg_col = 0; 2598 ++msg_row; 2599 } 2600 } 2601 2602 /* 2603 * Returns TRUE when messages should be printed with mch_errmsg(). 2604 * This is used when there is no valid screen, so we can see error messages. 2605 * If termcap is not active, we may be writing in an alternate console 2606 * window, cursor positioning may not work correctly (window size may be 2607 * different, e.g. for Win32 console) or we just don't know where the 2608 * cursor is. 2609 */ 2610 int 2611 msg_use_printf(void) 2612 { 2613 return (!msg_check_screen() 2614 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 2615 # ifdef VIMDLL 2616 || (!gui.in_use && !termcap_active) 2617 # else 2618 || !termcap_active 2619 # endif 2620 #endif 2621 || (swapping_screen() && !termcap_active) 2622 ); 2623 } 2624 2625 /* 2626 * Print a message when there is no valid screen. 2627 */ 2628 static void 2629 msg_puts_printf(char_u *str, int maxlen) 2630 { 2631 char_u *s = str; 2632 char_u *buf = NULL; 2633 char_u *p = s; 2634 2635 #ifdef MSWIN 2636 if (!(silent_mode && p_verbose == 0)) 2637 mch_settmode(TMODE_COOK); // handle CR and NL correctly 2638 #endif 2639 while ((maxlen < 0 || (int)(s - str) < maxlen) && *s != NUL) 2640 { 2641 if (!(silent_mode && p_verbose == 0)) 2642 { 2643 // NL --> CR NL translation (for Unix, not for "--version") 2644 if (*s == NL) 2645 { 2646 int n = (int)(s - p); 2647 2648 buf = alloc(n + 3); 2649 if (buf != NULL) 2650 { 2651 memcpy(buf, p, n); 2652 if (!info_message) 2653 buf[n++] = CAR; 2654 buf[n++] = NL; 2655 buf[n++] = NUL; 2656 if (info_message) // informative message, not an error 2657 mch_msg((char *)buf); 2658 else 2659 mch_errmsg((char *)buf); 2660 vim_free(buf); 2661 } 2662 p = s + 1; 2663 } 2664 } 2665 2666 // primitive way to compute the current column 2667 #ifdef FEAT_RIGHTLEFT 2668 if (cmdmsg_rl) 2669 { 2670 if (*s == CAR || *s == NL) 2671 msg_col = Columns - 1; 2672 else 2673 --msg_col; 2674 } 2675 else 2676 #endif 2677 { 2678 if (*s == CAR || *s == NL) 2679 msg_col = 0; 2680 else 2681 ++msg_col; 2682 } 2683 ++s; 2684 } 2685 2686 if (*p != NUL && !(silent_mode && p_verbose == 0)) 2687 { 2688 int c = -1; 2689 2690 if (maxlen > 0 && STRLEN(p) > (size_t)maxlen) 2691 { 2692 c = p[maxlen]; 2693 p[maxlen] = 0; 2694 } 2695 if (info_message) 2696 mch_msg((char *)p); 2697 else 2698 mch_errmsg((char *)p); 2699 if (c != -1) 2700 p[maxlen] = c; 2701 } 2702 2703 msg_didout = TRUE; // assume that line is not empty 2704 2705 #ifdef MSWIN 2706 if (!(silent_mode && p_verbose == 0)) 2707 mch_settmode(TMODE_RAW); 2708 #endif 2709 } 2710 2711 /* 2712 * Show the more-prompt and handle the user response. 2713 * This takes care of scrolling back and displaying previously displayed text. 2714 * When at hit-enter prompt "typed_char" is the already typed character, 2715 * otherwise it's NUL. 2716 * Returns TRUE when jumping ahead to "confirm_msg_tail". 2717 */ 2718 static int 2719 do_more_prompt(int typed_char) 2720 { 2721 static int entered = FALSE; 2722 int used_typed_char = typed_char; 2723 int oldState = State; 2724 int c; 2725 #ifdef FEAT_CON_DIALOG 2726 int retval = FALSE; 2727 #endif 2728 int toscroll; 2729 msgchunk_T *mp_last = NULL; 2730 msgchunk_T *mp; 2731 int i; 2732 2733 // We get called recursively when a timer callback outputs a message. In 2734 // that case don't show another prompt. Also when at the hit-Enter prompt 2735 // and nothing was typed. 2736 if (entered || (State == HITRETURN && typed_char == 0)) 2737 return FALSE; 2738 entered = TRUE; 2739 2740 if (typed_char == 'G') 2741 { 2742 // "g<": Find first line on the last page. 2743 mp_last = msg_sb_start(last_msgchunk); 2744 for (i = 0; i < Rows - 2 && mp_last != NULL 2745 && mp_last->sb_prev != NULL; ++i) 2746 mp_last = msg_sb_start(mp_last->sb_prev); 2747 } 2748 2749 State = ASKMORE; 2750 setmouse(); 2751 if (typed_char == NUL) 2752 msg_moremsg(FALSE); 2753 for (;;) 2754 { 2755 /* 2756 * Get a typed character directly from the user. 2757 */ 2758 if (used_typed_char != NUL) 2759 { 2760 c = used_typed_char; // was typed at hit-enter prompt 2761 used_typed_char = NUL; 2762 } 2763 else 2764 c = get_keystroke(); 2765 2766 #if defined(FEAT_MENU) && defined(FEAT_GUI) 2767 if (c == K_MENU) 2768 { 2769 int idx = get_menu_index(current_menu, ASKMORE); 2770 2771 // Used a menu. If it starts with CTRL-Y, it must 2772 // be a "Copy" for the clipboard. Otherwise 2773 // assume that we end 2774 if (idx == MENU_INDEX_INVALID) 2775 continue; 2776 c = *current_menu->strings[idx]; 2777 if (c != NUL && current_menu->strings[idx][1] != NUL) 2778 ins_typebuf(current_menu->strings[idx] + 1, 2779 current_menu->noremap[idx], 0, TRUE, 2780 current_menu->silent[idx]); 2781 } 2782 #endif 2783 2784 toscroll = 0; 2785 switch (c) 2786 { 2787 case BS: // scroll one line back 2788 case K_BS: 2789 case 'k': 2790 case K_UP: 2791 toscroll = -1; 2792 break; 2793 2794 case CAR: // one extra line 2795 case NL: 2796 case 'j': 2797 case K_DOWN: 2798 toscroll = 1; 2799 break; 2800 2801 case 'u': // Up half a page 2802 toscroll = -(Rows / 2); 2803 break; 2804 2805 case 'd': // Down half a page 2806 toscroll = Rows / 2; 2807 break; 2808 2809 case 'b': // one page back 2810 case K_PAGEUP: 2811 toscroll = -(Rows - 1); 2812 break; 2813 2814 case ' ': // one extra page 2815 case 'f': 2816 case K_PAGEDOWN: 2817 case K_LEFTMOUSE: 2818 toscroll = Rows - 1; 2819 break; 2820 2821 case 'g': // all the way back to the start 2822 toscroll = -999999; 2823 break; 2824 2825 case 'G': // all the way to the end 2826 toscroll = 999999; 2827 lines_left = 999999; 2828 break; 2829 2830 case ':': // start new command line 2831 #ifdef FEAT_CON_DIALOG 2832 if (!confirm_msg_used) 2833 #endif 2834 { 2835 // Since got_int is set all typeahead will be flushed, but we 2836 // want to keep this ':', remember that in a special way. 2837 typeahead_noflush(':'); 2838 #ifdef FEAT_TERMINAL 2839 skip_term_loop = TRUE; 2840 #endif 2841 cmdline_row = Rows - 1; // put ':' on this line 2842 skip_redraw = TRUE; // skip redraw once 2843 need_wait_return = FALSE; // don't wait in main() 2844 } 2845 // FALLTHROUGH 2846 case 'q': // quit 2847 case Ctrl_C: 2848 case ESC: 2849 #ifdef FEAT_CON_DIALOG 2850 if (confirm_msg_used) 2851 { 2852 // Jump to the choices of the dialog. 2853 retval = TRUE; 2854 } 2855 else 2856 #endif 2857 { 2858 got_int = TRUE; 2859 quit_more = TRUE; 2860 } 2861 // When there is some more output (wrapping line) display that 2862 // without another prompt. 2863 lines_left = Rows - 1; 2864 break; 2865 2866 #ifdef FEAT_CLIPBOARD 2867 case Ctrl_Y: 2868 // Strange way to allow copying (yanking) a modeless 2869 // selection at the more prompt. Use CTRL-Y, 2870 // because the same is used in Cmdline-mode and at the 2871 // hit-enter prompt. However, scrolling one line up 2872 // might be expected... 2873 if (clip_star.state == SELECT_DONE) 2874 clip_copy_modeless_selection(TRUE); 2875 continue; 2876 #endif 2877 default: // no valid response 2878 msg_moremsg(TRUE); 2879 continue; 2880 } 2881 2882 if (toscroll != 0) 2883 { 2884 if (toscroll < 0) 2885 { 2886 // go to start of last line 2887 if (mp_last == NULL) 2888 mp = msg_sb_start(last_msgchunk); 2889 else if (mp_last->sb_prev != NULL) 2890 mp = msg_sb_start(mp_last->sb_prev); 2891 else 2892 mp = NULL; 2893 2894 // go to start of line at top of the screen 2895 for (i = 0; i < Rows - 2 && mp != NULL && mp->sb_prev != NULL; 2896 ++i) 2897 mp = msg_sb_start(mp->sb_prev); 2898 2899 if (mp != NULL && mp->sb_prev != NULL) 2900 { 2901 // Find line to be displayed at top. 2902 for (i = 0; i > toscroll; --i) 2903 { 2904 if (mp == NULL || mp->sb_prev == NULL) 2905 break; 2906 mp = msg_sb_start(mp->sb_prev); 2907 if (mp_last == NULL) 2908 mp_last = msg_sb_start(last_msgchunk); 2909 else 2910 mp_last = msg_sb_start(mp_last->sb_prev); 2911 } 2912 2913 if (toscroll == -1 && screen_ins_lines(0, 0, 1, 2914 (int)Rows, 0, NULL) == OK) 2915 { 2916 // display line at top 2917 (void)disp_sb_line(0, mp); 2918 } 2919 else 2920 { 2921 // redisplay all lines 2922 screenclear(); 2923 for (i = 0; mp != NULL && i < Rows - 1; ++i) 2924 { 2925 mp = disp_sb_line(i, mp); 2926 ++msg_scrolled; 2927 } 2928 } 2929 toscroll = 0; 2930 } 2931 } 2932 else 2933 { 2934 // First display any text that we scrolled back. 2935 while (toscroll > 0 && mp_last != NULL) 2936 { 2937 // scroll up, display line at bottom 2938 msg_scroll_up(); 2939 inc_msg_scrolled(); 2940 screen_fill((int)Rows - 2, (int)Rows - 1, 0, 2941 (int)Columns, ' ', ' ', 0); 2942 mp_last = disp_sb_line((int)Rows - 2, mp_last); 2943 --toscroll; 2944 } 2945 } 2946 2947 if (toscroll <= 0) 2948 { 2949 // displayed the requested text, more prompt again 2950 screen_fill((int)Rows - 1, (int)Rows, 0, 2951 (int)Columns, ' ', ' ', 0); 2952 msg_moremsg(FALSE); 2953 continue; 2954 } 2955 2956 // display more text, return to caller 2957 lines_left = toscroll; 2958 } 2959 2960 break; 2961 } 2962 2963 // clear the --more-- message 2964 screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); 2965 State = oldState; 2966 setmouse(); 2967 if (quit_more) 2968 { 2969 msg_row = Rows - 1; 2970 msg_col = 0; 2971 } 2972 #ifdef FEAT_RIGHTLEFT 2973 else if (cmdmsg_rl) 2974 msg_col = Columns - 1; 2975 #endif 2976 2977 entered = FALSE; 2978 #ifdef FEAT_CON_DIALOG 2979 return retval; 2980 #else 2981 return FALSE; 2982 #endif 2983 } 2984 2985 #if defined(USE_MCH_ERRMSG) || defined(PROTO) 2986 2987 #ifdef mch_errmsg 2988 # undef mch_errmsg 2989 #endif 2990 #ifdef mch_msg 2991 # undef mch_msg 2992 #endif 2993 2994 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 2995 static void 2996 mch_errmsg_c(char *str) 2997 { 2998 int len = (int)STRLEN(str); 2999 DWORD nwrite = 0; 3000 DWORD mode = 0; 3001 HANDLE h = GetStdHandle(STD_ERROR_HANDLE); 3002 3003 if (GetConsoleMode(h, &mode) && enc_codepage >= 0 3004 && (int)GetConsoleCP() != enc_codepage) 3005 { 3006 WCHAR *w = enc_to_utf16((char_u *)str, &len); 3007 3008 WriteConsoleW(h, w, len, &nwrite, NULL); 3009 vim_free(w); 3010 } 3011 else 3012 { 3013 fprintf(stderr, "%s", str); 3014 } 3015 } 3016 #endif 3017 3018 /* 3019 * Give an error message. To be used when the screen hasn't been initialized 3020 * yet. When stderr can't be used, collect error messages until the GUI has 3021 * started and they can be displayed in a message box. 3022 */ 3023 void 3024 mch_errmsg(char *str) 3025 { 3026 #if !defined(MSWIN) || defined(FEAT_GUI_MSWIN) 3027 int len; 3028 #endif 3029 3030 #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI) && !defined(VIMDLL) 3031 // On Unix use stderr if it's a tty. 3032 // When not going to start the GUI also use stderr. 3033 // On Mac, when started from Finder, stderr is the console. 3034 if ( 3035 # ifdef UNIX 3036 # ifdef MACOS_X 3037 (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0) 3038 # else 3039 isatty(2) 3040 # endif 3041 # ifdef FEAT_GUI 3042 || 3043 # endif 3044 # endif 3045 # ifdef FEAT_GUI 3046 !(gui.in_use || gui.starting) 3047 # endif 3048 ) 3049 { 3050 fprintf(stderr, "%s", str); 3051 return; 3052 } 3053 #endif 3054 3055 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 3056 # ifdef VIMDLL 3057 if (!(gui.in_use || gui.starting)) 3058 # endif 3059 { 3060 mch_errmsg_c(str); 3061 return; 3062 } 3063 #endif 3064 3065 #if !defined(MSWIN) || defined(FEAT_GUI_MSWIN) 3066 // avoid a delay for a message that isn't there 3067 emsg_on_display = FALSE; 3068 3069 len = (int)STRLEN(str) + 1; 3070 if (error_ga.ga_growsize == 0) 3071 { 3072 error_ga.ga_growsize = 80; 3073 error_ga.ga_itemsize = 1; 3074 } 3075 if (ga_grow(&error_ga, len) == OK) 3076 { 3077 mch_memmove((char_u *)error_ga.ga_data + error_ga.ga_len, 3078 (char_u *)str, len); 3079 # ifdef UNIX 3080 // remove CR characters, they are displayed 3081 { 3082 char_u *p; 3083 3084 p = (char_u *)error_ga.ga_data + error_ga.ga_len; 3085 for (;;) 3086 { 3087 p = vim_strchr(p, '\r'); 3088 if (p == NULL) 3089 break; 3090 *p = ' '; 3091 } 3092 } 3093 # endif 3094 --len; // don't count the NUL at the end 3095 error_ga.ga_len += len; 3096 } 3097 #endif 3098 } 3099 3100 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 3101 static void 3102 mch_msg_c(char *str) 3103 { 3104 int len = (int)STRLEN(str); 3105 DWORD nwrite = 0; 3106 DWORD mode; 3107 HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); 3108 3109 3110 if (GetConsoleMode(h, &mode) && enc_codepage >= 0 3111 && (int)GetConsoleCP() != enc_codepage) 3112 { 3113 WCHAR *w = enc_to_utf16((char_u *)str, &len); 3114 3115 WriteConsoleW(h, w, len, &nwrite, NULL); 3116 vim_free(w); 3117 } 3118 else 3119 { 3120 printf("%s", str); 3121 } 3122 } 3123 #endif 3124 3125 /* 3126 * Give a message. To be used when the screen hasn't been initialized yet. 3127 * When there is no tty, collect messages until the GUI has started and they 3128 * can be displayed in a message box. 3129 */ 3130 void 3131 mch_msg(char *str) 3132 { 3133 #if (defined(UNIX) || defined(FEAT_GUI)) && !defined(ALWAYS_USE_GUI) && !defined(VIMDLL) 3134 // On Unix use stdout if we have a tty. This allows "vim -h | more" and 3135 // uses mch_errmsg() when started from the desktop. 3136 // When not going to start the GUI also use stdout. 3137 // On Mac, when started from Finder, stderr is the console. 3138 if ( 3139 # ifdef UNIX 3140 # ifdef MACOS_X 3141 (isatty(2) && strcmp("/dev/console", ttyname(2)) != 0) 3142 # else 3143 isatty(2) 3144 # endif 3145 # ifdef FEAT_GUI 3146 || 3147 # endif 3148 # endif 3149 # ifdef FEAT_GUI 3150 !(gui.in_use || gui.starting) 3151 # endif 3152 ) 3153 { 3154 printf("%s", str); 3155 return; 3156 } 3157 #endif 3158 3159 #if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(VIMDLL)) 3160 # ifdef VIMDLL 3161 if (!(gui.in_use || gui.starting)) 3162 # endif 3163 { 3164 mch_msg_c(str); 3165 return; 3166 } 3167 #endif 3168 #if !defined(MSWIN) || defined(FEAT_GUI_MSWIN) 3169 mch_errmsg(str); 3170 #endif 3171 } 3172 #endif // USE_MCH_ERRMSG 3173 3174 /* 3175 * Put a character on the screen at the current message position and advance 3176 * to the next position. Only for printable ASCII! 3177 */ 3178 static void 3179 msg_screen_putchar(int c, int attr) 3180 { 3181 msg_didout = TRUE; // remember that line is not empty 3182 screen_putchar(c, msg_row, msg_col, attr); 3183 #ifdef FEAT_RIGHTLEFT 3184 if (cmdmsg_rl) 3185 { 3186 if (--msg_col == 0) 3187 { 3188 msg_col = Columns; 3189 ++msg_row; 3190 } 3191 } 3192 else 3193 #endif 3194 { 3195 if (++msg_col >= Columns) 3196 { 3197 msg_col = 0; 3198 ++msg_row; 3199 } 3200 } 3201 } 3202 3203 static void 3204 msg_moremsg(int full) 3205 { 3206 int attr; 3207 char_u *s = (char_u *)_("-- More --"); 3208 3209 attr = HL_ATTR(HLF_M); 3210 screen_puts(s, (int)Rows - 1, 0, attr); 3211 if (full) 3212 screen_puts((char_u *) 3213 _(" SPACE/d/j: screen/page/line down, b/u/k: up, q: quit "), 3214 (int)Rows - 1, vim_strsize(s), attr); 3215 } 3216 3217 /* 3218 * Repeat the message for the current mode: ASKMORE, EXTERNCMD, CONFIRM or 3219 * exmode_active. 3220 */ 3221 void 3222 repeat_message(void) 3223 { 3224 if (State == ASKMORE) 3225 { 3226 msg_moremsg(TRUE); // display --more-- message again 3227 msg_row = Rows - 1; 3228 } 3229 #ifdef FEAT_CON_DIALOG 3230 else if (State == CONFIRM) 3231 { 3232 display_confirm_msg(); // display ":confirm" message again 3233 msg_row = Rows - 1; 3234 } 3235 #endif 3236 else if (State == EXTERNCMD) 3237 { 3238 windgoto(msg_row, msg_col); // put cursor back 3239 } 3240 else if (State == HITRETURN || State == SETWSIZE) 3241 { 3242 if (msg_row == Rows - 1) 3243 { 3244 // Avoid drawing the "hit-enter" prompt below the previous one, 3245 // overwrite it. Esp. useful when regaining focus and a 3246 // FocusGained autocmd exists but didn't draw anything. 3247 msg_didout = FALSE; 3248 msg_col = 0; 3249 msg_clr_eos(); 3250 } 3251 hit_return_msg(); 3252 msg_row = Rows - 1; 3253 } 3254 } 3255 3256 /* 3257 * msg_check_screen - check if the screen is initialized. 3258 * Also check msg_row and msg_col, if they are too big it may cause a crash. 3259 * While starting the GUI the terminal codes will be set for the GUI, but the 3260 * output goes to the terminal. Don't use the terminal codes then. 3261 */ 3262 static int 3263 msg_check_screen(void) 3264 { 3265 if (!full_screen || !screen_valid(FALSE)) 3266 return FALSE; 3267 3268 if (msg_row >= Rows) 3269 msg_row = Rows - 1; 3270 if (msg_col >= Columns) 3271 msg_col = Columns - 1; 3272 return TRUE; 3273 } 3274 3275 /* 3276 * Clear from current message position to end of screen. 3277 * Skip this when ":silent" was used, no need to clear for redirection. 3278 */ 3279 void 3280 msg_clr_eos(void) 3281 { 3282 if (msg_silent == 0) 3283 msg_clr_eos_force(); 3284 } 3285 3286 /* 3287 * Clear from current message position to end of screen. 3288 * Note: msg_col is not updated, so we remember the end of the message 3289 * for msg_check(). 3290 */ 3291 void 3292 msg_clr_eos_force(void) 3293 { 3294 if (msg_use_printf()) 3295 { 3296 if (full_screen) // only when termcap codes are valid 3297 { 3298 if (*T_CD) 3299 out_str(T_CD); // clear to end of display 3300 else if (*T_CE) 3301 out_str(T_CE); // clear to end of line 3302 } 3303 } 3304 else 3305 { 3306 #ifdef FEAT_RIGHTLEFT 3307 if (cmdmsg_rl) 3308 { 3309 screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0); 3310 screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); 3311 } 3312 else 3313 #endif 3314 { 3315 screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, 3316 ' ', ' ', 0); 3317 screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); 3318 } 3319 } 3320 } 3321 3322 /* 3323 * Clear the command line. 3324 */ 3325 void 3326 msg_clr_cmdline(void) 3327 { 3328 msg_row = cmdline_row; 3329 msg_col = 0; 3330 msg_clr_eos_force(); 3331 } 3332 3333 /* 3334 * end putting a message on the screen 3335 * call wait_return if the message does not fit in the available space 3336 * return TRUE if wait_return not called. 3337 */ 3338 int 3339 msg_end(void) 3340 { 3341 /* 3342 * If the string is larger than the window, 3343 * or the ruler option is set and we run into it, 3344 * we have to redraw the window. 3345 * Do not do this if we are abandoning the file or editing the command line. 3346 */ 3347 if (!exiting && need_wait_return && !(State & CMDLINE)) 3348 { 3349 wait_return(FALSE); 3350 return FALSE; 3351 } 3352 out_flush(); 3353 return TRUE; 3354 } 3355 3356 /* 3357 * If the written message runs into the shown command or ruler, we have to 3358 * wait for hit-return and redraw the window later. 3359 */ 3360 void 3361 msg_check(void) 3362 { 3363 if (msg_row == Rows - 1 && msg_col >= sc_col) 3364 { 3365 need_wait_return = TRUE; 3366 redraw_cmdline = TRUE; 3367 } 3368 } 3369 3370 /* 3371 * May write a string to the redirection file. 3372 * When "maxlen" is -1 write the whole string, otherwise up to "maxlen" bytes. 3373 */ 3374 static void 3375 redir_write(char_u *str, int maxlen) 3376 { 3377 char_u *s = str; 3378 static int cur_col = 0; 3379 3380 // Don't do anything for displaying prompts and the like. 3381 if (redir_off) 3382 return; 3383 3384 // If 'verbosefile' is set prepare for writing in that file. 3385 if (*p_vfile != NUL && verbose_fd == NULL) 3386 verbose_open(); 3387 3388 if (redirecting()) 3389 { 3390 // If the string doesn't start with CR or NL, go to msg_col 3391 if (*s != '\n' && *s != '\r') 3392 { 3393 while (cur_col < msg_col) 3394 { 3395 #ifdef FEAT_EVAL 3396 if (redir_execute) 3397 execute_redir_str((char_u *)" ", -1); 3398 else if (redir_reg) 3399 write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE); 3400 else if (redir_vname) 3401 var_redir_str((char_u *)" ", -1); 3402 else 3403 #endif 3404 if (redir_fd != NULL) 3405 fputs(" ", redir_fd); 3406 if (verbose_fd != NULL) 3407 fputs(" ", verbose_fd); 3408 ++cur_col; 3409 } 3410 } 3411 3412 #ifdef FEAT_EVAL 3413 if (redir_execute) 3414 execute_redir_str(s, maxlen); 3415 else if (redir_reg) 3416 write_reg_contents(redir_reg, s, maxlen, TRUE); 3417 else if (redir_vname) 3418 var_redir_str(s, maxlen); 3419 #endif 3420 3421 // Write and adjust the current column. 3422 while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) 3423 { 3424 #ifdef FEAT_EVAL 3425 if (!redir_reg && !redir_vname && !redir_execute) 3426 #endif 3427 if (redir_fd != NULL) 3428 putc(*s, redir_fd); 3429 if (verbose_fd != NULL) 3430 putc(*s, verbose_fd); 3431 if (*s == '\r' || *s == '\n') 3432 cur_col = 0; 3433 else if (*s == '\t') 3434 cur_col += (8 - cur_col % 8); 3435 else 3436 ++cur_col; 3437 ++s; 3438 } 3439 3440 if (msg_silent != 0) // should update msg_col 3441 msg_col = cur_col; 3442 } 3443 } 3444 3445 int 3446 redirecting(void) 3447 { 3448 return redir_fd != NULL || *p_vfile != NUL 3449 #ifdef FEAT_EVAL 3450 || redir_reg || redir_vname || redir_execute 3451 #endif 3452 ; 3453 } 3454 3455 /* 3456 * Before giving verbose message. 3457 * Must always be called paired with verbose_leave()! 3458 */ 3459 void 3460 verbose_enter(void) 3461 { 3462 if (*p_vfile != NUL) 3463 ++msg_silent; 3464 } 3465 3466 /* 3467 * After giving verbose message. 3468 * Must always be called paired with verbose_enter()! 3469 */ 3470 void 3471 verbose_leave(void) 3472 { 3473 if (*p_vfile != NUL) 3474 if (--msg_silent < 0) 3475 msg_silent = 0; 3476 } 3477 3478 /* 3479 * Like verbose_enter() and set msg_scroll when displaying the message. 3480 */ 3481 void 3482 verbose_enter_scroll(void) 3483 { 3484 if (*p_vfile != NUL) 3485 ++msg_silent; 3486 else 3487 // always scroll up, don't overwrite 3488 msg_scroll = TRUE; 3489 } 3490 3491 /* 3492 * Like verbose_leave() and set cmdline_row when displaying the message. 3493 */ 3494 void 3495 verbose_leave_scroll(void) 3496 { 3497 if (*p_vfile != NUL) 3498 { 3499 if (--msg_silent < 0) 3500 msg_silent = 0; 3501 } 3502 else 3503 cmdline_row = msg_row; 3504 } 3505 3506 /* 3507 * Called when 'verbosefile' is set: stop writing to the file. 3508 */ 3509 void 3510 verbose_stop(void) 3511 { 3512 if (verbose_fd != NULL) 3513 { 3514 fclose(verbose_fd); 3515 verbose_fd = NULL; 3516 } 3517 verbose_did_open = FALSE; 3518 } 3519 3520 /* 3521 * Open the file 'verbosefile'. 3522 * Return FAIL or OK. 3523 */ 3524 int 3525 verbose_open(void) 3526 { 3527 if (verbose_fd == NULL && !verbose_did_open) 3528 { 3529 // Only give the error message once. 3530 verbose_did_open = TRUE; 3531 3532 verbose_fd = mch_fopen((char *)p_vfile, "a"); 3533 if (verbose_fd == NULL) 3534 { 3535 semsg(_(e_notopen), p_vfile); 3536 return FAIL; 3537 } 3538 } 3539 return OK; 3540 } 3541 3542 /* 3543 * Give a warning message (for searching). 3544 * Use 'w' highlighting and may repeat the message after redrawing 3545 */ 3546 void 3547 give_warning(char_u *message, int hl) 3548 { 3549 // Don't do this for ":silent". 3550 if (msg_silent != 0) 3551 return; 3552 3553 // Don't want a hit-enter prompt here. 3554 ++no_wait_return; 3555 3556 #ifdef FEAT_EVAL 3557 set_vim_var_string(VV_WARNINGMSG, message, -1); 3558 #endif 3559 VIM_CLEAR(keep_msg); 3560 if (hl) 3561 keep_msg_attr = HL_ATTR(HLF_W); 3562 else 3563 keep_msg_attr = 0; 3564 if (msg_attr((char *)message, keep_msg_attr) && msg_scrolled == 0) 3565 set_keep_msg(message, keep_msg_attr); 3566 msg_didout = FALSE; // overwrite this message 3567 msg_nowait = TRUE; // don't wait for this message 3568 msg_col = 0; 3569 3570 --no_wait_return; 3571 } 3572 3573 #if defined(FEAT_EVAL) || defined(PROTO) 3574 void 3575 give_warning2(char_u *message, char_u *a1, int hl) 3576 { 3577 if (IObuff == NULL) 3578 { 3579 // Very early in initialisation and already something wrong, just give 3580 // the raw message so the user at least gets a hint. 3581 give_warning((char_u *)message, hl); 3582 } 3583 else 3584 { 3585 vim_snprintf((char *)IObuff, IOSIZE, (char *)message, a1); 3586 give_warning(IObuff, hl); 3587 } 3588 } 3589 #endif 3590 3591 /* 3592 * Advance msg cursor to column "col". 3593 */ 3594 void 3595 msg_advance(int col) 3596 { 3597 if (msg_silent != 0) // nothing to advance to 3598 { 3599 msg_col = col; // for redirection, may fill it up later 3600 return; 3601 } 3602 if (col >= Columns) // not enough room 3603 col = Columns - 1; 3604 #ifdef FEAT_RIGHTLEFT 3605 if (cmdmsg_rl) 3606 while (msg_col > Columns - col) 3607 msg_putchar(' '); 3608 else 3609 #endif 3610 while (msg_col < col) 3611 msg_putchar(' '); 3612 } 3613 3614 #if defined(FEAT_CON_DIALOG) || defined(PROTO) 3615 /* 3616 * Used for "confirm()" function, and the :confirm command prefix. 3617 * Versions which haven't got flexible dialogs yet, and console 3618 * versions, get this generic handler which uses the command line. 3619 * 3620 * type = one of: 3621 * VIM_QUESTION, VIM_INFO, VIM_WARNING, VIM_ERROR or VIM_GENERIC 3622 * title = title string (can be NULL for default) 3623 * (neither used in console dialogs at the moment) 3624 * 3625 * Format of the "buttons" string: 3626 * "Button1Name\nButton2Name\nButton3Name" 3627 * The first button should normally be the default/accept 3628 * The second button should be the 'Cancel' button 3629 * Other buttons- use your imagination! 3630 * A '&' in a button name becomes a shortcut, so each '&' should be before a 3631 * different letter. 3632 */ 3633 int 3634 do_dialog( 3635 int type UNUSED, 3636 char_u *title UNUSED, 3637 char_u *message, 3638 char_u *buttons, 3639 int dfltbutton, 3640 char_u *textfield UNUSED, // IObuff for inputdialog(), NULL 3641 // otherwise 3642 int ex_cmd) // when TRUE pressing : accepts default and starts 3643 // Ex command 3644 { 3645 int oldState; 3646 int retval = 0; 3647 char_u *hotkeys; 3648 int c; 3649 int i; 3650 3651 #ifndef NO_CONSOLE 3652 // Don't output anything in silent mode ("ex -s") 3653 if (silent_mode) 3654 return dfltbutton; // return default option 3655 #endif 3656 3657 #ifdef FEAT_GUI_DIALOG 3658 // When GUI is running and 'c' not in 'guioptions', use the GUI dialog 3659 if (gui.in_use && vim_strchr(p_go, GO_CONDIALOG) == NULL) 3660 { 3661 c = gui_mch_dialog(type, title, message, buttons, dfltbutton, 3662 textfield, ex_cmd); 3663 // avoid a hit-enter prompt without clearing the cmdline 3664 need_wait_return = FALSE; 3665 emsg_on_display = FALSE; 3666 cmdline_row = msg_row; 3667 3668 // Flush output to avoid that further messages and redrawing is done 3669 // in the wrong order. 3670 out_flush(); 3671 gui_mch_update(); 3672 3673 return c; 3674 } 3675 #endif 3676 3677 oldState = State; 3678 State = CONFIRM; 3679 setmouse(); 3680 3681 /* 3682 * Since we wait for a keypress, don't make the 3683 * user press RETURN as well afterwards. 3684 */ 3685 ++no_wait_return; 3686 hotkeys = msg_show_console_dialog(message, buttons, dfltbutton); 3687 3688 if (hotkeys != NULL) 3689 { 3690 for (;;) 3691 { 3692 // Get a typed character directly from the user. 3693 c = get_keystroke(); 3694 switch (c) 3695 { 3696 case CAR: // User accepts default option 3697 case NL: 3698 retval = dfltbutton; 3699 break; 3700 case Ctrl_C: // User aborts/cancels 3701 case ESC: 3702 retval = 0; 3703 break; 3704 default: // Could be a hotkey? 3705 if (c < 0) // special keys are ignored here 3706 continue; 3707 if (c == ':' && ex_cmd) 3708 { 3709 retval = dfltbutton; 3710 ins_char_typebuf(':'); 3711 break; 3712 } 3713 3714 // Make the character lowercase, as chars in "hotkeys" are. 3715 c = MB_TOLOWER(c); 3716 retval = 1; 3717 for (i = 0; hotkeys[i]; ++i) 3718 { 3719 if (has_mbyte) 3720 { 3721 if ((*mb_ptr2char)(hotkeys + i) == c) 3722 break; 3723 i += (*mb_ptr2len)(hotkeys + i) - 1; 3724 } 3725 else 3726 if (hotkeys[i] == c) 3727 break; 3728 ++retval; 3729 } 3730 if (hotkeys[i]) 3731 break; 3732 // No hotkey match, so keep waiting 3733 continue; 3734 } 3735 break; 3736 } 3737 3738 vim_free(hotkeys); 3739 } 3740 3741 State = oldState; 3742 setmouse(); 3743 --no_wait_return; 3744 msg_end_prompt(); 3745 3746 return retval; 3747 } 3748 3749 /* 3750 * Copy one character from "*from" to "*to", taking care of multi-byte 3751 * characters. Return the length of the character in bytes. 3752 */ 3753 static int 3754 copy_char( 3755 char_u *from, 3756 char_u *to, 3757 int lowercase) // make character lower case 3758 { 3759 int len; 3760 int c; 3761 3762 if (has_mbyte) 3763 { 3764 if (lowercase) 3765 { 3766 c = MB_TOLOWER((*mb_ptr2char)(from)); 3767 return (*mb_char2bytes)(c, to); 3768 } 3769 else 3770 { 3771 len = (*mb_ptr2len)(from); 3772 mch_memmove(to, from, (size_t)len); 3773 return len; 3774 } 3775 } 3776 else 3777 { 3778 if (lowercase) 3779 *to = (char_u)TOLOWER_LOC(*from); 3780 else 3781 *to = *from; 3782 return 1; 3783 } 3784 } 3785 3786 /* 3787 * Format the dialog string, and display it at the bottom of 3788 * the screen. Return a string of hotkey chars (if defined) for 3789 * each 'button'. If a button has no hotkey defined, the first character of 3790 * the button is used. 3791 * The hotkeys can be multi-byte characters, but without combining chars. 3792 * 3793 * Returns an allocated string with hotkeys, or NULL for error. 3794 */ 3795 static char_u * 3796 msg_show_console_dialog( 3797 char_u *message, 3798 char_u *buttons, 3799 int dfltbutton) 3800 { 3801 int len = 0; 3802 #define HOTK_LEN (has_mbyte ? MB_MAXBYTES : 1) 3803 int lenhotkey = HOTK_LEN; // count first button 3804 char_u *hotk = NULL; 3805 char_u *msgp = NULL; 3806 char_u *hotkp = NULL; 3807 char_u *r; 3808 int copy; 3809 #define HAS_HOTKEY_LEN 30 3810 char_u has_hotkey[HAS_HOTKEY_LEN]; 3811 int first_hotkey = FALSE; // first char of button is hotkey 3812 int idx; 3813 3814 has_hotkey[0] = FALSE; 3815 3816 /* 3817 * First loop: compute the size of memory to allocate. 3818 * Second loop: copy to the allocated memory. 3819 */ 3820 for (copy = 0; copy <= 1; ++copy) 3821 { 3822 r = buttons; 3823 idx = 0; 3824 while (*r) 3825 { 3826 if (*r == DLG_BUTTON_SEP) 3827 { 3828 if (copy) 3829 { 3830 *msgp++ = ','; 3831 *msgp++ = ' '; // '\n' -> ', ' 3832 3833 // advance to next hotkey and set default hotkey 3834 if (has_mbyte) 3835 hotkp += STRLEN(hotkp); 3836 else 3837 ++hotkp; 3838 hotkp[copy_char(r + 1, hotkp, TRUE)] = NUL; 3839 if (dfltbutton) 3840 --dfltbutton; 3841 3842 // If no hotkey is specified first char is used. 3843 if (idx < HAS_HOTKEY_LEN - 1 && !has_hotkey[++idx]) 3844 first_hotkey = TRUE; 3845 } 3846 else 3847 { 3848 len += 3; // '\n' -> ', '; 'x' -> '(x)' 3849 lenhotkey += HOTK_LEN; // each button needs a hotkey 3850 if (idx < HAS_HOTKEY_LEN - 1) 3851 has_hotkey[++idx] = FALSE; 3852 } 3853 } 3854 else if (*r == DLG_HOTKEY_CHAR || first_hotkey) 3855 { 3856 if (*r == DLG_HOTKEY_CHAR) 3857 ++r; 3858 first_hotkey = FALSE; 3859 if (copy) 3860 { 3861 if (*r == DLG_HOTKEY_CHAR) // '&&a' -> '&a' 3862 *msgp++ = *r; 3863 else 3864 { 3865 // '&a' -> '[a]' 3866 *msgp++ = (dfltbutton == 1) ? '[' : '('; 3867 msgp += copy_char(r, msgp, FALSE); 3868 *msgp++ = (dfltbutton == 1) ? ']' : ')'; 3869 3870 // redefine hotkey 3871 hotkp[copy_char(r, hotkp, TRUE)] = NUL; 3872 } 3873 } 3874 else 3875 { 3876 ++len; // '&a' -> '[a]' 3877 if (idx < HAS_HOTKEY_LEN - 1) 3878 has_hotkey[idx] = TRUE; 3879 } 3880 } 3881 else 3882 { 3883 // everything else copy literally 3884 if (copy) 3885 msgp += copy_char(r, msgp, FALSE); 3886 } 3887 3888 // advance to the next character 3889 MB_PTR_ADV(r); 3890 } 3891 3892 if (copy) 3893 { 3894 *msgp++ = ':'; 3895 *msgp++ = ' '; 3896 *msgp = NUL; 3897 } 3898 else 3899 { 3900 len += (int)(STRLEN(message) 3901 + 2 // for the NL's 3902 + STRLEN(buttons) 3903 + 3); // for the ": " and NUL 3904 lenhotkey++; // for the NUL 3905 3906 // If no hotkey is specified first char is used. 3907 if (!has_hotkey[0]) 3908 { 3909 first_hotkey = TRUE; 3910 len += 2; // "x" -> "[x]" 3911 } 3912 3913 /* 3914 * Now allocate and load the strings 3915 */ 3916 vim_free(confirm_msg); 3917 confirm_msg = alloc(len); 3918 if (confirm_msg == NULL) 3919 return NULL; 3920 *confirm_msg = NUL; 3921 hotk = alloc(lenhotkey); 3922 if (hotk == NULL) 3923 return NULL; 3924 3925 *confirm_msg = '\n'; 3926 STRCPY(confirm_msg + 1, message); 3927 3928 msgp = confirm_msg + 1 + STRLEN(message); 3929 hotkp = hotk; 3930 3931 // Define first default hotkey. Keep the hotkey string NUL 3932 // terminated to avoid reading past the end. 3933 hotkp[copy_char(buttons, hotkp, TRUE)] = NUL; 3934 3935 // Remember where the choices start, displaying starts here when 3936 // "hotkp" typed at the more prompt. 3937 confirm_msg_tail = msgp; 3938 *msgp++ = '\n'; 3939 } 3940 } 3941 3942 display_confirm_msg(); 3943 return hotk; 3944 } 3945 3946 /* 3947 * Display the ":confirm" message. Also called when screen resized. 3948 */ 3949 static void 3950 display_confirm_msg(void) 3951 { 3952 // avoid that 'q' at the more prompt truncates the message here 3953 ++confirm_msg_used; 3954 if (confirm_msg != NULL) 3955 msg_puts_attr((char *)confirm_msg, HL_ATTR(HLF_M)); 3956 --confirm_msg_used; 3957 } 3958 3959 #endif // FEAT_CON_DIALOG 3960 3961 #if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG) 3962 3963 int 3964 vim_dialog_yesno( 3965 int type, 3966 char_u *title, 3967 char_u *message, 3968 int dflt) 3969 { 3970 if (do_dialog(type, 3971 title == NULL ? (char_u *)_("Question") : title, 3972 message, 3973 (char_u *)_("&Yes\n&No"), dflt, NULL, FALSE) == 1) 3974 return VIM_YES; 3975 return VIM_NO; 3976 } 3977 3978 int 3979 vim_dialog_yesnocancel( 3980 int type, 3981 char_u *title, 3982 char_u *message, 3983 int dflt) 3984 { 3985 switch (do_dialog(type, 3986 title == NULL ? (char_u *)_("Question") : title, 3987 message, 3988 (char_u *)_("&Yes\n&No\n&Cancel"), dflt, NULL, FALSE)) 3989 { 3990 case 1: return VIM_YES; 3991 case 2: return VIM_NO; 3992 } 3993 return VIM_CANCEL; 3994 } 3995 3996 int 3997 vim_dialog_yesnoallcancel( 3998 int type, 3999 char_u *title, 4000 char_u *message, 4001 int dflt) 4002 { 4003 switch (do_dialog(type, 4004 title == NULL ? (char_u *)"Question" : title, 4005 message, 4006 (char_u *)_("&Yes\n&No\nSave &All\n&Discard All\n&Cancel"), 4007 dflt, NULL, FALSE)) 4008 { 4009 case 1: return VIM_YES; 4010 case 2: return VIM_NO; 4011 case 3: return VIM_ALL; 4012 case 4: return VIM_DISCARDALL; 4013 } 4014 return VIM_CANCEL; 4015 } 4016 4017 #endif // FEAT_GUI_DIALOG || FEAT_CON_DIALOG 4018 4019 #if defined(FEAT_EVAL) 4020 static char *e_printf = N_("E766: Insufficient arguments for printf()"); 4021 4022 /* 4023 * Get number argument from "idxp" entry in "tvs". First entry is 1. 4024 */ 4025 static varnumber_T 4026 tv_nr(typval_T *tvs, int *idxp) 4027 { 4028 int idx = *idxp - 1; 4029 varnumber_T n = 0; 4030 int err = FALSE; 4031 4032 if (tvs[idx].v_type == VAR_UNKNOWN) 4033 emsg(_(e_printf)); 4034 else 4035 { 4036 ++*idxp; 4037 n = tv_get_number_chk(&tvs[idx], &err); 4038 if (err) 4039 n = 0; 4040 } 4041 return n; 4042 } 4043 4044 /* 4045 * Get string argument from "idxp" entry in "tvs". First entry is 1. 4046 * If "tofree" is NULL tv_get_string_chk() is used. Some types (e.g. List) 4047 * are not converted to a string. 4048 * If "tofree" is not NULL echo_string() is used. All types are converted to 4049 * a string with the same format as ":echo". The caller must free "*tofree". 4050 * Returns NULL for an error. 4051 */ 4052 static char * 4053 tv_str(typval_T *tvs, int *idxp, char_u **tofree) 4054 { 4055 int idx = *idxp - 1; 4056 char *s = NULL; 4057 static char_u numbuf[NUMBUFLEN]; 4058 4059 if (tvs[idx].v_type == VAR_UNKNOWN) 4060 emsg(_(e_printf)); 4061 else 4062 { 4063 ++*idxp; 4064 if (tofree != NULL) 4065 s = (char *)echo_string(&tvs[idx], tofree, numbuf, get_copyID()); 4066 else 4067 s = (char *)tv_get_string_chk(&tvs[idx]); 4068 } 4069 return s; 4070 } 4071 4072 # ifdef FEAT_FLOAT 4073 /* 4074 * Get float argument from "idxp" entry in "tvs". First entry is 1. 4075 */ 4076 static double 4077 tv_float(typval_T *tvs, int *idxp) 4078 { 4079 int idx = *idxp - 1; 4080 double f = 0; 4081 4082 if (tvs[idx].v_type == VAR_UNKNOWN) 4083 emsg(_(e_printf)); 4084 else 4085 { 4086 ++*idxp; 4087 if (tvs[idx].v_type == VAR_FLOAT) 4088 f = tvs[idx].vval.v_float; 4089 else if (tvs[idx].v_type == VAR_NUMBER) 4090 f = (double)tvs[idx].vval.v_number; 4091 else 4092 emsg(_("E807: Expected Float argument for printf()")); 4093 } 4094 return f; 4095 } 4096 # endif 4097 #endif 4098 4099 #ifdef FEAT_FLOAT 4100 /* 4101 * Return the representation of infinity for printf() function: 4102 * "-inf", "inf", "+inf", " inf", "-INF", "INF", "+INF" or " INF". 4103 */ 4104 static const char * 4105 infinity_str(int positive, 4106 char fmt_spec, 4107 int force_sign, 4108 int space_for_positive) 4109 { 4110 static const char *table[] = 4111 { 4112 "-inf", "inf", "+inf", " inf", 4113 "-INF", "INF", "+INF", " INF" 4114 }; 4115 int idx = positive * (1 + force_sign + force_sign * space_for_positive); 4116 4117 if (ASCII_ISUPPER(fmt_spec)) 4118 idx += 4; 4119 return table[idx]; 4120 } 4121 #endif 4122 4123 /* 4124 * This code was included to provide a portable vsnprintf() and snprintf(). 4125 * Some systems may provide their own, but we always use this one for 4126 * consistency. 4127 * 4128 * This code is based on snprintf.c - a portable implementation of snprintf 4129 * by Mark Martinec <[email protected]>, Version 2.2, 2000-10-06. 4130 * Included with permission. It was heavily modified to fit in Vim. 4131 * The original code, including useful comments, can be found here: 4132 * http://www.ijs.si/software/snprintf/ 4133 * 4134 * This snprintf() only supports the following conversion specifiers: 4135 * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) 4136 * with flags: '-', '+', ' ', '0' and '#'. 4137 * An asterisk is supported for field width as well as precision. 4138 * 4139 * Limited support for floating point was added: 'f', 'F', 'e', 'E', 'g', 'G'. 4140 * 4141 * Length modifiers 'h' (short int) and 'l' (long int) and 'll' (long long int) 4142 * are supported. NOTE: for 'll' the argument is varnumber_T or uvarnumber_T. 4143 * 4144 * The locale is not used, the string is used as a byte string. This is only 4145 * relevant for double-byte encodings where the second byte may be '%'. 4146 * 4147 * It is permitted for "str_m" to be zero, and it is permitted to specify NULL 4148 * pointer for resulting string argument if "str_m" is zero (as per ISO C99). 4149 * 4150 * The return value is the number of characters which would be generated 4151 * for the given input, excluding the trailing NUL. If this value 4152 * is greater or equal to "str_m", not all characters from the result 4153 * have been stored in str, output bytes beyond the ("str_m"-1) -th character 4154 * are discarded. If "str_m" is greater than zero it is guaranteed 4155 * the resulting string will be NUL-terminated. 4156 */ 4157 4158 /* 4159 * When va_list is not supported we only define vim_snprintf(). 4160 * 4161 * vim_vsnprintf_typval() can be invoked with either "va_list" or a list of 4162 * "typval_T". When the latter is not used it must be NULL. 4163 */ 4164 4165 // When generating prototypes all of this is skipped, cproto doesn't 4166 // understand this. 4167 #ifndef PROTO 4168 4169 // Like vim_vsnprintf() but append to the string. 4170 int 4171 vim_snprintf_add(char *str, size_t str_m, const char *fmt, ...) 4172 { 4173 va_list ap; 4174 int str_l; 4175 size_t len = STRLEN(str); 4176 size_t space; 4177 4178 if (str_m <= len) 4179 space = 0; 4180 else 4181 space = str_m - len; 4182 va_start(ap, fmt); 4183 str_l = vim_vsnprintf(str + len, space, fmt, ap); 4184 va_end(ap); 4185 return str_l; 4186 } 4187 4188 int 4189 vim_snprintf(char *str, size_t str_m, const char *fmt, ...) 4190 { 4191 va_list ap; 4192 int str_l; 4193 4194 va_start(ap, fmt); 4195 str_l = vim_vsnprintf(str, str_m, fmt, ap); 4196 va_end(ap); 4197 return str_l; 4198 } 4199 4200 int 4201 vim_vsnprintf( 4202 char *str, 4203 size_t str_m, 4204 const char *fmt, 4205 va_list ap) 4206 { 4207 return vim_vsnprintf_typval(str, str_m, fmt, ap, NULL); 4208 } 4209 4210 int 4211 vim_vsnprintf_typval( 4212 char *str, 4213 size_t str_m, 4214 const char *fmt, 4215 va_list ap, 4216 typval_T *tvs) 4217 { 4218 size_t str_l = 0; 4219 const char *p = fmt; 4220 int arg_idx = 1; 4221 4222 if (p == NULL) 4223 p = ""; 4224 while (*p != NUL) 4225 { 4226 if (*p != '%') 4227 { 4228 char *q = strchr(p + 1, '%'); 4229 size_t n = (q == NULL) ? STRLEN(p) : (size_t)(q - p); 4230 4231 // Copy up to the next '%' or NUL without any changes. 4232 if (str_l < str_m) 4233 { 4234 size_t avail = str_m - str_l; 4235 4236 mch_memmove(str + str_l, p, n > avail ? avail : n); 4237 } 4238 p += n; 4239 str_l += n; 4240 } 4241 else 4242 { 4243 size_t min_field_width = 0, precision = 0; 4244 int zero_padding = 0, precision_specified = 0, justify_left = 0; 4245 int alternate_form = 0, force_sign = 0; 4246 4247 // If both the ' ' and '+' flags appear, the ' ' flag should be 4248 // ignored. 4249 int space_for_positive = 1; 4250 4251 // allowed values: \0, h, l, L 4252 char length_modifier = '\0'; 4253 4254 // temporary buffer for simple numeric->string conversion 4255 # if defined(FEAT_FLOAT) 4256 # define TMP_LEN 350 // On my system 1e308 is the biggest number possible. 4257 // That sounds reasonable to use as the maximum 4258 // printable. 4259 # else 4260 # define TMP_LEN 66 4261 # endif 4262 char tmp[TMP_LEN]; 4263 4264 // string address in case of string argument 4265 const char *str_arg = NULL; 4266 4267 // natural field width of arg without padding and sign 4268 size_t str_arg_l; 4269 4270 // unsigned char argument value - only defined for c conversion. 4271 // N.B. standard explicitly states the char argument for the c 4272 // conversion is unsigned 4273 unsigned char uchar_arg; 4274 4275 // number of zeros to be inserted for numeric conversions as 4276 // required by the precision or minimal field width 4277 size_t number_of_zeros_to_pad = 0; 4278 4279 // index into tmp where zero padding is to be inserted 4280 size_t zero_padding_insertion_ind = 0; 4281 4282 // current conversion specifier character 4283 char fmt_spec = '\0'; 4284 4285 // buffer for 's' and 'S' specs 4286 char_u *tofree = NULL; 4287 4288 4289 p++; // skip '%' 4290 4291 // parse flags 4292 while (*p == '0' || *p == '-' || *p == '+' || *p == ' ' 4293 || *p == '#' || *p == '\'') 4294 { 4295 switch (*p) 4296 { 4297 case '0': zero_padding = 1; break; 4298 case '-': justify_left = 1; break; 4299 case '+': force_sign = 1; space_for_positive = 0; break; 4300 case ' ': force_sign = 1; 4301 // If both the ' ' and '+' flags appear, the ' ' 4302 // flag should be ignored 4303 break; 4304 case '#': alternate_form = 1; break; 4305 case '\'': break; 4306 } 4307 p++; 4308 } 4309 // If the '0' and '-' flags both appear, the '0' flag should be 4310 // ignored. 4311 4312 // parse field width 4313 if (*p == '*') 4314 { 4315 int j; 4316 4317 p++; 4318 j = 4319 # if defined(FEAT_EVAL) 4320 tvs != NULL ? tv_nr(tvs, &arg_idx) : 4321 # endif 4322 va_arg(ap, int); 4323 if (j >= 0) 4324 min_field_width = j; 4325 else 4326 { 4327 min_field_width = -j; 4328 justify_left = 1; 4329 } 4330 } 4331 else if (VIM_ISDIGIT((int)(*p))) 4332 { 4333 // size_t could be wider than unsigned int; make sure we treat 4334 // argument like common implementations do 4335 unsigned int uj = *p++ - '0'; 4336 4337 while (VIM_ISDIGIT((int)(*p))) 4338 uj = 10 * uj + (unsigned int)(*p++ - '0'); 4339 min_field_width = uj; 4340 } 4341 4342 // parse precision 4343 if (*p == '.') 4344 { 4345 p++; 4346 precision_specified = 1; 4347 if (*p == '*') 4348 { 4349 int j; 4350 4351 j = 4352 # if defined(FEAT_EVAL) 4353 tvs != NULL ? tv_nr(tvs, &arg_idx) : 4354 # endif 4355 va_arg(ap, int); 4356 p++; 4357 if (j >= 0) 4358 precision = j; 4359 else 4360 { 4361 precision_specified = 0; 4362 precision = 0; 4363 } 4364 } 4365 else if (VIM_ISDIGIT((int)(*p))) 4366 { 4367 // size_t could be wider than unsigned int; make sure we 4368 // treat argument like common implementations do 4369 unsigned int uj = *p++ - '0'; 4370 4371 while (VIM_ISDIGIT((int)(*p))) 4372 uj = 10 * uj + (unsigned int)(*p++ - '0'); 4373 precision = uj; 4374 } 4375 } 4376 4377 // parse 'h', 'l' and 'll' length modifiers 4378 if (*p == 'h' || *p == 'l') 4379 { 4380 length_modifier = *p; 4381 p++; 4382 if (length_modifier == 'l' && *p == 'l') 4383 { 4384 // double l = __int64 / varnumber_T 4385 length_modifier = 'L'; 4386 p++; 4387 } 4388 } 4389 fmt_spec = *p; 4390 4391 // common synonyms: 4392 switch (fmt_spec) 4393 { 4394 case 'i': fmt_spec = 'd'; break; 4395 case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; 4396 case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; 4397 case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; 4398 default: break; 4399 } 4400 4401 # if defined(FEAT_EVAL) 4402 switch (fmt_spec) 4403 { 4404 case 'd': case 'u': case 'o': case 'x': case 'X': 4405 if (tvs != NULL && length_modifier == '\0') 4406 length_modifier = 'L'; 4407 } 4408 # endif 4409 4410 // get parameter value, do initial processing 4411 switch (fmt_spec) 4412 { 4413 // '%' and 'c' behave similar to 's' regarding flags and field 4414 // widths 4415 case '%': 4416 case 'c': 4417 case 's': 4418 case 'S': 4419 str_arg_l = 1; 4420 switch (fmt_spec) 4421 { 4422 case '%': 4423 str_arg = p; 4424 break; 4425 4426 case 'c': 4427 { 4428 int j; 4429 4430 j = 4431 # if defined(FEAT_EVAL) 4432 tvs != NULL ? tv_nr(tvs, &arg_idx) : 4433 # endif 4434 va_arg(ap, int); 4435 // standard demands unsigned char 4436 uchar_arg = (unsigned char)j; 4437 str_arg = (char *)&uchar_arg; 4438 break; 4439 } 4440 4441 case 's': 4442 case 'S': 4443 str_arg = 4444 # if defined(FEAT_EVAL) 4445 tvs != NULL ? tv_str(tvs, &arg_idx, &tofree) : 4446 # endif 4447 va_arg(ap, char *); 4448 if (str_arg == NULL) 4449 { 4450 str_arg = "[NULL]"; 4451 str_arg_l = 6; 4452 } 4453 // make sure not to address string beyond the specified 4454 // precision !!! 4455 else if (!precision_specified) 4456 str_arg_l = strlen(str_arg); 4457 // truncate string if necessary as requested by precision 4458 else if (precision == 0) 4459 str_arg_l = 0; 4460 else 4461 { 4462 // Don't put the #if inside memchr(), it can be a 4463 // macro. 4464 // memchr on HP does not like n > 2^31 !!! 4465 char *q = memchr(str_arg, '\0', 4466 precision <= (size_t)0x7fffffffL ? precision 4467 : (size_t)0x7fffffffL); 4468 str_arg_l = (q == NULL) ? precision 4469 : (size_t)(q - str_arg); 4470 } 4471 if (fmt_spec == 'S') 4472 { 4473 if (min_field_width != 0) 4474 min_field_width += STRLEN(str_arg) 4475 - mb_string2cells((char_u *)str_arg, -1); 4476 if (precision) 4477 { 4478 char_u *p1; 4479 size_t i = 0; 4480 4481 for (p1 = (char_u *)str_arg; *p1; 4482 p1 += mb_ptr2len(p1)) 4483 { 4484 i += (size_t)mb_ptr2cells(p1); 4485 if (i > precision) 4486 break; 4487 } 4488 str_arg_l = precision = p1 - (char_u *)str_arg; 4489 } 4490 } 4491 break; 4492 4493 default: 4494 break; 4495 } 4496 break; 4497 4498 case 'd': case 'u': 4499 case 'b': case 'B': 4500 case 'o': 4501 case 'x': case 'X': 4502 case 'p': 4503 { 4504 // NOTE: the u, b, o, x, X and p conversion specifiers 4505 // imply the value is unsigned; d implies a signed 4506 // value 4507 4508 // 0 if numeric argument is zero (or if pointer is 4509 // NULL for 'p'), +1 if greater than zero (or nonzero 4510 // for unsigned arguments), -1 if negative (unsigned 4511 // argument is never negative) 4512 int arg_sign = 0; 4513 4514 // only set for length modifier h, or for no length 4515 // modifiers 4516 int int_arg = 0; 4517 unsigned int uint_arg = 0; 4518 4519 // only set for length modifier l 4520 long int long_arg = 0; 4521 unsigned long int ulong_arg = 0; 4522 4523 // only set for length modifier ll 4524 varnumber_T llong_arg = 0; 4525 uvarnumber_T ullong_arg = 0; 4526 4527 // only set for b conversion 4528 uvarnumber_T bin_arg = 0; 4529 4530 // pointer argument value -only defined for p 4531 // conversion 4532 void *ptr_arg = NULL; 4533 4534 if (fmt_spec == 'p') 4535 { 4536 length_modifier = '\0'; 4537 ptr_arg = 4538 # if defined(FEAT_EVAL) 4539 tvs != NULL ? (void *)tv_str(tvs, &arg_idx, 4540 NULL) : 4541 # endif 4542 va_arg(ap, void *); 4543 if (ptr_arg != NULL) 4544 arg_sign = 1; 4545 } 4546 else if (fmt_spec == 'b' || fmt_spec == 'B') 4547 { 4548 bin_arg = 4549 # if defined(FEAT_EVAL) 4550 tvs != NULL ? 4551 (uvarnumber_T)tv_nr(tvs, &arg_idx) : 4552 # endif 4553 va_arg(ap, uvarnumber_T); 4554 if (bin_arg != 0) 4555 arg_sign = 1; 4556 } 4557 else if (fmt_spec == 'd') 4558 { 4559 // signed 4560 switch (length_modifier) 4561 { 4562 case '\0': 4563 case 'h': 4564 // char and short arguments are passed as int. 4565 int_arg = 4566 # if defined(FEAT_EVAL) 4567 tvs != NULL ? tv_nr(tvs, &arg_idx) : 4568 # endif 4569 va_arg(ap, int); 4570 if (int_arg > 0) 4571 arg_sign = 1; 4572 else if (int_arg < 0) 4573 arg_sign = -1; 4574 break; 4575 case 'l': 4576 long_arg = 4577 # if defined(FEAT_EVAL) 4578 tvs != NULL ? tv_nr(tvs, &arg_idx) : 4579 # endif 4580 va_arg(ap, long int); 4581 if (long_arg > 0) 4582 arg_sign = 1; 4583 else if (long_arg < 0) 4584 arg_sign = -1; 4585 break; 4586 case 'L': 4587 llong_arg = 4588 # if defined(FEAT_EVAL) 4589 tvs != NULL ? tv_nr(tvs, &arg_idx) : 4590 # endif 4591 va_arg(ap, varnumber_T); 4592 if (llong_arg > 0) 4593 arg_sign = 1; 4594 else if (llong_arg < 0) 4595 arg_sign = -1; 4596 break; 4597 } 4598 } 4599 else 4600 { 4601 // unsigned 4602 switch (length_modifier) 4603 { 4604 case '\0': 4605 case 'h': 4606 uint_arg = 4607 # if defined(FEAT_EVAL) 4608 tvs != NULL ? (unsigned) 4609 tv_nr(tvs, &arg_idx) : 4610 # endif 4611 va_arg(ap, unsigned int); 4612 if (uint_arg != 0) 4613 arg_sign = 1; 4614 break; 4615 case 'l': 4616 ulong_arg = 4617 # if defined(FEAT_EVAL) 4618 tvs != NULL ? (unsigned long) 4619 tv_nr(tvs, &arg_idx) : 4620 # endif 4621 va_arg(ap, unsigned long int); 4622 if (ulong_arg != 0) 4623 arg_sign = 1; 4624 break; 4625 case 'L': 4626 ullong_arg = 4627 # if defined(FEAT_EVAL) 4628 tvs != NULL ? (uvarnumber_T) 4629 tv_nr(tvs, &arg_idx) : 4630 # endif 4631 va_arg(ap, uvarnumber_T); 4632 if (ullong_arg != 0) 4633 arg_sign = 1; 4634 break; 4635 } 4636 } 4637 4638 str_arg = tmp; 4639 str_arg_l = 0; 4640 4641 // NOTE: 4642 // For d, i, u, o, x, and X conversions, if precision is 4643 // specified, the '0' flag should be ignored. This is so 4644 // with Solaris 2.6, Digital UNIX 4.0, HPUX 10, Linux, 4645 // FreeBSD, NetBSD; but not with Perl. 4646 if (precision_specified) 4647 zero_padding = 0; 4648 if (fmt_spec == 'd') 4649 { 4650 if (force_sign && arg_sign >= 0) 4651 tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; 4652 // leave negative numbers for sprintf to handle, to 4653 // avoid handling tricky cases like (short int)-32768 4654 } 4655 else if (alternate_form) 4656 { 4657 if (arg_sign != 0 4658 && (fmt_spec == 'b' || fmt_spec == 'B' 4659 || fmt_spec == 'x' || fmt_spec == 'X') ) 4660 { 4661 tmp[str_arg_l++] = '0'; 4662 tmp[str_arg_l++] = fmt_spec; 4663 } 4664 // alternate form should have no effect for p 4665 // conversion, but ... 4666 } 4667 4668 zero_padding_insertion_ind = str_arg_l; 4669 if (!precision_specified) 4670 precision = 1; // default precision is 1 4671 if (precision == 0 && arg_sign == 0) 4672 { 4673 // When zero value is formatted with an explicit 4674 // precision 0, the resulting formatted string is 4675 // empty (d, i, u, b, B, o, x, X, p). 4676 } 4677 else 4678 { 4679 char f[6]; 4680 int f_l = 0; 4681 4682 // construct a simple format string for sprintf 4683 f[f_l++] = '%'; 4684 if (!length_modifier) 4685 ; 4686 else if (length_modifier == 'L') 4687 { 4688 # ifdef MSWIN 4689 f[f_l++] = 'I'; 4690 f[f_l++] = '6'; 4691 f[f_l++] = '4'; 4692 # else 4693 f[f_l++] = 'l'; 4694 f[f_l++] = 'l'; 4695 # endif 4696 } 4697 else 4698 f[f_l++] = length_modifier; 4699 f[f_l++] = fmt_spec; 4700 f[f_l++] = '\0'; 4701 4702 if (fmt_spec == 'p') 4703 str_arg_l += sprintf(tmp + str_arg_l, f, ptr_arg); 4704 else if (fmt_spec == 'b' || fmt_spec == 'B') 4705 { 4706 char b[8 * sizeof(uvarnumber_T)]; 4707 size_t b_l = 0; 4708 uvarnumber_T bn = bin_arg; 4709 4710 do 4711 { 4712 b[sizeof(b) - ++b_l] = '0' + (bn & 0x1); 4713 bn >>= 1; 4714 } 4715 while (bn != 0); 4716 4717 memcpy(tmp + str_arg_l, b + sizeof(b) - b_l, b_l); 4718 str_arg_l += b_l; 4719 } 4720 else if (fmt_spec == 'd') 4721 { 4722 // signed 4723 switch (length_modifier) 4724 { 4725 case '\0': 4726 case 'h': str_arg_l += sprintf( 4727 tmp + str_arg_l, f, int_arg); 4728 break; 4729 case 'l': str_arg_l += sprintf( 4730 tmp + str_arg_l, f, long_arg); 4731 break; 4732 case 'L': str_arg_l += sprintf( 4733 tmp + str_arg_l, f, llong_arg); 4734 break; 4735 } 4736 } 4737 else 4738 { 4739 // unsigned 4740 switch (length_modifier) 4741 { 4742 case '\0': 4743 case 'h': str_arg_l += sprintf( 4744 tmp + str_arg_l, f, uint_arg); 4745 break; 4746 case 'l': str_arg_l += sprintf( 4747 tmp + str_arg_l, f, ulong_arg); 4748 break; 4749 case 'L': str_arg_l += sprintf( 4750 tmp + str_arg_l, f, ullong_arg); 4751 break; 4752 } 4753 } 4754 4755 // include the optional minus sign and possible 4756 // "0x" in the region before the zero padding 4757 // insertion point 4758 if (zero_padding_insertion_ind < str_arg_l 4759 && tmp[zero_padding_insertion_ind] == '-') 4760 zero_padding_insertion_ind++; 4761 if (zero_padding_insertion_ind + 1 < str_arg_l 4762 && tmp[zero_padding_insertion_ind] == '0' 4763 && (tmp[zero_padding_insertion_ind + 1] == 'x' 4764 || tmp[zero_padding_insertion_ind + 1] == 'X')) 4765 zero_padding_insertion_ind += 2; 4766 } 4767 4768 { 4769 size_t num_of_digits = str_arg_l 4770 - zero_padding_insertion_ind; 4771 4772 if (alternate_form && fmt_spec == 'o' 4773 // unless zero is already the first 4774 // character 4775 && !(zero_padding_insertion_ind < str_arg_l 4776 && tmp[zero_padding_insertion_ind] == '0')) 4777 { 4778 // assure leading zero for alternate-form 4779 // octal numbers 4780 if (!precision_specified 4781 || precision < num_of_digits + 1) 4782 { 4783 // precision is increased to force the 4784 // first character to be zero, except if a 4785 // zero value is formatted with an 4786 // explicit precision of zero 4787 precision = num_of_digits + 1; 4788 } 4789 } 4790 // zero padding to specified precision? 4791 if (num_of_digits < precision) 4792 number_of_zeros_to_pad = precision - num_of_digits; 4793 } 4794 // zero padding to specified minimal field width? 4795 if (!justify_left && zero_padding) 4796 { 4797 int n = (int)(min_field_width - (str_arg_l 4798 + number_of_zeros_to_pad)); 4799 if (n > 0) 4800 number_of_zeros_to_pad += n; 4801 } 4802 break; 4803 } 4804 4805 # ifdef FEAT_FLOAT 4806 case 'f': 4807 case 'F': 4808 case 'e': 4809 case 'E': 4810 case 'g': 4811 case 'G': 4812 { 4813 // Floating point. 4814 double f; 4815 double abs_f; 4816 char format[40]; 4817 int l; 4818 int remove_trailing_zeroes = FALSE; 4819 4820 f = 4821 # if defined(FEAT_EVAL) 4822 tvs != NULL ? tv_float(tvs, &arg_idx) : 4823 # endif 4824 va_arg(ap, double); 4825 abs_f = f < 0 ? -f : f; 4826 4827 if (fmt_spec == 'g' || fmt_spec == 'G') 4828 { 4829 // Would be nice to use %g directly, but it prints 4830 // "1.0" as "1", we don't want that. 4831 if ((abs_f >= 0.001 && abs_f < 10000000.0) 4832 || abs_f == 0.0) 4833 fmt_spec = ASCII_ISUPPER(fmt_spec) ? 'F' : 'f'; 4834 else 4835 fmt_spec = fmt_spec == 'g' ? 'e' : 'E'; 4836 remove_trailing_zeroes = TRUE; 4837 } 4838 4839 if ((fmt_spec == 'f' || fmt_spec == 'F') && 4840 # ifdef VAX 4841 abs_f > 1.0e38 4842 # else 4843 abs_f > 1.0e307 4844 # endif 4845 ) 4846 { 4847 // Avoid a buffer overflow 4848 STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, 4849 force_sign, space_for_positive)); 4850 str_arg_l = STRLEN(tmp); 4851 zero_padding = 0; 4852 } 4853 else 4854 { 4855 if (isnan(f)) 4856 { 4857 // Not a number: nan or NAN 4858 STRCPY(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" 4859 : "nan"); 4860 str_arg_l = 3; 4861 zero_padding = 0; 4862 } 4863 else if (isinf(f)) 4864 { 4865 STRCPY(tmp, infinity_str(f > 0.0, fmt_spec, 4866 force_sign, space_for_positive)); 4867 str_arg_l = STRLEN(tmp); 4868 zero_padding = 0; 4869 } 4870 else 4871 { 4872 // Regular float number 4873 format[0] = '%'; 4874 l = 1; 4875 if (force_sign) 4876 format[l++] = space_for_positive ? ' ' : '+'; 4877 if (precision_specified) 4878 { 4879 size_t max_prec = TMP_LEN - 10; 4880 4881 // Make sure we don't get more digits than we 4882 // have room for. 4883 if ((fmt_spec == 'f' || fmt_spec == 'F') 4884 && abs_f > 1.0) 4885 max_prec -= (size_t)log10(abs_f); 4886 if (precision > max_prec) 4887 precision = max_prec; 4888 l += sprintf(format + l, ".%d", (int)precision); 4889 } 4890 format[l] = fmt_spec == 'F' ? 'f' : fmt_spec; 4891 format[l + 1] = NUL; 4892 4893 str_arg_l = sprintf(tmp, format, f); 4894 } 4895 4896 if (remove_trailing_zeroes) 4897 { 4898 int i; 4899 char *tp; 4900 4901 // Using %g or %G: remove superfluous zeroes. 4902 if (fmt_spec == 'f' || fmt_spec == 'F') 4903 tp = tmp + str_arg_l - 1; 4904 else 4905 { 4906 tp = (char *)vim_strchr((char_u *)tmp, 4907 fmt_spec == 'e' ? 'e' : 'E'); 4908 if (tp != NULL) 4909 { 4910 // Remove superfluous '+' and leading 4911 // zeroes from the exponent. 4912 if (tp[1] == '+') 4913 { 4914 // Change "1.0e+07" to "1.0e07" 4915 STRMOVE(tp + 1, tp + 2); 4916 --str_arg_l; 4917 } 4918 i = (tp[1] == '-') ? 2 : 1; 4919 while (tp[i] == '0') 4920 { 4921 // Change "1.0e07" to "1.0e7" 4922 STRMOVE(tp + i, tp + i + 1); 4923 --str_arg_l; 4924 } 4925 --tp; 4926 } 4927 } 4928 4929 if (tp != NULL && !precision_specified) 4930 // Remove trailing zeroes, but keep the one 4931 // just after a dot. 4932 while (tp > tmp + 2 && *tp == '0' 4933 && tp[-1] != '.') 4934 { 4935 STRMOVE(tp, tp + 1); 4936 --tp; 4937 --str_arg_l; 4938 } 4939 } 4940 else 4941 { 4942 char *tp; 4943 4944 // Be consistent: some printf("%e") use 1.0e+12 4945 // and some 1.0e+012. Remove one zero in the last 4946 // case. 4947 tp = (char *)vim_strchr((char_u *)tmp, 4948 fmt_spec == 'e' ? 'e' : 'E'); 4949 if (tp != NULL && (tp[1] == '+' || tp[1] == '-') 4950 && tp[2] == '0' 4951 && vim_isdigit(tp[3]) 4952 && vim_isdigit(tp[4])) 4953 { 4954 STRMOVE(tp + 2, tp + 3); 4955 --str_arg_l; 4956 } 4957 } 4958 } 4959 if (zero_padding && min_field_width > str_arg_l 4960 && (tmp[0] == '-' || force_sign)) 4961 { 4962 // padding 0's should be inserted after the sign 4963 number_of_zeros_to_pad = min_field_width - str_arg_l; 4964 zero_padding_insertion_ind = 1; 4965 } 4966 str_arg = tmp; 4967 break; 4968 } 4969 # endif 4970 4971 default: 4972 // unrecognized conversion specifier, keep format string 4973 // as-is 4974 zero_padding = 0; // turn zero padding off for non-numeric 4975 // conversion 4976 justify_left = 1; 4977 min_field_width = 0; // reset flags 4978 4979 // discard the unrecognized conversion, just keep * 4980 // the unrecognized conversion character 4981 str_arg = p; 4982 str_arg_l = 0; 4983 if (*p != NUL) 4984 str_arg_l++; // include invalid conversion specifier 4985 // unchanged if not at end-of-string 4986 break; 4987 } 4988 4989 if (*p != NUL) 4990 p++; // step over the just processed conversion specifier 4991 4992 // insert padding to the left as requested by min_field_width; 4993 // this does not include the zero padding in case of numerical 4994 // conversions 4995 if (!justify_left) 4996 { 4997 // left padding with blank or zero 4998 int pn = (int)(min_field_width - (str_arg_l + number_of_zeros_to_pad)); 4999 5000 if (pn > 0) 5001 { 5002 if (str_l < str_m) 5003 { 5004 size_t avail = str_m - str_l; 5005 5006 vim_memset(str + str_l, zero_padding ? '0' : ' ', 5007 (size_t)pn > avail ? avail 5008 : (size_t)pn); 5009 } 5010 str_l += pn; 5011 } 5012 } 5013 5014 // zero padding as requested by the precision or by the minimal 5015 // field width for numeric conversions required? 5016 if (number_of_zeros_to_pad == 0) 5017 { 5018 // will not copy first part of numeric right now, * 5019 // force it to be copied later in its entirety 5020 zero_padding_insertion_ind = 0; 5021 } 5022 else 5023 { 5024 // insert first part of numerics (sign or '0x') before zero 5025 // padding 5026 int zn = (int)zero_padding_insertion_ind; 5027 5028 if (zn > 0) 5029 { 5030 if (str_l < str_m) 5031 { 5032 size_t avail = str_m - str_l; 5033 5034 mch_memmove(str + str_l, str_arg, 5035 (size_t)zn > avail ? avail 5036 : (size_t)zn); 5037 } 5038 str_l += zn; 5039 } 5040 5041 // insert zero padding as requested by the precision or min 5042 // field width 5043 zn = (int)number_of_zeros_to_pad; 5044 if (zn > 0) 5045 { 5046 if (str_l < str_m) 5047 { 5048 size_t avail = str_m - str_l; 5049 5050 vim_memset(str + str_l, '0', 5051 (size_t)zn > avail ? avail 5052 : (size_t)zn); 5053 } 5054 str_l += zn; 5055 } 5056 } 5057 5058 // insert formatted string 5059 // (or as-is conversion specifier for unknown conversions) 5060 { 5061 int sn = (int)(str_arg_l - zero_padding_insertion_ind); 5062 5063 if (sn > 0) 5064 { 5065 if (str_l < str_m) 5066 { 5067 size_t avail = str_m - str_l; 5068 5069 mch_memmove(str + str_l, 5070 str_arg + zero_padding_insertion_ind, 5071 (size_t)sn > avail ? avail : (size_t)sn); 5072 } 5073 str_l += sn; 5074 } 5075 } 5076 5077 // insert right padding 5078 if (justify_left) 5079 { 5080 // right blank padding to the field width 5081 int pn = (int)(min_field_width 5082 - (str_arg_l + number_of_zeros_to_pad)); 5083 5084 if (pn > 0) 5085 { 5086 if (str_l < str_m) 5087 { 5088 size_t avail = str_m - str_l; 5089 5090 vim_memset(str + str_l, ' ', 5091 (size_t)pn > avail ? avail 5092 : (size_t)pn); 5093 } 5094 str_l += pn; 5095 } 5096 } 5097 vim_free(tofree); 5098 } 5099 } 5100 5101 if (str_m > 0) 5102 { 5103 // make sure the string is nul-terminated even at the expense of 5104 // overwriting the last character (shouldn't happen, but just in case) 5105 // 5106 str[str_l <= str_m - 1 ? str_l : str_m - 1] = '\0'; 5107 } 5108 5109 if (tvs != NULL && tvs[arg_idx - 1].v_type != VAR_UNKNOWN) 5110 emsg(_("E767: Too many arguments to printf()")); 5111 5112 // Return the number of characters formatted (excluding trailing nul 5113 // character), that is, the number of characters that would have been 5114 // written to the buffer if it were large enough. 5115 return (int)str_l; 5116 } 5117 5118 #endif // PROTO 5119