home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / unix / vim-6.2.tar.bz2 / vim-6.2.tar / vim62 / src / ui.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-17  |  68.0 KB  |  2,922 lines

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