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  let save_mouse = &mouse
371  let save_term = &term
372  let save_ttymouse = &ttymouse
373  call test_override('no_query_mouse', 1)
374  set mouse=a term=xterm ttymouse=xterm2
375  5new
376  redraw!
377
378  let h = 0
379  let row = &lines - &cmdwinheight - 2
380  call feedkeys("q:" ..
381        \ MouseLeftClickCode(row, 1) ..
382        \ MouseLeftDragCode(row - 1, 1) ..
383        \ MouseLeftReleaseCode(row - 2, 1) ..
384        \ "alet h = \<C-R>=winheight(0)\<CR>\<CR>", 'Lx!')
385  call assert_equal(&cmdwinheight + 2, h)
386
387  let &mouse = save_mouse
388  let &term = save_term
389  let &ttymouse = save_ttymouse
390  call test_override('no_query_mouse', 0)
391  close!
392endfunc
393
394" TODO: for unclear reasons this test fails if it comes after
395" Test_xterm_mouse_ctrl_click()
396func Test_1xterm_mouse_wheel()
397  new
398  let save_mouse = &mouse
399  let save_term = &term
400  let save_wrap = &wrap
401  let save_ttymouse = &ttymouse
402  set mouse=a term=xterm nowrap
403  call setline(1, range(100000000000000, 100000000000100))
404
405  for ttymouse_val in g:Ttymouse_values
406    let msg = 'ttymouse=' .. ttymouse_val
407    exe 'set ttymouse=' .. ttymouse_val
408    go
409    call assert_equal(1, line('w0'), msg)
410    call assert_equal([0, 1, 1, 0], getpos('.'), msg)
411
412    call MouseWheelDown(1, 1)
413    call assert_equal(4, line('w0'), msg)
414    call assert_equal([0, 4, 1, 0], getpos('.'), msg)
415
416    call MouseWheelDown(1, 1)
417    call assert_equal(7, line('w0'), msg)
418    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
419
420    call MouseWheelUp(1, 1)
421    call assert_equal(4, line('w0'), msg)
422    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
423
424    call MouseWheelUp(1, 1)
425    call assert_equal(1, line('w0'), msg)
426    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
427
428    if has('gui')
429      " Horizontal wheel scrolling currently only works when vim is
430      " compiled with gui enabled.
431      call MouseWheelRight(1, 1)
432      call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
433      call assert_equal([0, 7, 7, 0], getpos('.'), msg)
434
435      call MouseWheelRight(1, 1)
436      call assert_equal(13, 1 + virtcol(".") - wincol(), msg)
437      call assert_equal([0, 7, 13, 0], getpos('.'), msg)
438
439      call MouseWheelLeft(1, 1)
440      call assert_equal(7, 1 + virtcol(".") - wincol(), msg)
441      call assert_equal([0, 7, 13, 0], getpos('.'), msg)
442
443      call MouseWheelLeft(1, 1)
444      call assert_equal(1, 1 + virtcol(".") - wincol(), msg)
445      call assert_equal([0, 7, 13, 0], getpos('.'), msg)
446    endif
447  endfor
448
449  let &mouse = save_mouse
450  let &term = save_term
451  let &wrap = save_wrap
452  let &ttymouse = save_ttymouse
453  bwipe!
454endfunc
455
456" Test that dragging beyond the window (at the bottom and at the top)
457" scrolls window content by the number of lines beyond the window.
458func Test_term_mouse_drag_beyond_window()
459  let save_mouse = &mouse
460  let save_term = &term
461  let save_ttymouse = &ttymouse
462  call test_override('no_query_mouse', 1)
463  set mouse=a term=xterm
464  let col = 1
465  call setline(1, range(1, 100))
466
467  " Split into 3 windows, and go into the middle window
468  " so we test dragging mouse below and above the window.
469  2split
470  wincmd j
471  2split
472
473  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
474    let msg = 'ttymouse=' .. ttymouse_val
475    exe 'set ttymouse=' .. ttymouse_val
476
477    " Line #10 at the top.
478    norm! 10zt
479    redraw
480    call assert_equal(10, winsaveview().topline, msg)
481    call assert_equal(2, winheight(0), msg)
482
483    let row = 4
484    call MouseLeftClick(row, col)
485    call assert_equal(10, winsaveview().topline, msg)
486
487    " Drag downwards. We're still in the window so topline should
488    " not change yet.
489    let row += 1
490    call MouseLeftDrag(row, col)
491    call assert_equal(10, winsaveview().topline, msg)
492
493    " We now leave the window at the bottom, so the window content should
494    " scroll by 1 line, then 2 lines (etc) as we drag further away.
495    let row += 1
496    call MouseLeftDrag(row, col)
497    call assert_equal(11, winsaveview().topline, msg)
498
499    let row += 1
500    call MouseLeftDrag(row, col)
501    call assert_equal(13, winsaveview().topline, msg)
502
503    " Now drag upwards.
504    let row -= 1
505    call MouseLeftDrag(row, col)
506    call assert_equal(14, winsaveview().topline, msg)
507
508    " We're now back in the window so the topline should not change.
509    let row -= 1
510    call MouseLeftDrag(row, col)
511    call assert_equal(14, winsaveview().topline, msg)
512
513    let row -= 1
514    call MouseLeftDrag(row, col)
515    call assert_equal(14, winsaveview().topline, msg)
516
517    " We now leave the window at the top so the window content should
518    " scroll by 1 line, then 2, then 3 (etc) in the opposite direction.
519    let row -= 1
520    call MouseLeftDrag(row, col)
521    call assert_equal(13, winsaveview().topline, msg)
522
523    let row -= 1
524    call MouseLeftDrag(row, col)
525    call assert_equal(11, winsaveview().topline, msg)
526
527    let row -= 1
528    call MouseLeftDrag(row, col)
529    call assert_equal(8, winsaveview().topline, msg)
530
531    call MouseLeftRelease(row, col)
532    call assert_equal(8, winsaveview().topline, msg)
533    call assert_equal(2, winheight(0), msg)
534  endfor
535
536  let &mouse = save_mouse
537  let &term = save_term
538  let &ttymouse = save_ttymouse
539  call test_override('no_query_mouse', 0)
540  bwipe!
541endfunc
542
543func Test_term_mouse_drag_window_separator()
544  let save_mouse = &mouse
545  let save_term = &term
546  let save_ttymouse = &ttymouse
547  call test_override('no_query_mouse', 1)
548  set mouse=a term=xterm
549
550  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
551    let msg = 'ttymouse=' .. ttymouse_val
552    exe 'set ttymouse=' .. ttymouse_val
553
554    " Split horizontally and test dragging the horizontal window separator.
555    split
556    let rowseparator = winheight(0) + 1
557    let row = rowseparator
558    let col = 1
559
560    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
561    if ttymouse_val !=# 'xterm2' || row <= 223
562      call MouseLeftClick(row, col)
563      let row -= 1
564      call MouseLeftDrag(row, col)
565      call assert_equal(rowseparator - 1, winheight(0) + 1, msg)
566      let row += 1
567      call MouseLeftDrag(row, col)
568      call assert_equal(rowseparator, winheight(0) + 1, msg)
569      call MouseLeftRelease(row, col)
570      call assert_equal(rowseparator, winheight(0) + 1, msg)
571    endif
572    bwipe!
573
574    " Split vertically and test dragging the vertical window separator.
575    vsplit
576    let colseparator = winwidth(0) + 1
577    let row = 1
578    let col = colseparator
579
580    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
581    if ttymouse_val !=# 'xterm2' || col <= 223
582      call MouseLeftClick(row, col)
583      let col -= 1
584      call MouseLeftDrag(row, col)
585      call assert_equal(colseparator - 1, winwidth(0) + 1, msg)
586      let col += 1
587      call MouseLeftDrag(row, col)
588      call assert_equal(colseparator, winwidth(0) + 1, msg)
589      call MouseLeftRelease(row, col)
590      call assert_equal(colseparator, winwidth(0) + 1, msg)
591    endif
592    bwipe!
593  endfor
594
595  let &mouse = save_mouse
596  let &term = save_term
597  let &ttymouse = save_ttymouse
598  call test_override('no_query_mouse', 0)
599endfunc
600
601func Test_term_mouse_drag_statusline()
602  let save_mouse = &mouse
603  let save_term = &term
604  let save_ttymouse = &ttymouse
605  call test_override('no_query_mouse', 1)
606  let save_laststatus = &laststatus
607  set mouse=a term=xterm laststatus=2
608
609  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
610    let msg = 'ttymouse=' .. ttymouse_val
611    exe 'set ttymouse=' .. ttymouse_val
612
613    call assert_equal(1, &cmdheight, msg)
614    let rowstatusline = winheight(0) + 1
615    let row = rowstatusline
616    let col = 1
617
618    if ttymouse_val ==# 'xterm2' && row > 223
619      " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
620      continue
621    endif
622
623    call MouseLeftClick(row, col)
624    let row -= 1
625    call MouseLeftDrag(row, col)
626    call assert_equal(2, &cmdheight, msg)
627    call assert_equal(rowstatusline - 1, winheight(0) + 1, msg)
628    let row += 1
629    call MouseLeftDrag(row, col)
630    call assert_equal(1, &cmdheight, msg)
631    call assert_equal(rowstatusline, winheight(0) + 1, msg)
632    call MouseLeftRelease(row, col)
633    call assert_equal(1, &cmdheight, msg)
634    call assert_equal(rowstatusline, winheight(0) + 1, msg)
635  endfor
636
637  let &mouse = save_mouse
638  let &term = save_term
639  let &ttymouse = save_ttymouse
640  call test_override('no_query_mouse', 0)
641  let &laststatus = save_laststatus
642endfunc
643
644func Test_term_mouse_click_tab()
645  let save_mouse = &mouse
646  let save_term = &term
647  let save_ttymouse = &ttymouse
648  call test_override('no_query_mouse', 1)
649  set mouse=a term=xterm
650  let row = 1
651
652  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
653    let msg = 'ttymouse=' .. ttymouse_val
654    exe 'set ttymouse=' .. ttymouse_val
655    e Xfoo
656    tabnew Xbar
657
658    let a = split(execute(':tabs'), "\n")
659    call assert_equal(['Tab page 1',
660        \              '    Xfoo',
661        \              'Tab page 2',
662        \              '>   Xbar'], a, msg)
663
664    " Test clicking on tab names in the tabline at the top.
665    let col = 2
666    redraw
667    call MouseLeftClick(row, col)
668    call MouseLeftRelease(row, col)
669    let a = split(execute(':tabs'), "\n")
670    call assert_equal(['Tab page 1',
671        \              '>   Xfoo',
672        \              'Tab page 2',
673        \              '    Xbar'], a, msg)
674
675    let col = 9
676    call MouseLeftClick(row, col)
677    call MouseLeftRelease(row, col)
678    let a = split(execute(':tabs'), "\n")
679    call assert_equal(['Tab page 1',
680        \              '    Xfoo',
681        \              'Tab page 2',
682        \              '>   Xbar'], a, msg)
683
684    %bwipe!
685  endfor
686
687  let &mouse = save_mouse
688  let &term = save_term
689  let &ttymouse = save_ttymouse
690  call test_override('no_query_mouse', 0)
691endfunc
692
693func Test_term_mouse_click_X_to_close_tab()
694  let save_mouse = &mouse
695  let save_term = &term
696  let save_ttymouse = &ttymouse
697  call test_override('no_query_mouse', 1)
698  set mouse=a term=xterm
699  let row = 1
700  let col = &columns
701
702  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
703    if ttymouse_val ==# 'xterm2' && col > 223
704      " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
705      continue
706    endif
707    let msg = 'ttymouse=' .. ttymouse_val
708    exe 'set ttymouse=' .. ttymouse_val
709    e Xtab1
710    tabnew Xtab2
711    tabnew Xtab3
712    tabn 2
713
714    let a = split(execute(':tabs'), "\n")
715    call assert_equal(['Tab page 1',
716        \              '    Xtab1',
717        \              'Tab page 2',
718        \              '>   Xtab2',
719        \              'Tab page 3',
720        \              '    Xtab3'], a, msg)
721
722    " Click on "X" in tabline to close current tab i.e. Xtab2.
723    redraw
724    call MouseLeftClick(row, col)
725    call MouseLeftRelease(row, col)
726    let a = split(execute(':tabs'), "\n")
727    call assert_equal(['Tab page 1',
728        \              '    Xtab1',
729        \              'Tab page 2',
730        \              '>   Xtab3'], a, msg)
731
732    %bwipe!
733  endfor
734
735  let &mouse = save_mouse
736  let &term = save_term
737  let &ttymouse = save_ttymouse
738  call test_override('no_query_mouse', 0)
739endfunc
740
741func Test_term_mouse_drag_to_move_tab()
742  let save_mouse = &mouse
743  let save_term = &term
744  let save_ttymouse = &ttymouse
745  call test_override('no_query_mouse', 1)
746  " Set 'mousetime' to 1 to avoid recognizing a double-click in the loop
747  set mouse=a term=xterm mousetime=1
748  let row = 1
749
750  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
751    let msg = 'ttymouse=' .. ttymouse_val
752    exe 'set ttymouse=' .. ttymouse_val
753    e Xtab1
754    tabnew Xtab2
755
756    let a = split(execute(':tabs'), "\n")
757    call assert_equal(['Tab page 1',
758        \              '    Xtab1',
759        \              'Tab page 2',
760        \              '>   Xtab2'], a, msg)
761    redraw
762
763    " Click in tab2 and drag it to tab1.
764    " Check getcharmod() to verify that click is not
765    " interpreted as a spurious double-click.
766    call MouseLeftClick(row, 10)
767    call assert_equal(0, getcharmod(), msg)
768    for col in [9, 8, 7, 6]
769      call MouseLeftDrag(row, col)
770    endfor
771    call MouseLeftRelease(row, col)
772    let a = split(execute(':tabs'), "\n")
773    call assert_equal(['Tab page 1',
774        \              '>   Xtab2',
775        \              'Tab page 2',
776        \              '    Xtab1'], a, msg)
777
778    " Click elsewhere so that click in next iteration is not
779    " interpreted as unwanted double-click.
780    call MouseLeftClick(row, 11)
781    call MouseLeftRelease(row, 11)
782
783    %bwipe!
784  endfor
785
786  let &mouse = save_mouse
787  let &term = save_term
788  let &ttymouse = save_ttymouse
789  call test_override('no_query_mouse', 0)
790  set mousetime&
791endfunc
792
793func Test_term_mouse_double_click_to_create_tab()
794  let save_mouse = &mouse
795  let save_term = &term
796  let save_ttymouse = &ttymouse
797  call test_override('no_query_mouse', 1)
798  " Set 'mousetime' to a small value, so that double-click works but we don't
799  " have to wait long to avoid a triple-click.
800  set mouse=a term=xterm mousetime=200
801  let row = 1
802  let col = 10
803
804  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
805    let msg = 'ttymouse=' .. ttymouse_val
806    exe 'set ttymouse=' .. ttymouse_val
807    e Xtab1
808    tabnew Xtab2
809
810    let a = split(execute(':tabs'), "\n")
811    call assert_equal(['Tab page 1',
812        \              '    Xtab1',
813        \              'Tab page 2',
814        \              '>   Xtab2'], a, msg)
815
816    redraw
817    call MouseLeftClick(row, col)
818    " Check getcharmod() to verify that first click is not
819    " interpreted as a spurious double-click.
820    call assert_equal(0, getcharmod(), msg)
821    call MouseLeftRelease(row, col)
822    call MouseLeftClick(row, col)
823    call assert_equal(32, getcharmod(), msg) " double-click
824    call MouseLeftRelease(row, col)
825    let a = split(execute(':tabs'), "\n")
826    call assert_equal(['Tab page 1',
827        \              '    Xtab1',
828        \              'Tab page 2',
829        \              '>   [No Name]',
830        \              'Tab page 3',
831        \              '    Xtab2'], a, msg)
832
833    " Click elsewhere so that click in next iteration is not
834    " interpreted as unwanted double click.
835    call MouseLeftClick(row, col + 1)
836    call MouseLeftRelease(row, col + 1)
837
838    %bwipe!
839  endfor
840
841  let &mouse = save_mouse
842  let &term = save_term
843  let &ttymouse = save_ttymouse
844  call test_override('no_query_mouse', 0)
845  set mousetime&
846endfunc
847
848" Test double/triple/quadruple click in normal mode to visually select.
849func Test_term_mouse_multiple_clicks_to_visually_select()
850  let save_mouse = &mouse
851  let save_term = &term
852  let save_ttymouse = &ttymouse
853  call test_override('no_query_mouse', 1)
854  set mouse=a term=xterm mousetime=200
855  new
856
857  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
858    let msg = 'ttymouse=' .. ttymouse_val
859    exe 'set ttymouse=' .. ttymouse_val
860    call setline(1, ['foo [foo bar] foo', 'foo'])
861
862    " Double-click on word should visually select the word.
863    call MouseLeftClick(1, 2)
864    call assert_equal(0, getcharmod(), msg)
865    call MouseLeftRelease(1, 2)
866    call MouseLeftClick(1, 2)
867    call assert_equal(32, getcharmod(), msg) " double-click
868    call MouseLeftRelease(1, 2)
869    call assert_equal('v', mode(), msg)
870    norm! r1
871    call assert_equal(['111 [foo bar] foo', 'foo'], getline(1, '$'), msg)
872
873    " Double-click on opening square bracket should visually
874    " select the whole [foo bar].
875    call MouseLeftClick(1, 5)
876    call assert_equal(0, getcharmod(), msg)
877    call MouseLeftRelease(1, 5)
878    call MouseLeftClick(1, 5)
879    call assert_equal(32, getcharmod(), msg) " double-click
880    call MouseLeftRelease(1, 5)
881    call assert_equal('v', mode(), msg)
882    norm! r2
883    call assert_equal(['111 222222222 foo', 'foo'], getline(1, '$'), msg)
884
885    " Triple-click should visually select the whole line.
886    call MouseLeftClick(1, 3)
887    call assert_equal(0, getcharmod(), msg)
888    call MouseLeftRelease(1, 3)
889    call MouseLeftClick(1, 3)
890    call assert_equal(32, getcharmod(), msg) " double-click
891    call MouseLeftRelease(1, 3)
892    call MouseLeftClick(1, 3)
893    call assert_equal(64, getcharmod(), msg) " triple-click
894    call MouseLeftRelease(1, 3)
895    call assert_equal('V', mode(), msg)
896    norm! r3
897    call assert_equal(['33333333333333333', 'foo'], getline(1, '$'), msg)
898
899    " Quadruple-click should start visual block select.
900    call MouseLeftClick(1, 2)
901    call assert_equal(0, getcharmod(), msg)
902    call MouseLeftRelease(1, 2)
903    call MouseLeftClick(1, 2)
904    call assert_equal(32, getcharmod(), msg) " double-click
905    call MouseLeftRelease(1, 2)
906    call MouseLeftClick(1, 2)
907    call assert_equal(64, getcharmod(), msg) " triple-click
908    call MouseLeftRelease(1, 2)
909    call MouseLeftClick(1, 2)
910    call assert_equal(96, getcharmod(), msg) " quadruple-click
911    call MouseLeftRelease(1, 2)
912    call assert_equal("\<c-v>", mode(), msg)
913    norm! r4
914    call assert_equal(['34333333333333333', 'foo'], getline(1, '$'), msg)
915
916    " Double-click on a space character should visually select all the
917    " consecutive space characters.
918    %d
919    call setline(1, '    one two')
920    call MouseLeftClick(1, 2)
921    call MouseLeftRelease(1, 2)
922    call MouseLeftClick(1, 2)
923    call MouseLeftRelease(1, 2)
924    call assert_equal('v', mode(), msg)
925    norm! r1
926    call assert_equal(['1111one two'], getline(1, '$'), msg)
927
928    " Double-click on a word with exclusive selection
929    set selection=exclusive
930    let @" = ''
931    call MouseLeftClick(1, 10)
932    call MouseLeftRelease(1, 10)
933    call MouseLeftClick(1, 10)
934    call MouseLeftRelease(1, 10)
935    norm! y
936    call assert_equal('two', @", msg)
937
938    " Double click to select a block of text with exclusive selection
939    %d
940    call setline(1, 'one (two) three')
941    call MouseLeftClick(1, 5)
942    call MouseLeftRelease(1, 5)
943    call MouseLeftClick(1, 5)
944    call MouseLeftRelease(1, 5)
945    norm! y
946    call assert_equal(5, col("'<"), msg)
947    call assert_equal(10, col("'>"), msg)
948
949    call MouseLeftClick(1, 9)
950    call MouseLeftRelease(1, 9)
951    call MouseLeftClick(1, 9)
952    call MouseLeftRelease(1, 9)
953    norm! y
954    call assert_equal(5, col("'<"), msg)
955    call assert_equal(10, col("'>"), msg)
956    set selection&
957
958    " Click somewhere else so that the clicks above is not combined with the
959    " clicks in the next iteration.
960    call MouseRightClick(3, 10)
961    call MouseRightRelease(3, 10)
962  endfor
963
964  let &mouse = save_mouse
965  let &term = save_term
966  let &ttymouse = save_ttymouse
967  set mousetime&
968  call test_override('no_query_mouse', 0)
969  bwipe!
970endfunc
971
972" Test for selecting text in visual blockwise mode using Alt-LeftClick
973func Test_mouse_alt_leftclick()
974  let save_mouse = &mouse
975  let save_term = &term
976  let save_ttymouse = &ttymouse
977  call test_override('no_query_mouse', 1)
978  set mouse=a term=xterm mousetime=200
979  set mousemodel=popup
980  new
981  call setline(1, 'one (two) three')
982
983  for ttymouse_val in g:Ttymouse_values
984    let msg = 'ttymouse=' .. ttymouse_val
985    exe 'set ttymouse=' .. ttymouse_val
986
987    " Left click with the Alt modifier key should extend the selection in
988    " blockwise visual mode.
989    let @" = ''
990    call MouseLeftClick(1, 3)
991    call MouseLeftRelease(1, 3)
992    call MouseAltLeftClick(1, 11)
993    call MouseLeftRelease(1, 11)
994    call assert_equal("\<C-V>", mode(), msg)
995    normal! y
996    call assert_equal('e (two) t', @")
997  endfor
998
999  let &mouse = save_mouse
1000  let &term = save_term
1001  let &ttymouse = save_ttymouse
1002  set mousetime& mousemodel&
1003  call test_override('no_query_mouse', 0)
1004  close!
1005endfunc
1006
1007func Test_xterm_mouse_click_in_fold_columns()
1008  new
1009  let save_mouse = &mouse
1010  let save_term = &term
1011  let save_ttymouse = &ttymouse
1012  let save_foldcolumn = &foldcolumn
1013  set mouse=a term=xterm foldcolumn=3 ttymouse=xterm2
1014
1015  " Create 2 nested folds.
1016  call setline(1, range(1, 7))
1017  2,6fold
1018  norm! zR
1019  4,5fold
1020  call assert_equal([-1, -1, -1, 4, 4, -1, -1],
1021        \           map(range(1, 7), 'foldclosed(v:val)'))
1022
1023  " Click in "+" of inner fold in foldcolumn should open it.
1024  redraw
1025  let row = 4
1026  let col = 2
1027  call MouseLeftClick(row, col)
1028  call MouseLeftRelease(row, col)
1029  call assert_equal([-1, -1, -1, -1, -1, -1, -1],
1030        \           map(range(1, 7), 'foldclosed(v:val)'))
1031
1032  " Click in "-" of outer fold in foldcolumn should close it.
1033  redraw
1034  let row = 2
1035  let col = 1
1036  call MouseLeftClick(row, col)
1037  call MouseLeftRelease(row, col)
1038  call assert_equal([-1, 2, 2, 2, 2, 2, -1],
1039        \           map(range(1, 7), 'foldclosed(v:val)'))
1040  norm! zR
1041
1042  " Click in "|" of inner fold in foldcolumn should close it.
1043  redraw
1044  let row = 5
1045  let col = 2
1046  call MouseLeftClick(row, col)
1047  call MouseLeftRelease(row, col)
1048  call assert_equal([-1, -1, -1, 4, 4, -1, -1],
1049        \           map(range(1, 7), 'foldclosed(v:val)'))
1050
1051  let &foldcolumn = save_foldcolumn
1052  let &ttymouse = save_ttymouse
1053  let &term = save_term
1054  let &mouse = save_mouse
1055  bwipe!
1056endfunc
1057
1058" Left or right click in Ex command line sets position of the cursor.
1059func Test_term_mouse_click_in_cmdline_to_set_pos()
1060  let save_mouse = &mouse
1061  let save_term = &term
1062  let save_ttymouse = &ttymouse
1063  call test_override('no_query_mouse', 1)
1064  set mouse=a term=xterm
1065  let row = &lines
1066
1067  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
1068    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
1069    if ttymouse_val !=# 'xterm2' || row <= 223
1070      let msg = 'ttymouse=' .. ttymouse_val
1071      exe 'set ttymouse=' .. ttymouse_val
1072
1073
1074      call feedkeys(':"3456789'
1075            \       .. MouseLeftClickCode(row, 7)
1076            \       .. MouseLeftReleaseCode(row, 7) .. 'L'
1077            \       .. MouseRightClickCode(row, 4)
1078            \       .. MouseRightReleaseCode(row, 4) .. 'R'
1079            \       .. "\<CR>", 'Lx!')
1080      call assert_equal('"3R456L789', @:, msg)
1081    endif
1082  endfor
1083
1084  let &mouse = save_mouse
1085  let &term = save_term
1086  let &ttymouse = save_ttymouse
1087  set mousetime&
1088  call test_override('no_query_mouse', 0)
1089endfunc
1090
1091" Middle click in command line pastes at position of cursor.
1092func Test_term_mouse_middle_click_in_cmdline_to_paste()
1093  CheckFeature clipboard_working
1094  let save_mouse = &mouse
1095  let save_term = &term
1096  let save_ttymouse = &ttymouse
1097  call test_override('no_query_mouse', 1)
1098  set mouse=a term=xterm
1099  let row = &lines
1100  " Column values does not matter, paste is done at position of cursor.
1101  let col = 1
1102  let @* = 'paste'
1103
1104  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
1105    let msg = 'ttymouse=' .. ttymouse_val
1106    exe 'set ttymouse=' .. ttymouse_val
1107
1108    call feedkeys(":\"->"
1109          \       .. MouseMiddleReleaseCode(row, col)
1110          \       .. MouseMiddleClickCode(row, col)
1111          \       .. "<-"
1112          \       .. MouseMiddleReleaseCode(row, col)
1113          \       .. MouseMiddleClickCode(row, col)
1114          \       .. "\<CR>", 'Lx!')
1115    call assert_equal('"->paste<-paste', @:, msg)
1116  endfor
1117
1118  let &mouse = save_mouse
1119  let &term = save_term
1120  let &ttymouse = save_ttymouse
1121  let @* = ''
1122  call test_override('no_query_mouse', 0)
1123endfunc
1124
1125" Test for making sure S-Middlemouse doesn't do anything
1126func Test_term_mouse_shift_middle_click()
1127  new
1128  let save_mouse = &mouse
1129  let save_term = &term
1130  let save_ttymouse = &ttymouse
1131  call test_override('no_query_mouse', 1)
1132  set mouse=a term=xterm ttymouse=xterm2 mousemodel=
1133
1134  call test_setmouse(1, 1)
1135  exe "normal \<S-MiddleMouse>"
1136  call assert_equal([''], getline(1, '$'))
1137  call assert_equal(1, winnr())
1138
1139  let &mouse = save_mouse
1140  let &term = save_term
1141  let &ttymouse = save_ttymouse
1142  set mousemodel&
1143  call test_override('no_query_mouse', 0)
1144  close!
1145endfunc
1146
1147" Test for using mouse in visual mode
1148func Test_term_mouse_visual_mode()
1149  new
1150  let save_mouse = &mouse
1151  let save_term = &term
1152  let save_ttymouse = &ttymouse
1153  call test_override('no_query_mouse', 1)
1154  set term=xterm ttymouse=xterm2
1155
1156  " If visual mode is not present in 'mouse', then left click should not
1157  " do anything in visal mode.
1158  call setline(1, ['one two three four'])
1159  set mouse=nci
1160  call cursor(1, 5)
1161  let @" = ''
1162  call feedkeys("ve"
1163        \ .. MouseLeftClickCode(1, 15) .. MouseLeftReleaseCode(1, 15)
1164        \ .. 'y', 'Lx!')
1165  call assert_equal(5, col('.'))
1166  call assert_equal('two', @")
1167
1168  " Pressing right click in visual mode should change the visual selection
1169  " if 'mousemodel' doesn't contain popup.
1170  " Right click after the visual selection
1171  set mousemodel=
1172  set mouse=a
1173  call test_setmouse(1, 13)
1174  exe "normal 5|ve\<RightMouse>y"
1175  call assert_equal('two three', @")
1176  call assert_equal(5, col('.'))
1177
1178  " Right click before the visual selection
1179  call test_setmouse(1, 9)
1180  exe "normal 15|ve\<RightMouse>y"
1181  call assert_equal('three four', @")
1182  call assert_equal(9, col('.'))
1183
1184  " Right click inside the selection closer to the start of the selection
1185  call test_setmouse(1, 7)
1186  exe "normal 5|vee\<RightMouse>lly"
1187  call assert_equal('three', @")
1188  call assert_equal(9, col('.'))
1189  call assert_equal(9, col("'<"))
1190  call assert_equal(13, col("'>"))
1191
1192  " Right click inside the selection closer to the end of the selection
1193  call test_setmouse(1, 11)
1194  exe "normal 5|vee\<RightMouse>ly"
1195  call assert_equal('two thre', @")
1196  call assert_equal(5, col('.'))
1197  call assert_equal(5, col("'<"))
1198  call assert_equal(12, col("'>"))
1199
1200  " Multi-line selection. Right click inside thse selection.
1201  call setline(1, repeat(['aaaaaa'], 7))
1202  call test_setmouse(3, 1)
1203  exe "normal ggVG\<RightMouse>y"
1204  call assert_equal(3, line("'<"))
1205  call test_setmouse(5, 1)
1206  exe "normal ggVG\<RightMouse>y"
1207  call assert_equal(5, line("'>"))
1208
1209  " Click right in the middle line of the selection
1210  call test_setmouse(4, 3)
1211  exe "normal ggVG$\<RightMouse>y"
1212  call assert_equal(4, line("'<"))
1213  call test_setmouse(4, 4)
1214  exe "normal ggVG$\<RightMouse>y"
1215  call assert_equal(4, line("'>"))
1216
1217  set mousemodel&
1218  let &mouse = save_mouse
1219  let &term = save_term
1220  let &ttymouse = save_ttymouse
1221  call test_override('no_query_mouse', 0)
1222  close!
1223endfunc
1224
1225" Test for displaying the popup menu using the right mouse click
1226func Test_term_mouse_popup_menu()
1227  CheckFeature menu
1228  new
1229  call setline(1, 'popup menu test')
1230  let save_mouse = &mouse
1231  let save_term = &term
1232  let save_ttymouse = &ttymouse
1233  let save_mousemodel = &mousemodel
1234  call test_override('no_query_mouse', 1)
1235  set mouse=a term=xterm mousemodel=popup
1236
1237  menu PopUp.foo :let g:menustr = 'foo'<CR>
1238  menu PopUp.bar :let g:menustr = 'bar'<CR>
1239  menu PopUp.baz :let g:menustr = 'baz'<CR>
1240
1241  for ttymouse_val in g:Ttymouse_values
1242    let msg = 'ttymouse=' .. ttymouse_val
1243    exe 'set ttymouse=' .. ttymouse_val
1244    let g:menustr = ''
1245    call feedkeys(MouseRightClickCode(1, 4)
1246		\ .. MouseRightReleaseCode(1, 4) .. "\<Down>\<Down>\<CR>", "x")
1247    call assert_equal('bar', g:menustr, msg)
1248  endfor
1249
1250  unmenu PopUp
1251  let &mouse = save_mouse
1252  let &term = save_term
1253  let &ttymouse = save_ttymouse
1254  let &mousemodel = save_mousemodel
1255  call test_override('no_query_mouse', 0)
1256  close!
1257endfunc
1258
1259" Test for 'mousemodel' set to popup_setpos to move the cursor where the popup
1260" menu is displayed.
1261func Test_term_mouse_popup_menu_setpos()
1262  CheckFeature menu
1263  5new
1264  call setline(1, ['the dish ran away with the spoon',
1265        \ 'the cow jumped over the moon' ])
1266  let save_mouse = &mouse
1267  let save_term = &term
1268  let save_ttymouse = &ttymouse
1269  let save_mousemodel = &mousemodel
1270  call test_override('no_query_mouse', 1)
1271  set mouse=a term=xterm mousemodel=popup_setpos
1272
1273  nmenu PopUp.foo :let g:menustr = 'foo'<CR>
1274  nmenu PopUp.bar :let g:menustr = 'bar'<CR>
1275  nmenu PopUp.baz :let g:menustr = 'baz'<CR>
1276  vmenu PopUp.foo y:<C-U>let g:menustr = 'foo'<CR>
1277  vmenu PopUp.bar y:<C-U>let g:menustr = 'bar'<CR>
1278  vmenu PopUp.baz y:<C-U>let g:menustr = 'baz'<CR>
1279
1280  for ttymouse_val in g:Ttymouse_values
1281    let msg = 'ttymouse=' .. ttymouse_val
1282    exe 'set ttymouse=' .. ttymouse_val
1283    let g:menustr = ''
1284    call cursor(1, 1)
1285    call feedkeys(MouseRightClickCode(1, 5)
1286		\ .. MouseRightReleaseCode(1, 5) .. "\<Down>\<Down>\<CR>", "x")
1287    call assert_equal('bar', g:menustr, msg)
1288    call assert_equal([1, 5], [line('.'), col('.')], msg)
1289
1290    " Test for right click in visual mode inside the selection
1291    let @" = ''
1292    call cursor(1, 10)
1293    call feedkeys('vee' .. MouseRightClickCode(1, 12)
1294		\ .. MouseRightReleaseCode(1, 12) .. "\<Down>\<CR>", "x")
1295    call assert_equal([1, 10], [line('.'), col('.')], msg)
1296    call assert_equal('ran away', @", msg)
1297
1298    " Test for right click in visual mode before the selection
1299    let @" = ''
1300    call cursor(1, 10)
1301    call feedkeys('vee' .. MouseRightClickCode(1, 2)
1302		\ .. MouseRightReleaseCode(1, 2) .. "\<Down>\<CR>", "x")
1303    call assert_equal([1, 2], [line('.'), col('.')], msg)
1304    call assert_equal('', @", msg)
1305
1306    " Test for right click in visual mode after the selection
1307    let @" = ''
1308    call cursor(1, 10)
1309    call feedkeys('vee' .. MouseRightClickCode(1, 20)
1310		\ .. MouseRightReleaseCode(1, 20) .. "\<Down>\<CR>", "x")
1311    call assert_equal([1, 20], [line('.'), col('.')], msg)
1312    call assert_equal('', @", msg)
1313
1314    " Test for right click in block-wise visual mode inside the selection
1315    let @" = ''
1316    call cursor(1, 16)
1317    call feedkeys("\<C-V>j3l" .. MouseRightClickCode(2, 17)
1318		\ .. MouseRightReleaseCode(2, 17) .. "\<Down>\<CR>", "x")
1319    call assert_equal([1, 16], [line('.'), col('.')], msg)
1320    call assert_equal("\<C-V>4", getregtype('"'), msg)
1321
1322    " Test for right click in block-wise visual mode outside the selection
1323    let @" = ''
1324    call cursor(1, 16)
1325    call feedkeys("\<C-V>j3l" .. MouseRightClickCode(2, 2)
1326		\ .. MouseRightReleaseCode(2, 2) .. "\<Down>\<CR>", "x")
1327    call assert_equal([2, 2], [line('.'), col('.')], msg)
1328    call assert_equal('v', getregtype('"'), msg)
1329    call assert_equal('', @", msg)
1330
1331    " Try clicking on the status line
1332    let @" = ''
1333    call cursor(1, 10)
1334    call feedkeys('vee' .. MouseRightClickCode(6, 2)
1335		\ .. MouseRightReleaseCode(6, 2) .. "\<Down>\<CR>", "x")
1336    call assert_equal([1, 10], [line('.'), col('.')], msg)
1337    call assert_equal('ran away', @", msg)
1338
1339    " Try clicking outside the window
1340    let @" = ''
1341    call cursor(7, 2)
1342    call feedkeys('vee' .. MouseRightClickCode(7, 2)
1343		\ .. MouseRightReleaseCode(7, 2) .. "\<Down>\<CR>", "x")
1344    call assert_equal(2, winnr(), msg)
1345    call assert_equal('', @", msg)
1346    wincmd w
1347  endfor
1348
1349  unmenu PopUp
1350  let &mouse = save_mouse
1351  let &term = save_term
1352  let &ttymouse = save_ttymouse
1353  let &mousemodel = save_mousemodel
1354  call test_override('no_query_mouse', 0)
1355  close!
1356endfunc
1357
1358" Test for searching for the word under the cursor using Shift-Right or
1359" Shift-Left click.
1360func Test_term_mouse_search()
1361  new
1362  let save_mouse = &mouse
1363  let save_term = &term
1364  let save_ttymouse = &ttymouse
1365  call test_override('no_query_mouse', 1)
1366  set mouse=a term=xterm ttymouse=xterm2
1367  set mousemodel=
1368
1369  " In normal mode, Shift-Left or Shift-Right click should search for the word
1370  " under the cursor.
1371  call setline(1, ['one two three four', 'four three two one'])
1372  call test_setmouse(1, 4)
1373  exe "normal \<S-LeftMouse>"
1374  call assert_equal([2, 12], [line('.'), col('.')])
1375  call test_setmouse(2, 16)
1376  exe "normal \<S-RightMouse>"
1377  call assert_equal([1, 1], [line('.'), col('.')])
1378
1379  " In visual mode, Shift-Left or Shift-Right click should search for the word
1380  " under the cursor and extend the selection.
1381  call test_setmouse(1, 4)
1382  exe "normal 4|ve\<S-LeftMouse>y"
1383  call assert_equal([2, 12], [line("'>"), col("'>")])
1384  call test_setmouse(2, 16)
1385  exe "normal 2G16|ve\<S-RightMouse>y"
1386  call assert_equal([1, 1], [line("'<"), col("'<")])
1387
1388  set mousemodel&
1389  let &mouse = save_mouse
1390  let &term = save_term
1391  let &ttymouse = save_ttymouse
1392  call test_override('no_query_mouse', 0)
1393  close!
1394endfunc
1395
1396" Test for selecting an entry in the quickfix/location list window using the
1397" mouse.
1398func Test_term_mouse_quickfix_window()
1399  let save_mouse = &mouse
1400  let save_term = &term
1401  let save_ttymouse = &ttymouse
1402  call test_override('no_query_mouse', 1)
1403  set mouse=a term=xterm ttymouse=xterm2
1404  set mousemodel=
1405
1406  cgetexpr "Xfile1:1:L1"
1407  copen 5
1408  call test_setmouse(&lines - 7, 1)
1409  exe "normal \<2-LeftMouse>"
1410  call assert_equal('Xfile1', @%)
1411  %bw!
1412
1413  lgetexpr "Xfile2:1:L1"
1414  lopen 5
1415  call test_setmouse(&lines - 7, 1)
1416  exe "normal \<2-LeftMouse>"
1417  call assert_equal('Xfile2', @%)
1418  %bw!
1419
1420  set mousemodel&
1421  let &mouse = save_mouse
1422  let &term = save_term
1423  let &ttymouse = save_ttymouse
1424  call test_override('no_query_mouse', 0)
1425endfunc
1426
1427" Test for the 'h' flag in the 'mouse' option. Using mouse in the help window.
1428func Test_term_mouse_help_window()
1429  let save_mouse = &mouse
1430  let save_term = &term
1431  let save_ttymouse = &ttymouse
1432  call test_override('no_query_mouse', 1)
1433  set mouse=h term=xterm mousetime=200
1434
1435  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
1436    let msg = 'ttymouse=' .. ttymouse_val
1437    exe 'set ttymouse=' .. ttymouse_val
1438    help
1439    let @" = ''
1440    call MouseLeftClick(2, 5)
1441    call MouseLeftRelease(2, 5)
1442    call MouseLeftClick(1, 1)
1443    call MouseLeftDrag(1, 10)
1444    call MouseLeftRelease(1, 10)
1445    norm! y
1446    call assert_equal('*help.txt*', @", msg)
1447    helpclose
1448
1449    " Click somewhere else to make sure the left click above is not combined
1450    " with the next left click and treated as a double click
1451    call MouseRightClick(5, 10)
1452    call MouseRightRelease(5, 10)
1453  endfor
1454
1455  let &mouse = save_mouse
1456  let &term = save_term
1457  let &ttymouse = save_ttymouse
1458  set mousetime&
1459  call test_override('no_query_mouse', 0)
1460  %bw!
1461endfunc
1462
1463" Test for the translation of various mouse terminal codes
1464func Test_mouse_termcodes()
1465  let save_mouse = &mouse
1466  let save_term = &term
1467  let save_ttymouse = &ttymouse
1468  call test_override('no_query_mouse', 1)
1469  set mouse=a term=xterm mousetime=200
1470
1471  new
1472  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
1473    let msg = 'ttymouse=' .. ttymouse_val
1474    exe 'set ttymouse=' .. ttymouse_val
1475
1476    let mouse_codes = [
1477          \ ["\<LeftMouse>", "<LeftMouse>"],
1478          \ ["\<MiddleMouse>", "<MiddleMouse>"],
1479          \ ["\<RightMouse>", "<RightMouse>"],
1480          \ ["\<S-LeftMouse>", "<S-LeftMouse>"],
1481          \ ["\<S-MiddleMouse>", "<S-MiddleMouse>"],
1482          \ ["\<S-RightMouse>", "<S-RightMouse>"],
1483          \ ["\<C-LeftMouse>", "<C-LeftMouse>"],
1484          \ ["\<C-MiddleMouse>", "<C-MiddleMouse>"],
1485          \ ["\<C-RightMouse>", "<C-RightMouse>"],
1486          \ ["\<M-LeftMouse>", "<M-LeftMouse>"],
1487          \ ["\<M-MiddleMouse>", "<M-MiddleMouse>"],
1488          \ ["\<M-RightMouse>", "<M-RightMouse>"],
1489          \ ["\<2-LeftMouse>", "<2-LeftMouse>"],
1490          \ ["\<2-MiddleMouse>", "<2-MiddleMouse>"],
1491          \ ["\<2-RightMouse>", "<2-RightMouse>"],
1492          \ ["\<3-LeftMouse>", "<3-LeftMouse>"],
1493          \ ["\<3-MiddleMouse>", "<3-MiddleMouse>"],
1494          \ ["\<3-RightMouse>", "<3-RightMouse>"],
1495          \ ["\<4-LeftMouse>", "<4-LeftMouse>"],
1496          \ ["\<4-MiddleMouse>", "<4-MiddleMouse>"],
1497          \ ["\<4-RightMouse>", "<4-RightMouse>"],
1498          \ ["\<LeftDrag>", "<LeftDrag>"],
1499          \ ["\<MiddleDrag>", "<MiddleDrag>"],
1500          \ ["\<RightDrag>", "<RightDrag>"],
1501          \ ["\<LeftRelease>", "<LeftRelease>"],
1502          \ ["\<MiddleRelease>", "<MiddleRelease>"],
1503          \ ["\<RightRelease>", "<RightRelease>"],
1504          \ ["\<ScrollWheelUp>", "<ScrollWheelUp>"],
1505          \ ["\<S-ScrollWheelUp>", "<S-ScrollWheelUp>"],
1506          \ ["\<C-ScrollWheelUp>", "<C-ScrollWheelUp>"],
1507          \ ["\<ScrollWheelDown>", "<ScrollWheelDown>"],
1508          \ ["\<S-ScrollWheelDown>", "<S-ScrollWheelDown>"],
1509          \ ["\<C-ScrollWheelDown>", "<C-ScrollWheelDown>"],
1510          \ ["\<ScrollWheelLeft>", "<ScrollWheelLeft>"],
1511          \ ["\<S-ScrollWheelLeft>", "<S-ScrollWheelLeft>"],
1512          \ ["\<C-ScrollWheelLeft>", "<C-ScrollWheelLeft>"],
1513          \ ["\<ScrollWheelRight>", "<ScrollWheelRight>"],
1514          \ ["\<S-ScrollWheelRight>", "<S-ScrollWheelRight>"],
1515          \ ["\<C-ScrollWheelRight>", "<C-ScrollWheelRight>"]
1516          \ ]
1517
1518    for [code, outstr] in mouse_codes
1519      exe "normal ggC\<C-K>" . code
1520      call assert_equal(outstr, getline(1), msg)
1521    endfor
1522  endfor
1523
1524  let &mouse = save_mouse
1525  let &term = save_term
1526  let &ttymouse = save_ttymouse
1527  set mousetime&
1528  call test_override('no_query_mouse', 0)
1529  %bw!
1530endfunc
1531
1532" This only checks if the sequence is recognized.
1533func Test_term_rgb_response()
1534  set t_RF=x
1535  set t_RB=y
1536
1537  " response to t_RF, 4 digits
1538  let red = 0x12
1539  let green = 0x34
1540  let blue = 0x56
1541  let seq = printf("\<Esc>]10;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1542  call feedkeys(seq, 'Lx!')
1543  call assert_equal(seq, v:termrfgresp)
1544
1545  " response to t_RF, 2 digits
1546  let red = 0x78
1547  let green = 0x9a
1548  let blue = 0xbc
1549  let seq = printf("\<Esc>]10;rgb:%02x/%02x/%02x\x07", red, green, blue)
1550  call feedkeys(seq, 'Lx!')
1551  call assert_equal(seq, v:termrfgresp)
1552
1553  " response to t_RB, 4 digits, dark
1554  set background=light
1555  eval 'background'->test_option_not_set()
1556  let red = 0x29
1557  let green = 0x4a
1558  let blue = 0x6b
1559  let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1560  call feedkeys(seq, 'Lx!')
1561  call assert_equal(seq, v:termrbgresp)
1562  call assert_equal('dark', &background)
1563
1564  " response to t_RB, 4 digits, light
1565  set background=dark
1566  call test_option_not_set('background')
1567  let red = 0x81
1568  let green = 0x63
1569  let blue = 0x65
1570  let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
1571  call feedkeys(seq, 'Lx!')
1572  call assert_equal(seq, v:termrbgresp)
1573  call assert_equal('light', &background)
1574
1575  " response to t_RB, 2 digits, dark
1576  set background=light
1577  call test_option_not_set('background')
1578  let red = 0x47
1579  let green = 0x59
1580  let blue = 0x5b
1581  let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
1582  call feedkeys(seq, 'Lx!')
1583  call assert_equal(seq, v:termrbgresp)
1584  call assert_equal('dark', &background)
1585
1586  " response to t_RB, 2 digits, light
1587  set background=dark
1588  call test_option_not_set('background')
1589  let red = 0x83
1590  let green = 0xa4
1591  let blue = 0xc2
1592  let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
1593  call feedkeys(seq, 'Lx!')
1594  call assert_equal(seq, v:termrbgresp)
1595  call assert_equal('light', &background)
1596
1597  set t_RF= t_RB=
1598endfunc
1599
1600" This only checks if the sequence is recognized.
1601" This must be after other tests, because it has side effects to xterm
1602" properties.
1603func Test_xx01_term_style_response()
1604  " Termresponse is only parsed when t_RV is not empty.
1605  set t_RV=x
1606  call test_override('term_props', 1)
1607
1608  " send the termresponse to trigger requesting the XT codes
1609  let seq = "\<Esc>[>41;337;0c"
1610  call feedkeys(seq, 'Lx!')
1611  call assert_equal(seq, v:termresponse)
1612
1613  let seq = "\<Esc>P1$r2 q\<Esc>\\"
1614  call feedkeys(seq, 'Lx!')
1615  call assert_equal(seq, v:termstyleresp)
1616
1617  call assert_equal(#{
1618        \ cursor_style: 'u',
1619        \ cursor_blink_mode: 'u',
1620        \ underline_rgb: 'u',
1621        \ mouse: 's'
1622        \ }, terminalprops())
1623
1624  set t_RV=
1625  call test_override('term_props', 0)
1626endfunc
1627
1628" This checks the iTerm2 version response.
1629" This must be after other tests, because it has side effects to xterm
1630" properties.
1631func Test_xx02_iTerm2_response()
1632  " Termresponse is only parsed when t_RV is not empty.
1633  set t_RV=x
1634  call test_override('term_props', 1)
1635
1636  " Old versions of iTerm2 used a different style term response.
1637  set ttymouse=xterm
1638  call test_option_not_set('ttymouse')
1639  let seq = "\<Esc>[>0;95;c"
1640  call feedkeys(seq, 'Lx!')
1641  call assert_equal(seq, v:termresponse)
1642  call assert_equal('xterm', &ttymouse)
1643
1644  set ttymouse=xterm
1645  call test_option_not_set('ttymouse')
1646  let seq = "\<Esc>[>0;95;0c"
1647  call feedkeys(seq, 'Lx!')
1648  call assert_equal(seq, v:termresponse)
1649  call assert_equal('sgr', &ttymouse)
1650
1651  call assert_equal(#{
1652        \ cursor_style: 'n',
1653        \ cursor_blink_mode: 'u',
1654        \ underline_rgb: 'u',
1655        \ mouse: 's'
1656        \ }, terminalprops())
1657
1658  set t_RV=
1659  call test_override('term_props', 0)
1660endfunc
1661
1662" This checks the libvterm version response.
1663" This must be after other tests, because it has side effects to xterm
1664" properties.
1665func Test_xx03_libvterm_response()
1666  " Termresponse is only parsed when t_RV is not empty.
1667  set t_RV=x
1668  call test_override('term_props', 1)
1669
1670  set ttymouse=xterm
1671  call test_option_not_set('ttymouse')
1672  let seq = "\<Esc>[>0;100;0c"
1673  call feedkeys(seq, 'Lx!')
1674  call assert_equal(seq, v:termresponse)
1675  call assert_equal('sgr', &ttymouse)
1676
1677  call assert_equal(#{
1678        \ cursor_style: 'n',
1679        \ cursor_blink_mode: 'u',
1680        \ underline_rgb: 'u',
1681        \ mouse: 's'
1682        \ }, terminalprops())
1683
1684  set t_RV=
1685  call test_override('term_props', 0)
1686endfunc
1687
1688" This checks the Mac Terminal.app version response.
1689" This must be after other tests, because it has side effects to xterm
1690" properties.
1691func Test_xx04_Mac_Terminal_response()
1692  " Termresponse is only parsed when t_RV is not empty.
1693  set t_RV=x
1694  call test_override('term_props', 1)
1695
1696  set ttymouse=xterm
1697  " t_8u is not reset
1698  let &t_8u = "\<Esc>[58;2;%lu;%lu;%lum"
1699  call test_option_not_set('ttymouse')
1700  let seq = "\<Esc>[>1;95;0c"
1701  call feedkeys(seq, 'Lx!')
1702  call assert_equal(seq, v:termresponse)
1703  call assert_equal('sgr', &ttymouse)
1704
1705  call assert_equal(#{
1706        \ cursor_style: 'n',
1707        \ cursor_blink_mode: 'u',
1708        \ underline_rgb: 'y',
1709        \ mouse: 's'
1710        \ }, terminalprops())
1711  call assert_equal("\<Esc>[58;2;%lu;%lu;%lum", &t_8u)
1712
1713  " Reset is_not_xterm and is_mac_terminal.
1714  set t_RV=
1715  set term=xterm
1716  set t_RV=x
1717  call test_override('term_props', 0)
1718endfunc
1719
1720" This checks the mintty version response.
1721" This must be after other tests, because it has side effects to xterm
1722" properties.
1723func Test_xx05_mintty_response()
1724  " Termresponse is only parsed when t_RV is not empty.
1725  set t_RV=x
1726  call test_override('term_props', 1)
1727
1728  set ttymouse=xterm
1729  call test_option_not_set('ttymouse')
1730  let seq = "\<Esc>[>77;20905;0c"
1731  call feedkeys(seq, 'Lx!')
1732  call assert_equal(seq, v:termresponse)
1733  call assert_equal('sgr', &ttymouse)
1734
1735  call assert_equal(#{
1736        \ cursor_style: 'n',
1737        \ cursor_blink_mode: 'u',
1738        \ underline_rgb: 'y',
1739        \ mouse: 's'
1740        \ }, terminalprops())
1741
1742  set t_RV=
1743  call test_override('term_props', 0)
1744endfunc
1745
1746" This checks the screen version response.
1747" This must be after other tests, because it has side effects to xterm
1748" properties.
1749func Test_xx06_screen_response()
1750  " Termresponse is only parsed when t_RV is not empty.
1751  set t_RV=x
1752  call test_override('term_props', 1)
1753
1754  " Old versions of screen don't support SGR mouse mode.
1755  set ttymouse=xterm
1756  call test_option_not_set('ttymouse')
1757  let seq = "\<Esc>[>83;40500;0c"
1758  call feedkeys(seq, 'Lx!')
1759  call assert_equal(seq, v:termresponse)
1760  call assert_equal('xterm', &ttymouse)
1761
1762  " screen supports SGR mouse mode starting in version 4.7.
1763  set ttymouse=xterm
1764  call test_option_not_set('ttymouse')
1765  let seq = "\<Esc>[>83;40700;0c"
1766  call feedkeys(seq, 'Lx!')
1767  call assert_equal(seq, v:termresponse)
1768  call assert_equal('sgr', &ttymouse)
1769
1770  call assert_equal(#{
1771        \ cursor_style: 'n',
1772        \ cursor_blink_mode: 'n',
1773        \ underline_rgb: 'y',
1774        \ mouse: 's'
1775        \ }, terminalprops())
1776
1777  set t_RV=
1778  call test_override('term_props', 0)
1779endfunc
1780
1781" This checks the xterm version response.
1782" This must be after other tests, because it has side effects to xterm
1783" properties.
1784func Test_xx07_xterm_response()
1785  " Termresponse is only parsed when t_RV is not empty.
1786  set t_RV=x
1787  call test_override('term_props', 1)
1788
1789  " Do Terminal.app first to check that is_mac_terminal is reset.
1790  set ttymouse=xterm
1791  call test_option_not_set('ttymouse')
1792  let seq = "\<Esc>[>1;95;0c"
1793  call feedkeys(seq, 'Lx!')
1794  call assert_equal(seq, v:termresponse)
1795  call assert_equal('sgr', &ttymouse)
1796
1797  " xterm < 95: "xterm" (actually unmodified)
1798  set t_RV=
1799  set term=xterm
1800  set t_RV=x
1801  set ttymouse=xterm
1802  call test_option_not_set('ttymouse')
1803  let seq = "\<Esc>[>0;94;0c"
1804  call feedkeys(seq, 'Lx!')
1805  call assert_equal(seq, v:termresponse)
1806  call assert_equal('xterm', &ttymouse)
1807
1808  call assert_equal(#{
1809        \ cursor_style: 'n',
1810        \ cursor_blink_mode: 'u',
1811        \ underline_rgb: 'y',
1812        \ mouse: 'u'
1813        \ }, terminalprops())
1814
1815  " xterm >= 95 < 277 "xterm2"
1816  set ttymouse=xterm
1817  call test_option_not_set('ttymouse')
1818  let seq = "\<Esc>[>0;267;0c"
1819  call feedkeys(seq, 'Lx!')
1820  call assert_equal(seq, v:termresponse)
1821  call assert_equal('xterm2', &ttymouse)
1822
1823  call assert_equal(#{
1824        \ cursor_style: 'n',
1825        \ cursor_blink_mode: 'u',
1826        \ underline_rgb: 'u',
1827        \ mouse: '2'
1828        \ }, terminalprops())
1829
1830  " xterm >= 277: "sgr"
1831  set ttymouse=xterm
1832  call test_option_not_set('ttymouse')
1833  let seq = "\<Esc>[>0;277;0c"
1834  call feedkeys(seq, 'Lx!')
1835  call assert_equal(seq, v:termresponse)
1836  call assert_equal('sgr', &ttymouse)
1837
1838  call assert_equal(#{
1839        \ cursor_style: 'n',
1840        \ cursor_blink_mode: 'u',
1841        \ underline_rgb: 'u',
1842        \ mouse: 's'
1843        \ }, terminalprops())
1844
1845  " xterm >= 279: "sgr" and cursor_style not reset; also check t_8u reset
1846  set ttymouse=xterm
1847  call test_option_not_set('ttymouse')
1848  let &t_8u = "\<Esc>[58;2;%lu;%lu;%lum"
1849  let seq = "\<Esc>[>0;279;0c"
1850  call feedkeys(seq, 'Lx!')
1851  call assert_equal(seq, v:termresponse)
1852  call assert_equal('sgr', &ttymouse)
1853
1854  call assert_equal(#{
1855        \ cursor_style: 'u',
1856        \ cursor_blink_mode: 'u',
1857        \ underline_rgb: 'u',
1858        \ mouse: 's'
1859        \ }, terminalprops())
1860  call assert_equal('', &t_8u)
1861
1862  set t_RV=
1863  call test_override('term_props', 0)
1864endfunc
1865
1866func Test_get_termcode()
1867  try
1868    let k1 = &t_k1
1869  catch /E113/
1870    throw 'Skipped: Unable to query termcodes'
1871  endtry
1872  set t_k1=
1873  set t_k1&
1874  call assert_equal(k1, &t_k1)
1875
1876  " use external termcap first
1877  set nottybuiltin
1878  set t_k1=
1879  set t_k1&
1880  " when using external termcap may get something else, but it must not be
1881  " empty, since we would fallback to the builtin one.
1882  call assert_notequal('', &t_k1)
1883
1884  if &term =~ 'xterm'
1885    " use internal termcap first
1886    let term_save = &term
1887    let &term = 'builtin_' .. &term
1888    set t_k1=
1889    set t_k1&
1890    call assert_equal(k1, &t_k1)
1891    let &term = term_save
1892  endif
1893
1894  set ttybuiltin
1895endfunc
1896
1897func Test_list_builtin_terminals()
1898  CheckRunVimInTerminal
1899  let buf = RunVimInTerminal('', #{rows: 14})
1900  call term_sendkeys(buf, ":set cmdheight=3\<CR>")
1901  call term_wait(buf, 100)
1902  call term_sendkeys(buf, ":set term=xxx\<CR>")
1903  call term_wait(buf, 100)
1904  call assert_match('builtin_dumb', term_getline(buf, 11))
1905  call assert_match('Not found in termcap', term_getline(buf, 12))
1906  call StopVimInTerminal(buf)
1907endfunc
1908
1909func GetEscCodeCSI27(key, modifier)
1910  let key = printf("%d", char2nr(a:key))
1911  let mod = printf("%d", a:modifier)
1912  return "\<Esc>[27;" .. mod .. ';' .. key .. '~'
1913endfunc
1914
1915func GetEscCodeCSIu(key, modifier)
1916  let key = printf("%d", char2nr(a:key))
1917  let mod = printf("%d", a:modifier)
1918  return "\<Esc>[" .. key .. ';' .. mod .. 'u'
1919endfunc
1920
1921" This checks the CSI sequences when in modifyOtherKeys mode.
1922" The mode doesn't need to be enabled, the codes are always detected.
1923func RunTest_modifyOtherKeys(func)
1924  new
1925  set timeoutlen=10
1926
1927  " Shift-X is sent as 'X' with the shift modifier
1928  call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!')
1929  call assert_equal('X', getline(1))
1930
1931  " Ctrl-i is Tab
1932  call setline(1, '')
1933  call feedkeys('a' .. a:func('i', 5) .. "\<Esc>", 'Lx!')
1934  call assert_equal("\t", getline(1))
1935
1936  " Ctrl-I is also Tab
1937  call setline(1, '')
1938  call feedkeys('a' .. a:func('I', 5) .. "\<Esc>", 'Lx!')
1939  call assert_equal("\t", getline(1))
1940
1941  " Alt-x is ø
1942  call setline(1, '')
1943  call feedkeys('a' .. a:func('x', 3) .. "\<Esc>", 'Lx!')
1944  call assert_equal("ø", getline(1))
1945
1946  " Meta-x is also ø
1947  call setline(1, '')
1948  call feedkeys('a' .. a:func('x', 9) .. "\<Esc>", 'Lx!')
1949  call assert_equal("ø", getline(1))
1950
1951  " Alt-X is Ø
1952  call setline(1, '')
1953  call feedkeys('a' .. a:func('X', 3) .. "\<Esc>", 'Lx!')
1954  call assert_equal("Ø", getline(1))
1955
1956  " Meta-X is ø
1957  call setline(1, '')
1958  call feedkeys('a' .. a:func('X', 9) .. "\<Esc>", 'Lx!')
1959  call assert_equal("Ø", getline(1))
1960
1961  " Ctrl-6 is Ctrl-^
1962  split aaa
1963  edit bbb
1964  call feedkeys(a:func('6', 5), 'Lx!')
1965  call assert_equal("aaa", bufname())
1966  bwipe aaa
1967  bwipe bbb
1968
1969  bwipe!
1970  set timeoutlen&
1971endfunc
1972
1973func Test_modifyOtherKeys_basic()
1974  call RunTest_modifyOtherKeys(function('GetEscCodeCSI27'))
1975  call RunTest_modifyOtherKeys(function('GetEscCodeCSIu'))
1976endfunc
1977
1978func Test_modifyOtherKeys_no_mapping()
1979  set timeoutlen=10
1980
1981  let @a = 'aaa'
1982  call feedkeys(":let x = '" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a'\<CR>", 'Lx!')
1983  call assert_equal("let x = 'aaa'", @:)
1984
1985  new
1986  call feedkeys("a" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a\<Esc>", 'Lx!')
1987  call assert_equal("aaa", getline(1))
1988  bwipe!
1989
1990  new
1991  call feedkeys("axx\<CR>yy" .. GetEscCodeCSI27('G', 5) .. GetEscCodeCSI27('K', 5) .. "a\<Esc>", 'Lx!')
1992  call assert_equal("axx", getline(1))
1993  call assert_equal("yy", getline(2))
1994  bwipe!
1995
1996  set timeoutlen&
1997endfunc
1998
1999func RunTest_mapping_shift(key, func)
2000  call setline(1, '')
2001  if a:key == '|'
2002    exe 'inoremap \| xyz'
2003  else
2004    exe 'inoremap ' .. a:key .. ' xyz'
2005  endif
2006  call feedkeys('a' .. a:func(a:key, 2) .. "\<Esc>", 'Lx!')
2007  call assert_equal("xyz", getline(1))
2008  if a:key == '|'
2009    exe 'iunmap \|'
2010  else
2011    exe 'iunmap ' .. a:key
2012  endif
2013endfunc
2014
2015func Test_modifyOtherKeys_mapped()
2016  set timeoutlen=10
2017  imap ' <C-W>
2018  imap <C-W><C-A> c-a
2019  call setline(1, '')
2020
2021  " single quote is turned into single byte CTRL-W
2022  " CTRL-A is added with a separate modifier, and needs to be simplified before
2023  " the mapping can match.
2024  call feedkeys("a'" .. GetEscCodeCSI27('A', 5) .. "\<Esc>", 'Lx!')
2025  call assert_equal('c-a', getline(1))
2026
2027  iunmap '
2028  iunmap <C-W><C-A>
2029  set timeoutlen&
2030endfunc
2031
2032func RunTest_mapping_works_with_shift(func)
2033  new
2034  set timeoutlen=10
2035
2036  call RunTest_mapping_shift('@', a:func)
2037  call RunTest_mapping_shift('A', a:func)
2038  call RunTest_mapping_shift('Z', a:func)
2039  call RunTest_mapping_shift('^', a:func)
2040  call RunTest_mapping_shift('_', a:func)
2041  call RunTest_mapping_shift('{', a:func)
2042  call RunTest_mapping_shift('|', a:func)
2043  call RunTest_mapping_shift('}', a:func)
2044  call RunTest_mapping_shift('~', a:func)
2045
2046  bwipe!
2047  set timeoutlen&
2048endfunc
2049
2050func Test_mapping_works_with_shift_plain()
2051  call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27'))
2052  call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu'))
2053endfunc
2054
2055func RunTest_mapping_mods(map, key, func, code)
2056  call setline(1, '')
2057  exe 'inoremap ' .. a:map .. ' xyz'
2058  call feedkeys('a' .. a:func(a:key, a:code) .. "\<Esc>", 'Lx!')
2059  call assert_equal("xyz", getline(1))
2060  exe 'iunmap ' .. a:map
2061endfunc
2062
2063func RunTest_mapping_works_with_mods(func, mods, code)
2064  new
2065  set timeoutlen=10
2066
2067  if a:mods !~ 'S'
2068    " Shift by itself has no effect
2069    call RunTest_mapping_mods('<' .. a:mods .. '-@>', '@', a:func, a:code)
2070  endif
2071  call RunTest_mapping_mods('<' .. a:mods .. '-A>', 'A', a:func, a:code)
2072  call RunTest_mapping_mods('<' .. a:mods .. '-Z>', 'Z', a:func, a:code)
2073  if a:mods !~ 'S'
2074    " with Shift code is always upper case
2075    call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'a', a:func, a:code)
2076    call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'z', a:func, a:code)
2077  endif
2078  if a:mods != 'A'
2079    " with Alt code is not in upper case
2080    call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'A', a:func, a:code)
2081    call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'Z', a:func, a:code)
2082  endif
2083  call RunTest_mapping_mods('<' .. a:mods .. '-á>', 'á', a:func, a:code)
2084  if a:mods !~ 'S'
2085    " Shift by itself has no effect
2086    call RunTest_mapping_mods('<' .. a:mods .. '-^>', '^', a:func, a:code)
2087    call RunTest_mapping_mods('<' .. a:mods .. '-_>', '_', a:func, a:code)
2088    call RunTest_mapping_mods('<' .. a:mods .. '-{>', '{', a:func, a:code)
2089    call RunTest_mapping_mods('<' .. a:mods .. '-\|>', '|', a:func, a:code)
2090    call RunTest_mapping_mods('<' .. a:mods .. '-}>', '}', a:func, a:code)
2091    call RunTest_mapping_mods('<' .. a:mods .. '-~>', '~', a:func, a:code)
2092  endif
2093
2094  bwipe!
2095  set timeoutlen&
2096endfunc
2097
2098func Test_mapping_works_with_shift()
2099  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S', 2)
2100  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S', 2)
2101endfunc
2102
2103func Test_mapping_works_with_ctrl()
2104  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5)
2105  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5)
2106endfunc
2107
2108func Test_mapping_works_with_shift_ctrl()
2109  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6)
2110  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6)
2111endfunc
2112
2113" Below we also test the "u" code with Alt, This works, but libvterm would not
2114" send the Alt key like this but by prefixing an Esc.
2115
2116func Test_mapping_works_with_alt()
2117  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'A', 3)
2118  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'A', 3)
2119endfunc
2120
2121func Test_mapping_works_with_shift_alt()
2122  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S-A', 4)
2123  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S-A', 4)
2124endfunc
2125
2126func Test_mapping_works_with_ctrl_alt()
2127  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-A', 7)
2128  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-A', 7)
2129endfunc
2130
2131func Test_mapping_works_with_shift_ctrl_alt()
2132  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8)
2133  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
2134endfunc
2135
2136func Test_insert_literal()
2137  set timeoutlen=10
2138  new
2139  " CTRL-V CTRL-X inserts a ^X
2140  call feedkeys('a' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
2141  call assert_equal("\<C-X>", getline(1))
2142
2143  call setline(1, '')
2144  call feedkeys('a' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
2145  call assert_equal("\<C-X>", getline(1))
2146
2147  " CTRL-SHIFT-V CTRL-X inserts escape sequence
2148  call setline(1, '')
2149  call feedkeys('a' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
2150  call assert_equal("\<Esc>[88;5u", getline(1))
2151
2152  call setline(1, '')
2153  call feedkeys('a' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
2154  call assert_equal("\<Esc>[27;5;88~", getline(1))
2155
2156  bwipe!
2157  set timeoutlen&
2158endfunc
2159
2160func Test_cmdline_literal()
2161  set timeoutlen=10
2162
2163  " CTRL-V CTRL-Y inserts a ^Y
2164  call feedkeys(':' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2165  call assert_equal("\"\<C-Y>", @:)
2166
2167  call feedkeys(':' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2168  call assert_equal("\"\<C-Y>", @:)
2169
2170  " CTRL-SHIFT-V CTRL-Y inserts escape sequence
2171  call feedkeys(':' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2172  call assert_equal("\"\<Esc>[89;5u", @:)
2173
2174  call setline(1, '')
2175  call feedkeys(':' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
2176  call assert_equal("\"\<Esc>[27;5;89~", @:)
2177
2178  set timeoutlen&
2179endfunc
2180
2181" Test for translation of special key codes (<xF1>, <xF2>, etc.)
2182func Test_Keycode_Tranlsation()
2183  let keycodes = [
2184        \ ["<xUp>", "<Up>"],
2185        \ ["<xDown>", "<Down>"],
2186        \ ["<xLeft>", "<Left>"],
2187        \ ["<xRight>", "<Right>"],
2188        \ ["<xHome>", "<Home>"],
2189        \ ["<xEnd>", "<End>"],
2190        \ ["<zHome>", "<Home>"],
2191        \ ["<zEnd>", "<End>"],
2192        \ ["<xF1>", "<F1>"],
2193        \ ["<xF2>", "<F2>"],
2194        \ ["<xF3>", "<F3>"],
2195        \ ["<xF4>", "<F4>"],
2196        \ ["<S-xF1>", "<S-F1>"],
2197        \ ["<S-xF2>", "<S-F2>"],
2198        \ ["<S-xF3>", "<S-F3>"],
2199        \ ["<S-xF4>", "<S-F4>"]]
2200  for [k1, k2] in keycodes
2201    exe "nnoremap " .. k1 .. " 2wx"
2202    call assert_true(maparg(k1, 'n', 0, 1).lhs == k2)
2203    exe "nunmap " .. k1
2204  endfor
2205endfunc
2206
2207" vim: shiftwidth=2 sts=2 expandtab
2208