1 /* vi:set ts=8 sts=4 sw=4: 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 * ui.c: functions that handle the user interface. 12 * 1. Keyboard input stuff, and a bit of windowing stuff. These are called 13 * before the machine specific stuff (mch_*) so that we can call the GUI 14 * stuff instead if the GUI is running. 15 * 2. Clipboard stuff. 16 * 3. Input buffer stuff. 17 */ 18 19 #include "vim.h" 20 21 void 22 ui_write(s, len) 23 char_u *s; 24 int len; 25 { 26 #ifdef FEAT_GUI 27 if (gui.in_use && !gui.dying && !gui.starting) 28 { 29 gui_write(s, len); 30 if (p_wd) 31 gui_wait_for_chars(p_wd); 32 return; 33 } 34 #endif 35 #ifndef NO_CONSOLE 36 /* Don't output anything in silent mode ("ex -s") unless 'verbose' set */ 37 if (!(silent_mode && p_verbose == 0)) 38 { 39 #ifdef FEAT_MBYTE 40 char_u *tofree = NULL; 41 42 if (output_conv.vc_type != CONV_NONE) 43 { 44 /* Convert characters from 'encoding' to 'termencoding'. */ 45 tofree = string_convert(&output_conv, s, &len); 46 if (tofree != NULL) 47 s = tofree; 48 } 49 #endif 50 51 mch_write(s, len); 52 53 #ifdef FEAT_MBYTE 54 if (output_conv.vc_type != CONV_NONE) 55 vim_free(tofree); 56 #endif 57 } 58 #endif 59 } 60 61 #if defined(UNIX) || defined(VMS) || defined(PROTO) 62 /* 63 * When executing an external program, there may be some typed characters that 64 * are not consumed by it. Give them back to ui_inchar() and they are stored 65 * here for the next call. 66 */ 67 static char_u *ta_str = NULL; 68 static int ta_off; /* offset for next char to use when ta_str != NULL */ 69 static int ta_len; /* length of ta_str when it's not NULL*/ 70 71 void 72 ui_inchar_undo(s, len) 73 char_u *s; 74 int len; 75 { 76 char_u *new; 77 int newlen; 78 79 newlen = len; 80 if (ta_str != NULL) 81 newlen += ta_len - ta_off; 82 new = alloc(newlen); 83 if (new != NULL) 84 { 85 if (ta_str != NULL) 86 { 87 mch_memmove(new, ta_str + ta_off, (size_t)(ta_len - ta_off)); 88 mch_memmove(new + ta_len - ta_off, s, (size_t)len); 89 vim_free(ta_str); 90 } 91 else 92 mch_memmove(new, s, (size_t)len); 93 ta_str = new; 94 ta_len = newlen; 95 ta_off = 0; 96 } 97 } 98 #endif 99 100 /* 101 * ui_inchar(): low level input funcion. 102 * Get characters from the keyboard. 103 * Return the number of characters that are available. 104 * If "wtime" == 0 do not wait for characters. 105 * If "wtime" == -1 wait forever for characters. 106 * If "wtime" > 0 wait "wtime" milliseconds for a character. 107 * 108 * "tb_change_cnt" is the value of typebuf.tb_change_cnt if "buf" points into 109 * it. When typebuf.tb_change_cnt changes (e.g., when a message is received 110 * from a remote client) "buf" can no longer be used. "tb_change_cnt" is NULL 111 * otherwise. 112 */ 113 int 114 ui_inchar(buf, maxlen, wtime, tb_change_cnt) 115 char_u *buf; 116 int maxlen; 117 long wtime; /* don't use "time", MIPS cannot handle it */ 118 int tb_change_cnt; 119 { 120 int retval = 0; 121 122 #if defined(FEAT_GUI) && (defined(UNIX) || defined(VMS)) 123 /* 124 * Use the typeahead if there is any. 125 */ 126 if (ta_str != NULL) 127 { 128 if (maxlen >= ta_len - ta_off) 129 { 130 mch_memmove(buf, ta_str + ta_off, (size_t)ta_len); 131 vim_free(ta_str); 132 ta_str = NULL; 133 return ta_len; 134 } 135 mch_memmove(buf, ta_str + ta_off, (size_t)maxlen); 136 ta_off += maxlen; 137 return maxlen; 138 } 139 #endif 140 141 #ifdef FEAT_PROFILE 142 if (do_profiling && wtime != 0) 143 prof_inchar_enter(); 144 #endif 145 146 #ifdef NO_CONSOLE_INPUT 147 /* Don't wait for character input when the window hasn't been opened yet. 148 * Do try reading, this works when redirecting stdin from a file. 149 * Must return something, otherwise we'll loop forever. If we run into 150 * this very often we probably got stuck, exit Vim. */ 151 if (no_console_input()) 152 { 153 static int count = 0; 154 155 # ifndef NO_CONSOLE 156 retval = mch_inchar(buf, maxlen, (wtime >= 0 && wtime < 10) 157 ? 10L : wtime, tb_change_cnt); 158 if (retval > 0 || typebuf_changed(tb_change_cnt) || wtime >= 0) 159 goto theend; 160 # endif 161 if (wtime == -1 && ++count == 1000) 162 read_error_exit(); 163 buf[0] = CAR; 164 retval = 1; 165 goto theend; 166 } 167 #endif 168 169 /* When doing a blocking wait there is no need for CTRL-C to interrupt 170 * something, don't let it set got_int when it was mapped. */ 171 if (mapped_ctrl_c && (wtime == -1 || wtime > 100L)) 172 ctrl_c_interrupts = FALSE; 173 174 #ifdef FEAT_GUI 175 if (gui.in_use) 176 { 177 if (gui_wait_for_chars(wtime) && !typebuf_changed(tb_change_cnt)) 178 retval = read_from_input_buf(buf, (long)maxlen); 179 } 180 #endif 181 #ifndef NO_CONSOLE 182 # ifdef FEAT_GUI 183 else 184 # endif 185 { 186 if (wtime == -1 || wtime > 100L) 187 /* allow signals to kill us */ 188 (void)vim_handle_signal(SIGNAL_UNBLOCK); 189 retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt); 190 if (wtime == -1 || wtime > 100L) 191 /* block SIGHUP et al. */ 192 (void)vim_handle_signal(SIGNAL_BLOCK); 193 } 194 #endif 195 196 ctrl_c_interrupts = TRUE; 197 198 #ifdef NO_CONSOLE_INPUT 199 theend: 200 #endif 201 #ifdef FEAT_PROFILE 202 if (do_profiling && wtime != 0) 203 prof_inchar_exit(); 204 #endif 205 return retval; 206 } 207 208 /* 209 * return non-zero if a character is available 210 */ 211 int 212 ui_char_avail() 213 { 214 #ifdef FEAT_GUI 215 if (gui.in_use) 216 { 217 gui_mch_update(); 218 return input_available(); 219 } 220 #endif 221 #ifndef NO_CONSOLE 222 # ifdef NO_CONSOLE_INPUT 223 if (no_console_input()) 224 return 0; 225 # endif 226 return mch_char_avail(); 227 #else 228 return 0; 229 #endif 230 } 231 232 /* 233 * Delay for the given number of milliseconds. If ignoreinput is FALSE then we 234 * cancel the delay if a key is hit. 235 */ 236 void 237 ui_delay(msec, ignoreinput) 238 long msec; 239 int ignoreinput; 240 { 241 #ifdef FEAT_GUI 242 if (gui.in_use && !ignoreinput) 243 gui_wait_for_chars(msec); 244 else 245 #endif 246 mch_delay(msec, ignoreinput); 247 } 248 249 /* 250 * If the machine has job control, use it to suspend the program, 251 * otherwise fake it by starting a new shell. 252 * When running the GUI iconify the window. 253 */ 254 void 255 ui_suspend() 256 { 257 #ifdef FEAT_GUI 258 if (gui.in_use) 259 { 260 gui_mch_iconify(); 261 return; 262 } 263 #endif 264 mch_suspend(); 265 } 266 267 #if !defined(UNIX) || !defined(SIGTSTP) || defined(PROTO) || defined(__BEOS__) 268 /* 269 * When the OS can't really suspend, call this function to start a shell. 270 * This is never called in the GUI. 271 */ 272 void 273 suspend_shell() 274 { 275 if (*p_sh == NUL) 276 EMSG(_(e_shellempty)); 277 else 278 { 279 MSG_PUTS(_("new shell started\n")); 280 do_shell(NULL, 0); 281 } 282 } 283 #endif 284 285 /* 286 * Try to get the current Vim shell size. Put the result in Rows and Columns. 287 * Use the new sizes as defaults for 'columns' and 'lines'. 288 * Return OK when size could be determined, FAIL otherwise. 289 */ 290 int 291 ui_get_shellsize() 292 { 293 int retval; 294 295 #ifdef FEAT_GUI 296 if (gui.in_use) 297 retval = gui_get_shellsize(); 298 else 299 #endif 300 retval = mch_get_shellsize(); 301 302 check_shellsize(); 303 304 /* adjust the default for 'lines' and 'columns' */ 305 if (retval == OK) 306 { 307 set_number_default("lines", Rows); 308 set_number_default("columns", Columns); 309 } 310 return retval; 311 } 312 313 /* 314 * Set the size of the Vim shell according to Rows and Columns, if possible. 315 * The gui_set_shellsize() or mch_set_shellsize() function will try to set the 316 * new size. If this is not possible, it will adjust Rows and Columns. 317 */ 318 /*ARGSUSED*/ 319 void 320 ui_set_shellsize(mustset) 321 int mustset; /* set by the user */ 322 { 323 #ifdef FEAT_GUI 324 if (gui.in_use) 325 gui_set_shellsize(mustset, 326 # ifdef WIN3264 327 TRUE 328 # else 329 FALSE 330 # endif 331 ); 332 else 333 #endif 334 mch_set_shellsize(); 335 } 336 337 /* 338 * Called when Rows and/or Columns changed. Adjust scroll region and mouse 339 * region. 340 */ 341 void 342 ui_new_shellsize() 343 { 344 if (full_screen && !exiting) 345 { 346 #ifdef FEAT_GUI 347 if (gui.in_use) 348 gui_new_shellsize(); 349 else 350 #endif 351 mch_new_shellsize(); 352 } 353 } 354 355 void 356 ui_breakcheck() 357 { 358 #ifdef FEAT_GUI 359 if (gui.in_use) 360 gui_mch_update(); 361 else 362 #endif 363 mch_breakcheck(); 364 } 365 366 /***************************************************************************** 367 * Functions for copying and pasting text between applications. 368 * This is always included in a GUI version, but may also be included when the 369 * clipboard and mouse is available to a terminal version such as xterm. 370 * Note: there are some more functions in ops.c that handle selection stuff. 371 * 372 * Also note that the majority of functions here deal with the X 'primary' 373 * (visible - for Visual mode use) selection, and only that. There are no 374 * versions of these for the 'clipboard' selection, as Visual mode has no use 375 * for them. 376 */ 377 378 #if defined(FEAT_CLIPBOARD) || defined(PROTO) 379 380 /* 381 * Selection stuff using Visual mode, for cutting and pasting text to other 382 * windows. 383 */ 384 385 /* 386 * Call this to initialise the clipboard. Pass it FALSE if the clipboard code 387 * is included, but the clipboard can not be used, or TRUE if the clipboard can 388 * be used. Eg unix may call this with FALSE, then call it again with TRUE if 389 * the GUI starts. 390 */ 391 void 392 clip_init(can_use) 393 int can_use; 394 { 395 VimClipboard *cb; 396 397 cb = &clip_star; 398 for (;;) 399 { 400 cb->available = can_use; 401 cb->owned = FALSE; 402 cb->start.lnum = 0; 403 cb->start.col = 0; 404 cb->end.lnum = 0; 405 cb->end.col = 0; 406 cb->state = SELECT_CLEARED; 407 408 if (cb == &clip_plus) 409 break; 410 cb = &clip_plus; 411 } 412 } 413 414 /* 415 * Check whether the VIsual area has changed, and if so try to become the owner 416 * of the selection, and free any old converted selection we may still have 417 * lying around. If the VIsual mode has ended, make a copy of what was 418 * selected so we can still give it to others. Will probably have to make sure 419 * this is called whenever VIsual mode is ended. 420 */ 421 void 422 clip_update_selection() 423 { 424 pos_T start, end; 425 426 /* If visual mode is only due to a redo command ("."), then ignore it */ 427 if (!redo_VIsual_busy && VIsual_active && (State & NORMAL)) 428 { 429 if (lt(VIsual, curwin->w_cursor)) 430 { 431 start = VIsual; 432 end = curwin->w_cursor; 433 #ifdef FEAT_MBYTE 434 if (has_mbyte) 435 end.col += (*mb_ptr2len)(ml_get_cursor()) - 1; 436 #endif 437 } 438 else 439 { 440 start = curwin->w_cursor; 441 end = VIsual; 442 } 443 if (!equalpos(clip_star.start, start) 444 || !equalpos(clip_star.end, end) 445 || clip_star.vmode != VIsual_mode) 446 { 447 clip_clear_selection(); 448 clip_star.start = start; 449 clip_star.end = end; 450 clip_star.vmode = VIsual_mode; 451 clip_free_selection(&clip_star); 452 clip_own_selection(&clip_star); 453 clip_gen_set_selection(&clip_star); 454 } 455 } 456 } 457 458 void 459 clip_own_selection(cbd) 460 VimClipboard *cbd; 461 { 462 /* 463 * Also want to check somehow that we are reading from the keyboard rather 464 * than a mapping etc. 465 */ 466 if (!cbd->owned && cbd->available) 467 { 468 cbd->owned = (clip_gen_own_selection(cbd) == OK); 469 #ifdef FEAT_X11 470 if (cbd == &clip_star) 471 { 472 /* May have to show a different kind of highlighting for the selected 473 * area. There is no specific redraw command for this, just redraw 474 * all windows on the current buffer. */ 475 if (cbd->owned 476 && get_real_state() == VISUAL 477 && clip_isautosel() 478 && hl_attr(HLF_V) != hl_attr(HLF_VNC)) 479 redraw_curbuf_later(INVERTED_ALL); 480 } 481 #endif 482 } 483 } 484 485 void 486 clip_lose_selection(cbd) 487 VimClipboard *cbd; 488 { 489 #ifdef FEAT_X11 490 int was_owned = cbd->owned; 491 #endif 492 int visual_selection = (cbd == &clip_star); 493 494 clip_free_selection(cbd); 495 cbd->owned = FALSE; 496 if (visual_selection) 497 clip_clear_selection(); 498 clip_gen_lose_selection(cbd); 499 #ifdef FEAT_X11 500 if (visual_selection) 501 { 502 /* May have to show a different kind of highlighting for the selected 503 * area. There is no specific redraw command for this, just redraw all 504 * windows on the current buffer. */ 505 if (was_owned 506 && get_real_state() == VISUAL 507 && clip_isautosel() 508 && hl_attr(HLF_V) != hl_attr(HLF_VNC)) 509 { 510 update_curbuf(INVERTED_ALL); 511 setcursor(); 512 cursor_on(); 513 out_flush(); 514 # ifdef FEAT_GUI 515 if (gui.in_use) 516 gui_update_cursor(TRUE, FALSE); 517 # endif 518 } 519 } 520 #endif 521 } 522 523 void 524 clip_copy_selection() 525 { 526 if (VIsual_active && (State & NORMAL) && clip_star.available) 527 { 528 if (clip_isautosel()) 529 clip_update_selection(); 530 clip_free_selection(&clip_star); 531 clip_own_selection(&clip_star); 532 if (clip_star.owned) 533 clip_get_selection(&clip_star); 534 clip_gen_set_selection(&clip_star); 535 } 536 } 537 538 /* 539 * Called when Visual mode is ended: update the selection. 540 */ 541 void 542 clip_auto_select() 543 { 544 if (clip_isautosel()) 545 clip_copy_selection(); 546 } 547 548 /* 549 * Return TRUE if automatic selection of Visual area is desired. 550 */ 551 int 552 clip_isautosel() 553 { 554 return ( 555 #ifdef FEAT_GUI 556 gui.in_use ? (vim_strchr(p_go, GO_ASEL) != NULL) : 557 #endif 558 clip_autoselect); 559 } 560 561 562 /* 563 * Stuff for general mouse selection, without using Visual mode. 564 */ 565 566 static int clip_compare_pos __ARGS((int row1, int col1, int row2, int col2)); 567 static void clip_invert_area __ARGS((int, int, int, int, int how)); 568 static void clip_invert_rectangle __ARGS((int row, int col, int height, int width, int invert)); 569 static void clip_get_word_boundaries __ARGS((VimClipboard *, int, int)); 570 static int clip_get_line_end __ARGS((int)); 571 static void clip_update_modeless_selection __ARGS((VimClipboard *, int, int, 572 int, int)); 573 574 /* flags for clip_invert_area() */ 575 #define CLIP_CLEAR 1 576 #define CLIP_SET 2 577 #define CLIP_TOGGLE 3 578 579 /* 580 * Start, continue or end a modeless selection. Used when editing the 581 * command-line and in the cmdline window. 582 */ 583 void 584 clip_modeless(button, is_click, is_drag) 585 int button; 586 int is_click; 587 int is_drag; 588 { 589 int repeat; 590 591 repeat = ((clip_star.mode == SELECT_MODE_CHAR 592 || clip_star.mode == SELECT_MODE_LINE) 593 && (mod_mask & MOD_MASK_2CLICK)) 594 || (clip_star.mode == SELECT_MODE_WORD 595 && (mod_mask & MOD_MASK_3CLICK)); 596 if (is_click && button == MOUSE_RIGHT) 597 { 598 /* Right mouse button: If there was no selection, start one. 599 * Otherwise extend the existing selection. */ 600 if (clip_star.state == SELECT_CLEARED) 601 clip_start_selection(mouse_col, mouse_row, FALSE); 602 clip_process_selection(button, mouse_col, mouse_row, repeat); 603 } 604 else if (is_click) 605 clip_start_selection(mouse_col, mouse_row, repeat); 606 else if (is_drag) 607 { 608 /* Don't try extending a selection if there isn't one. Happens when 609 * button-down is in the cmdline and them moving mouse upwards. */ 610 if (clip_star.state != SELECT_CLEARED) 611 clip_process_selection(button, mouse_col, mouse_row, repeat); 612 } 613 else /* release */ 614 clip_process_selection(MOUSE_RELEASE, mouse_col, mouse_row, FALSE); 615 } 616 617 /* 618 * Compare two screen positions ala strcmp() 619 */ 620 static int 621 clip_compare_pos(row1, col1, row2, col2) 622 int row1; 623 int col1; 624 int row2; 625 int col2; 626 { 627 if (row1 > row2) return(1); 628 if (row1 < row2) return(-1); 629 if (col1 > col2) return(1); 630 if (col1 < col2) return(-1); 631 return(0); 632 } 633 634 /* 635 * Start the selection 636 */ 637 void 638 clip_start_selection(col, row, repeated_click) 639 int col; 640 int row; 641 int repeated_click; 642 { 643 VimClipboard *cb = &clip_star; 644 645 if (cb->state == SELECT_DONE) 646 clip_clear_selection(); 647 648 row = check_row(row); 649 col = check_col(col); 650 #ifdef FEAT_MBYTE 651 col = mb_fix_col(col, row); 652 #endif 653 654 cb->start.lnum = row; 655 cb->start.col = col; 656 cb->end = cb->start; 657 cb->origin_row = (short_u)cb->start.lnum; 658 cb->state = SELECT_IN_PROGRESS; 659 660 if (repeated_click) 661 { 662 if (++cb->mode > SELECT_MODE_LINE) 663 cb->mode = SELECT_MODE_CHAR; 664 } 665 else 666 cb->mode = SELECT_MODE_CHAR; 667 668 #ifdef FEAT_GUI 669 /* clear the cursor until the selection is made */ 670 if (gui.in_use) 671 gui_undraw_cursor(); 672 #endif 673 674 switch (cb->mode) 675 { 676 case SELECT_MODE_CHAR: 677 cb->origin_start_col = cb->start.col; 678 cb->word_end_col = clip_get_line_end((int)cb->start.lnum); 679 break; 680 681 case SELECT_MODE_WORD: 682 clip_get_word_boundaries(cb, (int)cb->start.lnum, cb->start.col); 683 cb->origin_start_col = cb->word_start_col; 684 cb->origin_end_col = cb->word_end_col; 685 686 clip_invert_area((int)cb->start.lnum, cb->word_start_col, 687 (int)cb->end.lnum, cb->word_end_col, CLIP_SET); 688 cb->start.col = cb->word_start_col; 689 cb->end.col = cb->word_end_col; 690 break; 691 692 case SELECT_MODE_LINE: 693 clip_invert_area((int)cb->start.lnum, 0, (int)cb->start.lnum, 694 (int)Columns, CLIP_SET); 695 cb->start.col = 0; 696 cb->end.col = Columns; 697 break; 698 } 699 700 cb->prev = cb->start; 701 702 #ifdef DEBUG_SELECTION 703 printf("Selection started at (%u,%u)\n", cb->start.lnum, cb->start.col); 704 #endif 705 } 706 707 /* 708 * Continue processing the selection 709 */ 710 void 711 clip_process_selection(button, col, row, repeated_click) 712 int button; 713 int col; 714 int row; 715 int_u repeated_click; 716 { 717 VimClipboard *cb = &clip_star; 718 int diff; 719 int slen = 1; /* cursor shape width */ 720 721 if (button == MOUSE_RELEASE) 722 { 723 /* Check to make sure we have something selected */ 724 if (cb->start.lnum == cb->end.lnum && cb->start.col == cb->end.col) 725 { 726 #ifdef FEAT_GUI 727 if (gui.in_use) 728 gui_update_cursor(FALSE, FALSE); 729 #endif 730 cb->state = SELECT_CLEARED; 731 return; 732 } 733 734 #ifdef DEBUG_SELECTION 735 printf("Selection ended: (%u,%u) to (%u,%u)\n", cb->start.lnum, 736 cb->start.col, cb->end.lnum, cb->end.col); 737 #endif 738 if (clip_isautosel() 739 || ( 740 #ifdef FEAT_GUI 741 gui.in_use ? (vim_strchr(p_go, GO_ASELML) != NULL) : 742 #endif 743 clip_autoselectml)) 744 clip_copy_modeless_selection(FALSE); 745 #ifdef FEAT_GUI 746 if (gui.in_use) 747 gui_update_cursor(FALSE, FALSE); 748 #endif 749 750 cb->state = SELECT_DONE; 751 return; 752 } 753 754 row = check_row(row); 755 col = check_col(col); 756 #ifdef FEAT_MBYTE 757 col = mb_fix_col(col, row); 758 #endif 759 760 if (col == (int)cb->prev.col && row == cb->prev.lnum && !repeated_click) 761 return; 762 763 /* 764 * When extending the selection with the right mouse button, swap the 765 * start and end if the position is before half the selection 766 */ 767 if (cb->state == SELECT_DONE && button == MOUSE_RIGHT) 768 { 769 /* 770 * If the click is before the start, or the click is inside the 771 * selection and the start is the closest side, set the origin to the 772 * end of the selection. 773 */ 774 if (clip_compare_pos(row, col, (int)cb->start.lnum, cb->start.col) < 0 775 || (clip_compare_pos(row, col, 776 (int)cb->end.lnum, cb->end.col) < 0 777 && (((cb->start.lnum == cb->end.lnum 778 && cb->end.col - col > col - cb->start.col)) 779 || ((diff = (cb->end.lnum - row) - 780 (row - cb->start.lnum)) > 0 781 || (diff == 0 && col < (int)(cb->start.col + 782 cb->end.col) / 2))))) 783 { 784 cb->origin_row = (short_u)cb->end.lnum; 785 cb->origin_start_col = cb->end.col - 1; 786 cb->origin_end_col = cb->end.col; 787 } 788 else 789 { 790 cb->origin_row = (short_u)cb->start.lnum; 791 cb->origin_start_col = cb->start.col; 792 cb->origin_end_col = cb->start.col; 793 } 794 if (cb->mode == SELECT_MODE_WORD && !repeated_click) 795 cb->mode = SELECT_MODE_CHAR; 796 } 797 798 /* set state, for when using the right mouse button */ 799 cb->state = SELECT_IN_PROGRESS; 800 801 #ifdef DEBUG_SELECTION 802 printf("Selection extending to (%d,%d)\n", row, col); 803 #endif 804 805 if (repeated_click && ++cb->mode > SELECT_MODE_LINE) 806 cb->mode = SELECT_MODE_CHAR; 807 808 switch (cb->mode) 809 { 810 case SELECT_MODE_CHAR: 811 /* If we're on a different line, find where the line ends */ 812 if (row != cb->prev.lnum) 813 cb->word_end_col = clip_get_line_end(row); 814 815 /* See if we are before or after the origin of the selection */ 816 if (clip_compare_pos(row, col, cb->origin_row, 817 cb->origin_start_col) >= 0) 818 { 819 if (col >= (int)cb->word_end_col) 820 clip_update_modeless_selection(cb, cb->origin_row, 821 cb->origin_start_col, row, (int)Columns); 822 else 823 { 824 #ifdef FEAT_MBYTE 825 if (has_mbyte && mb_lefthalve(row, col)) 826 slen = 2; 827 #endif 828 clip_update_modeless_selection(cb, cb->origin_row, 829 cb->origin_start_col, row, col + slen); 830 } 831 } 832 else 833 { 834 #ifdef FEAT_MBYTE 835 if (has_mbyte 836 && mb_lefthalve(cb->origin_row, cb->origin_start_col)) 837 slen = 2; 838 #endif 839 if (col >= (int)cb->word_end_col) 840 clip_update_modeless_selection(cb, row, cb->word_end_col, 841 cb->origin_row, cb->origin_start_col + slen); 842 else 843 clip_update_modeless_selection(cb, row, col, 844 cb->origin_row, cb->origin_start_col + slen); 845 } 846 break; 847 848 case SELECT_MODE_WORD: 849 /* If we are still within the same word, do nothing */ 850 if (row == cb->prev.lnum && col >= (int)cb->word_start_col 851 && col < (int)cb->word_end_col && !repeated_click) 852 return; 853 854 /* Get new word boundaries */ 855 clip_get_word_boundaries(cb, row, col); 856 857 /* Handle being after the origin point of selection */ 858 if (clip_compare_pos(row, col, cb->origin_row, 859 cb->origin_start_col) >= 0) 860 clip_update_modeless_selection(cb, cb->origin_row, 861 cb->origin_start_col, row, cb->word_end_col); 862 else 863 clip_update_modeless_selection(cb, row, cb->word_start_col, 864 cb->origin_row, cb->origin_end_col); 865 break; 866 867 case SELECT_MODE_LINE: 868 if (row == cb->prev.lnum && !repeated_click) 869 return; 870 871 if (clip_compare_pos(row, col, cb->origin_row, 872 cb->origin_start_col) >= 0) 873 clip_update_modeless_selection(cb, cb->origin_row, 0, row, 874 (int)Columns); 875 else 876 clip_update_modeless_selection(cb, row, 0, cb->origin_row, 877 (int)Columns); 878 break; 879 } 880 881 cb->prev.lnum = row; 882 cb->prev.col = col; 883 884 #ifdef DEBUG_SELECTION 885 printf("Selection is: (%u,%u) to (%u,%u)\n", cb->start.lnum, 886 cb->start.col, cb->end.lnum, cb->end.col); 887 #endif 888 } 889 890 #if 0 /* not used */ 891 /* 892 * Called after an Expose event to redraw the selection 893 */ 894 void 895 clip_redraw_selection(x, y, w, h) 896 int x; 897 int y; 898 int w; 899 int h; 900 { 901 VimClipboard *cb = &clip_star; 902 int row1, col1, row2, col2; 903 int row; 904 int start; 905 int end; 906 907 if (cb->state == SELECT_CLEARED) 908 return; 909 910 row1 = check_row(Y_2_ROW(y)); 911 col1 = check_col(X_2_COL(x)); 912 row2 = check_row(Y_2_ROW(y + h - 1)); 913 col2 = check_col(X_2_COL(x + w - 1)); 914 915 /* Limit the rows that need to be re-drawn */ 916 if (cb->start.lnum > row1) 917 row1 = cb->start.lnum; 918 if (cb->end.lnum < row2) 919 row2 = cb->end.lnum; 920 921 /* Look at each row that might need to be re-drawn */ 922 for (row = row1; row <= row2; row++) 923 { 924 /* For the first selection row, use the starting selection column */ 925 if (row == cb->start.lnum) 926 start = cb->start.col; 927 else 928 start = 0; 929 930 /* For the last selection row, use the ending selection column */ 931 if (row == cb->end.lnum) 932 end = cb->end.col; 933 else 934 end = Columns; 935 936 if (col1 > start) 937 start = col1; 938 939 if (col2 < end) 940 end = col2 + 1; 941 942 if (end > start) 943 gui_mch_invert_rectangle(row, start, 1, end - start); 944 } 945 } 946 #endif 947 948 # if defined(FEAT_GUI) || defined(PROTO) 949 /* 950 * Redraw part of the selection if character at "row,col" is inside of it. 951 * Only used for the GUI. 952 */ 953 void 954 clip_may_redraw_selection(row, col, len) 955 int row, col; 956 int len; 957 { 958 int start = col; 959 int end = col + len; 960 961 if (clip_star.state != SELECT_CLEARED 962 && row >= clip_star.start.lnum 963 && row <= clip_star.end.lnum) 964 { 965 if (row == clip_star.start.lnum && start < (int)clip_star.start.col) 966 start = clip_star.start.col; 967 if (row == clip_star.end.lnum && end > (int)clip_star.end.col) 968 end = clip_star.end.col; 969 if (end > start) 970 clip_invert_area(row, start, row, end, 0); 971 } 972 } 973 # endif 974 975 /* 976 * Called from outside to clear selected region from the display 977 */ 978 void 979 clip_clear_selection() 980 { 981 VimClipboard *cb = &clip_star; 982 983 if (cb->state == SELECT_CLEARED) 984 return; 985 986 clip_invert_area((int)cb->start.lnum, cb->start.col, (int)cb->end.lnum, 987 cb->end.col, CLIP_CLEAR); 988 cb->state = SELECT_CLEARED; 989 } 990 991 /* 992 * Clear the selection if any lines from "row1" to "row2" are inside of it. 993 */ 994 void 995 clip_may_clear_selection(row1, row2) 996 int row1, row2; 997 { 998 if (clip_star.state == SELECT_DONE 999 && row2 >= clip_star.start.lnum 1000 && row1 <= clip_star.end.lnum) 1001 clip_clear_selection(); 1002 } 1003 1004 /* 1005 * Called before the screen is scrolled up or down. Adjusts the line numbers 1006 * of the selection. Call with big number when clearing the screen. 1007 */ 1008 void 1009 clip_scroll_selection(rows) 1010 int rows; /* negative for scroll down */ 1011 { 1012 int lnum; 1013 1014 if (clip_star.state == SELECT_CLEARED) 1015 return; 1016 1017 lnum = clip_star.start.lnum - rows; 1018 if (lnum <= 0) 1019 clip_star.start.lnum = 0; 1020 else if (lnum >= screen_Rows) /* scrolled off of the screen */ 1021 clip_star.state = SELECT_CLEARED; 1022 else 1023 clip_star.start.lnum = lnum; 1024 1025 lnum = clip_star.end.lnum - rows; 1026 if (lnum < 0) /* scrolled off of the screen */ 1027 clip_star.state = SELECT_CLEARED; 1028 else if (lnum >= screen_Rows) 1029 clip_star.end.lnum = screen_Rows - 1; 1030 else 1031 clip_star.end.lnum = lnum; 1032 } 1033 1034 /* 1035 * Invert a region of the display between a starting and ending row and column 1036 * Values for "how": 1037 * CLIP_CLEAR: undo inversion 1038 * CLIP_SET: set inversion 1039 * CLIP_TOGGLE: set inversion if pos1 < pos2, undo inversion otherwise. 1040 * 0: invert (GUI only). 1041 */ 1042 static void 1043 clip_invert_area(row1, col1, row2, col2, how) 1044 int row1; 1045 int col1; 1046 int row2; 1047 int col2; 1048 int how; 1049 { 1050 int invert = FALSE; 1051 1052 if (how == CLIP_SET) 1053 invert = TRUE; 1054 1055 /* Swap the from and to positions so the from is always before */ 1056 if (clip_compare_pos(row1, col1, row2, col2) > 0) 1057 { 1058 int tmp_row, tmp_col; 1059 1060 tmp_row = row1; 1061 tmp_col = col1; 1062 row1 = row2; 1063 col1 = col2; 1064 row2 = tmp_row; 1065 col2 = tmp_col; 1066 } 1067 else if (how == CLIP_TOGGLE) 1068 invert = TRUE; 1069 1070 /* If all on the same line, do it the easy way */ 1071 if (row1 == row2) 1072 { 1073 clip_invert_rectangle(row1, col1, 1, col2 - col1, invert); 1074 } 1075 else 1076 { 1077 /* Handle a piece of the first line */ 1078 if (col1 > 0) 1079 { 1080 clip_invert_rectangle(row1, col1, 1, (int)Columns - col1, invert); 1081 row1++; 1082 } 1083 1084 /* Handle a piece of the last line */ 1085 if (col2 < Columns - 1) 1086 { 1087 clip_invert_rectangle(row2, 0, 1, col2, invert); 1088 row2--; 1089 } 1090 1091 /* Handle the rectangle thats left */ 1092 if (row2 >= row1) 1093 clip_invert_rectangle(row1, 0, row2 - row1 + 1, (int)Columns, 1094 invert); 1095 } 1096 } 1097 1098 /* 1099 * Invert or un-invert a rectangle of the screen. 1100 * "invert" is true if the result is inverted. 1101 */ 1102 static void 1103 clip_invert_rectangle(row, col, height, width, invert) 1104 int row; 1105 int col; 1106 int height; 1107 int width; 1108 int invert; 1109 { 1110 #ifdef FEAT_GUI 1111 if (gui.in_use) 1112 gui_mch_invert_rectangle(row, col, height, width); 1113 else 1114 #endif 1115 screen_draw_rectangle(row, col, height, width, invert); 1116 } 1117 1118 /* 1119 * Copy the currently selected area into the '*' register so it will be 1120 * available for pasting. 1121 * When "both" is TRUE also copy to the '+' register. 1122 */ 1123 /*ARGSUSED*/ 1124 void 1125 clip_copy_modeless_selection(both) 1126 int both; 1127 { 1128 char_u *buffer; 1129 char_u *bufp; 1130 int row; 1131 int start_col; 1132 int end_col; 1133 int line_end_col; 1134 int add_newline_flag = FALSE; 1135 int len; 1136 #ifdef FEAT_MBYTE 1137 char_u *p; 1138 int i; 1139 #endif 1140 int row1 = clip_star.start.lnum; 1141 int col1 = clip_star.start.col; 1142 int row2 = clip_star.end.lnum; 1143 int col2 = clip_star.end.col; 1144 1145 /* Can't use ScreenLines unless initialized */ 1146 if (ScreenLines == NULL) 1147 return; 1148 1149 /* 1150 * Make sure row1 <= row2, and if row1 == row2 that col1 <= col2. 1151 */ 1152 if (row1 > row2) 1153 { 1154 row = row1; row1 = row2; row2 = row; 1155 row = col1; col1 = col2; col2 = row; 1156 } 1157 else if (row1 == row2 && col1 > col2) 1158 { 1159 row = col1; col1 = col2; col2 = row; 1160 } 1161 #ifdef FEAT_MBYTE 1162 /* correct starting point for being on right halve of double-wide char */ 1163 p = ScreenLines + LineOffset[row1]; 1164 if (enc_dbcs != 0) 1165 col1 -= (*mb_head_off)(p, p + col1); 1166 else if (enc_utf8 && p[col1] == 0) 1167 --col1; 1168 #endif 1169 1170 /* Create a temporary buffer for storing the text */ 1171 len = (row2 - row1 + 1) * Columns + 1; 1172 #ifdef FEAT_MBYTE 1173 if (enc_dbcs != 0) 1174 len *= 2; /* max. 2 bytes per display cell */ 1175 else if (enc_utf8) 1176 len *= 9; /* max. 3 bytes per display cell + 2 composing chars */ 1177 #endif 1178 buffer = lalloc((long_u)len, TRUE); 1179 if (buffer == NULL) /* out of memory */ 1180 return; 1181 1182 /* Process each row in the selection */ 1183 for (bufp = buffer, row = row1; row <= row2; row++) 1184 { 1185 if (row == row1) 1186 start_col = col1; 1187 else 1188 start_col = 0; 1189 1190 if (row == row2) 1191 end_col = col2; 1192 else 1193 end_col = Columns; 1194 1195 line_end_col = clip_get_line_end(row); 1196 1197 /* See if we need to nuke some trailing whitespace */ 1198 if (end_col >= Columns && (row < row2 || end_col > line_end_col)) 1199 { 1200 /* Get rid of trailing whitespace */ 1201 end_col = line_end_col; 1202 if (end_col < start_col) 1203 end_col = start_col; 1204 1205 /* If the last line extended to the end, add an extra newline */ 1206 if (row == row2) 1207 add_newline_flag = TRUE; 1208 } 1209 1210 /* If after the first row, we need to always add a newline */ 1211 if (row > row1 && !LineWraps[row - 1]) 1212 *bufp++ = NL; 1213 1214 if (row < screen_Rows && end_col <= screen_Columns) 1215 { 1216 #ifdef FEAT_MBYTE 1217 if (enc_dbcs != 0) 1218 { 1219 p = ScreenLines + LineOffset[row]; 1220 for (i = start_col; i < end_col; ++i) 1221 if (enc_dbcs == DBCS_JPNU && p[i] == 0x8e) 1222 { 1223 /* single-width double-byte char */ 1224 *bufp++ = 0x8e; 1225 *bufp++ = ScreenLines2[LineOffset[row] + i]; 1226 } 1227 else 1228 { 1229 *bufp++ = p[i]; 1230 if (MB_BYTE2LEN(p[i]) == 2) 1231 *bufp++ = p[++i]; 1232 } 1233 } 1234 else if (enc_utf8) 1235 { 1236 int off; 1237 1238 off = LineOffset[row]; 1239 for (i = start_col; i < end_col; ++i) 1240 { 1241 /* The base character is either in ScreenLinesUC[] or 1242 * ScreenLines[]. */ 1243 if (ScreenLinesUC[off + i] == 0) 1244 *bufp++ = ScreenLines[off + i]; 1245 else 1246 { 1247 bufp += utf_char2bytes(ScreenLinesUC[off + i], bufp); 1248 if (ScreenLinesC1[off + i] != 0) 1249 { 1250 /* Add one or two composing characters. */ 1251 bufp += utf_char2bytes(ScreenLinesC1[off + i], 1252 bufp); 1253 if (ScreenLinesC2[off + i] != 0) 1254 bufp += utf_char2bytes(ScreenLinesC2[off + i], 1255 bufp); 1256 } 1257 } 1258 /* Skip right halve of double-wide character. */ 1259 if (ScreenLines[off + i + 1] == 0) 1260 ++i; 1261 } 1262 } 1263 else 1264 #endif 1265 { 1266 STRNCPY(bufp, ScreenLines + LineOffset[row] + start_col, 1267 end_col - start_col); 1268 bufp += end_col - start_col; 1269 } 1270 } 1271 } 1272 1273 /* Add a newline at the end if the selection ended there */ 1274 if (add_newline_flag) 1275 *bufp++ = NL; 1276 1277 /* First cleanup any old selection and become the owner. */ 1278 clip_free_selection(&clip_star); 1279 clip_own_selection(&clip_star); 1280 1281 /* Yank the text into the '*' register. */ 1282 clip_yank_selection(MCHAR, buffer, (long)(bufp - buffer), &clip_star); 1283 1284 /* Make the register contents available to the outside world. */ 1285 clip_gen_set_selection(&clip_star); 1286 1287 #ifdef FEAT_X11 1288 if (both) 1289 { 1290 /* Do the same for the '+' register. */ 1291 clip_free_selection(&clip_plus); 1292 clip_own_selection(&clip_plus); 1293 clip_yank_selection(MCHAR, buffer, (long)(bufp - buffer), &clip_plus); 1294 clip_gen_set_selection(&clip_plus); 1295 } 1296 #endif 1297 vim_free(buffer); 1298 } 1299 1300 /* 1301 * Find the starting and ending positions of the word at the given row and 1302 * column. Only white-separated words are recognized here. 1303 */ 1304 #define CHAR_CLASS(c) (c <= ' ' ? ' ' : vim_iswordc(c)) 1305 1306 static void 1307 clip_get_word_boundaries(cb, row, col) 1308 VimClipboard *cb; 1309 int row; 1310 int col; 1311 { 1312 int start_class; 1313 int temp_col; 1314 char_u *p; 1315 #ifdef FEAT_MBYTE 1316 int mboff; 1317 #endif 1318 1319 if (row >= screen_Rows || col >= screen_Columns || ScreenLines == NULL) 1320 return; 1321 1322 p = ScreenLines + LineOffset[row]; 1323 #ifdef FEAT_MBYTE 1324 /* Correct for starting in the right halve of a double-wide char */ 1325 if (enc_dbcs != 0) 1326 col -= dbcs_screen_head_off(p, p + col); 1327 else if (enc_utf8 && p[col] == 0) 1328 --col; 1329 #endif 1330 start_class = CHAR_CLASS(p[col]); 1331 1332 temp_col = col; 1333 for ( ; temp_col > 0; temp_col--) 1334 #ifdef FEAT_MBYTE 1335 if (enc_dbcs != 0 1336 && (mboff = dbcs_screen_head_off(p, p + temp_col - 1)) > 0) 1337 temp_col -= mboff; 1338 else 1339 #endif 1340 if (CHAR_CLASS(p[temp_col - 1]) != start_class 1341 #ifdef FEAT_MBYTE 1342 && !(enc_utf8 && p[temp_col - 1] == 0) 1343 #endif 1344 ) 1345 break; 1346 cb->word_start_col = temp_col; 1347 1348 temp_col = col; 1349 for ( ; temp_col < screen_Columns; temp_col++) 1350 #ifdef FEAT_MBYTE 1351 if (enc_dbcs != 0 && dbcs_ptr2cells(p + temp_col) == 2) 1352 ++temp_col; 1353 else 1354 #endif 1355 if (CHAR_CLASS(p[temp_col]) != start_class 1356 #ifdef FEAT_MBYTE 1357 && !(enc_utf8 && p[temp_col] == 0) 1358 #endif 1359 ) 1360 break; 1361 cb->word_end_col = temp_col; 1362 } 1363 1364 /* 1365 * Find the column position for the last non-whitespace character on the given 1366 * line. 1367 */ 1368 static int 1369 clip_get_line_end(row) 1370 int row; 1371 { 1372 int i; 1373 1374 if (row >= screen_Rows || ScreenLines == NULL) 1375 return 0; 1376 for (i = screen_Columns; i > 0; i--) 1377 if (ScreenLines[LineOffset[row] + i - 1] != ' ') 1378 break; 1379 return i; 1380 } 1381 1382 /* 1383 * Update the currently selected region by adding and/or subtracting from the 1384 * beginning or end and inverting the changed area(s). 1385 */ 1386 static void 1387 clip_update_modeless_selection(cb, row1, col1, row2, col2) 1388 VimClipboard *cb; 1389 int row1; 1390 int col1; 1391 int row2; 1392 int col2; 1393 { 1394 /* See if we changed at the beginning of the selection */ 1395 if (row1 != cb->start.lnum || col1 != (int)cb->start.col) 1396 { 1397 clip_invert_area(row1, col1, (int)cb->start.lnum, cb->start.col, 1398 CLIP_TOGGLE); 1399 cb->start.lnum = row1; 1400 cb->start.col = col1; 1401 } 1402 1403 /* See if we changed at the end of the selection */ 1404 if (row2 != cb->end.lnum || col2 != (int)cb->end.col) 1405 { 1406 clip_invert_area((int)cb->end.lnum, cb->end.col, row2, col2, 1407 CLIP_TOGGLE); 1408 cb->end.lnum = row2; 1409 cb->end.col = col2; 1410 } 1411 } 1412 1413 int 1414 clip_gen_own_selection(cbd) 1415 VimClipboard *cbd; 1416 { 1417 #ifdef FEAT_XCLIPBOARD 1418 # ifdef FEAT_GUI 1419 if (gui.in_use) 1420 return clip_mch_own_selection(cbd); 1421 else 1422 # endif 1423 return clip_xterm_own_selection(cbd); 1424 #else 1425 return clip_mch_own_selection(cbd); 1426 #endif 1427 } 1428 1429 void 1430 clip_gen_lose_selection(cbd) 1431 VimClipboard *cbd; 1432 { 1433 #ifdef FEAT_XCLIPBOARD 1434 # ifdef FEAT_GUI 1435 if (gui.in_use) 1436 clip_mch_lose_selection(cbd); 1437 else 1438 # endif 1439 clip_xterm_lose_selection(cbd); 1440 #else 1441 clip_mch_lose_selection(cbd); 1442 #endif 1443 } 1444 1445 void 1446 clip_gen_set_selection(cbd) 1447 VimClipboard *cbd; 1448 { 1449 #ifdef FEAT_XCLIPBOARD 1450 # ifdef FEAT_GUI 1451 if (gui.in_use) 1452 clip_mch_set_selection(cbd); 1453 else 1454 # endif 1455 clip_xterm_set_selection(cbd); 1456 #else 1457 clip_mch_set_selection(cbd); 1458 #endif 1459 } 1460 1461 void 1462 clip_gen_request_selection(cbd) 1463 VimClipboard *cbd; 1464 { 1465 #ifdef FEAT_XCLIPBOARD 1466 # ifdef FEAT_GUI 1467 if (gui.in_use) 1468 clip_mch_request_selection(cbd); 1469 else 1470 # endif 1471 clip_xterm_request_selection(cbd); 1472 #else 1473 clip_mch_request_selection(cbd); 1474 #endif 1475 } 1476 1477 #endif /* FEAT_CLIPBOARD */ 1478 1479 /***************************************************************************** 1480 * Functions that handle the input buffer. 1481 * This is used for any GUI version, and the unix terminal version. 1482 * 1483 * For Unix, the input characters are buffered to be able to check for a 1484 * CTRL-C. This should be done with signals, but I don't know how to do that 1485 * in a portable way for a tty in RAW mode. 1486 * 1487 * For the client-server code in the console the received keys are put in the 1488 * input buffer. 1489 */ 1490 1491 #if defined(USE_INPUT_BUF) || defined(PROTO) 1492 1493 /* 1494 * Internal typeahead buffer. Includes extra space for long key code 1495 * descriptions which would otherwise overflow. The buffer is considered full 1496 * when only this extra space (or part of it) remains. 1497 */ 1498 #if defined(FEAT_SUN_WORKSHOP) || defined(FEAT_NETBEANS_INTG) \ 1499 || defined(FEAT_CLIENTSERVER) 1500 /* 1501 * Sun WorkShop and NetBeans stuff debugger commands into the input buffer. 1502 * This requires a larger buffer... 1503 * (Madsen) Go with this for remote input as well ... 1504 */ 1505 # define INBUFLEN 4096 1506 #else 1507 # define INBUFLEN 250 1508 #endif 1509 1510 static char_u inbuf[INBUFLEN + MAX_KEY_CODE_LEN]; 1511 static int inbufcount = 0; /* number of chars in inbuf[] */ 1512 1513 /* 1514 * vim_is_input_buf_full(), vim_is_input_buf_empty(), add_to_input_buf(), and 1515 * trash_input_buf() are functions for manipulating the input buffer. These 1516 * are used by the gui_* calls when a GUI is used to handle keyboard input. 1517 */ 1518 1519 int 1520 vim_is_input_buf_full() 1521 { 1522 return (inbufcount >= INBUFLEN); 1523 } 1524 1525 int 1526 vim_is_input_buf_empty() 1527 { 1528 return (inbufcount == 0); 1529 } 1530 1531 #if defined(FEAT_OLE) || defined(PROTO) 1532 int 1533 vim_free_in_input_buf() 1534 { 1535 return (INBUFLEN - inbufcount); 1536 } 1537 #endif 1538 1539 #if defined(FEAT_GUI_GTK) || defined(PROTO) 1540 int 1541 vim_used_in_input_buf() 1542 { 1543 return inbufcount; 1544 } 1545 #endif 1546 1547 #if defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) || defined(PROTO) 1548 /* 1549 * Return the current contents of the input buffer and make it empty. 1550 * The returned pointer must be passed to set_input_buf() later. 1551 */ 1552 char_u * 1553 get_input_buf() 1554 { 1555 garray_T *gap; 1556 1557 /* We use a growarray to store the data pointer and the length. */ 1558 gap = (garray_T *)alloc((unsigned)sizeof(garray_T)); 1559 if (gap != NULL) 1560 { 1561 /* Add one to avoid a zero size. */ 1562 gap->ga_data = alloc((unsigned)inbufcount + 1); 1563 if (gap->ga_data != NULL) 1564 mch_memmove(gap->ga_data, inbuf, (size_t)inbufcount); 1565 gap->ga_len = inbufcount; 1566 } 1567 trash_input_buf(); 1568 return (char_u *)gap; 1569 } 1570 1571 /* 1572 * Restore the input buffer with a pointer returned from get_input_buf(). 1573 * The allocated memory is freed, this only works once! 1574 */ 1575 void 1576 set_input_buf(p) 1577 char_u *p; 1578 { 1579 garray_T *gap = (garray_T *)p; 1580 1581 if (gap != NULL) 1582 { 1583 if (gap->ga_data != NULL) 1584 { 1585 mch_memmove(inbuf, gap->ga_data, gap->ga_len); 1586 inbufcount = gap->ga_len; 1587 vim_free(gap->ga_data); 1588 } 1589 vim_free(gap); 1590 } 1591 } 1592 #endif 1593 1594 #if defined(FEAT_GUI) || defined(FEAT_MOUSE_GPM) \ 1595 || defined(FEAT_XCLIPBOARD) || defined(VMS) \ 1596 || defined(FEAT_SNIFF) || defined(FEAT_CLIENTSERVER) || defined(PROTO) 1597 /* 1598 * Add the given bytes to the input buffer 1599 * Special keys start with CSI. A real CSI must have been translated to 1600 * CSI KS_EXTRA KE_CSI. K_SPECIAL doesn't require translation. 1601 */ 1602 void 1603 add_to_input_buf(s, len) 1604 char_u *s; 1605 int len; 1606 { 1607 if (inbufcount + len > INBUFLEN + MAX_KEY_CODE_LEN) 1608 return; /* Shouldn't ever happen! */ 1609 1610 #ifdef FEAT_HANGULIN 1611 if ((State & (INSERT|CMDLINE)) && hangul_input_state_get()) 1612 if ((len = hangul_input_process(s, len)) == 0) 1613 return; 1614 #endif 1615 1616 while (len--) 1617 inbuf[inbufcount++] = *s++; 1618 } 1619 #endif 1620 1621 #if (defined(FEAT_XIM) && defined(FEAT_GUI_GTK)) \ 1622 || (defined(FEAT_MBYTE) && defined(FEAT_MBYTE_IME)) \ 1623 || defined(PROTO) 1624 /* 1625 * Add "str[len]" to the input buffer while escaping CSI bytes. 1626 */ 1627 void 1628 add_to_input_buf_csi(char_u *str, int len) 1629 { 1630 int i; 1631 char_u buf[2]; 1632 1633 for (i = 0; i < len; ++i) 1634 { 1635 add_to_input_buf(str + i, 1); 1636 if (str[i] == CSI) 1637 { 1638 /* Turn CSI into K_CSI. */ 1639 buf[0] = KS_EXTRA; 1640 buf[1] = (int)KE_CSI; 1641 add_to_input_buf(buf, 2); 1642 } 1643 } 1644 } 1645 #endif 1646 1647 #if defined(FEAT_HANGULIN) || defined(PROTO) 1648 void 1649 push_raw_key (s, len) 1650 char_u *s; 1651 int len; 1652 { 1653 while (len--) 1654 inbuf[inbufcount++] = *s++; 1655 } 1656 #endif 1657 1658 #if defined(FEAT_GUI) || defined(FEAT_EVAL) || defined(FEAT_EX_EXTRA) \ 1659 || defined(PROTO) 1660 /* Remove everything from the input buffer. Called when ^C is found */ 1661 void 1662 trash_input_buf() 1663 { 1664 inbufcount = 0; 1665 } 1666 #endif 1667 1668 /* 1669 * Read as much data from the input buffer as possible up to maxlen, and store 1670 * it in buf. 1671 * Note: this function used to be Read() in unix.c 1672 */ 1673 int 1674 read_from_input_buf(buf, maxlen) 1675 char_u *buf; 1676 long maxlen; 1677 { 1678 if (inbufcount == 0) /* if the buffer is empty, fill it */ 1679 fill_input_buf(TRUE); 1680 if (maxlen > inbufcount) 1681 maxlen = inbufcount; 1682 mch_memmove(buf, inbuf, (size_t)maxlen); 1683 inbufcount -= maxlen; 1684 if (inbufcount) 1685 mch_memmove(inbuf, inbuf + maxlen, (size_t)inbufcount); 1686 return (int)maxlen; 1687 } 1688 1689 /*ARGSUSED*/ 1690 void 1691 fill_input_buf(exit_on_error) 1692 int exit_on_error; 1693 { 1694 #if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX) 1695 int len; 1696 int try; 1697 static int did_read_something = FALSE; 1698 # ifdef FEAT_MBYTE 1699 static char_u *rest = NULL; /* unconverted rest of previous read */ 1700 static int restlen = 0; 1701 int unconverted; 1702 # endif 1703 #endif 1704 1705 #ifdef FEAT_GUI 1706 if (gui.in_use 1707 # ifdef NO_CONSOLE_INPUT 1708 /* Don't use the GUI input when the window hasn't been opened yet. 1709 * We get here from ui_inchar() when we should try reading from stdin. */ 1710 && !no_console_input() 1711 # endif 1712 ) 1713 { 1714 gui_mch_update(); 1715 return; 1716 } 1717 #endif 1718 #if defined(UNIX) || defined(OS2) || defined(VMS) || defined(MACOS_X_UNIX) 1719 if (vim_is_input_buf_full()) 1720 return; 1721 /* 1722 * Fill_input_buf() is only called when we really need a character. 1723 * If we can't get any, but there is some in the buffer, just return. 1724 * If we can't get any, and there isn't any in the buffer, we give up and 1725 * exit Vim. 1726 */ 1727 # ifdef __BEOS__ 1728 /* 1729 * On the BeBox version (for now), all input is secretly performed within 1730 * beos_select() which is called from RealWaitForChar(). 1731 */ 1732 while (!vim_is_input_buf_full() && RealWaitForChar(read_cmd_fd, 0, NULL)) 1733 ; 1734 len = inbufcount; 1735 inbufcount = 0; 1736 # else 1737 1738 # ifdef FEAT_SNIFF 1739 if (sniff_request_waiting) 1740 { 1741 add_to_input_buf((char_u *)"\233sniff",6); /* results in K_SNIFF */ 1742 sniff_request_waiting = 0; 1743 want_sniff_request = 0; 1744 return; 1745 } 1746 # endif 1747 1748 # ifdef FEAT_MBYTE 1749 if (rest != NULL) 1750 { 1751 /* Use remainder of previous call, starts with an invalid character 1752 * that may become valid when reading more. */ 1753 if (restlen > INBUFLEN - inbufcount) 1754 unconverted = INBUFLEN - inbufcount; 1755 else 1756 unconverted = restlen; 1757 mch_memmove(inbuf + inbufcount, rest, unconverted); 1758 if (unconverted == restlen) 1759 { 1760 vim_free(rest); 1761 rest = NULL; 1762 } 1763 else 1764 { 1765 restlen -= unconverted; 1766 mch_memmove(rest, rest + unconverted, restlen); 1767 } 1768 inbufcount += unconverted; 1769 } 1770 else 1771 unconverted = 0; 1772 #endif 1773 1774 len = 0; /* to avoid gcc warning */ 1775 for (try = 0; try < 100; ++try) 1776 { 1777 # ifdef VMS 1778 len = vms_read( 1779 # else 1780 len = read(read_cmd_fd, 1781 # endif 1782 (char *)inbuf + inbufcount, (size_t)((INBUFLEN - inbufcount) 1783 # ifdef FEAT_MBYTE 1784 / input_conv.vc_factor 1785 # endif 1786 )); 1787 # if 0 1788 ) /* avoid syntax highlight error */ 1789 # endif 1790 1791 if (len > 0 || got_int) 1792 break; 1793 /* 1794 * If reading stdin results in an error, continue reading stderr. 1795 * This helps when using "foo | xargs vim". 1796 */ 1797 if (!did_read_something && !isatty(read_cmd_fd) && read_cmd_fd == 0) 1798 { 1799 int m = cur_tmode; 1800 1801 /* We probably set the wrong file descriptor to raw mode. Switch 1802 * back to cooked mode, use another descriptor and set the mode to 1803 * what it was. */ 1804 settmode(TMODE_COOK); 1805 #ifdef HAVE_DUP 1806 /* Use stderr for stdin, also works for shell commands. */ 1807 close(0); 1808 dup(2); 1809 #else 1810 read_cmd_fd = 2; /* read from stderr instead of stdin */ 1811 #endif 1812 settmode(m); 1813 } 1814 if (!exit_on_error) 1815 return; 1816 } 1817 # endif 1818 if (len <= 0 && !got_int) 1819 read_error_exit(); 1820 if (len > 0) 1821 did_read_something = TRUE; 1822 if (got_int) 1823 { 1824 /* Interrupted, pretend a CTRL-C was typed. */ 1825 inbuf[0] = 3; 1826 inbufcount = 1; 1827 } 1828 else 1829 { 1830 # ifdef FEAT_MBYTE 1831 /* 1832 * May perform conversion on the input characters. 1833 * Include the unconverted rest of the previous call. 1834 * If there is an incomplete char at the end it is kept for the next 1835 * time, reading more bytes should make conversion possible. 1836 * Don't do this in the unlikely event that the input buffer is too 1837 * small ("rest" still contains more bytes). 1838 */ 1839 if (input_conv.vc_type != CONV_NONE) 1840 { 1841 inbufcount -= unconverted; 1842 len = convert_input_safe(inbuf + inbufcount, 1843 len + unconverted, INBUFLEN - inbufcount, 1844 rest == NULL ? &rest : NULL, &restlen); 1845 } 1846 # endif 1847 while (len-- > 0) 1848 { 1849 /* 1850 * if a CTRL-C was typed, remove it from the buffer and set got_int 1851 */ 1852 if (inbuf[inbufcount] == 3 && ctrl_c_interrupts) 1853 { 1854 /* remove everything typed before the CTRL-C */ 1855 mch_memmove(inbuf, inbuf + inbufcount, (size_t)(len + 1)); 1856 inbufcount = 0; 1857 got_int = TRUE; 1858 } 1859 ++inbufcount; 1860 } 1861 } 1862 #endif /* UNIX or OS2 or VMS*/ 1863 } 1864 #endif /* defined(UNIX) || defined(FEAT_GUI) || defined(OS2) || defined(VMS) */ 1865 1866 /* 1867 * Exit because of an input read error. 1868 */ 1869 void 1870 read_error_exit() 1871 { 1872 if (silent_mode) /* Normal way to exit for "ex -s" */ 1873 getout(0); 1874 STRCPY(IObuff, _("Vim: Error reading input, exiting...\n")); 1875 preserve_exit(); 1876 } 1877 1878 #if defined(CURSOR_SHAPE) || defined(PROTO) 1879 /* 1880 * May update the shape of the cursor. 1881 */ 1882 void 1883 ui_cursor_shape() 1884 { 1885 # ifdef FEAT_GUI 1886 if (gui.in_use) 1887 gui_update_cursor_later(); 1888 else 1889 # endif 1890 term_cursor_shape(); 1891 1892 # ifdef MCH_CURSOR_SHAPE 1893 mch_update_cursor(); 1894 # endif 1895 } 1896 #endif 1897 1898 #if defined(FEAT_CLIPBOARD) || defined(FEAT_GUI) || defined(FEAT_RIGHTLEFT) \ 1899 || defined(PROTO) 1900 /* 1901 * Check bounds for column number 1902 */ 1903 int 1904 check_col(col) 1905 int col; 1906 { 1907 if (col < 0) 1908 return 0; 1909 if (col >= (int)screen_Columns) 1910 return (int)screen_Columns - 1; 1911 return col; 1912 } 1913 1914 /* 1915 * Check bounds for row number 1916 */ 1917 int 1918 check_row(row) 1919 int row; 1920 { 1921 if (row < 0) 1922 return 0; 1923 if (row >= (int)screen_Rows) 1924 return (int)screen_Rows - 1; 1925 return row; 1926 } 1927 #endif 1928 1929 /* 1930 * Stuff for the X clipboard. Shared between VMS and Unix. 1931 */ 1932 1933 #if defined(FEAT_XCLIPBOARD) || defined(FEAT_GUI_X11) || defined(PROTO) 1934 # include <X11/Xatom.h> 1935 # include <X11/Intrinsic.h> 1936 1937 /* 1938 * Open the application context (if it hasn't been opened yet). 1939 * Used for Motif and Athena GUI and the xterm clipboard. 1940 */ 1941 void 1942 open_app_context() 1943 { 1944 if (app_context == NULL) 1945 { 1946 XtToolkitInitialize(); 1947 app_context = XtCreateApplicationContext(); 1948 } 1949 } 1950 1951 static Atom vim_atom; /* Vim's own special selection format */ 1952 #ifdef FEAT_MBYTE 1953 static Atom vimenc_atom; /* Vim's extended selection format */ 1954 #endif 1955 static Atom compound_text_atom; 1956 static Atom text_atom; 1957 static Atom targets_atom; 1958 1959 void 1960 x11_setup_atoms(dpy) 1961 Display *dpy; 1962 { 1963 vim_atom = XInternAtom(dpy, VIM_ATOM_NAME, False); 1964 #ifdef FEAT_MBYTE 1965 vimenc_atom = XInternAtom(dpy, VIMENC_ATOM_NAME,False); 1966 #endif 1967 compound_text_atom = XInternAtom(dpy, "COMPOUND_TEXT", False); 1968 text_atom = XInternAtom(dpy, "TEXT", False); 1969 targets_atom = XInternAtom(dpy, "TARGETS", False); 1970 clip_star.sel_atom = XA_PRIMARY; 1971 clip_plus.sel_atom = XInternAtom(dpy, "CLIPBOARD", False); 1972 } 1973 1974 /* 1975 * X Selection stuff, for cutting and pasting text to other windows. 1976 */ 1977 1978 static void clip_x11_request_selection_cb __ARGS((Widget, XtPointer, Atom *, Atom *, XtPointer, long_u *, int *)); 1979 1980 /* ARGSUSED */ 1981 static void 1982 clip_x11_request_selection_cb(w, success, sel_atom, type, value, length, 1983 format) 1984 Widget w; 1985 XtPointer success; 1986 Atom *sel_atom; 1987 Atom *type; 1988 XtPointer value; 1989 long_u *length; 1990 int *format; 1991 { 1992 int motion_type; 1993 long_u len; 1994 char_u *p; 1995 char **text_list = NULL; 1996 VimClipboard *cbd; 1997 #ifdef FEAT_MBYTE 1998 char_u *tmpbuf = NULL; 1999 #endif 2000 2001 if (*sel_atom == clip_plus.sel_atom) 2002 cbd = &clip_plus; 2003 else 2004 cbd = &clip_star; 2005 2006 if (value == NULL || *length == 0) 2007 { 2008 clip_free_selection(cbd); /* ??? [what's the query?] */ 2009 *(int *)success = FALSE; 2010 return; 2011 } 2012 motion_type = MCHAR; 2013 p = (char_u *)value; 2014 len = *length; 2015 if (*type == vim_atom) 2016 { 2017 motion_type = *p++; 2018 len--; 2019 } 2020 2021 #ifdef FEAT_MBYTE 2022 else if (*type == vimenc_atom) 2023 { 2024 char_u *enc; 2025 vimconv_T conv; 2026 int convlen; 2027 2028 motion_type = *p++; 2029 --len; 2030 2031 enc = p; 2032 p += STRLEN(p) + 1; 2033 len -= p - enc; 2034 2035 /* If the encoding of the text is different from 'encoding', attempt 2036 * converting it. */ 2037 conv.vc_type = CONV_NONE; 2038 convert_setup(&conv, enc, p_enc); 2039 if (conv.vc_type != CONV_NONE) 2040 { 2041 convlen = len; /* Need to use an int here. */ 2042 tmpbuf = string_convert(&conv, p, &convlen); 2043 len = convlen; 2044 if (tmpbuf != NULL) 2045 p = tmpbuf; 2046 convert_setup(&conv, NULL, NULL); 2047 } 2048 } 2049 #endif 2050 2051 else if (*type == compound_text_atom || ( 2052 #ifdef FEAT_MBYTE 2053 enc_dbcs != 0 && 2054 #endif 2055 *type == text_atom)) 2056 { 2057 XTextProperty text_prop; 2058 int n_text = 0; 2059 int status; 2060 2061 text_prop.value = (unsigned char *)value; 2062 text_prop.encoding = *type; 2063 text_prop.format = *format; 2064 text_prop.nitems = STRLEN(value); 2065 status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop, 2066 &text_list, &n_text); 2067 if (status != Success || n_text < 1) 2068 { 2069 *(int *)success = FALSE; 2070 return; 2071 } 2072 p = (char_u *)text_list[0]; 2073 len = STRLEN(p); 2074 } 2075 clip_yank_selection(motion_type, p, (long)len, cbd); 2076 2077 if (text_list != NULL) 2078 XFreeStringList(text_list); 2079 #ifdef FEAT_MBYTE 2080 vim_free(tmpbuf); 2081 #endif 2082 XtFree((char *)value); 2083 *(int *)success = TRUE; 2084 } 2085 2086 void 2087 clip_x11_request_selection(myShell, dpy, cbd) 2088 Widget myShell; 2089 Display *dpy; 2090 VimClipboard *cbd; 2091 { 2092 XEvent event; 2093 Atom type; 2094 static int success; 2095 int i; 2096 int nbytes = 0; 2097 char_u *buffer; 2098 2099 for (i = 2100 #ifdef FEAT_MBYTE 2101 0 2102 #else 2103 1 2104 #endif 2105 ; i < 5; i++) 2106 { 2107 switch (i) 2108 { 2109 #ifdef FEAT_MBYTE 2110 case 0: type = vimenc_atom; break; 2111 #endif 2112 case 1: type = vim_atom; break; 2113 case 2: type = compound_text_atom; break; 2114 case 3: type = text_atom; break; 2115 default: type = XA_STRING; 2116 } 2117 XtGetSelectionValue(myShell, cbd->sel_atom, type, 2118 clip_x11_request_selection_cb, (XtPointer)&success, CurrentTime); 2119 2120 /* Make sure the request for the selection goes out before waiting for 2121 * a response. */ 2122 XFlush(dpy); 2123 2124 /* 2125 * Wait for result of selection request, otherwise if we type more 2126 * characters, then they will appear before the one that requested the 2127 * paste! Don't worry, we will catch up with any other events later. 2128 */ 2129 for (;;) 2130 { 2131 if (XCheckTypedEvent(dpy, SelectionNotify, &event)) 2132 break; 2133 2134 /* Do we need this? Probably not. */ 2135 XSync(dpy, False); 2136 2137 /* Bernhard Walle solved a slow paste response in an X terminal by 2138 * adding: usleep(10000); here. */ 2139 } 2140 2141 /* this is where clip_x11_request_selection_cb() is actually called */ 2142 XtDispatchEvent(&event); 2143 2144 if (success) 2145 return; 2146 } 2147 2148 /* Final fallback position - use the X CUT_BUFFER0 store */ 2149 buffer = (char_u *)XFetchBuffer(dpy, &nbytes, 0); 2150 if (nbytes > 0) 2151 { 2152 /* Got something */ 2153 clip_yank_selection(MCHAR, buffer, (long)nbytes, cbd); 2154 XFree((void *)buffer); 2155 if (p_verbose > 0) 2156 verb_msg((char_u *)_("Used CUT_BUFFER0 instead of empty selection")); 2157 } 2158 } 2159 2160 static Boolean clip_x11_convert_selection_cb __ARGS((Widget, Atom *, Atom *, Atom *, XtPointer *, long_u *, int *)); 2161 2162 /* ARGSUSED */ 2163 static Boolean 2164 clip_x11_convert_selection_cb(w, sel_atom, target, type, value, length, format) 2165 Widget w; 2166 Atom *sel_atom; 2167 Atom *target; 2168 Atom *type; 2169 XtPointer *value; 2170 long_u *length; 2171 int *format; 2172 { 2173 char_u *string; 2174 char_u *result; 2175 int motion_type; 2176 VimClipboard *cbd; 2177 int i; 2178 2179 if (*sel_atom == clip_plus.sel_atom) 2180 cbd = &clip_plus; 2181 else 2182 cbd = &clip_star; 2183 2184 if (!cbd->owned) 2185 return False; /* Shouldn't ever happen */ 2186 2187 /* requestor wants to know what target types we support */ 2188 if (*target == targets_atom) 2189 { 2190 Atom *array; 2191 2192 if ((array = (Atom *)XtMalloc((unsigned)(sizeof(Atom) * 6))) == NULL) 2193 return False; 2194 *value = (XtPointer)array; 2195 i = 0; 2196 array[i++] = XA_STRING; 2197 array[i++] = targets_atom; 2198 #ifdef FEAT_MBYTE 2199 array[i++] = vimenc_atom; 2200 #endif 2201 array[i++] = vim_atom; 2202 array[i++] = text_atom; 2203 array[i++] = compound_text_atom; 2204 *type = XA_ATOM; 2205 /* This used to be: *format = sizeof(Atom) * 8; but that caused 2206 * crashes on 64 bit machines. (Peter Derr) */ 2207 *format = 32; 2208 *length = i; 2209 return True; 2210 } 2211 2212 if ( *target != XA_STRING 2213 #ifdef FEAT_MBYTE 2214 && *target != vimenc_atom 2215 #endif 2216 && *target != vim_atom 2217 && *target != text_atom 2218 && *target != compound_text_atom) 2219 return False; 2220 2221 clip_get_selection(cbd); 2222 motion_type = clip_convert_selection(&string, length, cbd); 2223 if (motion_type < 0) 2224 return False; 2225 2226 /* For our own format, the first byte contains the motion type */ 2227 if (*target == vim_atom) 2228 (*length)++; 2229 2230 #ifdef FEAT_MBYTE 2231 /* Our own format with encoding: motion 'encoding' NUL text */ 2232 if (*target == vimenc_atom) 2233 *length += STRLEN(p_enc) + 2; 2234 #endif 2235 2236 *value = XtMalloc((Cardinal)*length); 2237 result = (char_u *)*value; 2238 if (result == NULL) 2239 { 2240 vim_free(string); 2241 return False; 2242 } 2243 2244 if (*target == XA_STRING) 2245 { 2246 mch_memmove(result, string, (size_t)(*length)); 2247 *type = XA_STRING; 2248 } 2249 else if (*target == compound_text_atom 2250 || *target == text_atom) 2251 { 2252 XTextProperty text_prop; 2253 char *string_nt = (char *)alloc((unsigned)*length + 1); 2254 2255 /* create NUL terminated string which XmbTextListToTextProperty wants */ 2256 mch_memmove(string_nt, string, (size_t)*length); 2257 string_nt[*length] = NUL; 2258 XmbTextListToTextProperty(X_DISPLAY, (char **)&string_nt, 1, 2259 XCompoundTextStyle, &text_prop); 2260 vim_free(string_nt); 2261 XtFree(*value); /* replace with COMPOUND text */ 2262 *value = (XtPointer)(text_prop.value); /* from plain text */ 2263 *length = text_prop.nitems; 2264 *type = compound_text_atom; 2265 } 2266 2267 #ifdef FEAT_MBYTE 2268 else if (*target == vimenc_atom) 2269 { 2270 int l = STRLEN(p_enc); 2271 2272 result[0] = motion_type; 2273 STRCPY(result + 1, p_enc); 2274 mch_memmove(result + l + 2, string, (size_t)(*length - l - 2)); 2275 *type = vimenc_atom; 2276 } 2277 #endif 2278 2279 else 2280 { 2281 result[0] = motion_type; 2282 mch_memmove(result + 1, string, (size_t)(*length - 1)); 2283 *type = vim_atom; 2284 } 2285 *format = 8; /* 8 bits per char */ 2286 vim_free(string); 2287 return True; 2288 } 2289 2290 static void clip_x11_lose_ownership_cb __ARGS((Widget, Atom *)); 2291 2292 /* ARGSUSED */ 2293 static void 2294 clip_x11_lose_ownership_cb(w, sel_atom) 2295 Widget w; 2296 Atom *sel_atom; 2297 { 2298 if (*sel_atom == clip_plus.sel_atom) 2299 clip_lose_selection(&clip_plus); 2300 else 2301 clip_lose_selection(&clip_star); 2302 } 2303 2304 void 2305 clip_x11_lose_selection(myShell, cbd) 2306 Widget myShell; 2307 VimClipboard *cbd; 2308 { 2309 XtDisownSelection(myShell, cbd->sel_atom, CurrentTime); 2310 } 2311 2312 int 2313 clip_x11_own_selection(myShell, cbd) 2314 Widget myShell; 2315 VimClipboard *cbd; 2316 { 2317 if (XtOwnSelection(myShell, cbd->sel_atom, CurrentTime, 2318 clip_x11_convert_selection_cb, clip_x11_lose_ownership_cb, 2319 NULL) == False) 2320 return FAIL; 2321 return OK; 2322 } 2323 2324 /* 2325 * Send the current selection to the clipboard. Do nothing for X because we 2326 * will fill in the selection only when requested by another app. 2327 */ 2328 /*ARGSUSED*/ 2329 void 2330 clip_x11_set_selection(cbd) 2331 VimClipboard *cbd; 2332 { 2333 } 2334 #endif 2335 2336 #if defined(FEAT_MOUSE) || defined(PROTO) 2337 2338 /* 2339 * Move the cursor to the specified row and column on the screen. 2340 * Change current window if neccesary. Returns an integer with the 2341 * CURSOR_MOVED bit set if the cursor has moved or unset otherwise. 2342 * 2343 * The MOUSE_FOLD_CLOSE bit is set when clicked on the '-' in a fold column. 2344 * The MOUSE_FOLD_OPEN bit is set when clicked on the '+' in a fold column. 2345 * 2346 * If flags has MOUSE_FOCUS, then the current window will not be changed, and 2347 * if the mouse is outside the window then the text will scroll, or if the 2348 * mouse was previously on a status line, then the status line may be dragged. 2349 * 2350 * If flags has MOUSE_MAY_VIS, then VIsual mode will be started before the 2351 * cursor is moved unless the cursor was on a status line. 2352 * This function returns one of IN_UNKNOWN, IN_BUFFER, IN_STATUS_LINE or 2353 * IN_SEP_LINE depending on where the cursor was clicked. 2354 * 2355 * If flags has MOUSE_MAY_STOP_VIS, then Visual mode will be stopped, unless 2356 * the mouse is on the status line of the same window. 2357 * 2358 * If flags has MOUSE_DID_MOVE, nothing is done if the mouse didn't move since 2359 * the last call. 2360 * 2361 * If flags has MOUSE_SETPOS, nothing is done, only the current position is 2362 * remembered. 2363 */ 2364 int 2365 jump_to_mouse(flags, inclusive, which_button) 2366 int flags; 2367 int *inclusive; /* used for inclusive operator, can be NULL */ 2368 int which_button; /* MOUSE_LEFT, MOUSE_RIGHT, MOUSE_MIDDLE */ 2369 { 2370 static int on_status_line = 0; /* #lines below bottom of window */ 2371 #ifdef FEAT_VERTSPLIT 2372 static int on_sep_line = 0; /* on separator right of window */ 2373 #endif 2374 static int prev_row = -1; 2375 static int prev_col = -1; 2376 static win_T *dragwin = NULL; /* window being dragged */ 2377 static int did_drag = FALSE; /* drag was noticed */ 2378 2379 win_T *wp, *old_curwin; 2380 pos_T old_cursor; 2381 int count; 2382 int first; 2383 int row = mouse_row; 2384 int col = mouse_col; 2385 #ifdef FEAT_FOLDING 2386 int mouse_char; 2387 #endif 2388 2389 mouse_past_bottom = FALSE; 2390 mouse_past_eol = FALSE; 2391 2392 if (flags & MOUSE_RELEASED) 2393 { 2394 /* On button release we may change window focus if positioned on a 2395 * status line and no dragging happened. */ 2396 if (dragwin != NULL && !did_drag) 2397 flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE); 2398 dragwin = NULL; 2399 did_drag = FALSE; 2400 } 2401 2402 if ((flags & MOUSE_DID_MOVE) 2403 && prev_row == mouse_row 2404 && prev_col == mouse_col) 2405 { 2406 retnomove: 2407 /* before moving the cursor for a left click wich is NOT in a status 2408 * line, stop Visual mode */ 2409 if (on_status_line) 2410 return IN_STATUS_LINE; 2411 #ifdef FEAT_VERTSPLIT 2412 if (on_sep_line) 2413 return IN_SEP_LINE; 2414 #endif 2415 #ifdef FEAT_VISUAL 2416 if (flags & MOUSE_MAY_STOP_VIS) 2417 { 2418 end_visual_mode(); 2419 redraw_curbuf_later(INVERTED); /* delete the inversion */ 2420 } 2421 #endif 2422 #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD) 2423 /* Continue a modeless selection in another window. */ 2424 if (cmdwin_type != 0 && row < W_WINROW(curwin)) 2425 return IN_OTHER_WIN; 2426 #endif 2427 return IN_BUFFER; 2428 } 2429 2430 prev_row = mouse_row; 2431 prev_col = mouse_col; 2432 2433 if (flags & MOUSE_SETPOS) 2434 goto retnomove; /* ugly goto... */ 2435 2436 #ifdef FEAT_FOLDING 2437 /* Remember the character under the mouse, it might be a '-' or '+' in the 2438 * fold column. */ 2439 if (row >= 0 && row < Rows && col >= 0 && col <= Columns 2440 && ScreenLines != NULL) 2441 mouse_char = ScreenLines[LineOffset[row] + col]; 2442 else 2443 mouse_char = ' '; 2444 #endif 2445 2446 old_curwin = curwin; 2447 old_cursor = curwin->w_cursor; 2448 2449 if (!(flags & MOUSE_FOCUS)) 2450 { 2451 if (row < 0 || col < 0) /* check if it makes sense */ 2452 return IN_UNKNOWN; 2453 2454 #ifdef FEAT_WINDOWS 2455 /* find the window where the row is in */ 2456 wp = mouse_find_win(&row, &col); 2457 #else 2458 wp = firstwin; 2459 #endif 2460 dragwin = NULL; 2461 /* 2462 * winpos and height may change in win_enter()! 2463 */ 2464 if (row >= wp->w_height) /* In (or below) status line */ 2465 { 2466 on_status_line = row - wp->w_height + 1; 2467 dragwin = wp; 2468 } 2469 else 2470 on_status_line = 0; 2471 #ifdef FEAT_VERTSPLIT 2472 if (col >= wp->w_width) /* In separator line */ 2473 { 2474 on_sep_line = col - wp->w_width + 1; 2475 dragwin = wp; 2476 } 2477 else 2478 on_sep_line = 0; 2479 2480 /* The rightmost character of the status line might be a vertical 2481 * separator character if there is no connecting window to the right. */ 2482 if (on_status_line && on_sep_line) 2483 { 2484 if (stl_connected(wp)) 2485 on_sep_line = 0; 2486 else 2487 on_status_line = 0; 2488 } 2489 #endif 2490 2491 #ifdef FEAT_VISUAL 2492 /* Before jumping to another buffer, or moving the cursor for a left 2493 * click, stop Visual mode. */ 2494 if (VIsual_active 2495 && (wp->w_buffer != curwin->w_buffer 2496 || (!on_status_line 2497 # ifdef FEAT_VERTSPLIT 2498 && !on_sep_line 2499 # endif 2500 # ifdef FEAT_FOLDING 2501 && ( 2502 # ifdef FEAT_RIGHTLEFT 2503 wp->w_p_rl ? col < W_WIDTH(wp) - wp->w_p_fdc : 2504 # endif 2505 col >= wp->w_p_fdc 2506 # ifdef FEAT_CMDWIN 2507 + (cmdwin_type == 0 && wp == curwin ? 0 : 1) 2508 # endif 2509 ) 2510 # endif 2511 && (flags & MOUSE_MAY_STOP_VIS)))) 2512 { 2513 end_visual_mode(); 2514 redraw_curbuf_later(INVERTED); /* delete the inversion */ 2515 } 2516 #endif 2517 #ifdef FEAT_CMDWIN 2518 if (cmdwin_type != 0 && wp != curwin) 2519 { 2520 /* A click outside the command-line window: Use modeless 2521 * selection if possible. Allow dragging the status line of 2522 * windows just above the command-line window. */ 2523 if (wp->w_winrow + wp->w_height 2524 != curwin->w_prev->w_winrow + curwin->w_prev->w_height) 2525 { 2526 on_status_line = 0; 2527 dragwin = NULL; 2528 } 2529 # ifdef FEAT_VERTSPLIT 2530 on_sep_line = 0; 2531 # endif 2532 # ifdef FEAT_CLIPBOARD 2533 if (on_status_line) 2534 return IN_STATUS_LINE; 2535 return IN_OTHER_WIN; 2536 # else 2537 row = 0; 2538 col += wp->w_wincol; 2539 wp = curwin; 2540 # endif 2541 } 2542 #endif 2543 #ifdef FEAT_WINDOWS 2544 /* Only change window focus when not clicking on or dragging the 2545 * status line. Do change focus when releasing the mouse button 2546 * (MOUSE_FOCUS was set above if we dragged first). */ 2547 if (dragwin == NULL || (flags & MOUSE_RELEASED)) 2548 win_enter(wp, TRUE); /* can make wp invalid! */ 2549 # ifdef CHECK_DOUBLE_CLICK 2550 /* set topline, to be able to check for double click ourselves */ 2551 if (curwin != old_curwin) 2552 set_mouse_topline(curwin); 2553 # endif 2554 #endif 2555 if (on_status_line) /* In (or below) status line */ 2556 { 2557 /* Don't use start_arrow() if we're in the same window */ 2558 if (curwin == old_curwin) 2559 return IN_STATUS_LINE; 2560 else 2561 return IN_STATUS_LINE | CURSOR_MOVED; 2562 } 2563 #ifdef FEAT_VERTSPLIT 2564 if (on_sep_line) /* In (or below) status line */ 2565 { 2566 /* Don't use start_arrow() if we're in the same window */ 2567 if (curwin == old_curwin) 2568 return IN_SEP_LINE; 2569 else 2570 return IN_SEP_LINE | CURSOR_MOVED; 2571 } 2572 #endif 2573 2574 curwin->w_cursor.lnum = curwin->w_topline; 2575 #ifdef FEAT_GUI 2576 /* remember topline, needed for double click */ 2577 gui_prev_topline = curwin->w_topline; 2578 # ifdef FEAT_DIFF 2579 gui_prev_topfill = curwin->w_topfill; 2580 # endif 2581 #endif 2582 } 2583 else if (on_status_line && which_button == MOUSE_LEFT) 2584 { 2585 #ifdef FEAT_WINDOWS 2586 if (dragwin != NULL) 2587 { 2588 /* Drag the status line */ 2589 count = row - dragwin->w_winrow - dragwin->w_height + 1 2590 - on_status_line; 2591 win_drag_status_line(dragwin, count); 2592 did_drag |= count; 2593 } 2594 #endif 2595 return IN_STATUS_LINE; /* Cursor didn't move */ 2596 } 2597 #ifdef FEAT_VERTSPLIT 2598 else if (on_sep_line && which_button == MOUSE_LEFT) 2599 { 2600 if (dragwin != NULL) 2601 { 2602 /* Drag the separator column */ 2603 count = col - dragwin->w_wincol - dragwin->w_width + 1 2604 - on_sep_line; 2605 win_drag_vsep_line(dragwin, count); 2606 did_drag |= count; 2607 } 2608 return IN_SEP_LINE; /* Cursor didn't move */ 2609 } 2610 #endif 2611 else /* keep_window_focus must be TRUE */ 2612 { 2613 #ifdef FEAT_VISUAL 2614 /* before moving the cursor for a left click, stop Visual mode */ 2615 if (flags & MOUSE_MAY_STOP_VIS) 2616 { 2617 end_visual_mode(); 2618 redraw_curbuf_later(INVERTED); /* delete the inversion */ 2619 } 2620 #endif 2621 2622 #if defined(FEAT_CMDWIN) && defined(FEAT_CLIPBOARD) 2623 /* Continue a modeless selection in another window. */ 2624 if (cmdwin_type != 0 && row < W_WINROW(curwin)) 2625 return IN_OTHER_WIN; 2626 #endif 2627 2628 row -= W_WINROW(curwin); 2629 #ifdef FEAT_VERTSPLIT 2630 col -= W_WINCOL(curwin); 2631 #endif 2632 2633 /* 2634 * When clicking beyond the end of the window, scroll the screen. 2635 * Scroll by however many rows outside the window we are. 2636 */ 2637 if (row < 0) 2638 { 2639 count = 0; 2640 for (first = TRUE; curwin->w_topline > 1; ) 2641 { 2642 #ifdef FEAT_DIFF 2643 if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) 2644 ++count; 2645 else 2646 #endif 2647 count += plines(curwin->w_topline - 1); 2648 if (!first && count > -row) 2649 break; 2650 first = FALSE; 2651 #ifdef FEAT_FOLDING 2652 hasFolding(curwin->w_topline, &curwin->w_topline, NULL); 2653 #endif 2654 #ifdef FEAT_DIFF 2655 if (curwin->w_topfill < diff_check(curwin, curwin->w_topline)) 2656 ++curwin->w_topfill; 2657 else 2658 #endif 2659 { 2660 --curwin->w_topline; 2661 #ifdef FEAT_DIFF 2662 curwin->w_topfill = 0; 2663 #endif 2664 } 2665 } 2666 #ifdef FEAT_DIFF 2667 check_topfill(curwin, FALSE); 2668 #endif 2669 curwin->w_valid &= 2670 ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); 2671 redraw_later(VALID); 2672 row = 0; 2673 } 2674 else if (row >= curwin->w_height) 2675 { 2676 count = 0; 2677 for (first = TRUE; curwin->w_topline < curbuf->b_ml.ml_line_count; ) 2678 { 2679 #ifdef FEAT_DIFF 2680 if (curwin->w_topfill > 0) 2681 ++count; 2682 else 2683 #endif 2684 count += plines(curwin->w_topline); 2685 if (!first && count > row - curwin->w_height + 1) 2686 break; 2687 first = FALSE; 2688 #ifdef FEAT_FOLDING 2689 if (hasFolding(curwin->w_topline, NULL, &curwin->w_topline) 2690 && curwin->w_topline == curbuf->b_ml.ml_line_count) 2691 break; 2692 #endif 2693 #ifdef FEAT_DIFF 2694 if (curwin->w_topfill > 0) 2695 --curwin->w_topfill; 2696 else 2697 #endif 2698 { 2699 ++curwin->w_topline; 2700 #ifdef FEAT_DIFF 2701 curwin->w_topfill = 2702 diff_check_fill(curwin, curwin->w_topline); 2703 #endif 2704 } 2705 } 2706 #ifdef FEAT_DIFF 2707 check_topfill(curwin, FALSE); 2708 #endif 2709 redraw_later(VALID); 2710 curwin->w_valid &= 2711 ~(VALID_WROW|VALID_CROW|VALID_BOTLINE|VALID_BOTLINE_AP); 2712 row = curwin->w_height - 1; 2713 } 2714 else if (row == 0) 2715 { 2716 /* When dragging the mouse, while the text has been scrolled up as 2717 * far as it goes, moving the mouse in the top line should scroll 2718 * the text down (done later when recomputing w_topline). */ 2719 if (mouse_dragging 2720 && curwin->w_cursor.lnum 2721 == curwin->w_buffer->b_ml.ml_line_count 2722 && curwin->w_cursor.lnum == curwin->w_topline) 2723 curwin->w_valid &= ~(VALID_TOPLINE); 2724 } 2725 } 2726 2727 #ifdef FEAT_FOLDING 2728 /* Check for position outside of the fold column. */ 2729 if ( 2730 # ifdef FEAT_RIGHTLEFT 2731 curwin->w_p_rl ? col < W_WIDTH(curwin) - curwin->w_p_fdc : 2732 # endif 2733 col >= curwin->w_p_fdc 2734 # ifdef FEAT_CMDWIN 2735 + (cmdwin_type == 0 ? 0 : 1) 2736 # endif 2737 ) 2738 mouse_char = ' '; 2739 #endif 2740 2741 /* compute the position in the buffer line from the posn on the screen */ 2742 if (mouse_comp_pos(curwin, &row, &col, &curwin->w_cursor.lnum)) 2743 mouse_past_bottom = TRUE; 2744 2745 #ifdef FEAT_VISUAL 2746 /* Start Visual mode before coladvance(), for when 'sel' != "old" */ 2747 if ((flags & MOUSE_MAY_VIS) && !VIsual_active) 2748 { 2749 check_visual_highlight(); 2750 VIsual = old_cursor; 2751 VIsual_active = TRUE; 2752 VIsual_reselect = TRUE; 2753 /* if 'selectmode' contains "mouse", start Select mode */ 2754 may_start_select('o'); 2755 setmouse(); 2756 if (p_smd) 2757 redraw_cmdline = TRUE; /* show visual mode later */ 2758 } 2759 #endif 2760 2761 curwin->w_curswant = col; 2762 curwin->w_set_curswant = FALSE; /* May still have been TRUE */ 2763 if (coladvance(col) == FAIL) /* Mouse click beyond end of line */ 2764 { 2765 if (inclusive != NULL) 2766 *inclusive = TRUE; 2767 mouse_past_eol = TRUE; 2768 } 2769 else if (inclusive != NULL) 2770 *inclusive = FALSE; 2771 2772 count = IN_BUFFER; 2773 if (curwin != old_curwin || curwin->w_cursor.lnum != old_cursor.lnum 2774 || curwin->w_cursor.col != old_cursor.col) 2775 count |= CURSOR_MOVED; /* Cursor has moved */ 2776 2777 #ifdef FEAT_FOLDING 2778 if (mouse_char == '+') 2779 count |= MOUSE_FOLD_OPEN; 2780 else if (mouse_char != ' ') 2781 count |= MOUSE_FOLD_CLOSE; 2782 #endif 2783 2784 return count; 2785 } 2786 2787 /* 2788 * Compute the position in the buffer line from the posn on the screen in 2789 * window "win". 2790 * Returns TRUE if the position is below the last line. 2791 */ 2792 int 2793 mouse_comp_pos(win, rowp, colp, lnump) 2794 win_T *win; 2795 int *rowp; 2796 int *colp; 2797 linenr_T *lnump; 2798 { 2799 int col = *colp; 2800 int row = *rowp; 2801 linenr_T lnum; 2802 int retval = FALSE; 2803 int off; 2804 int count; 2805 2806 #ifdef FEAT_RIGHTLEFT 2807 if (win->w_p_rl) 2808 col = W_WIDTH(win) - 1 - col; 2809 #endif 2810 2811 lnum = win->w_topline; 2812 2813 while (row > 0) 2814 { 2815 #ifdef FEAT_DIFF 2816 /* Don't include filler lines in "count" */ 2817 if (win->w_p_diff 2818 # ifdef FEAT_FOLDING 2819 && !hasFoldingWin(win, lnum, NULL, NULL, TRUE, NULL) 2820 # endif 2821 ) 2822 { 2823 if (lnum == win->w_topline) 2824 row -= win->w_topfill; 2825 else 2826 row -= diff_check_fill(win, lnum); 2827 count = plines_win_nofill(win, lnum, TRUE); 2828 } 2829 else 2830 #endif 2831 count = plines_win(win, lnum, TRUE); 2832 if (count > row) 2833 break; /* Position is in this buffer line. */ 2834 #ifdef FEAT_FOLDING 2835 (void)hasFoldingWin(win, lnum, NULL, &lnum, TRUE, NULL); 2836 #endif 2837 if (lnum == win->w_buffer->b_ml.ml_line_count) 2838 { 2839 retval = TRUE; 2840 break; /* past end of file */ 2841 } 2842 row -= count; 2843 ++lnum; 2844 } 2845 2846 if (!retval) 2847 { 2848 /* Compute the column without wrapping. */ 2849 off = win_col_off(win) - win_col_off2(win); 2850 if (col < off) 2851 col = off; 2852 col += row * (W_WIDTH(win) - off); 2853 /* add skip column (for long wrapping line) */ 2854 col += win->w_skipcol; 2855 } 2856 2857 if (!win->w_p_wrap) 2858 col += win->w_leftcol; 2859 2860 /* skip line number and fold column in front of the line */ 2861 col -= win_col_off(win); 2862 if (col < 0) 2863 { 2864 #ifdef FEAT_NETBEANS_INTG 2865 if (usingNetbeans) 2866 netbeans_gutter_click(lnum); 2867 #endif 2868 col = 0; 2869 } 2870 2871 *colp = col; 2872 *rowp = row; 2873 *lnump = lnum; 2874 return retval; 2875 } 2876 2877 #if defined(FEAT_WINDOWS) || defined(PROTO) 2878 /* 2879 * Find the window at screen position "*rowp" and "*colp". The positions are 2880 * updated to become relative to the top-left of the window. 2881 */ 2882 /*ARGSUSED*/ 2883 win_T * 2884 mouse_find_win(rowp, colp) 2885 int *rowp; 2886 int *colp; 2887 { 2888 frame_T *fp; 2889 2890 fp = topframe; 2891 for (;;) 2892 { 2893 if (fp->fr_layout == FR_LEAF) 2894 break; 2895 #ifdef FEAT_VERTSPLIT 2896 if (fp->fr_layout == FR_ROW) 2897 { 2898 for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) 2899 { 2900 if (*colp < fp->fr_width) 2901 break; 2902 *colp -= fp->fr_width; 2903 } 2904 } 2905 #endif 2906 else /* fr_layout == FR_COL */ 2907 { 2908 for (fp = fp->fr_child; fp->fr_next != NULL; fp = fp->fr_next) 2909 { 2910 if (*rowp < fp->fr_height) 2911 break; 2912 *rowp -= fp->fr_height; 2913 } 2914 } 2915 } 2916 return fp->fr_win; 2917 } 2918 #endif 2919 2920 #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined (FEAT_GUI_MAC) \ 2921 || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \ 2922 || defined(FEAT_GUI_PHOTON) || defined(PROTO) 2923 /* 2924 * Translate window coordinates to buffer position without any side effects 2925 */ 2926 int 2927 get_fpos_of_mouse(mpos) 2928 pos_T *mpos; 2929 { 2930 win_T *wp; 2931 int row = mouse_row; 2932 int col = mouse_col; 2933 2934 if (row < 0 || col < 0) /* check if it makes sense */ 2935 return IN_UNKNOWN; 2936 2937 #ifdef FEAT_WINDOWS 2938 /* find the window where the row is in */ 2939 wp = mouse_find_win(&row, &col); 2940 #else 2941 wp = firstwin; 2942 #endif 2943 /* 2944 * winpos and height may change in win_enter()! 2945 */ 2946 if (row >= wp->w_height) /* In (or below) status line */ 2947 return IN_STATUS_LINE; 2948 #ifdef FEAT_VERTSPLIT 2949 if (col >= wp->w_width) /* In vertical separator line */ 2950 return IN_SEP_LINE; 2951 #endif 2952 2953 if (wp != curwin) 2954 return IN_UNKNOWN; 2955 2956 /* compute the position in the buffer line from the posn on the screen */ 2957 if (mouse_comp_pos(curwin, &row, &col, &mpos->lnum)) 2958 return IN_STATUS_LINE; /* past bottom */ 2959 2960 mpos->col = vcol2col(wp, mpos->lnum, col); 2961 2962 if (mpos->col > 0) 2963 --mpos->col; 2964 return IN_BUFFER; 2965 } 2966 2967 /* 2968 * Convert a virtual (screen) column to a character column. 2969 * The first column is one. 2970 */ 2971 int 2972 vcol2col(wp, lnum, vcol) 2973 win_T *wp; 2974 linenr_T lnum; 2975 int vcol; 2976 { 2977 /* try to advance to the specified column */ 2978 int col = 0; 2979 int count = 0; 2980 char_u *ptr; 2981 2982 ptr = ml_get_buf(wp->w_buffer, lnum, FALSE); 2983 while (count <= vcol && *ptr != NUL) 2984 { 2985 ++col; 2986 count += win_lbr_chartabsize(wp, ptr, count, NULL); 2987 mb_ptr_adv(ptr); 2988 } 2989 return col; 2990 } 2991 #endif 2992 2993 #endif /* FEAT_MOUSE */ 2994 2995 #if defined(FEAT_GUI) || defined(WIN3264) || defined(PROTO) 2996 /* 2997 * Called when focus changed. Used for the GUI or for systems where this can 2998 * be done in the console (Win32). 2999 */ 3000 void 3001 ui_focus_change(in_focus) 3002 int in_focus; /* TRUE if focus gained. */ 3003 { 3004 static time_t last_time = (time_t)0; 3005 int need_redraw = FALSE; 3006 3007 /* When activated: Check if any file was modified outside of Vim. 3008 * Only do this when not done within the last two seconds (could get 3009 * several events in a row). */ 3010 if (in_focus && last_time + 2 < time(NULL)) 3011 { 3012 need_redraw = check_timestamps( 3013 # ifdef FEAT_GUI 3014 gui.in_use 3015 # else 3016 FALSE 3017 # endif 3018 ); 3019 last_time = time(NULL); 3020 } 3021 3022 #ifdef FEAT_AUTOCMD 3023 /* 3024 * Fire the focus gained/lost autocommand. 3025 */ 3026 need_redraw |= apply_autocmds(in_focus ? EVENT_FOCUSGAINED 3027 : EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf); 3028 #endif 3029 3030 if (need_redraw) 3031 { 3032 /* Something was executed, make sure the cursor is put back where it 3033 * belongs. */ 3034 need_wait_return = FALSE; 3035 3036 if (State & CMDLINE) 3037 redrawcmdline(); 3038 else if (State == HITRETURN || State == SETWSIZE || State == ASKMORE 3039 || State == EXTERNCMD || State == CONFIRM || exmode_active) 3040 repeat_message(); 3041 else if ((State & NORMAL) || (State & INSERT)) 3042 { 3043 if (must_redraw != 0) 3044 update_screen(0); 3045 setcursor(); 3046 } 3047 cursor_on(); /* redrawing may have switched it off */ 3048 out_flush(); 3049 # ifdef FEAT_GUI 3050 if (gui.in_use) 3051 { 3052 gui_update_cursor(FALSE, TRUE); 3053 gui_update_scrollbars(FALSE); 3054 } 3055 # endif 3056 } 3057 #ifdef FEAT_TITLE 3058 /* File may have been changed from 'readonly' to 'noreadonly' */ 3059 if (need_maketitle) 3060 maketitle(); 3061 #endif 3062 } 3063 #endif 3064 3065 #if defined(USE_IM_CONTROL) || defined(PROTO) 3066 /* 3067 * Save current Input Method status to specified place. 3068 */ 3069 void 3070 im_save_status(psave) 3071 long *psave; 3072 { 3073 /* Don't save when 'imdisable' is set or "xic" is NULL, IM is always 3074 * disabled then (but might start later). 3075 * Also don't save when inside a mapping, vgetc_im_active has not been set 3076 * then. 3077 * And don't save when the keys were stuffed (e.g., for a "." command). 3078 * And don't save when the GUI is running but our window doesn't have 3079 * input focus (e.g., when a find dialog is open). */ 3080 if (!p_imdisable && KeyTyped && !KeyStuffed 3081 # ifdef FEAT_XIM 3082 && xic != NULL 3083 # endif 3084 # ifdef FEAT_GUI 3085 && (!gui.in_use || gui.in_focus) 3086 # endif 3087 ) 3088 { 3089 /* Do save when IM is on, or IM is off and saved status is on. */ 3090 if (vgetc_im_active) 3091 *psave = B_IMODE_IM; 3092 else if (*psave == B_IMODE_IM) 3093 *psave = B_IMODE_NONE; 3094 } 3095 } 3096 #endif 3097