1" Tests for decoding escape sequences sent by the terminal.
2
3" This only works for Unix in a terminal
4source check.vim
5CheckNotGui
6CheckUnix
7
8source shared.vim
9source mouse.vim
10source view_util.vim
11source term_util.vim
12
13func Test_term_mouse_left_click()
14  new
15  let save_mouse = &mouse
16  let save_term = &term
17  let save_ttymouse = &ttymouse
18  call test_override('no_query_mouse', 1)
19  set mouse=a term=xterm
20  call setline(1, ['line 1', 'line 2', 'line 3 is a bit longer'])
21
22  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
23    let msg = 'ttymouse=' .. ttymouse_val
24    exe 'set ttymouse=' .. ttymouse_val
25    go
26    call assert_equal([0, 1, 1, 0], getpos('.'), msg)
27    let row = 2
28    let col = 6
29    call MouseLeftClick(row, col)
30    call MouseLeftRelease(row, col)
31    call assert_equal([0, 2, 6, 0], getpos('.'), msg)
32  endfor
33
34  let &mouse = save_mouse
35  let &term = save_term
36  let &ttymouse = save_ttymouse
37  call test_override('no_query_mouse', 0)
38  bwipe!
39endfunc
40
41func Test_xterm_mouse_right_click_extends_visual()
42  if has('mac')
43    throw "Skipped: test right click in visual mode does not work on macOs (why?)"
44  endif
45  let save_mouse = &mouse
46  let save_term = &term
47  let save_ttymouse = &ttymouse
48  call test_override('no_query_mouse', 1)
49  set mouse=a term=xterm
50
51  for visual_mode in ["v", "V", "\<C-V>"]
52    for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
53      let msg = 'visual=' .. visual_mode .. ' ttymouse=' .. ttymouse_val
54      exe 'set ttymouse=' .. ttymouse_val
55
56      call setline(1, repeat([repeat('-', 7)], 7))
57      call MouseLeftClick(4, 4)
58      call MouseLeftRelease(4, 4)
59      exe  "norm! " .. visual_mode
60
61      " Right click extends top left of visual area.
62      call MouseRightClick(2, 2)
63      call MouseRightRelease(2, 2)
64
65      " Right click extends bottom right of visual area.
66      call MouseRightClick(6, 6)
67      call MouseRightRelease(6, 6)
68      norm! r1gv
69
70      " Right click shrinks top left of visual area.
71      call MouseRightClick(3, 3)
72      call MouseRightRelease(3, 3)
73
74      " Right click shrinks bottom right of visual area.
75      call MouseRightClick(5, 5)
76      call MouseRightRelease(5, 5)
77      norm! r2
78
79      if visual_mode ==# 'v'
80        call assert_equal(['-------',
81              \            '-111111',
82              \            '1122222',
83              \            '2222222',
84              \            '2222211',
85              \            '111111-',
86              \            '-------'], getline(1, '$'), msg)
87      elseif visual_mode ==# 'V'
88        call assert_equal(['-------',
89              \            '1111111',
90              \            '2222222',
91              \            '2222222',
92              \            '2222222',
93              \            '1111111',
94              \            '-------'], getline(1, '$'), msg)
95      else
96        call assert_equal(['-------',
97              \            '-11111-',
98              \            '-12221-',
99              \            '-12221-',
100              \            '-12221-',
101              \            '-11111-',
102              \            '-------'], getline(1, '$'), msg)
103      endif
104    endfor
105  endfor
106
107  let &mouse = save_mouse
108  let &term = save_term
109  let &ttymouse = save_ttymouse
110  call test_override('no_query_mouse', 0)
111  bwipe!
112endfunc
113
114" Test that <C-LeftMouse> jumps to help tag and <C-RightMouse> jumps back.
115" Also test for g<LeftMouse> and g<RightMouse>.
116func Test_xterm_mouse_tagjump()
117  let save_mouse = &mouse
118  let save_term = &term
119  let save_ttymouse = &ttymouse
120  set mouse=a term=xterm
121
122  for ttymouse_val in g:Ttymouse_values
123    let msg = 'ttymouse=' .. ttymouse_val
124    exe 'set ttymouse=' .. ttymouse_val
125    help
126    /usr_02.txt
127    norm! zt
128
129    " CTRL-left click to jump to a tag
130    let row = 1
131    let col = 1
132    call MouseCtrlLeftClick(row, col)
133    call MouseLeftRelease(row, col)
134    call assert_match('usr_02.txt$', bufname('%'), msg)
135    call assert_equal('*usr_02.txt*', expand('<cWORD>'), msg)
136
137    " CTRL-right click to pop a tag
138    call MouseCtrlRightClick(row, col)
139    call MouseRightRelease(row, col)
140    call assert_match('help.txt$', bufname('%'), msg)
141    call assert_equal('|usr_02.txt|', expand('<cWORD>'), msg)
142
143    " Jump to a tag
144    exe "normal \<C-]>"
145    call assert_match('usr_02.txt$', bufname('%'), msg)
146    call assert_equal('*usr_02.txt*', expand('<cWORD>'), msg)
147
148    " Use CTRL-right click in insert mode to pop the tag
149    new
150    let str = 'iHello' .. MouseCtrlRightClickCode(row, col)
151          \ .. MouseRightReleaseCode(row, col) .. "\<C-C>"
152    call assert_fails('call feedkeys(str, "Lx!")', 'E37:', msg)
153    close!
154
155    " CTRL-right click with a count
156    let str = "4" .. MouseCtrlRightClickCode(row, col)
157          \ .. MouseRightReleaseCode(row, col)
158    call assert_fails('call feedkeys(str, "Lx!")', 'E555:', msg)
159    call assert_match('help.txt$', bufname('%'), msg)
160    call assert_equal(1, line('.'), msg)
161
162    " g<LeftMouse> to jump to a tag
163    /usr_02.txt
164    norm! zt
165    call test_setmouse(row, col)
166    exe "normal g\<LeftMouse>"
167    call assert_match('usr_02.txt$', bufname('%'), msg)
168    call assert_equal('*usr_02.txt*', expand('<cWORD>'), msg)
169
170    " g<RightMouse> to pop to a tag
171    call test_setmouse(row, col)
172    exe "normal g\<RightMouse>"
173    call assert_match('help.txt$', bufname('%'), msg)
174    call assert_equal('|usr_02.txt|', expand('<cWORD>'), msg)
175
176    %bw!
177  endfor
178
179  let &mouse = save_mouse
180  let &term = save_term
181  let &ttymouse = save_ttymouse
182endfunc
183
184func Test_term_mouse_middle_click()
185  CheckFeature clipboard_working
186
187  new
188  let save_mouse = &mouse
189  let save_term = &term
190  let save_ttymouse = &ttymouse
191  call test_override('no_query_mouse', 1)
192  let save_quotestar = @*
193  let save_quoteplus = @+
194  set mouse=a term=xterm
195
196  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
197    let msg = 'ttymouse=' .. ttymouse_val
198    exe 'set ttymouse=' .. ttymouse_val
199    call setline(1, ['123456789', '123456789'])
200    let @* = 'abc'
201
202    " Middle-click in the middle of the line pastes text where clicked.
203    let row = 1
204    let col = 6
205    call MouseMiddleClick(row, col)
206    call MouseMiddleRelease(row, col)
207    call assert_equal(['12345abc6789', '123456789'], getline(1, '$'), msg)
208
209    " Middle-click beyond end of the line pastes text at the end of the line.
210    let col = 20
211    call MouseMiddleClick(row, col)
212    call MouseMiddleRelease(row, col)
213    call assert_equal(['12345abc6789abc', '123456789'], getline(1, '$'), msg)
214
215    " Middle-click beyond the last line pastes in the last line.
216    let row = 5
217    let col = 3
218    call MouseMiddleClick(row, col)
219    call MouseMiddleRelease(row, col)
220    call assert_equal(['12345abc6789abc', '12abc3456789'], getline(1, '$'), msg)
221
222    " Middle mouse click in operator pending mode beeps
223    call assert_beeps('exe "normal c\<MiddleMouse>"')
224
225    " Clicking middle mouse in visual mode, yanks the selection and pastes the
226    " clipboard contents
227    let save_clipboard = &clipboard
228    set clipboard=
229    let @" = ''
230    call cursor(1, 1)
231    call feedkeys("v3l" ..
232          \ MouseMiddleClickCode(2, 7) .. MouseMiddleReleaseCode(2, 7), 'Lx!')
233    call assert_equal(['12345abc6789abc', '12abc3abc456789'],
234          \ getline(1, '$'), msg)
235    call assert_equal('1234', @", msg)
236    let &clipboard = save_clipboard
237
238    " Clicking middle mouse in select mode, replaces the selected text with
239    " the clipboard contents
240    let @+ = 'xyz'
241    call cursor(1, 3)
242    exe "normal gh\<Right>\<Right>\<MiddleMouse>"
243    call assert_equal(['12xyzabc6789abc', '12abc3abc456789'],
244          \ getline(1, '$'), msg)
245
246    " Prefixing middle click with [ or ] fixes the indent after pasting.
247    %d
248    call setline(1, "    one two")
249    call setreg('r', 'red blue', 'l')
250    call test_setmouse(1, 5)
251    exe "normal \"r[\<MiddleMouse>"
252    call assert_equal('    red blue', getline(1), msg)
253    call test_setmouse(2, 5)
254    exe "normal \"r]\<MiddleMouse>"
255    call assert_equal('    red blue', getline(3), msg)
256    %d
257  endfor
258
259  let &mouse = save_mouse
260  let &term = save_term
261  let &ttymouse = save_ttymouse
262  call test_override('no_query_mouse', 0)
263  let @* = save_quotestar
264  let @+ = save_quotestar
265  bwipe!
266endfunc
267
268" If clipboard is not working, then clicking the middle mouse button in visual
269" mode, will copy and paste the selected text.
270func Test_term_mouse_middle_click_no_clipboard()
271  if has('clipboard_working')
272    throw 'Skipped: clipboard support works'
273  endif
274  new
275  let save_mouse = &mouse
276  let save_term = &term
277  let save_ttymouse = &ttymouse
278  call test_override('no_query_mouse', 1)
279  set mouse=a term=xterm
280
281  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
282    let msg = 'ttymouse=' .. ttymouse_val
283    exe 'set ttymouse=' .. ttymouse_val
284    call setline(1, ['123456789', '123456789'])
285
286    " Clicking middle mouse in visual mode, yanks the selection and pastes it
287    call cursor(1, 1)
288    call feedkeys("v3l" ..
289          \ MouseMiddleClickCode(2, 7) .. MouseMiddleReleaseCode(2, 7), 'Lx!')
290    call assert_equal(['123456789', '1234561234789'],
291          \ getline(1, '$'), msg)
292  endfor
293
294  call test_override('no_query_mouse', 0)
295  let &ttymouse = save_ttymouse
296  let &term = save_term
297  let &mouse = save_mouse
298  close!
299endfunc
300
301func Test_term_mouse_middle_click_insert_mode()
302  CheckFeature clipboard_working
303
304  new
305  let save_mouse = &mouse
306  let save_term = &term
307  let save_ttymouse = &ttymouse
308  call test_override('no_query_mouse', 1)
309  set mouse=a term=xterm
310
311  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
312    let msg = 'ttymouse=' .. ttymouse_val
313    exe 'set ttymouse=' .. ttymouse_val
314    call setline(1, ['123456789', '123456789'])
315    let @* = 'abc'
316
317    " Middle-click in inesrt mode doesn't move the cursor but inserts the
318    " contents of aregister
319    call cursor(1, 4)
320    call feedkeys('i' ..
321          \ MouseMiddleClickCode(2, 7) .. MouseMiddleReleaseCode(2, 7) ..
322          \ "\<C-C>", 'Lx!')
323    call assert_equal(['123abc456789', '123456789'],
324          \ getline(1, '$'), msg)
325    call assert_equal([1, 6], [line('.'), col('.')], msg)
326
327    " Middle-click in replace mode
328    call cursor(1, 1)
329    call feedkeys('$R' ..
330          \ MouseMiddleClickCode(2, 7) .. MouseMiddleReleaseCode(2, 7) ..
331          \ "\<C-C>", 'Lx!')
332    call assert_equal(['123abc45678abc', '123456789'],
333          \ getline(1, '$'), msg)
334    call assert_equal([1, 14], [line('.'), col('.')], msg)
335  endfor
336
337  let &mouse = save_mouse
338  let &term = save_term
339  let &ttymouse = save_ttymouse
340  call test_override('no_query_mouse', 0)
341  close!
342endfunc
343
344" Test for switching window using mouse in insert mode
345func Test_term_mouse_switch_win_insert_mode()
346  5new
347  let save_mouse = &mouse
348  let save_term = &term
349  let save_ttymouse = &ttymouse
350  call test_override('no_query_mouse', 1)
351  set mouse=a term=xterm ttymouse=xterm2
352
353  call feedkeys('ivim' ..
354        \ MouseLeftClickCode(8, 6) .. MouseLeftReleaseCode(8, 6) ..
355        \ "\<C-C>", 'Lx!')
356  call assert_equal(2, winnr())
357  wincmd w
358  call assert_equal('n', mode())
359  call assert_equal(['vim'], getline(1, '$'))
360
361  let &mouse = save_mouse
362  let &term = save_term
363  let &ttymouse = save_ttymouse
364  call test_override('no_query_mouse', 0)
365  close!
366endfunc
367
368" Test for using the mouse to increaes the height of the cmdline window
369func Test_mouse_cmdwin_resize()
370  CheckFeature cmdwin
371
372  let save_mouse = &mouse
373  let save_term = &term
374  let save_ttymouse = &ttymouse
375  call test_override('no_query_mouse', 1)
376  set mouse=a term=xterm ttymouse=xterm2
377  5new
378  redraw!
379
380  let h = 0
381  let row = &lines - &cmdwinheight - 2
382  call feedkeys("q:" ..
383        \ MouseLeftClickCode(row, 1) ..
384        \ MouseLeftDragCode(row - 1, 1) ..
385        \ MouseLeftReleaseCode(row - 2, 1) ..
386        \ "alet h = \<C-R>=winheight(0)\<CR>\<CR>", 'Lx!')
387  call assert_equal(&cmdwinheight + 2, h)
388
389  let &mouse = save_mouse
390  let &term = save_term
391  let &ttymouse = save_ttymouse
392  call test_override('no_query_mouse', 0)
393  close!
394endfunc
395
396" TODO: for unclear reasons this test fails if it comes after
397" Test_xterm_mouse_ctrl_click()
398func Test_1xterm_mouse_wheel()
399  new
400  let save_mouse = &mouse
401  let save_term = &term
402  let save_wrap = &wrap
403  let save_ttymouse = &ttymouse
404  set mouse=a term=xterm nowrap
405  call setline(1, range(100000000000000, 100000000000100))
406
407  for ttymouse_val in g:Ttymouse_values
408    let msg = 'ttymouse=' .. ttymouse_val
409    exe 'set ttymouse=' .. ttymouse_val
410    go
411    call assert_equal(1, line('w0'), msg)
412    call assert_equal([0, 1, 1, 0], getpos('.'), msg)
413
414    call MouseWheelDown(1, 1)
415    call assert_equal(4, line('w0'), msg)
416    call assert_equal([0, 4, 1, 0], getpos('.'), msg)
417
418    call MouseWheelDown(1, 1)
419    call assert_equal(7, line('w0'), msg)
420    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
421
422    call MouseWheelUp(1, 1)
423    call assert_equal(4, line('w0'), msg)
424    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
425
426    call MouseWheelUp(1, 1)
427    call assert_equal(1, line('w0'), msg)
428    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
429
430    if has('gui')
431      " Horizontal wheel scrolling currently only works when vim is
432      " compiled with gui enabled.
433      call MouseWheelRight(1, 1)
434      call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
435      call assert_equal([0, 7, 7, 0], getpos('.'), msg)
436
437      call MouseWheelRight(1, 1)
438      call assert_equal(13, 1 + virtcol(".") - wincol(), msg)
439      call assert_equal([0, 7, 13, 0], getpos('.'), msg)
440
441      call MouseWheelLeft(1, 1)
442      call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
443      call assert_equal([0, 7, 13, 0], getpos('.'), msg)
444
445      call MouseWheelLeft(1, 1)
446      call assert_equal(1, 1 + virtcol(".") - wincol(), msg)
447      call assert_equal([0, 7, 13, 0], getpos('.'), msg)
448    endif
449  endfor
450
451  let &mouse = save_mouse
452  let &term = save_term
453  let &wrap = save_wrap
454  let &ttymouse = save_ttymouse
455  bwipe!
456endfunc
457
458" Test that dragging beyond the window (at the bottom and at the top)
459" scrolls window content by the number of lines beyond the window.
460func Test_term_mouse_drag_beyond_window()
461  let save_mouse = &mouse
462  let save_term = &term
463  let save_ttymouse = &ttymouse
464  call test_override('no_query_mouse', 1)
465  set mouse=a term=xterm
466  let col = 1
467  call setline(1, range(1, 100))
468
469  " Split into 3 windows, and go into the middle window
470  " so we test dragging mouse below and above the window.
471  2split
472  wincmd j
473  2split
474
475  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
476    let msg = 'ttymouse=' .. ttymouse_val
477    exe 'set ttymouse=' .. ttymouse_val
478
479    " Line #10 at the top.
480    norm! 10zt
481    redraw
482    call assert_equal(10, winsaveview().topline, msg)
483    call assert_equal(2, winheight(0), msg)
484
485    let row = 4
486    call MouseLeftClick(row, col)
487    call assert_equal(10, winsaveview().topline, msg)
488
489    " Drag downwards. We're still in the window so topline should
490    " not change yet.
491    let row += 1
492    call MouseLeftDrag(row, col)
493    call assert_equal(10, winsaveview().topline, msg)
494
495    " We now leave the window at the bottom, so the window content should
496    " scroll by 1 line, then 2 lines (etc) as we drag further away.
497    let row += 1
498    call MouseLeftDrag(row, col)
499    call assert_equal(11, winsaveview().topline, msg)
500
501    let row += 1
502    call MouseLeftDrag(row, col)
503    call assert_equal(13, winsaveview().topline, msg)
504
505    " Now drag upwards.
506    let row -= 1
507    call MouseLeftDrag(row, col)
508    call assert_equal(14, winsaveview().topline, msg)
509
510    " We're now back in the window so the topline should not change.
511    let row -= 1
512    call MouseLeftDrag(row, col)
513    call assert_equal(14, winsaveview().topline, msg)
514
515    let row -= 1
516    call MouseLeftDrag(row, col)
517    call assert_equal(14, winsaveview().topline, msg)
518
519    " We now leave the window at the top so the window content should
520    " scroll by 1 line, then 2, then 3 (etc) in the opposite direction.
521    let row -= 1
522    call MouseLeftDrag(row, col)
523    call assert_equal(13, winsaveview().topline, msg)
524
525    let row -= 1
526    call MouseLeftDrag(row, col)
527    call assert_equal(11, winsaveview().topline, msg)
528
529    let row -= 1
530    call MouseLeftDrag(row, col)
531    call assert_equal(8, winsaveview().topline, msg)
532
533    call MouseLeftRelease(row, col)
534    call assert_equal(8, winsaveview().topline, msg)
535    call assert_equal(2, winheight(0), msg)
536  endfor
537
538  let &mouse = save_mouse
539  let &term = save_term
540  let &ttymouse = save_ttymouse
541  call test_override('no_query_mouse', 0)
542  bwipe!
543endfunc
544
545func Test_term_mouse_drag_window_separator()
546  let save_mouse = &mouse
547  let save_term = &term
548  let save_ttymouse = &ttymouse
549  call test_override('no_query_mouse', 1)
550  set mouse=a term=xterm
551
552  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
553    let msg = 'ttymouse=' .. ttymouse_val
554    exe 'set ttymouse=' .. ttymouse_val
555
556    " Split horizontally and test dragging the horizontal window separator.
557    split
558    let rowseparator = winheight(0) + 1
559    let row = rowseparator
560    let col = 1
561
562    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
563    if ttymouse_val !=# 'xterm2' || row <= 223
564      call MouseLeftClick(row, col)
565      let row -= 1
566      call MouseLeftDrag(row, col)
567      call assert_equal(rowseparator - 1, winheight(0) + 1, msg)
568      let row += 1
569      call MouseLeftDrag(row, col)
570      call assert_equal(rowseparator, winheight(0) + 1, msg)
571      call MouseLeftRelease(row, col)
572      call assert_equal(rowseparator, winheight(0) + 1, msg)
573    endif
574    bwipe!
575
576    " Split vertically and test dragging the vertical window separator.
577    vsplit
578    let colseparator = winwidth(0) + 1
579    let row = 1
580    let col = colseparator
581
582    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
583    if ttymouse_val !=# 'xterm2' || col <= 223
584      call MouseLeftClick(row, col)
585      let col -= 1
586      call MouseLeftDrag(row, col)
587      call assert_equal(colseparator - 1, winwidth(0) + 1, msg)
588      let col += 1
589      call MouseLeftDrag(row, col)
590      call assert_equal(colseparator, winwidth(0) + 1, msg)
591      call MouseLeftRelease(row, col)
592      call assert_equal(colseparator, winwidth(0) + 1, msg)
593    endif
594    bwipe!
595  endfor
596
597  let &mouse = save_mouse
598  let &term = save_term
599  let &ttymouse = save_ttymouse
600  call test_override('no_query_mouse', 0)
601endfunc
602
603func Test_term_mouse_drag_statusline()
604  let save_mouse = &mouse
605  let save_term = &term
606  let save_ttymouse = &ttymouse
607  call test_override('no_query_mouse', 1)
608  let save_laststatus = &laststatus
609  set mouse=a term=xterm laststatus=2
610
611  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
612    let msg = 'ttymouse=' .. ttymouse_val
613    exe 'set ttymouse=' .. ttymouse_val
614
615    call assert_equal(1, &cmdheight, msg)
616    let rowstatusline = winheight(0) + 1
617    let row = rowstatusline
618    let col = 1
619
620    if ttymouse_val ==# 'xterm2' && row > 223
621      " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
622      continue
623    endif
624
625    call MouseLeftClick(row, col)
626    let row -= 1
627    call MouseLeftDrag(row, col)
628    call assert_equal(2, &cmdheight, msg)
629    call assert_equal(rowstatusline - 1, winheight(0) + 1, msg)
630    let row += 1
631    call MouseLeftDrag(row, col)
632    call assert_equal(1, &cmdheight, msg)
633    call assert_equal(rowstatusline, winheight(0) + 1, msg)
634    call MouseLeftRelease(row, col)
635    call assert_equal(1, &cmdheight, msg)
636    call assert_equal(rowstatusline, winheight(0) + 1, msg)
637  endfor
638
639  let &mouse = save_mouse
640  let &term = save_term
641  let &ttymouse = save_ttymouse
642  call test_override('no_query_mouse', 0)
643  let &laststatus = save_laststatus
644endfunc
645
646func Test_term_mouse_click_tab()
647  let save_mouse = &mouse
648  let save_term = &term
649  let save_ttymouse = &ttymouse
650  call test_override('no_query_mouse', 1)
651  set mouse=a term=xterm
652  let row = 1
653
654  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
655    let msg = 'ttymouse=' .. ttymouse_val
656    exe 'set ttymouse=' .. ttymouse_val
657    e Xfoo
658    tabnew Xbar
659
660    let a = split(execute(':tabs'), "\n")
661    call assert_equal(['Tab page 1',
662        \              '    Xfoo',
663        \              'Tab page 2',
664        \              '>   Xbar'], a, msg)
665
666    " Test clicking on tab names in the tabline at the top.
667    let col = 2
668    redraw
669    call MouseLeftClick(row, col)
670    call MouseLeftRelease(row, col)
671    let a = split(execute(':tabs'), "\n")
672    call assert_equal(['Tab page 1',
673        \              '>   Xfoo',
674        \              'Tab page 2',
675        \              '    Xbar'], a, msg)
676
677    let col = 9
678    call MouseLeftClick(row, col)
679    call MouseLeftRelease(row, col)
680    let a = split(execute(':tabs'), "\n")
681    call assert_equal(['Tab page 1',
682        \              '    Xfoo',
683        \              'Tab page 2',
684        \              '>   Xbar'], a, msg)
685
686    %bwipe!
687  endfor
688
689  let &mouse = save_mouse
690  let &term = save_term
691  let &ttymouse = save_ttymouse
692  call test_override('no_query_mouse', 0)
693endfunc
694
695func Test_term_mouse_click_X_to_close_tab()
696  let save_mouse = &mouse
697  let save_term = &term
698  let save_ttymouse = &ttymouse
699  call test_override('no_query_mouse', 1)
700  set mouse=a term=xterm
701  let row = 1
702  let col = &columns
703
704  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
705    if ttymouse_val ==# 'xterm2' && col > 223
706      " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
707      continue
708    endif
709    let msg = 'ttymouse=' .. ttymouse_val
710    exe 'set ttymouse=' .. ttymouse_val
711    e Xtab1
712    tabnew Xtab2
713    tabnew Xtab3
714    tabn 2
715
716    let a = split(execute(':tabs'), "\n")
717    call assert_equal(['Tab page 1',
718        \              '    Xtab1',
719        \              'Tab page 2',
720        \              '>   Xtab2',
721        \              'Tab page 3',
722        \              '    Xtab3'], a, msg)
723
724    " Click on "X" in tabline to close current tab i.e. Xtab2.
725    redraw
726    call MouseLeftClick(row, col)
727    call MouseLeftRelease(row, col)
728    let a = split(execute(':tabs'), "\n")
729    call assert_equal(['Tab page 1',
730        \              '    Xtab1',
731        \              'Tab page 2',
732        \              '>   Xtab3'], a, msg)
733
734    %bwipe!
735  endfor
736
737  let &mouse = save_mouse
738  let &term = save_term
739  let &ttymouse = save_ttymouse
740  call test_override('no_query_mouse', 0)
741endfunc
742
743func Test_term_mouse_drag_to_move_tab()
744  let save_mouse = &mouse
745  let save_term = &term
746  let save_ttymouse = &ttymouse
747  call test_override('no_query_mouse', 1)
748  " Set 'mousetime' to 1 to avoid recognizing a double-click in the loop
749  set mouse=a term=xterm mousetime=1
750  let row = 1
751
752  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
753    let msg = 'ttymouse=' .. ttymouse_val
754    exe 'set ttymouse=' .. ttymouse_val
755    e Xtab1
756    tabnew Xtab2
757
758    let a = split(execute(':tabs'), "\n")
759    call assert_equal(['Tab page 1',
760        \              '    Xtab1',
761        \              'Tab page 2',
762        \              '>   Xtab2'], a, msg)
763    redraw
764
765    " Click in tab2 and drag it to tab1.
766    " Check getcharmod() to verify that click is not
767    " interpreted as a spurious double-click.
768    call MouseLeftClick(row, 10)
769    call assert_equal(0, getcharmod(), msg)
770    for col in [9, 8, 7, 6]
771      call MouseLeftDrag(row, col)
772    endfor
773    call MouseLeftRelease(row, col)
774    let a = split(execute(':tabs'), "\n")
775    call assert_equal(['Tab page 1',
776        \              '>   Xtab2',
777        \              'Tab page 2',
778        \              '    Xtab1'], a, msg)
779
780    " Click elsewhere so that click in next iteration is not
781    " interpreted as unwanted double-click.
782    call MouseLeftClick(row, 11)
783    call MouseLeftRelease(row, 11)
784
785    %bwipe!
786  endfor
787
788  let &mouse = save_mouse
789  let &term = save_term
790  let &ttymouse = save_ttymouse
791  call test_override('no_query_mouse', 0)
792  set mousetime&
793endfunc
794
795func Test_term_mouse_double_click_to_create_tab()
796  let save_mouse = &mouse
797  let save_term = &term
798  let save_ttymouse = &ttymouse
799  call test_override('no_query_mouse', 1)
800  " Set 'mousetime' to a small value, so that double-click works but we don't
801  " have to wait long to avoid a triple-click.
802  set mouse=a term=xterm mousetime=200
803  let row = 1
804  let col = 10
805
806  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
807    let msg = 'ttymouse=' .. ttymouse_val
808    exe 'set ttymouse=' .. ttymouse_val
809    e Xtab1
810    tabnew Xtab2
811
812    let a = split(execute(':tabs'), "\n")
813    call assert_equal(['Tab page 1',
814        \              '    Xtab1',
815        \              'Tab page 2',
816        \              '>   Xtab2'], a, msg)
817
818    redraw
819    call MouseLeftClick(row, col)
820    " Check getcharmod() to verify that first click is not
821    " interpreted as a spurious double-click.
822    call assert_equal(0, getcharmod(), msg)
823    call MouseLeftRelease(row, col)
824    call MouseLeftClick(row, col)
825    call assert_equal(32, getcharmod(), msg) " double-click
826    call MouseLeftRelease(row, col)
827    let a = split(execute(':tabs'), "\n")
828    call assert_equal(['Tab page 1',
829        \              '    Xtab1',
830        \              'Tab page 2',
831        \              '>   [No Name]',
832        \              'Tab page 3',
833        \              '    Xtab2'], a, msg)
834
835    " Click elsewhere so that click in next iteration is not
836    " interpreted as unwanted double click.
837    call MouseLeftClick(row, col + 1)
838    call MouseLeftRelease(row, col + 1)
839
840    %bwipe!
841  endfor
842
843  let &mouse = save_mouse
844  let &term = save_term
845  let &ttymouse = save_ttymouse
846  call test_override('no_query_mouse', 0)
847  set mousetime&
848endfunc
849
850" Test double/triple/quadruple click in normal mode to visually select.
851func Test_term_mouse_multiple_clicks_to_visually_select()
852  let save_mouse = &mouse
853  let save_term = &term
854  let save_ttymouse = &ttymouse
855  call test_override('no_query_mouse', 1)
856
857  " 'mousetime' must be sufficiently large, or else the test is flaky when
858  " using a ssh connection with X forwarding; i.e. ssh -X (issue #7563).
859  set mouse=a term=xterm mousetime=600
860  new
861
862  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
863    let msg = 'ttymouse=' .. ttymouse_val
864    exe 'set ttymouse=' .. ttymouse_val
865    call setline(1, ['foo [foo bar] foo', 'foo'])
866
867    " Double-click on word should visually select the word.
868    call MouseLeftClick(1, 2)
869    call assert_equal(0, getcharmod(), msg)
870    call MouseLeftRelease(1, 2)
871    call MouseLeftClick(1, 2)
872    call assert_equal(32, getcharmod(), msg) " double-click
873    call MouseLeftRelease(1, 2)
874    call assert_equal('v', mode(), msg)
875    norm! r1
876    call assert_equal(['111 [foo bar] foo', 'foo'], getline(1, '$'), msg)
877
878    " Double-click on opening square bracket should visually
879    " select the whole [foo bar].
880    call MouseLeftClick(1, 5)
881    call assert_equal(0, getcharmod(), msg)
882    call MouseLeftRelease(1, 5)
883    call MouseLeftClick(1, 5)
884    call assert_equal(32, getcharmod(), msg) " double-click
885    call MouseLeftRelease(1, 5)
886    call assert_equal('v', mode(), msg)
887    norm! r2
888    call assert_equal(['111 222222222 foo', 'foo'], getline(1, '$'), msg)
889
890    " Triple-click should visually select the whole line.
891    call MouseLeftClick(1, 3)
892    call assert_equal(0, getcharmod(), msg)
893    call MouseLeftRelease(1, 3)
894    call MouseLeftClick(1, 3)
895    call assert_equal(32, getcharmod(), msg) " double-click
896    call MouseLeftRelease(1, 3)
897    call MouseLeftClick(1, 3)
898    call assert_equal(64, getcharmod(), msg) " triple-click
899    call MouseLeftRelease(1, 3)
900    call assert_equal('V', mode(), msg)
901    norm! r3
902    call assert_equal(['33333333333333333', 'foo'], getline(1, '$'), msg)
903
904    " Quadruple-click should start visual block select.
905    call MouseLeftClick(1, 2)
906    call assert_equal(0, getcharmod(), msg)
907    call MouseLeftRelease(1, 2)
908    call MouseLeftClick(1, 2)
909    call assert_equal(32, getcharmod(), msg) " double-click
910    call MouseLeftRelease(1, 2)
911    call MouseLeftClick(1, 2)
912    call assert_equal(64, getcharmod(), msg) " triple-click
913    call MouseLeftRelease(1, 2)
914    call MouseLeftClick(1, 2)
915    call assert_equal(96, getcharmod(), msg) " quadruple-click
916    call MouseLeftRelease(1, 2)
917    call assert_equal("\<c-v>", mode(), msg)
918    norm! r4
919    call assert_equal(['34333333333333333', 'foo'], getline(1, '$'), msg)
920
921    " Double-click on a space character should visually select all the
922    " consecutive space characters.
923    %d
924    call setline(1, '    one two')
925    call MouseLeftClick(1, 2)
926    call MouseLeftRelease(1, 2)
927    call MouseLeftClick(1, 2)
928    call MouseLeftRelease(1, 2)
929    call assert_equal('v', mode(), msg)
930    norm! r1
931    call assert_equal(['1111one two'], getline(1, '$'), msg)
932
933    " Double-click on a word with exclusive selection
934    set selection=exclusive
935    let @" = ''
936    call MouseLeftClick(1, 10)
937    call MouseLeftRelease(1, 10)
938    call MouseLeftClick(1, 10)
939    call MouseLeftRelease(1, 10)
940    norm! y
941    call assert_equal('two', @", msg)
942
943    " Double click to select a block of text with exclusive selection
944    %d
945    call setline(1, 'one (two) three')
946    call MouseLeftClick(1, 5)
947    call MouseLeftRelease(1, 5)
948    call MouseLeftClick(1, 5)
949    call MouseLeftRelease(1, 5)
950    norm! y
951    call assert_equal(5, col("'<"), msg)
952    call assert_equal(10, col("'>"), msg)
953
954    call MouseLeftClick(1, 9)
955    call MouseLeftRelease(1, 9)
956    call MouseLeftClick(1, 9)
957    call MouseLeftRelease(1, 9)
958    norm! y
959    call assert_equal(5, col("'<"), msg)
960    call assert_equal(10, col("'>"), msg)
961    set selection&
962
963    " Click somewhere else so that the clicks above is not combined with the
964    " clicks in the next iteration.
965    call MouseRightClick(3, 10)
966    call MouseRightRelease(3, 10)
967  endfor
968
969  let &mouse = save_mouse
970  let &term = save_term
971  let &ttymouse = save_ttymouse
972  set mousetime&
973  call test_override('no_query_mouse', 0)
974  bwipe!
975endfunc
976
977" Test for selecting text in visual blockwise mode using Alt-LeftClick
978func Test_mouse_alt_leftclick()
979  let save_mouse = &mouse
980  let save_term = &term
981  let save_ttymouse = &ttymouse
982  call test_override('no_query_mouse', 1)
983  set mouse=a term=xterm mousetime=200
984  set mousemodel=popup
985  new
986  call setline(1, 'one (two) three')
987
988  for ttymouse_val in g:Ttymouse_values
989    let msg = 'ttymouse=' .. ttymouse_val
990    exe 'set ttymouse=' .. ttymouse_val
991
992    " Left click with the Alt modifier key should extend the selection in
993    " blockwise visual mode.
994    let @" = ''
995    call MouseLeftClick(1, 3)
996    call MouseLeftRelease(1, 3)
997    call MouseAltLeftClick(1, 11)
998    call MouseLeftRelease(1, 11)
999    call assert_equal("\<C-V>", mode(), msg)
1000    normal! y
1001    call assert_equal('e (two) t', @")
1002  endfor
1003
1004  let &mouse = save_mouse
1005  let &term = save_term
1006  let &ttymouse = save_ttymouse
1007  set mousetime& mousemodel&
1008  call test_override('no_query_mouse', 0)
1009  close!
1010endfunc
1011
1012func Test_xterm_mouse_click_in_fold_columns()
1013  new
1014  let save_mouse = &mouse
1015  let save_term = &term
1016  let save_ttymouse = &ttymouse
1017  let save_foldcolumn = &foldcolumn
1018  set mouse=a term=xterm foldcolumn=3 ttymouse=xterm2
1019
1020  " Create 2 nested folds.
1021  call setline(1, range(1, 7))
1022  2,6fold
1023  norm! zR
1024  4,5fold
1025  call assert_equal([-1, -1, -1, 4, 4, -1, -1],
1026        \           map(range(1, 7), 'foldclosed(v:val)'))
1027
1028  " Click in "+" of inner fold in foldcolumn should open it.
1029  redraw
1030  let row = 4
1031  let col = 2
1032  call MouseLeftClick(row, col)
1033  call MouseLeftRelease(row, col)
1034  call assert_equal([-1, -1, -1, -1, -1, -1, -1],
1035        \           map(range(1, 7), 'foldclosed(v:val)'))
1036
1037  " Click in "-" of outer fold in foldcolumn should close it.
1038  redraw
1039  let row = 2
1040  let col = 1
1041  call MouseLeftClick(row, col)
1042  call MouseLeftRelease(row, col)
1043  call assert_equal([-1, 2, 2, 2, 2, 2, -1],
1044        \           map(range(1, 7), 'foldclosed(v:val)'))
1045  norm! zR
1046
1047  " Click in "|" of inner fold in foldcolumn should close it.
1048  redraw
1049  let row = 5
1050  let col = 2
1051  call MouseLeftClick(row, col)
1052  call MouseLeftRelease(row, col)
1053  call assert_equal([-1, -1, -1, 4, 4, -1, -1],
1054        \           map(range(1, 7), 'foldclosed(v:val)'))
1055
1056  let &foldcolumn = save_foldcolumn
1057  let &ttymouse = save_ttymouse
1058  let &term = save_term
1059  let &mouse = save_mouse
1060  bwipe!
1061endfunc
1062
1063" Left or right click in Ex command line sets position of the cursor.
1064func Test_term_mouse_click_in_cmdline_to_set_pos()
1065  let save_mouse = &mouse
1066  let save_term = &term
1067  let save_ttymouse = &ttymouse
1068  call test_override('no_query_mouse', 1)
1069  set mouse=a term=xterm
1070  let row = &lines
1071
1072  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
1073    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
1074    if ttymouse_val !=# 'xterm2' || row <= 223
1075      let msg = 'ttymouse=' .. ttymouse_val
1076      exe 'set ttymouse=' .. ttymouse_val
1077
1078
1079      call feedkeys(':"3456789'
1080            \       .. MouseLeftClickCode(row, 7)
1081            \       .. MouseLeftReleaseCode(row, 7) .. 'L'
1082            \       .. MouseRightClickCode(row, 4)
1083            \       .. MouseRightReleaseCode(row, 4) .. 'R'
1084            \       .. "\<CR>", 'Lx!')
1085      call assert_equal('"3R456L789', @:, msg)
1086    endif
1087  endfor
1088
1089  let &mouse = save_mouse
1090  let &term = save_term
1091  let &ttymouse = save_ttymouse
1092  set mousetime&
1093  call test_override('no_query_mouse', 0)
1094endfunc
1095
1096" Middle click in command line pastes at position of cursor.
1097func Test_term_mouse_middle_click_in_cmdline_to_paste()
1098  CheckFeature clipboard_working
1099  let save_mouse = &mouse
1100  let save_term = &term
1101  let save_ttymouse = &ttymouse
1102  call test_override('no_query_mouse', 1)
1103  set mouse=a term=xterm
1104  let row = &lines
1105  " Column values does not matter, paste is done at position of cursor.
1106  let col = 1
1107  let @* = 'paste'
1108
1109  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
1110    let msg = 'ttymouse=' .. ttymouse_val
1111    exe 'set ttymouse=' .. ttymouse_val
1112
1113    call feedkeys(":\"->"
1114          \       .. MouseMiddleReleaseCode(row, col)
1115          \       .. MouseMiddleClickCode(row, col)
1116          \       .. "<-"
1117          \       .. MouseMiddleReleaseCode(row, col)
1118          \       .. MouseMiddleClickCode(row, col)
1119          \       .. "\<CR>", 'Lx!')
1120    call assert_equal('"->paste<-paste', @:, msg)
1121  endfor
1122
1123  let &mouse = save_mouse
1124  let &term = save_term
1125  let &ttymouse = save_ttymouse
1126  let @* = ''
1127  call test_override('no_query_mouse', 0)
1128endfunc
1129
1130" Test for making sure S-Middlemouse doesn't do anything
1131func Test_term_mouse_shift_middle_click()
1132  new
1133  let save_mouse = &mouse
1134  let save_term = &term
1135  let save_ttymouse = &ttymouse
1136  call test_override('no_query_mouse', 1)
1137  set mouse=a term=xterm ttymouse=xterm2 mousemodel=
1138
1139  call test_setmouse(1, 1)
1140  exe "normal \<S-MiddleMouse>"
1141  call assert_equal([''], getline(1, '$'))
1142  call assert_equal(1, winnr())
1143
1144  let &mouse = save_mouse
1145  let &term = save_term
1146  let &ttymouse = save_ttymouse
1147  set mousemodel&
1148  call test_override('no_query_mouse', 0)
1149  close!
1150endfunc
1151
1152" Test for using mouse in visual mode
1153func Test_term_mouse_visual_mode()
1154  new
1155  let save_mouse = &mouse
1156  let save_term = &term
1157  let save_ttymouse = &ttymouse
1158  call test_override('no_query_mouse', 1)
1159  set term=xterm ttymouse=xterm2
1160
1161  " If visual mode is not present in 'mouse', then left click should not
1162  " do anything in visal mode.
1163  call setline(1, ['one two three four'])
1164  set mouse=nci
1165  call cursor(1, 5)
1166  let @" = ''
1167  call feedkeys("ve"
1168        \ .. MouseLeftClickCode(1, 15) .. MouseLeftReleaseCode(1, 15)
1169        \ .. 'y', 'Lx!')
1170  call assert_equal(5, col('.'))
1171  call assert_equal('two', @")
1172
1173  " Pressing right click in visual mode should change the visual selection
1174  " if 'mousemodel' doesn't contain popup.
1175  " Right click after the visual selection
1176  set mousemodel=
1177  set mouse=a
1178  call test_setmouse(1, 13)
1179  exe "normal 5|ve\<RightMouse>y"
1180  call assert_equal('two three', @")
1181  call assert_equal(5, col('.'))
1182
1183  " Right click before the visual selection
1184  call test_setmouse(1, 9)
1185  exe "normal 15|ve\<RightMouse>y"
1186  call assert_equal('three four', @")
1187  call assert_equal(9, col('.'))
1188
1189  " Right click inside the selection closer to the start of the selection
1190  call test_setmouse(1, 7)
1191  exe "normal 5|vee\<RightMouse>lly"
1192  call assert_equal('three', @")
1193  call assert_equal(9, col('.'))
1194  call assert_equal(9, col("'<"))
1195  call assert_equal(13, col("'>"))
1196
1197  " Right click inside the selection closer to the end of the selection
1198  call test_setmouse(1, 11)
1199  exe "normal 5|vee\<RightMouse>ly"
1200  call assert_equal('two thre', @")
1201  call assert_equal(5, col('.'))
1202  call assert_equal(5, col("'<"))
1203  call assert_equal(12, col("'>"))
1204
1205  " Multi-line selection. Right click inside thse selection.
1206  call setline(1, repeat(['aaaaaa'], 7))
1207  call test_setmouse(3, 1)
1208  exe "normal ggVG\<RightMouse>y"
1209  call assert_equal(3, line("'<"))
1210  call test_setmouse(5, 1)
1211  exe "normal ggVG\<RightMouse>y"
1212  call assert_equal(5, line("'>"))
1213
1214  " Click right in the middle line of the selection
1215  call test_setmouse(4, 3)
1216  exe "normal ggVG$\<RightMouse>y"
1217  call assert_equal(4, line("'<"))
1218  call test_setmouse(4, 4)
1219  exe "normal ggVG$\<RightMouse>y"
1220  call assert_equal(4, line("'>"))
1221
1222  set mousemodel&
1223  let &mouse = save_mouse
1224  let &term = save_term
1225  let &ttymouse = save_ttymouse
1226  call test_override('no_query_mouse', 0)
1227  close!
1228endfunc
1229
1230" Test for displaying the popup menu using the right mouse click
1231func Test_term_mouse_popup_menu()
1232  CheckFeature menu
1233  new
1234  call setline(1, 'popup menu test')
1235  let save_mouse = &mouse
1236  let save_term = &term
1237  let save_ttymouse = &ttymouse
1238  let save_mousemodel = &mousemodel
1239  call test_override('no_query_mouse', 1)
1240  set mouse=a term=xterm mousemodel=popup
1241
1242  menu PopUp.foo :let g:menustr = 'foo'<CR>
1243  menu PopUp.bar :let g:menustr = 'bar'<CR>
1244  menu PopUp.baz :let g:menustr = 'baz'<CR>
1245
1246  for ttymouse_val in g:Ttymouse_values
1247    let msg = 'ttymouse=' .. ttymouse_val
1248    exe 'set ttymouse=' .. ttymouse_val
1249    let g:menustr = ''
1250    call feedkeys(MouseRightClickCode(1, 4)
1251		\ .. MouseRightReleaseCode(1, 4) .. "\<Down>\<Down>\<CR>", "x")
1252    call assert_equal('bar', g:menustr, msg)
1253  endfor
1254
1255  unmenu PopUp
1256  let &mouse = save_mouse
1257  let &term = save_term
1258  let &ttymouse = save_ttymouse
1259  let &mousemodel = save_mousemodel
1260  call test_override('no_query_mouse', 0)
1261  close!
1262endfunc
1263
1264" Test for 'mousemodel' set to popup_setpos to move the cursor where the popup
1265" menu is displayed.
1266func Test_term_mouse_popup_menu_setpos()
1267  CheckFeature menu
1268  5new
1269  call setline(1, ['the dish ran away with the spoon',
1270        \ 'the cow jumped over the moon' ])
1271  let save_mouse = &mouse
1272  let save_term = &term
1273  let save_ttymouse = &ttymouse
1274  let save_mousemodel = &mousemodel
1275  call test_override('no_query_mouse', 1)
1276  set mouse=a term=xterm mousemodel=popup_setpos
1277
1278  nmenu PopUp.foo :let g:menustr = 'foo'<CR>
1279  nmenu PopUp.bar :let g:menustr = 'bar'<CR>
1280  nmenu PopUp.baz :let g:menustr = 'baz'<CR>
1281  vmenu PopUp.foo y:<C-U>let g:menustr = 'foo'<CR>
1282  vmenu PopUp.bar y:<C-U>let g:menustr = 'bar'<CR>
1283  vmenu PopUp.baz y:<C-U>let g:menustr = 'baz'<CR>
1284
1285  for ttymouse_val in g:Ttymouse_values
1286    let msg = 'ttymouse=' .. ttymouse_val
1287    exe 'set ttymouse=' .. ttymouse_val
1288    let g:menustr = ''
1289    call cursor(1, 1)
1290    call feedkeys(MouseRightClickCode(1, 5)
1291		\ .. MouseRightReleaseCode(1, 5) .. "\<Down>\<Down>\<CR>", "x")
1292    call assert_equal('bar', g:menustr, msg)
1293    call assert_equal([1, 5], [line('.'), col('.')], msg)
1294
1295    " Test for right click in visual mode inside the selection
1296    let @" = ''
1297    call cursor(1, 10)
1298    call feedkeys('vee' .. MouseRightClickCode(1, 12)
1299		\ .. MouseRightReleaseCode(1, 12) .. "\<Down>\<CR>", "x")
1300    call assert_equal([1, 10], [line('.'), col('.')], msg)
1301    call assert_equal('ran away', @", msg)
1302
1303    " Test for right click in visual mode before the selection
1304    let @" = ''
1305    call cursor(1, 10)
1306    call feedkeys('vee' .. MouseRightClickCode(1, 2)
1307		\ .. MouseRightReleaseCode(1, 2) .. "\<Down>\<CR>", "x")
1308    call assert_equal([1, 2], [line('.'), col('.')], msg)
1309    call assert_equal('', @", msg)
1310
1311    " Test for right click in visual mode after the selection
1312    let @" = ''
1313    call cursor(1, 10)
1314    call feedkeys('vee' .. MouseRightClickCode(1, 20)
1315		\ .. MouseRightReleaseCode(1, 20) .. "\<Down>\<CR>", "x")
1316    call assert_equal([1, 20], [line('.'), col('.')], msg)
1317    call assert_equal('', @", msg)
1318
1319    " Test for right click in block-wise visual mode inside the selection
1320    let @" = ''
1321    call cursor(1, 16)
1322    call feedkeys("\<C-V>j3l" .. MouseRightClickCode(2, 17)
1323		\ .. MouseRightReleaseCode(2, 17) .. "\<Down>\<CR>", "x")
1324    call assert_equal([1, 16], [line('.'), col('.')], msg)
1325    call assert_equal("\<C-V>4", getregtype('"'), msg)
1326
1327    " Test for right click in block-wise visual mode outside the selection
1328    let @" = ''
1329    call cursor(1, 16)
1330    call feedkeys("\<C-V>j3l" .. MouseRightClickCode(2, 2)
1331		\ .. MouseRightReleaseCode(2, 2) .. "\<Down>\<CR>", "x")
1332    call assert_equal([2, 2], [line('.'), col('.')], msg)
1333    call assert_equal('v', getregtype('"'), msg)
1334    call assert_equal('', @", msg)
1335
1336    " Try clicking on the status line
1337    let @" = ''
1338    call cursor(1, 10)
1339    call feedkeys('vee' .. MouseRightClickCode(6, 2)
1340		\ .. MouseRightReleaseCode(6, 2) .. "\<Down>\<CR>", "x")
1341    call assert_equal([1, 10], [line('.'), col('.')], msg)
1342    call assert_equal('ran away', @", msg)
1343
1344    " Try clicking outside the window
1345    let @" = ''
1346    call cursor(7, 2)
1347    call feedkeys('vee' .. MouseRightClickCode(7, 2)
1348		\ .. MouseRightReleaseCode(7, 2) .. "\<Down>\<CR>", "x")
1349    call assert_equal(2, winnr(), msg)
1350    call assert_equal('', @", msg)
1351    wincmd w
1352  endfor
1353
1354  unmenu PopUp
1355  let &mouse = save_mouse
1356  let &term = save_term
1357  let &ttymouse = save_ttymouse
1358  let &mousemodel = save_mousemodel
1359  call test_override('no_query_mouse', 0)
1360  close!
1361endfunc
1362
1363" Test for searching for the word under the cursor using Shift-Right or
1364" Shift-Left click.
1365func Test_term_mouse_search()
1366  new
1367  let save_mouse = &mouse
1368  let save_term = &term
1369  let save_ttymouse = &ttymouse
1370  call test_override('no_query_mouse', 1)
1371  set mouse=a term=xterm ttymouse=xterm2
1372  set mousemodel=
1373
1374  " In normal mode, Shift-Left or Shift-Right click should search for the word
1375  " under the cursor.
1376  call setline(1, ['one two three four', 'four three two one'])
1377  call test_setmouse(1, 4)
1378  exe "normal \<S-LeftMouse>"
1379  call assert_equal([2, 12], [line('.'), col('.')])
1380  call test_setmouse(2, 16)
1381  exe "normal \<S-RightMouse>"
1382  call assert_equal([1, 1], [line('.'), col('.')])
1383
1384  " In visual mode, Shift-Left or Shift-Right click should search for the word
1385  " under the cursor and extend the selection.
1386  call test_setmouse(1, 4)
1387  exe "normal 4|ve\<S-LeftMouse>y"
1388  call assert_equal([2, 12], [line("'>"), col("'>")])
1389  call test_setmouse(2, 16)
1390  exe "normal 2G16|ve\<S-RightMouse>y"
1391  call assert_equal([1, 1], [line("'<"), col("'<")])
1392
1393  set mousemodel&
1394  let &mouse = save_mouse
1395  let &term = save_term
1396  let &ttymouse = save_ttymouse
1397  call test_override('no_query_mouse', 0)
1398  close!
1399endfunc
1400
1401" Test for selecting an entry in the quickfix/location list window using the
1402" mouse.
1403func Test_term_mouse_quickfix_window()
1404  let save_mouse = &mouse
1405  let save_term = &term
1406  let save_ttymouse = &ttymouse
1407  call test_override('no_query_mouse', 1)
1408  set mouse=a term=xterm ttymouse=xterm2
1409  set mousemodel=
1410
1411  cgetexpr "Xfile1:1:L1"
1412  copen 5
1413  call test_setmouse(&lines - 7, 1)
1414  exe "normal \<2-LeftMouse>"
1415  call assert_equal('Xfile1', @%)
1416  %bw!
1417
1418  lgetexpr "Xfile2:1:L1"
1419  lopen 5
1420  call test_setmouse(&lines - 7, 1)
1421  exe "normal \<2-LeftMouse>"
1422  call assert_equal('Xfile2', @%)
1423  %bw!
1424
1425  set mousemodel&
1426  let &mouse = save_mouse
1427  let &term = save_term
1428  let &ttymouse = save_ttymouse
1429  call test_override('no_query_mouse', 0)
1430endfunc
1431
1432" Test for the 'h' flag in the 'mouse' option. Using mouse in the help window.
1433func Test_term_mouse_help_window()
1434  let save_mouse = &mouse
1435  let save_term = &term
1436  let save_ttymouse = &ttymouse
1437  call test_override('no_query_mouse', 1)
1438  set mouse=h term=xterm mousetime=200
1439
1440  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
1441    let msg = 'ttymouse=' .. ttymouse_val
1442    exe 'set ttymouse=' .. ttymouse_val
1443    help
1444    let @" = ''
1445    call MouseLeftClick(2, 5)
1446    call MouseLeftRelease(2, 5)
1447    call MouseLeftClick(1, 1)
1448    call MouseLeftDrag(1, 10)
1449    call MouseLeftRelease(1, 10)
1450    norm! y
1451    call assert_equal('*help.txt*', @", msg)
1452    helpclose
1453
1454    " Click somewhere else to make sure the left click above is not combined
1455    " with the next left click and treated as a double click
1456    call MouseRightClick(5, 10)
1457    call MouseRightRelease(5, 10)
1458  endfor
1459
1460  let &mouse = save_mouse
1461  let &term = save_term
1462  let &ttymouse = save_ttymouse
1463  set mousetime&
1464  call test_override('no_query_mouse', 0)
1465  %bw!
1466endfunc
1467
1468" Test for the translation of various mouse terminal codes
1469func Test_mouse_termcodes()
1470  let save_mouse = &mouse
1471  let save_term = &term
1472  let save_ttymouse = &ttymouse
1473  call test_override('no_query_mouse', 1)
1474  set mouse=a term=xterm mousetime=200
1475
1476  new
1477  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
1478    let msg = 'ttymouse=' .. ttymouse_val
1479    exe 'set ttymouse=' .. ttymouse_val
1480
1481    let mouse_codes = [
1482          \ ["\<LeftMouse>", "<LeftMouse>"],
1483          \ ["\<MiddleMouse>", "<MiddleMouse>"],
1484          \ ["\<RightMouse>", "<RightMouse>"],
1485          \ ["\<S-LeftMouse>", "<S-LeftMouse>"],
1486          \ ["\<S-MiddleMouse>", "<S-MiddleMouse>"],
1487          \ ["\<S-RightMouse>", "<S-RightMouse>"],
1488          \ ["\<C-LeftMouse>", "<C-LeftMouse>"],
1489          \ ["\<C-MiddleMouse>", "<C-MiddleMouse>"],
1490          \ ["\<C-RightMouse>", "<C-RightMouse>"],
1491          \ ["\<M-LeftMouse>", "<M-LeftMouse>"],
1492          \ ["\<M-MiddleMouse>", "<M-MiddleMouse>"],
1493          \ ["\<M-RightMouse>", "<M-RightMouse>"],
1494          \ ["\<2-LeftMouse>", "<2-LeftMouse>"],
1495          \ ["\<2-MiddleMouse>", "<2-MiddleMouse>"],
1496          \ ["\<2-RightMouse>", "<2-RightMouse>"],
1497          \ ["\<3-LeftMouse>", "<3-LeftMouse>"],
1498          \ ["\<3-MiddleMouse>", "<3-MiddleMouse>"],
1499          \ ["\<3-RightMouse>", "<3-RightMouse>"],
1500          \ ["\<4-LeftMouse>", "<4-LeftMouse>"],
1501          \ ["\<4-MiddleMouse>", "<4-MiddleMouse>"],
1502          \ ["\<4-RightMouse>", "<4-RightMouse>"],
1503          \ ["\<LeftDrag>", "<LeftDrag>"],
1504          \ ["\<MiddleDrag>", "<MiddleDrag>"],
1505          \ ["\<RightDrag>", "<RightDrag>"],
1506          \ ["\<LeftRelease>", "<LeftRelease>"],
1507          \ ["\<MiddleRelease>", "<MiddleRelease>"],
1508          \ ["\<RightRelease>", "<RightRelease>"],
1509          \ ["\<ScrollWheelUp>", "<ScrollWheelUp>"],
1510          \ ["\<S-ScrollWheelUp>", "<S-ScrollWheelUp>"],
1511          \ ["\<C-ScrollWheelUp>", "<C-ScrollWheelUp>"],
1512          \ ["\<ScrollWheelDown>", "<ScrollWheelDown>"],
1513          \ ["\<S-ScrollWheelDown>", "<S-ScrollWheelDown>"],
1514          \ ["\<C-ScrollWheelDown>", "<C-ScrollWheelDown>"],
1515          \ ["\<ScrollWheelLeft>", "<ScrollWheelLeft>"],
1516          \ ["\<S-ScrollWheelLeft>", "<S-ScrollWheelLeft>"],
1517          \ ["\<C-ScrollWheelLeft>", "<C-ScrollWheelLeft>"],
1518          \ ["\<ScrollWheelRight>", "<ScrollWheelRight>"],
1519          \ ["\<S-ScrollWheelRight>", "<S-ScrollWheelRight>"],
1520          \ ["\<C-ScrollWheelRight>", "<C-ScrollWheelRight>"]
1521          \ ]
1522
1523    for [code, outstr] in mouse_codes
1524      exe "normal ggC\<C-K>" . code
1525      call assert_equal(outstr, getline(1), msg)
1526    endfor
1527  endfor
1528
1529  let &mouse = save_mouse
1530  let &term = save_term
1531  let &ttymouse = save_ttymouse
1532  set mousetime&
1533  call test_override('no_query_mouse', 0)
1534  %bw!
1535endfunc
1536
1537" This only checks if the sequence is recognized.
1538func Test_term_rgb_response()
1539  set t_RF=x
1540  set t_RB=y
1541
1542  " response to t_RF, 4 digits
1543  let red = 0x12
1544  let green = 0x34
1545  let blue = 0x56
1546  let seq = printf("\<Esc>]10;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1547  call feedkeys(seq, 'Lx!')
1548  call assert_equal(seq, v:termrfgresp)
1549
1550  " response to t_RF, 2 digits
1551  let red = 0x78
1552  let green = 0x9a
1553  let blue = 0xbc
1554  let seq = printf("\<Esc>]10;rgb:%02x/%02x/%02x\x07", red, green, blue)
1555  call feedkeys(seq, 'Lx!')
1556  call assert_equal(seq, v:termrfgresp)
1557
1558  " response to t_RB, 4 digits, dark
1559  set background=light
1560  eval 'background'->test_option_not_set()
1561  let red = 0x29
1562  let green = 0x4a
1563  let blue = 0x6b
1564  let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1565  call feedkeys(seq, 'Lx!')
1566  call assert_equal(seq, v:termrbgresp)
1567  call assert_equal('dark', &background)
1568
1569  " response to t_RB, 4 digits, light
1570  set background=dark
1571  call test_option_not_set('background')
1572  let red = 0x81
1573  let green = 0x63
1574  let blue = 0x65
1575  let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1576  call feedkeys(seq, 'Lx!')
1577  call assert_equal(seq, v:termrbgresp)
1578  call assert_equal('light', &background)
1579
1580  " response to t_RB, 2 digits, dark
1581  set background=light
1582  call test_option_not_set('background')
1583  let red = 0x47
1584  let green = 0x59
1585  let blue = 0x5b
1586  let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
1587  call feedkeys(seq, 'Lx!')
1588  call assert_equal(seq, v:termrbgresp)
1589  call assert_equal('dark', &background)
1590
1591  " response to t_RB, 2 digits, light
1592  set background=dark
1593  call test_option_not_set('background')
1594  let red = 0x83
1595  let green = 0xa4
1596  let blue = 0xc2
1597  let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
1598  call feedkeys(seq, 'Lx!')
1599  call assert_equal(seq, v:termrbgresp)
1600  call assert_equal('light', &background)
1601
1602  set t_RF= t_RB=
1603endfunc
1604
1605" This only checks if the sequence is recognized.
1606" This must be after other tests, because it has side effects to xterm
1607" properties.
1608func Test_xx01_term_style_response()
1609  " Termresponse is only parsed when t_RV is not empty.
1610  set t_RV=x
1611  call test_override('term_props', 1)
1612
1613  " send the termresponse to trigger requesting the XT codes
1614  let seq = "\<Esc>[>41;337;0c"
1615  call feedkeys(seq, 'Lx!')
1616  call assert_equal(seq, v:termresponse)
1617
1618  let seq = "\<Esc>P1$r2 q\<Esc>\\"
1619  call feedkeys(seq, 'Lx!')
1620  call assert_equal(seq, v:termstyleresp)
1621
1622  call assert_equal(#{
1623        \ cursor_style: 'u',
1624        \ cursor_blink_mode: 'u',
1625        \ underline_rgb: 'u',
1626        \ mouse: 's'
1627        \ }, terminalprops())
1628
1629  set t_RV=
1630  call test_override('term_props', 0)
1631endfunc
1632
1633" This checks the iTerm2 version response.
1634" This must be after other tests, because it has side effects to xterm
1635" properties.
1636func Test_xx02_iTerm2_response()
1637  " Termresponse is only parsed when t_RV is not empty.
1638  set t_RV=x
1639  call test_override('term_props', 1)
1640
1641  " Old versions of iTerm2 used a different style term response.
1642  set ttymouse=xterm
1643  call test_option_not_set('ttymouse')
1644  let seq = "\<Esc>[>0;95;c"
1645  call feedkeys(seq, 'Lx!')
1646  call assert_equal(seq, v:termresponse)
1647  call assert_equal('xterm', &ttymouse)
1648
1649  set ttymouse=xterm
1650  call test_option_not_set('ttymouse')
1651  let seq = "\<Esc>[>0;95;0c"
1652  call feedkeys(seq, 'Lx!')
1653  call assert_equal(seq, v:termresponse)
1654  call assert_equal('sgr', &ttymouse)
1655
1656  call assert_equal(#{
1657        \ cursor_style: 'n',
1658        \ cursor_blink_mode: 'u',
1659        \ underline_rgb: 'u',
1660        \ mouse: 's'
1661        \ }, terminalprops())
1662
1663  set t_RV=
1664  call test_override('term_props', 0)
1665endfunc
1666
1667" This checks the libvterm version response.
1668" This must be after other tests, because it has side effects to xterm
1669" properties.
1670func Test_xx03_libvterm_response()
1671  " Termresponse is only parsed when t_RV is not empty.
1672  set t_RV=x
1673  call test_override('term_props', 1)
1674
1675  set ttymouse=xterm
1676  call test_option_not_set('ttymouse')
1677  let seq = "\<Esc>[>0;100;0c"
1678  call feedkeys(seq, 'Lx!')
1679  call assert_equal(seq, v:termresponse)
1680  call assert_equal('sgr', &ttymouse)
1681
1682  call assert_equal(#{
1683        \ cursor_style: 'n',
1684        \ cursor_blink_mode: 'u',
1685        \ underline_rgb: 'u',
1686        \ mouse: 's'
1687        \ }, terminalprops())
1688
1689  set t_RV=
1690  call test_override('term_props', 0)
1691endfunc
1692
1693" This checks the Mac Terminal.app version response.
1694" This must be after other tests, because it has side effects to xterm
1695" properties.
1696func Test_xx04_Mac_Terminal_response()
1697  " Termresponse is only parsed when t_RV is not empty.
1698  set t_RV=x
1699  call test_override('term_props', 1)
1700
1701  set ttymouse=xterm
1702  " t_8u is not reset
1703  let &t_8u = "\<Esc>[58;2;%lu;%lu;%lum"
1704  call test_option_not_set('ttymouse')
1705  let seq = "\<Esc>[>1;95;0c"
1706  call feedkeys(seq, 'Lx!')
1707  call assert_equal(seq, v:termresponse)
1708  call assert_equal('sgr', &ttymouse)
1709
1710  call assert_equal(#{
1711        \ cursor_style: 'n',
1712        \ cursor_blink_mode: 'u',
1713        \ underline_rgb: 'y',
1714        \ mouse: 's'
1715        \ }, terminalprops())
1716  call assert_equal("\<Esc>[58;2;%lu;%lu;%lum", &t_8u)
1717
1718  " Reset is_not_xterm and is_mac_terminal.
1719  set t_RV=
1720  set term=xterm
1721  set t_RV=x
1722  call test_override('term_props', 0)
1723endfunc
1724
1725" This checks the mintty version response.
1726" This must be after other tests, because it has side effects to xterm
1727" properties.
1728func Test_xx05_mintty_response()
1729  " Termresponse is only parsed when t_RV is not empty.
1730  set t_RV=x
1731  call test_override('term_props', 1)
1732
1733  set ttymouse=xterm
1734  call test_option_not_set('ttymouse')
1735  let seq = "\<Esc>[>77;20905;0c"
1736  call feedkeys(seq, 'Lx!')
1737  call assert_equal(seq, v:termresponse)
1738  call assert_equal('sgr', &ttymouse)
1739
1740  call assert_equal(#{
1741        \ cursor_style: 'n',
1742        \ cursor_blink_mode: 'u',
1743        \ underline_rgb: 'y',
1744        \ mouse: 's'
1745        \ }, terminalprops())
1746
1747  set t_RV=
1748  call test_override('term_props', 0)
1749endfunc
1750
1751" This checks the screen version response.
1752" This must be after other tests, because it has side effects to xterm
1753" properties.
1754func Test_xx06_screen_response()
1755  " Termresponse is only parsed when t_RV is not empty.
1756  set t_RV=x
1757  call test_override('term_props', 1)
1758
1759  " Old versions of screen don't support SGR mouse mode.
1760  set ttymouse=xterm
1761  call test_option_not_set('ttymouse')
1762  let seq = "\<Esc>[>83;40500;0c"
1763  call feedkeys(seq, 'Lx!')
1764  call assert_equal(seq, v:termresponse)
1765  call assert_equal('xterm', &ttymouse)
1766
1767  " screen supports SGR mouse mode starting in version 4.7.
1768  set ttymouse=xterm
1769  call test_option_not_set('ttymouse')
1770  let seq = "\<Esc>[>83;40700;0c"
1771  call feedkeys(seq, 'Lx!')
1772  call assert_equal(seq, v:termresponse)
1773  call assert_equal('sgr', &ttymouse)
1774
1775  call assert_equal(#{
1776        \ cursor_style: 'n',
1777        \ cursor_blink_mode: 'n',
1778        \ underline_rgb: 'y',
1779        \ mouse: 's'
1780        \ }, terminalprops())
1781
1782  set t_RV=
1783  call test_override('term_props', 0)
1784endfunc
1785
1786" This checks the xterm version response.
1787" This must be after other tests, because it has side effects to xterm
1788" properties.
1789func Test_xx07_xterm_response()
1790  " Termresponse is only parsed when t_RV is not empty.
1791  set t_RV=x
1792  call test_override('term_props', 1)
1793
1794  " Do Terminal.app first to check that is_mac_terminal is reset.
1795  set ttymouse=xterm
1796  call test_option_not_set('ttymouse')
1797  let seq = "\<Esc>[>1;95;0c"
1798  call feedkeys(seq, 'Lx!')
1799  call assert_equal(seq, v:termresponse)
1800  call assert_equal('sgr', &ttymouse)
1801
1802  " xterm < 95: "xterm" (actually unmodified)
1803  set t_RV=
1804  set term=xterm
1805  set t_RV=x
1806  set ttymouse=xterm
1807  call test_option_not_set('ttymouse')
1808  let seq = "\<Esc>[>0;94;0c"
1809  call feedkeys(seq, 'Lx!')
1810  call assert_equal(seq, v:termresponse)
1811  call assert_equal('xterm', &ttymouse)
1812
1813  call assert_equal(#{
1814        \ cursor_style: 'n',
1815        \ cursor_blink_mode: 'u',
1816        \ underline_rgb: 'y',
1817        \ mouse: 'u'
1818        \ }, terminalprops())
1819
1820  " xterm >= 95 < 277 "xterm2"
1821  set ttymouse=xterm
1822  call test_option_not_set('ttymouse')
1823  let seq = "\<Esc>[>0;267;0c"
1824  call feedkeys(seq, 'Lx!')
1825  call assert_equal(seq, v:termresponse)
1826  call assert_equal('xterm2', &ttymouse)
1827
1828  call assert_equal(#{
1829        \ cursor_style: 'n',
1830        \ cursor_blink_mode: 'u',
1831        \ underline_rgb: 'u',
1832        \ mouse: '2'
1833        \ }, terminalprops())
1834
1835  " xterm >= 277: "sgr"
1836  set ttymouse=xterm
1837  call test_option_not_set('ttymouse')
1838  let seq = "\<Esc>[>0;277;0c"
1839  call feedkeys(seq, 'Lx!')
1840  call assert_equal(seq, v:termresponse)
1841  call assert_equal('sgr', &ttymouse)
1842
1843  call assert_equal(#{
1844        \ cursor_style: 'n',
1845        \ cursor_blink_mode: 'u',
1846        \ underline_rgb: 'u',
1847        \ mouse: 's'
1848        \ }, terminalprops())
1849
1850  " xterm >= 279: "sgr" and cursor_style not reset; also check t_8u reset
1851  set ttymouse=xterm
1852  call test_option_not_set('ttymouse')
1853  let &t_8u = "\<Esc>[58;2;%lu;%lu;%lum"
1854  let seq = "\<Esc>[>0;279;0c"
1855  call feedkeys(seq, 'Lx!')
1856  call assert_equal(seq, v:termresponse)
1857  call assert_equal('sgr', &ttymouse)
1858
1859  call assert_equal(#{
1860        \ cursor_style: 'u',
1861        \ cursor_blink_mode: 'u',
1862        \ underline_rgb: 'u',
1863        \ mouse: 's'
1864        \ }, terminalprops())
1865  call assert_equal('', &t_8u)
1866
1867  set t_RV=
1868  call test_override('term_props', 0)
1869endfunc
1870
1871func Test_focus_events()
1872  let save_term = &term
1873  let save_ttymouse = &ttymouse
1874  set term=xterm ttymouse=xterm2
1875
1876  au FocusGained * let g:focus_gained += 1
1877  au FocusLost * let g:focus_lost += 1
1878  let g:focus_gained = 0
1879  let g:focus_lost = 0
1880
1881  call feedkeys("\<Esc>[O", "Lx!")
1882  call assert_equal(1, g:focus_lost)
1883  call feedkeys("\<Esc>[I", "Lx!")
1884  call assert_equal(1, g:focus_gained)
1885
1886  " still works when 'ttymouse' is empty
1887  set ttymouse=
1888  call feedkeys("\<Esc>[O", "Lx!")
1889  call assert_equal(2, g:focus_lost)
1890  call feedkeys("\<Esc>[I", "Lx!")
1891  call assert_equal(2, g:focus_gained)
1892
1893  au! FocusGained
1894  au! FocusLost
1895  let &term = save_term
1896  let &ttymouse = save_ttymouse
1897endfunc
1898
1899func Test_get_termcode()
1900  try
1901    let k1 = &t_k1
1902  catch /E113/
1903    throw 'Skipped: Unable to query termcodes'
1904  endtry
1905  set t_k1=
1906  set t_k1&
1907  call assert_equal(k1, &t_k1)
1908
1909  " use external termcap first
1910  set nottybuiltin
1911  set t_k1=
1912  set t_k1&
1913  " when using external termcap may get something else, but it must not be
1914  " empty, since we would fallback to the builtin one.
1915  call assert_notequal('', &t_k1)
1916
1917  if &term =~ 'xterm'
1918    " use internal termcap first
1919    let term_save = &term
1920    let &term = 'builtin_' .. &term
1921    set t_k1=
1922    set t_k1&
1923    call assert_equal(k1, &t_k1)
1924    let &term = term_save
1925  endif
1926
1927  set ttybuiltin
1928endfunc
1929
1930func Test_list_builtin_terminals()
1931  CheckRunVimInTerminal
1932  call RunVimInTerminal('', #{rows: 14})
1933  call term_sendkeys('', ":set cmdheight=3\<CR>")
1934  call TermWait('', 100)
1935  call term_sendkeys('', ":set term=xxx\<CR>")
1936  call TermWait('', 100)
1937  call assert_match('builtin_dumb', term_getline('', 11))
1938  call assert_match('Not found in termcap', term_getline('', 12))
1939  call StopVimInTerminal('')
1940endfunc
1941
1942func GetEscCodeCSI27(key, modifier)
1943  let key = printf("%d", char2nr(a:key))
1944  let mod = printf("%d", a:modifier)
1945  return "\<Esc>[27;" .. mod .. ';' .. key .. '~'
1946endfunc
1947
1948func GetEscCodeCSIu(key, modifier)
1949  let key = printf("%d", char2nr(a:key))
1950  let mod = printf("%d", a:modifier)
1951  return "\<Esc>[" .. key .. ';' .. mod .. 'u'
1952endfunc
1953
1954" This checks the CSI sequences when in modifyOtherKeys mode.
1955" The mode doesn't need to be enabled, the codes are always detected.
1956func RunTest_modifyOtherKeys(func)
1957  new
1958  set timeoutlen=10
1959
1960  " Shift-X is sent as 'X' with the shift modifier
1961  call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!')
1962  call assert_equal('X', getline(1))
1963
1964  " Ctrl-i is Tab
1965  call setline(1, '')
1966  call feedkeys('a' .. a:func('i', 5) .. "\<Esc>", 'Lx!')
1967  call assert_equal("\t", getline(1))
1968
1969  " Ctrl-I is also Tab
1970  call setline(1, '')
1971  call feedkeys('a' .. a:func('I', 5) .. "\<Esc>", 'Lx!')
1972  call assert_equal("\t", getline(1))
1973
1974  " Alt-x is ø
1975  call setline(1, '')
1976  call feedkeys('a' .. a:func('x', 3) .. "\<Esc>", 'Lx!')
1977  call assert_equal("ø", getline(1))
1978
1979  " Meta-x is also ø
1980  call setline(1, '')
1981  call feedkeys('a' .. a:func('x', 9) .. "\<Esc>", 'Lx!')
1982  call assert_equal("ø", getline(1))
1983
1984  " Alt-X is Ø
1985  call setline(1, '')
1986  call feedkeys('a' .. a:func('X', 3) .. "\<Esc>", 'Lx!')
1987  call assert_equal("Ø", getline(1))
1988
1989  " Meta-X is ø
1990  call setline(1, '')
1991  call feedkeys('a' .. a:func('X', 9) .. "\<Esc>", 'Lx!')
1992  call assert_equal("Ø", getline(1))
1993
1994  " Ctrl-6 is Ctrl-^
1995  split aaa
1996  edit bbb
1997  call feedkeys(a:func('6', 5), 'Lx!')
1998  call assert_equal("aaa", bufname())
1999  bwipe aaa
2000  bwipe bbb
2001
2002  " Ctrl-V X 33 is 3
2003  call setline(1, '')
2004  call feedkeys("a\<C-V>" .. a:func('X', 2) .. "33\<Esc>", 'Lx!')
2005  call assert_equal("3", getline(1))
2006
2007  " Ctrl-V U 12345 is Unicode 12345
2008  call setline(1, '')
2009  call feedkeys("a\<C-V>" .. a:func('U', 2) .. "12345\<Esc>", 'Lx!')
2010  call assert_equal("\U12345", getline(1))
2011
2012  bwipe!
2013  set timeoutlen&
2014endfunc
2015
2016func Test_modifyOtherKeys_basic()
2017  call RunTest_modifyOtherKeys(function('GetEscCodeCSI27'))
2018  call RunTest_modifyOtherKeys(function('GetEscCodeCSIu'))
2019endfunc
2020
2021func Test_modifyOtherKeys_no_mapping()
2022  set timeoutlen=10
2023
2024  let @a = 'aaa'
2025  call feedkeys(":let x = '" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a'\<CR>", 'Lx!')
2026  call assert_equal("let x = 'aaa'", @:)
2027
2028  new
2029  call feedkeys("a" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a\<Esc>", 'Lx!')
2030  call assert_equal("aaa", getline(1))
2031  bwipe!
2032
2033  new
2034  call feedkeys("axx\<CR>yy" .. GetEscCodeCSI27('G', 5) .. GetEscCodeCSI27('K', 5) .. "a\<Esc>", 'Lx!')
2035  call assert_equal("axx", getline(1))
2036  call assert_equal("yy", getline(2))
2037  bwipe!
2038
2039  set timeoutlen&
2040endfunc
2041
2042func RunTest_mapping_shift(key, func)
2043  call setline(1, '')
2044  if a:key == '|'
2045    exe 'inoremap \| xyz'
2046  else
2047    exe 'inoremap ' .. a:key .. ' xyz'
2048  endif
2049  call feedkeys('a' .. a:func(a:key, 2) .. "\<Esc>", 'Lx!')
2050  call assert_equal("xyz", getline(1))
2051  if a:key == '|'
2052    exe 'iunmap \|'
2053  else
2054    exe 'iunmap ' .. a:key
2055  endif
2056endfunc
2057
2058func Test_modifyOtherKeys_mapped()
2059  set timeoutlen=10
2060  imap ' <C-W>
2061  imap <C-W><C-A> c-a
2062  call setline(1, '')
2063
2064  " single quote is turned into single byte CTRL-W
2065  " CTRL-A is added with a separate modifier, and needs to be simplified before
2066  " the mapping can match.
2067  call feedkeys("a'" .. GetEscCodeCSI27('A', 5) .. "\<Esc>", 'Lx!')
2068  call assert_equal('c-a', getline(1))
2069
2070  iunmap '
2071  iunmap <C-W><C-A>
2072  set timeoutlen&
2073endfunc
2074
2075" Whether Shift-Tab sends "ESC [ Z" or "ESC [ 27 ; 2 ; 9 ~" is unpredictable,
2076" both should work.
2077func Test_modifyOtherKeys_shift_tab()
2078  set timeoutlen=10
2079
2080  call setline(1, '')
2081  call feedkeys("a\<C-K>" .. GetEscCodeCSI27("\t", '2') .. "\<Esc>", 'Lx!')
2082  eval getline(1)->assert_equal('<S-Tab>')
2083
2084  call setline(1, '')
2085  call feedkeys("a\<C-K>\<Esc>[Z\<Esc>", 'Lx!')
2086  eval getline(1)->assert_equal('<S-Tab>')
2087
2088  set timeoutlen&
2089  bwipe!
2090endfunc
2091
2092func RunTest_mapping_works_with_shift(func)
2093  new
2094  set timeoutlen=10
2095
2096  call RunTest_mapping_shift('@', a:func)
2097  call RunTest_mapping_shift('A', a:func)
2098  call RunTest_mapping_shift('Z', a:func)
2099  call RunTest_mapping_shift('^', a:func)
2100  call RunTest_mapping_shift('_', a:func)
2101  call RunTest_mapping_shift('{', a:func)
2102  call RunTest_mapping_shift('|', a:func)
2103  call RunTest_mapping_shift('}', a:func)
2104  call RunTest_mapping_shift('~', a:func)
2105
2106  bwipe!
2107  set timeoutlen&
2108endfunc
2109
2110func Test_mapping_works_with_shift_plain()
2111  call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27'))
2112  call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu'))
2113endfunc
2114
2115func RunTest_mapping_mods(map, key, func, code)
2116  call setline(1, '')
2117  exe 'inoremap ' .. a:map .. ' xyz'
2118  call feedkeys('a' .. a:func(a:key, a:code) .. "\<Esc>", 'Lx!')
2119  call assert_equal("xyz", getline(1))
2120  exe 'iunmap ' .. a:map
2121endfunc
2122
2123func RunTest_mapping_works_with_mods(func, mods, code)
2124  new
2125  set timeoutlen=10
2126
2127  if a:mods !~ 'S'
2128    " Shift by itself has no effect
2129    call RunTest_mapping_mods('<' .. a:mods .. '-@>', '@', a:func, a:code)
2130  endif
2131  call RunTest_mapping_mods('<' .. a:mods .. '-A>', 'A', a:func, a:code)
2132  call RunTest_mapping_mods('<' .. a:mods .. '-Z>', 'Z', a:func, a:code)
2133  if a:mods !~ 'S'
2134    " with Shift code is always upper case
2135    call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'a', a:func, a:code)
2136    call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'z', a:func, a:code)
2137  endif
2138  if a:mods != 'A'
2139    " with Alt code is not in upper case
2140    call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'A', a:func, a:code)
2141    call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'Z', a:func, a:code)
2142  endif
2143  call RunTest_mapping_mods('<' .. a:mods .. '-á>', 'á', a:func, a:code)
2144  if a:mods !~ 'S'
2145    " Shift by itself has no effect
2146    call RunTest_mapping_mods('<' .. a:mods .. '-^>', '^', a:func, a:code)
2147    call RunTest_mapping_mods('<' .. a:mods .. '-_>', '_', a:func, a:code)
2148    call RunTest_mapping_mods('<' .. a:mods .. '-{>', '{', a:func, a:code)
2149    call RunTest_mapping_mods('<' .. a:mods .. '-\|>', '|', a:func, a:code)
2150    call RunTest_mapping_mods('<' .. a:mods .. '-}>', '}', a:func, a:code)
2151    call RunTest_mapping_mods('<' .. a:mods .. '-~>', '~', a:func, a:code)
2152  endif
2153
2154  bwipe!
2155  set timeoutlen&
2156endfunc
2157
2158func Test_mapping_works_with_shift()
2159  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S', 2)
2160  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S', 2)
2161endfunc
2162
2163func Test_mapping_works_with_ctrl()
2164  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5)
2165  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5)
2166
2167  new
2168  set timeoutlen=10
2169
2170  " CTRL-@ actually produces the code for CTRL-2, which is converted
2171  call RunTest_mapping_mods('<C-@>', '2', function('GetEscCodeCSI27'), 5)
2172  call RunTest_mapping_mods('<C-@>', '2', function('GetEscCodeCSIu'), 5)
2173
2174  " CTRL-^ actually produces the code for CTRL-6, which is converted
2175  call RunTest_mapping_mods('<C-^>', '6', function('GetEscCodeCSI27'), 5)
2176  call RunTest_mapping_mods('<C-^>', '6', function('GetEscCodeCSIu'), 5)
2177
2178  " CTRL-_ actually produces the code for CTRL--, which is converted
2179  call RunTest_mapping_mods('<C-_>', '-', function('GetEscCodeCSI27'), 5)
2180  call RunTest_mapping_mods('<C-_>', '-', function('GetEscCodeCSIu'), 5)
2181
2182  bwipe!
2183  set timeoutlen&
2184endfunc
2185
2186func Test_mapping_works_with_shift_ctrl()
2187  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6)
2188  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6)
2189
2190  new
2191  set timeoutlen=10
2192
2193  " Ctrl-Shift-[ actually produces CTRL-Shift-{ which is mapped as <C-{>
2194  call RunTest_mapping_mods('<C-{>', '{', function('GetEscCodeCSI27'), 6)
2195  call RunTest_mapping_mods('<C-{>', '{', function('GetEscCodeCSIu'), 6)
2196
2197  " Ctrl-Shift-] actually produces CTRL-Shift-} which is mapped as <C-}>
2198  call RunTest_mapping_mods('<C-{>', '{', function('GetEscCodeCSI27'), 6)
2199  call RunTest_mapping_mods('<C-{>', '{', function('GetEscCodeCSIu'), 6)
2200
2201  " Ctrl-Shift-\ actually produces CTRL-Shift-| which is mapped as <C-|>
2202  call RunTest_mapping_mods('<C-\|>', '|', function('GetEscCodeCSI27'), 6)
2203  call RunTest_mapping_mods('<C-\|>', '|', function('GetEscCodeCSIu'), 6)
2204
2205  bwipe!
2206  set timeoutlen&
2207endfunc
2208
2209" Below we also test the "u" code with Alt, This works, but libvterm would not
2210" send the Alt key like this but by prefixing an Esc.
2211
2212func Test_mapping_works_with_alt()
2213  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'A', 3)
2214  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'A', 3)
2215endfunc
2216
2217func Test_mapping_works_with_shift_alt()
2218  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S-A', 4)
2219  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S-A', 4)
2220endfunc
2221
2222func Test_mapping_works_with_alt_and_shift()
2223  new
2224  set timeoutlen=10
2225
2226  " mapping <A-?> works even though the code is A-S-?
2227  for c in ['!', '$', '+', ':', '?', '^', '~']
2228    call RunTest_mapping_mods('<A-' .. c .. '>', c, function('GetEscCodeCSI27'), 4)
2229    call RunTest_mapping_mods('<A-' .. c .. '>', c, function('GetEscCodeCSIu'), 4)
2230  endfor
2231
2232  bwipe!
2233  set timeoutlen&
2234endfunc
2235
2236func Test_mapping_works_with_ctrl_alt()
2237  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-A', 7)
2238  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-A', 7)
2239endfunc
2240
2241func Test_mapping_works_with_shift_ctrl_alt()
2242  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8)
2243  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
2244endfunc
2245
2246func Test_insert_literal()
2247  set timeoutlen=10
2248  new
2249  " CTRL-V CTRL-X inserts a ^X
2250  call feedkeys('a' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
2251  call assert_equal("\<C-X>", getline(1))
2252
2253  call setline(1, '')
2254  call feedkeys('a' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
2255  call assert_equal("\<C-X>", getline(1))
2256
2257  " CTRL-SHIFT-V CTRL-X inserts escape sequence
2258  call setline(1, '')
2259  call feedkeys('a' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
2260  call assert_equal("\<Esc>[88;5u", getline(1))
2261
2262  call setline(1, '')
2263  call feedkeys('a' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
2264  call assert_equal("\<Esc>[27;5;88~", getline(1))
2265
2266  bwipe!
2267  set timeoutlen&
2268endfunc
2269
2270func Test_cmdline_literal()
2271  set timeoutlen=10
2272
2273  " CTRL-V CTRL-Y inserts a ^Y
2274  call feedkeys(':' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2275  call assert_equal("\"\<C-Y>", @:)
2276
2277  call feedkeys(':' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2278  call assert_equal("\"\<C-Y>", @:)
2279
2280  " CTRL-SHIFT-V CTRL-Y inserts escape sequence
2281  call feedkeys(':' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2282  call assert_equal("\"\<Esc>[89;5u", @:)
2283
2284  call setline(1, '')
2285  call feedkeys(':' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2286  call assert_equal("\"\<Esc>[27;5;89~", @:)
2287
2288  set timeoutlen&
2289endfunc
2290
2291" Test for translation of special key codes (<xF1>, <xF2>, etc.)
2292func Test_Keycode_Translation()
2293  let keycodes = [
2294        \ ["<xUp>", "<Up>"],
2295        \ ["<xDown>", "<Down>"],
2296        \ ["<xLeft>", "<Left>"],
2297        \ ["<xRight>", "<Right>"],
2298        \ ["<xHome>", "<Home>"],
2299        \ ["<xEnd>", "<End>"],
2300        \ ["<zHome>", "<Home>"],
2301        \ ["<zEnd>", "<End>"],
2302        \ ["<xF1>", "<F1>"],
2303        \ ["<xF2>", "<F2>"],
2304        \ ["<xF3>", "<F3>"],
2305        \ ["<xF4>", "<F4>"],
2306        \ ["<S-xF1>", "<S-F1>"],
2307        \ ["<S-xF2>", "<S-F2>"],
2308        \ ["<S-xF3>", "<S-F3>"],
2309        \ ["<S-xF4>", "<S-F4>"]]
2310  for [k1, k2] in keycodes
2311    exe "nnoremap " .. k1 .. " 2wx"
2312    call assert_true(maparg(k1, 'n', 0, 1).lhs == k2)
2313    exe "nunmap " .. k1
2314  endfor
2315endfunc
2316
2317" Test for terminal keycodes that doesn't have termcap entries
2318func Test_special_term_keycodes()
2319  new
2320  " Test for <xHome>, <S-xHome> and <C-xHome>
2321  " send <K_SPECIAL> <KS_EXTRA> keycode
2322  call feedkeys("i\<C-K>\x80\xfd\x3f\n", 'xt')
2323  " send <K_SPECIAL> <KS_MODIFIER> bitmap <K_SPECIAL> <KS_EXTRA> keycode
2324  call feedkeys("i\<C-K>\x80\xfc\x2\x80\xfd\x3f\n", 'xt')
2325  call feedkeys("i\<C-K>\x80\xfc\x4\x80\xfd\x3f\n", 'xt')
2326  " Test for <xEnd>, <S-xEnd> and <C-xEnd>
2327  call feedkeys("i\<C-K>\x80\xfd\x3d\n", 'xt')
2328  call feedkeys("i\<C-K>\x80\xfc\x2\x80\xfd\x3d\n", 'xt')
2329  call feedkeys("i\<C-K>\x80\xfc\x4\x80\xfd\x3d\n", 'xt')
2330  " Test for <zHome>, <S-zHome> and <C-zHome>
2331  call feedkeys("i\<C-K>\x80\xfd\x40\n", 'xt')
2332  call feedkeys("i\<C-K>\x80\xfc\x2\x80\xfd\x40\n", 'xt')
2333  call feedkeys("i\<C-K>\x80\xfc\x4\x80\xfd\x40\n", 'xt')
2334  " Test for <zEnd>, <S-zEnd> and <C-zEnd>
2335  call feedkeys("i\<C-K>\x80\xfd\x3e\n", 'xt')
2336  call feedkeys("i\<C-K>\x80\xfc\x2\x80\xfd\x3e\n", 'xt')
2337  call feedkeys("i\<C-K>\x80\xfc\x4\x80\xfd\x3e\n", 'xt')
2338  " Test for <xUp>, <xDown>, <xLeft> and <xRight>
2339  call feedkeys("i\<C-K>\x80\xfd\x41\n", 'xt')
2340  call feedkeys("i\<C-K>\x80\xfd\x42\n", 'xt')
2341  call feedkeys("i\<C-K>\x80\xfd\x43\n", 'xt')
2342  call feedkeys("i\<C-K>\x80\xfd\x44\n", 'xt')
2343  call assert_equal(['<Home>', '<S-Home>', '<C-Home>',
2344        \ '<End>', '<S-End>', '<C-End>',
2345        \ '<Home>', '<S-Home>', '<C-Home>',
2346        \ '<End>', '<S-End>', '<C-End>',
2347        \ '<Up>', '<Down>', '<Left>', '<Right>', ''], getline(1, '$'))
2348  bw!
2349endfunc
2350
2351func Test_terminal_builtin_without_gui()
2352  CheckNotMSWindows
2353
2354  " builtin_gui should not be output by :set term=xxx
2355  let output = systemlist("TERM=dumb " .. v:progpath .. " --clean -c ':set t_ti= t_te=' -c 'set term=xxx' -c ':q!'")
2356  redraw!
2357  call map(output, {_, val -> trim(val)})
2358  call assert_equal(-1, index(output, 'builtin_gui'))
2359  call assert_notequal(-1, index(output, 'builtin_dumb'))
2360endfunc
2361
2362
2363" vim: shiftwidth=2 sts=2 expandtab
2364