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