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