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
10
11func Test_term_mouse_left_click()
12  new
13  let save_mouse = &mouse
14  let save_term = &term
15  let save_ttymouse = &ttymouse
16  call test_override('no_query_mouse', 1)
17  set mouse=a term=xterm
18  call setline(1, ['line 1', 'line 2', 'line 3 is a bit longer'])
19
20  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
21    let msg = 'ttymouse=' .. ttymouse_val
22    exe 'set ttymouse=' .. ttymouse_val
23    go
24    call assert_equal([0, 1, 1, 0], getpos('.'), msg)
25    let row = 2
26    let col = 6
27    call MouseLeftClick(row, col)
28    call MouseLeftRelease(row, col)
29    call assert_equal([0, 2, 6, 0], getpos('.'), msg)
30  endfor
31
32  let &mouse = save_mouse
33  let &term = save_term
34  let &ttymouse = save_ttymouse
35  call test_override('no_query_mouse', 0)
36  bwipe!
37endfunc
38
39func Test_xterm_mouse_right_click_extends_visual()
40  if has('mac')
41    throw "Skipped: test right click in visual mode does not work on macOs (why?)"
42  endif
43  let save_mouse = &mouse
44  let save_term = &term
45  let save_ttymouse = &ttymouse
46  call test_override('no_query_mouse', 1)
47  set mouse=a term=xterm
48
49  for visual_mode in ["v", "V", "\<C-V>"]
50    for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
51      let msg = 'visual=' .. visual_mode .. ' ttymouse=' .. ttymouse_val
52      exe 'set ttymouse=' .. ttymouse_val
53
54      call setline(1, repeat([repeat('-', 7)], 7))
55      call MouseLeftClick(4, 4)
56      call MouseLeftRelease(4, 4)
57      exe  "norm! " .. visual_mode
58
59      " Right click extends top left of visual area.
60      call MouseRightClick(2, 2)
61      call MouseRightRelease(2, 2)
62
63      " Right click extends bottom right of visual area.
64      call MouseRightClick(6, 6)
65      call MouseRightRelease(6, 6)
66      norm! r1gv
67
68      " Right click shrinks top left of visual area.
69      call MouseRightClick(3, 3)
70      call MouseRightRelease(3, 3)
71
72      " Right click shrinks bottom right of visual area.
73      call MouseRightClick(5, 5)
74      call MouseRightRelease(5, 5)
75      norm! r2
76
77      if visual_mode ==# 'v'
78        call assert_equal(['-------',
79              \            '-111111',
80              \            '1122222',
81              \            '2222222',
82              \            '2222211',
83              \            '111111-',
84              \            '-------'], getline(1, '$'), msg)
85      elseif visual_mode ==# 'V'
86        call assert_equal(['-------',
87              \            '1111111',
88              \            '2222222',
89              \            '2222222',
90              \            '2222222',
91              \            '1111111',
92              \            '-------'], getline(1, '$'), msg)
93      else
94        call assert_equal(['-------',
95              \            '-11111-',
96              \            '-12221-',
97              \            '-12221-',
98              \            '-12221-',
99              \            '-11111-',
100              \            '-------'], getline(1, '$'), msg)
101      endif
102    endfor
103  endfor
104
105  let &mouse = save_mouse
106  let &term = save_term
107  let &ttymouse = save_ttymouse
108  call test_override('no_query_mouse', 0)
109  bwipe!
110endfunc
111
112" Test that <C-LeftMouse> jumps to help tag and <C-RightMouse> jumps back.
113func Test_xterm_mouse_ctrl_click()
114  let save_mouse = &mouse
115  let save_term = &term
116  let save_ttymouse = &ttymouse
117  set mouse=a term=xterm
118
119  for ttymouse_val in g:Ttymouse_values
120    let msg = 'ttymouse=' .. ttymouse_val
121    exe 'set ttymouse=' .. ttymouse_val
122    help
123    /usr_02.txt
124    norm! zt
125    let row = 1
126    let col = 1
127    call MouseCtrlLeftClick(row, col)
128    call MouseLeftRelease(row, col)
129    call assert_match('usr_02.txt$', bufname('%'), msg)
130    call assert_equal('*usr_02.txt*', expand('<cWORD>'), msg)
131
132    call MouseCtrlRightClick(row, col)
133    call MouseRightRelease(row, col)
134    call assert_match('help.txt$', bufname('%'), msg)
135    call assert_equal('|usr_02.txt|', expand('<cWORD>'), msg)
136
137    helpclose
138  endfor
139
140  let &mouse = save_mouse
141  let &term = save_term
142  let &ttymouse = save_ttymouse
143endfunc
144
145func Test_term_mouse_middle_click()
146  CheckFeature clipboard_working
147
148  new
149  let save_mouse = &mouse
150  let save_term = &term
151  let save_ttymouse = &ttymouse
152  call test_override('no_query_mouse', 1)
153  let save_quotestar = @*
154  let @* = 'abc'
155  set mouse=a term=xterm
156
157  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
158    let msg = 'ttymouse=' .. ttymouse_val
159    exe 'set ttymouse=' .. ttymouse_val
160    call setline(1, ['123456789', '123456789'])
161
162    " Middle-click in the middle of the line pastes text where clicked.
163    let row = 1
164    let col = 6
165    call MouseMiddleClick(row, col)
166    call MouseMiddleRelease(row, col)
167    call assert_equal(['12345abc6789', '123456789'], getline(1, '$'), msg)
168
169    " Middle-click beyond end of the line pastes text at the end of the line.
170    let col = 20
171    call MouseMiddleClick(row, col)
172    call MouseMiddleRelease(row, col)
173    call assert_equal(['12345abc6789abc', '123456789'], getline(1, '$'), msg)
174
175    " Middle-click beyond the last line pastes in the last line.
176    let row = 5
177    let col = 3
178    call MouseMiddleClick(row, col)
179    call MouseMiddleRelease(row, col)
180    call assert_equal(['12345abc6789abc', '12abc3456789'], getline(1, '$'), msg)
181  endfor
182
183  let &mouse = save_mouse
184  let &term = save_term
185  let &ttymouse = save_ttymouse
186  call test_override('no_query_mouse', 0)
187  let @* = save_quotestar
188  bwipe!
189endfunc
190
191" TODO: for unclear reasons this test fails if it comes after
192" Test_xterm_mouse_ctrl_click()
193func Test_1xterm_mouse_wheel()
194  new
195  let save_mouse = &mouse
196  let save_term = &term
197  let save_ttymouse = &ttymouse
198  set mouse=a term=xterm
199  call setline(1, range(1, 100))
200
201  for ttymouse_val in g:Ttymouse_values
202    let msg = 'ttymouse=' .. ttymouse_val
203    exe 'set ttymouse=' .. ttymouse_val
204    go
205    call assert_equal(1, line('w0'), msg)
206    call assert_equal([0, 1, 1, 0], getpos('.'), msg)
207
208    call MouseWheelDown(1, 1)
209    call assert_equal(4, line('w0'), msg)
210    call assert_equal([0, 4, 1, 0], getpos('.'), msg)
211
212    call MouseWheelDown(1, 1)
213    call assert_equal(7, line('w0'), msg)
214    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
215
216    call MouseWheelUp(1, 1)
217    call assert_equal(4, line('w0'), msg)
218    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
219
220    call MouseWheelUp(1, 1)
221    call assert_equal(1, line('w0'), msg)
222    call assert_equal([0, 7, 1, 0], getpos('.'), msg)
223  endfor
224
225  let &mouse = save_mouse
226  let &term = save_term
227  let &ttymouse = save_ttymouse
228  bwipe!
229endfunc
230
231" Test that dragging beyond the window (at the bottom and at the top)
232" scrolls window content by the number of lines beyond the window.
233func Test_term_mouse_drag_beyond_window()
234  let save_mouse = &mouse
235  let save_term = &term
236  let save_ttymouse = &ttymouse
237  call test_override('no_query_mouse', 1)
238  set mouse=a term=xterm
239  let col = 1
240  call setline(1, range(1, 100))
241
242  " Split into 3 windows, and go into the middle window
243  " so we test dragging mouse below and above the window.
244  2split
245  wincmd j
246  2split
247
248  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
249    let msg = 'ttymouse=' .. ttymouse_val
250    exe 'set ttymouse=' .. ttymouse_val
251
252    " Line #10 at the top.
253    norm! 10zt
254    redraw
255    call assert_equal(10, winsaveview().topline, msg)
256    call assert_equal(2, winheight(0), msg)
257
258    let row = 4
259    call MouseLeftClick(row, col)
260    call assert_equal(10, winsaveview().topline, msg)
261
262    " Drag downwards. We're still in the window so topline should
263    " not change yet.
264    let row += 1
265    call MouseLeftDrag(row, col)
266    call assert_equal(10, winsaveview().topline, msg)
267
268    " We now leave the window at the bottom, so the window content should
269    " scroll by 1 line, then 2 lines (etc) as we drag further away.
270    let row += 1
271    call MouseLeftDrag(row, col)
272    call assert_equal(11, winsaveview().topline, msg)
273
274    let row += 1
275    call MouseLeftDrag(row, col)
276    call assert_equal(13, winsaveview().topline, msg)
277
278    " Now drag upwards.
279    let row -= 1
280    call MouseLeftDrag(row, col)
281    call assert_equal(14, winsaveview().topline, msg)
282
283    " We're now back in the window so the topline should not change.
284    let row -= 1
285    call MouseLeftDrag(row, col)
286    call assert_equal(14, winsaveview().topline, msg)
287
288    let row -= 1
289    call MouseLeftDrag(row, col)
290    call assert_equal(14, winsaveview().topline, msg)
291
292    " We now leave the window at the top so the window content should
293    " scroll by 1 line, then 2, then 3 (etc) in the opposite direction.
294    let row -= 1
295    call MouseLeftDrag(row, col)
296    call assert_equal(13, winsaveview().topline, msg)
297
298    let row -= 1
299    call MouseLeftDrag(row, col)
300    call assert_equal(11, winsaveview().topline, msg)
301
302    let row -= 1
303    call MouseLeftDrag(row, col)
304    call assert_equal(8, winsaveview().topline, msg)
305
306    call MouseLeftRelease(row, col)
307    call assert_equal(8, winsaveview().topline, msg)
308    call assert_equal(2, winheight(0), msg)
309  endfor
310
311  let &mouse = save_mouse
312  let &term = save_term
313  let &ttymouse = save_ttymouse
314  call test_override('no_query_mouse', 0)
315  bwipe!
316endfunc
317
318func Test_term_mouse_drag_window_separator()
319  let save_mouse = &mouse
320  let save_term = &term
321  let save_ttymouse = &ttymouse
322  call test_override('no_query_mouse', 1)
323  set mouse=a term=xterm
324
325  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
326    let msg = 'ttymouse=' .. ttymouse_val
327    exe 'set ttymouse=' .. ttymouse_val
328
329    " Split horizontally and test dragging the horizontal window separator.
330    split
331    let rowseparator = winheight(0) + 1
332    let row = rowseparator
333    let col = 1
334
335    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
336    if ttymouse_val !=# 'xterm2' || row <= 223
337      call MouseLeftClick(row, col)
338      let row -= 1
339      call MouseLeftDrag(row, col)
340      call assert_equal(rowseparator - 1, winheight(0) + 1, msg)
341      let row += 1
342      call MouseLeftDrag(row, col)
343      call assert_equal(rowseparator, winheight(0) + 1, msg)
344      call MouseLeftRelease(row, col)
345      call assert_equal(rowseparator, winheight(0) + 1, msg)
346    endif
347    bwipe!
348
349    " Split vertically and test dragging the vertical window separator.
350    vsplit
351    let colseparator = winwidth(0) + 1
352    let row = 1
353    let col = colseparator
354
355    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
356    if ttymouse_val !=# 'xterm2' || col <= 223
357      call MouseLeftClick(row, col)
358      let col -= 1
359      call MouseLeftDrag(row, col)
360      call assert_equal(colseparator - 1, winwidth(0) + 1, msg)
361      let col += 1
362      call MouseLeftDrag(row, col)
363      call assert_equal(colseparator, winwidth(0) + 1, msg)
364      call MouseLeftRelease(row, col)
365      call assert_equal(colseparator, winwidth(0) + 1, msg)
366    endif
367    bwipe!
368  endfor
369
370  let &mouse = save_mouse
371  let &term = save_term
372  let &ttymouse = save_ttymouse
373  call test_override('no_query_mouse', 0)
374endfunc
375
376func Test_term_mouse_drag_statusline()
377  let save_mouse = &mouse
378  let save_term = &term
379  let save_ttymouse = &ttymouse
380  call test_override('no_query_mouse', 1)
381  let save_laststatus = &laststatus
382  set mouse=a term=xterm laststatus=2
383
384  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
385    let msg = 'ttymouse=' .. ttymouse_val
386    exe 'set ttymouse=' .. ttymouse_val
387
388    call assert_equal(1, &cmdheight, msg)
389    let rowstatusline = winheight(0) + 1
390    let row = rowstatusline
391    let col = 1
392
393    if ttymouse_val ==# 'xterm2' && row > 223
394      " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
395      continue
396    endif
397
398    call MouseLeftClick(row, col)
399    let row -= 1
400    call MouseLeftDrag(row, col)
401    call assert_equal(2, &cmdheight, msg)
402    call assert_equal(rowstatusline - 1, winheight(0) + 1, msg)
403    let row += 1
404    call MouseLeftDrag(row, col)
405    call assert_equal(1, &cmdheight, msg)
406    call assert_equal(rowstatusline, winheight(0) + 1, msg)
407    call MouseLeftRelease(row, col)
408    call assert_equal(1, &cmdheight, msg)
409    call assert_equal(rowstatusline, winheight(0) + 1, msg)
410  endfor
411
412  let &mouse = save_mouse
413  let &term = save_term
414  let &ttymouse = save_ttymouse
415  call test_override('no_query_mouse', 0)
416  let &laststatus = save_laststatus
417endfunc
418
419func Test_term_mouse_click_tab()
420  let save_mouse = &mouse
421  let save_term = &term
422  let save_ttymouse = &ttymouse
423  call test_override('no_query_mouse', 1)
424  set mouse=a term=xterm
425  let row = 1
426
427  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
428    let msg = 'ttymouse=' .. ttymouse_val
429    exe 'set ttymouse=' .. ttymouse_val
430    e Xfoo
431    tabnew Xbar
432
433    let a = split(execute(':tabs'), "\n")
434    call assert_equal(['Tab page 1',
435        \              '    Xfoo',
436        \              'Tab page 2',
437        \              '>   Xbar'], a, msg)
438
439    " Test clicking on tab names in the tabline at the top.
440    let col = 2
441    redraw
442    call MouseLeftClick(row, col)
443    call MouseLeftRelease(row, col)
444    let a = split(execute(':tabs'), "\n")
445    call assert_equal(['Tab page 1',
446        \              '>   Xfoo',
447        \              'Tab page 2',
448        \              '    Xbar'], a, msg)
449
450    let col = 9
451    call MouseLeftClick(row, col)
452    call MouseLeftRelease(row, col)
453    let a = split(execute(':tabs'), "\n")
454    call assert_equal(['Tab page 1',
455        \              '    Xfoo',
456        \              'Tab page 2',
457        \              '>   Xbar'], a, msg)
458
459    %bwipe!
460  endfor
461
462  let &mouse = save_mouse
463  let &term = save_term
464  let &ttymouse = save_ttymouse
465  call test_override('no_query_mouse', 0)
466endfunc
467
468func Test_term_mouse_click_X_to_close_tab()
469  let save_mouse = &mouse
470  let save_term = &term
471  let save_ttymouse = &ttymouse
472  call test_override('no_query_mouse', 1)
473  set mouse=a term=xterm
474  let row = 1
475  let col = &columns
476
477  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec + g:Ttymouse_netterm
478    if ttymouse_val ==# 'xterm2' && col > 223
479      " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
480      continue
481    endif
482    let msg = 'ttymouse=' .. ttymouse_val
483    exe 'set ttymouse=' .. ttymouse_val
484    e Xtab1
485    tabnew Xtab2
486    tabnew Xtab3
487    tabn 2
488
489    let a = split(execute(':tabs'), "\n")
490    call assert_equal(['Tab page 1',
491        \              '    Xtab1',
492        \              'Tab page 2',
493        \              '>   Xtab2',
494        \              'Tab page 3',
495        \              '    Xtab3'], a, msg)
496
497    " Click on "X" in tabline to close current tab i.e. Xtab2.
498    redraw
499    call MouseLeftClick(row, col)
500    call MouseLeftRelease(row, col)
501    let a = split(execute(':tabs'), "\n")
502    call assert_equal(['Tab page 1',
503        \              '    Xtab1',
504        \              'Tab page 2',
505        \              '>   Xtab3'], a, msg)
506
507    %bwipe!
508  endfor
509
510  let &mouse = save_mouse
511  let &term = save_term
512  let &ttymouse = save_ttymouse
513  call test_override('no_query_mouse', 0)
514endfunc
515
516func Test_term_mouse_drag_to_move_tab()
517  let save_mouse = &mouse
518  let save_term = &term
519  let save_ttymouse = &ttymouse
520  call test_override('no_query_mouse', 1)
521  " Set 'mousetime' to 1 to avoid recognizing a double-click in the loop
522  set mouse=a term=xterm mousetime=1
523  let row = 1
524
525  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
526    let msg = 'ttymouse=' .. ttymouse_val
527    exe 'set ttymouse=' .. ttymouse_val
528    e Xtab1
529    tabnew Xtab2
530
531    let a = split(execute(':tabs'), "\n")
532    call assert_equal(['Tab page 1',
533        \              '    Xtab1',
534        \              'Tab page 2',
535        \              '>   Xtab2'], a, msg)
536    redraw
537
538    " Click in tab2 and drag it to tab1.
539    " Check getcharmod() to verify that click is not
540    " interpreted as a spurious double-click.
541    call MouseLeftClick(row, 10)
542    call assert_equal(0, getcharmod(), msg)
543    for col in [9, 8, 7, 6]
544      call MouseLeftDrag(row, col)
545    endfor
546    call MouseLeftRelease(row, col)
547    let a = split(execute(':tabs'), "\n")
548    call assert_equal(['Tab page 1',
549        \              '>   Xtab2',
550        \              'Tab page 2',
551        \              '    Xtab1'], a, msg)
552
553    " Click elsewhere so that click in next iteration is not
554    " interpreted as unwanted double-click.
555    call MouseLeftClick(row, 11)
556    call MouseLeftRelease(row, 11)
557
558    %bwipe!
559  endfor
560
561  let &mouse = save_mouse
562  let &term = save_term
563  let &ttymouse = save_ttymouse
564  call test_override('no_query_mouse', 0)
565  set mousetime&
566endfunc
567
568func Test_term_mouse_double_click_to_create_tab()
569  let save_mouse = &mouse
570  let save_term = &term
571  let save_ttymouse = &ttymouse
572  call test_override('no_query_mouse', 1)
573  " Set 'mousetime' to a small value, so that double-click works but we don't
574  " have to wait long to avoid a triple-click.
575  set mouse=a term=xterm mousetime=200
576  let row = 1
577  let col = 10
578
579  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
580    let msg = 'ttymouse=' .. ttymouse_val
581    exe 'set ttymouse=' .. ttymouse_val
582    e Xtab1
583    tabnew Xtab2
584
585    let a = split(execute(':tabs'), "\n")
586    call assert_equal(['Tab page 1',
587        \              '    Xtab1',
588        \              'Tab page 2',
589        \              '>   Xtab2'], a, msg)
590
591    redraw
592    call MouseLeftClick(row, col)
593    " Check getcharmod() to verify that first click is not
594    " interpreted as a spurious double-click.
595    call assert_equal(0, getcharmod(), msg)
596    call MouseLeftRelease(row, col)
597    call MouseLeftClick(row, col)
598    call assert_equal(32, getcharmod(), msg) " double-click
599    call MouseLeftRelease(row, col)
600    let a = split(execute(':tabs'), "\n")
601    call assert_equal(['Tab page 1',
602        \              '    Xtab1',
603        \              'Tab page 2',
604        \              '>   [No Name]',
605        \              'Tab page 3',
606        \              '    Xtab2'], a, msg)
607
608    " Click elsewhere so that click in next iteration is not
609    " interpreted as unwanted double click.
610    call MouseLeftClick(row, col + 1)
611    call MouseLeftRelease(row, col + 1)
612
613    %bwipe!
614  endfor
615
616  let &mouse = save_mouse
617  let &term = save_term
618  let &ttymouse = save_ttymouse
619  call test_override('no_query_mouse', 0)
620  set mousetime&
621endfunc
622
623" Test double/triple/quadruple click in normal mode to visually select.
624func Test_term_mouse_multiple_clicks_to_visually_select()
625  let save_mouse = &mouse
626  let save_term = &term
627  let save_ttymouse = &ttymouse
628  call test_override('no_query_mouse', 1)
629  set mouse=a term=xterm mousetime=200
630  new
631
632  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
633    let msg = 'ttymouse=' .. ttymouse_val
634    exe 'set ttymouse=' .. ttymouse_val
635    call setline(1, ['foo [foo bar] foo', 'foo'])
636
637    " Double-click on word should visually select the word.
638    call MouseLeftClick(1, 2)
639    call assert_equal(0, getcharmod(), msg)
640    call MouseLeftRelease(1, 2)
641    call MouseLeftClick(1, 2)
642    call assert_equal(32, getcharmod(), msg) " double-click
643    call MouseLeftRelease(1, 2)
644    call assert_equal('v', mode(), msg)
645    norm! r1
646    call assert_equal(['111 [foo bar] foo', 'foo'], getline(1, '$'), msg)
647
648    " Double-click on opening square bracket should visually
649    " select the whole [foo bar].
650    call MouseLeftClick(1, 5)
651    call assert_equal(0, getcharmod(), msg)
652    call MouseLeftRelease(1, 5)
653    call MouseLeftClick(1, 5)
654    call assert_equal(32, getcharmod(), msg) " double-click
655    call MouseLeftRelease(1, 5)
656    call assert_equal('v', mode(), msg)
657    norm! r2
658    call assert_equal(['111 222222222 foo', 'foo'], getline(1, '$'), msg)
659
660    " Triple-click should visually select the whole line.
661    call MouseLeftClick(1, 3)
662    call assert_equal(0, getcharmod(), msg)
663    call MouseLeftRelease(1, 3)
664    call MouseLeftClick(1, 3)
665    call assert_equal(32, getcharmod(), msg) " double-click
666    call MouseLeftRelease(1, 3)
667    call MouseLeftClick(1, 3)
668    call assert_equal(64, getcharmod(), msg) " triple-click
669    call MouseLeftRelease(1, 3)
670    call assert_equal('V', mode(), msg)
671    norm! r3
672    call assert_equal(['33333333333333333', 'foo'], getline(1, '$'), msg)
673
674    " Quadruple-click should start visual block select.
675    call MouseLeftClick(1, 2)
676    call assert_equal(0, getcharmod(), msg)
677    call MouseLeftRelease(1, 2)
678    call MouseLeftClick(1, 2)
679    call assert_equal(32, getcharmod(), msg) " double-click
680    call MouseLeftRelease(1, 2)
681    call MouseLeftClick(1, 2)
682    call assert_equal(64, getcharmod(), msg) " triple-click
683    call MouseLeftRelease(1, 2)
684    call MouseLeftClick(1, 2)
685    call assert_equal(96, getcharmod(), msg) " quadruple-click
686    call MouseLeftRelease(1, 2)
687    call assert_equal("\<c-v>", mode(), msg)
688    norm! r4
689    call assert_equal(['34333333333333333', 'foo'], getline(1, '$'), msg)
690  endfor
691
692  let &mouse = save_mouse
693  let &term = save_term
694  let &ttymouse = save_ttymouse
695  set mousetime&
696  call test_override('no_query_mouse', 0)
697  bwipe!
698endfunc
699
700func Test_xterm_mouse_click_in_fold_columns()
701  new
702  let save_mouse = &mouse
703  let save_term = &term
704  let save_ttymouse = &ttymouse
705  let save_foldcolumn = &foldcolumn
706  set mouse=a term=xterm foldcolumn=3 ttymouse=xterm2
707
708  " Create 2 nested folds.
709  call setline(1, range(1, 7))
710  2,6fold
711  norm! zR
712  4,5fold
713  call assert_equal([-1, -1, -1, 4, 4, -1, -1],
714        \           map(range(1, 7), 'foldclosed(v:val)'))
715
716  " Click in "+" of inner fold in foldcolumn should open it.
717  redraw
718  let row = 4
719  let col = 2
720  call MouseLeftClick(row, col)
721  call MouseLeftRelease(row, col)
722  call assert_equal([-1, -1, -1, -1, -1, -1, -1],
723        \           map(range(1, 7), 'foldclosed(v:val)'))
724
725  " Click in "-" of outer fold in foldcolumn should close it.
726  redraw
727  let row = 2
728  let col = 1
729  call MouseLeftClick(row, col)
730  call MouseLeftRelease(row, col)
731  call assert_equal([-1, 2, 2, 2, 2, 2, -1],
732        \           map(range(1, 7), 'foldclosed(v:val)'))
733  norm! zR
734
735  " Click in "|" of inner fold in foldcolumn should close it.
736  redraw
737  let row = 5
738  let col = 2
739  call MouseLeftClick(row, col)
740  call MouseLeftRelease(row, col)
741  call assert_equal([-1, -1, -1, 4, 4, -1, -1],
742        \           map(range(1, 7), 'foldclosed(v:val)'))
743
744  let &foldcolumn = save_foldcolumn
745  let &ttymouse = save_ttymouse
746  let &term = save_term
747  let &mouse = save_mouse
748  bwipe!
749endfunc
750
751" Left or right click in Ex command line sets position of the cursor.
752func Test_term_mouse_click_in_cmdline_to_set_pos()
753  let save_mouse = &mouse
754  let save_term = &term
755  let save_ttymouse = &ttymouse
756  call test_override('no_query_mouse', 1)
757  set mouse=a term=xterm
758  let row = &lines
759
760  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
761    " When 'ttymouse' is 'xterm2', row/col bigger than 223 are not supported.
762    if ttymouse_val !=# 'xterm2' || row <= 223
763      let msg = 'ttymouse=' .. ttymouse_val
764      exe 'set ttymouse=' .. ttymouse_val
765
766
767      call feedkeys(':"3456789'
768            \       .. MouseLeftClickCode(row, 7)
769            \       .. MouseLeftReleaseCode(row, 7) .. 'L'
770            \       .. MouseRightClickCode(row, 4)
771            \       .. MouseRightReleaseCode(row, 4) .. 'R'
772            \       .. "\<CR>", 'Lx!')
773      call assert_equal('"3R456L789', @:, msg)
774    endif
775  endfor
776
777  let &mouse = save_mouse
778  let &term = save_term
779  let &ttymouse = save_ttymouse
780  set mousetime&
781  call test_override('no_query_mouse', 0)
782endfunc
783
784" Middle click in command line pastes at position of cursor.
785func Test_term_mouse_middle_click_in_cmdline_to_paste()
786  CheckFeature clipboard_working
787  let save_mouse = &mouse
788  let save_term = &term
789  let save_ttymouse = &ttymouse
790  call test_override('no_query_mouse', 1)
791  set mouse=a term=xterm
792  let row = &lines
793  " Column values does not matter, paste is done at position of cursor.
794  let col = 1
795  let @* = 'paste'
796
797  for ttymouse_val in g:Ttymouse_values + g:Ttymouse_dec
798    let msg = 'ttymouse=' .. ttymouse_val
799    exe 'set ttymouse=' .. ttymouse_val
800
801    call feedkeys(":\"->"
802          \       .. MouseMiddleReleaseCode(row, col)
803          \       .. MouseMiddleClickCode(row, col)
804          \       .. "<-"
805          \       .. MouseMiddleReleaseCode(row, col)
806          \       .. MouseMiddleClickCode(row, col)
807          \       .. "\<CR>", 'Lx!')
808    call assert_equal('"->paste<-paste', @:, msg)
809  endfor
810
811  let &mouse = save_mouse
812  let &term = save_term
813  let &ttymouse = save_ttymouse
814  let @* = ''
815  call test_override('no_query_mouse', 0)
816endfunc
817
818" Test for displaying the popup menu using the right mouse click
819func Test_mouse_popup_menu()
820  CheckFeature menu
821  new
822  call setline(1, 'popup menu test')
823  let save_mouse = &mouse
824  let save_term = &term
825  let save_ttymouse = &ttymouse
826  let save_mousemodel = &mousemodel
827  call test_override('no_query_mouse', 1)
828  set mouse=a term=xterm mousemodel=popup
829
830  menu PopUp.foo :let g:menustr = 'foo'<CR>
831  menu PopUp.bar :let g:menustr = 'bar'<CR>
832  menu PopUp.baz :let g:menustr = 'baz'<CR>
833
834  for ttymouse_val in g:Ttymouse_values
835    exe 'set ttymouse=' .. ttymouse_val
836    let g:menustr = ''
837    call feedkeys(MouseRightClickCode(1, 4)
838		\ .. MouseRightReleaseCode(1, 4) .. "\<Down>\<Down>\<CR>", "x")
839    call assert_equal('bar', g:menustr)
840  endfor
841
842  unmenu PopUp
843  let &mouse = save_mouse
844  let &term = save_term
845  let &ttymouse = save_ttymouse
846  let &mousemodel = save_mousemodel
847  call test_override('no_query_mouse', 0)
848  close!
849endfunc
850
851" This only checks if the sequence is recognized.
852func Test_term_rgb_response()
853  set t_RF=x
854  set t_RB=y
855
856  " response to t_RF, 4 digits
857  let red = 0x12
858  let green = 0x34
859  let blue = 0x56
860  let seq = printf("\<Esc>]10;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
861  call feedkeys(seq, 'Lx!')
862  call assert_equal(seq, v:termrfgresp)
863
864  " response to t_RF, 2 digits
865  let red = 0x78
866  let green = 0x9a
867  let blue = 0xbc
868  let seq = printf("\<Esc>]10;rgb:%02x/%02x/%02x\x07", red, green, blue)
869  call feedkeys(seq, 'Lx!')
870  call assert_equal(seq, v:termrfgresp)
871
872  " response to t_RB, 4 digits, dark
873  set background=light
874  eval 'background'->test_option_not_set()
875  let red = 0x29
876  let green = 0x4a
877  let blue = 0x6b
878  let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
879  call feedkeys(seq, 'Lx!')
880  call assert_equal(seq, v:termrbgresp)
881  call assert_equal('dark', &background)
882
883  " response to t_RB, 4 digits, light
884  set background=dark
885  call test_option_not_set('background')
886  let red = 0x81
887  let green = 0x63
888  let blue = 0x65
889  let seq = printf("\<Esc>]11;rgb:%02x00/%02x00/%02x00\x07", red, green, blue)
890  call feedkeys(seq, 'Lx!')
891  call assert_equal(seq, v:termrbgresp)
892  call assert_equal('light', &background)
893
894  " response to t_RB, 2 digits, dark
895  set background=light
896  call test_option_not_set('background')
897  let red = 0x47
898  let green = 0x59
899  let blue = 0x5b
900  let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
901  call feedkeys(seq, 'Lx!')
902  call assert_equal(seq, v:termrbgresp)
903  call assert_equal('dark', &background)
904
905  " response to t_RB, 2 digits, light
906  set background=dark
907  call test_option_not_set('background')
908  let red = 0x83
909  let green = 0xa4
910  let blue = 0xc2
911  let seq = printf("\<Esc>]11;rgb:%02x/%02x/%02x\x07", red, green, blue)
912  call feedkeys(seq, 'Lx!')
913  call assert_equal(seq, v:termrbgresp)
914  call assert_equal('light', &background)
915
916  set t_RF= t_RB=
917endfunc
918
919" This only checks if the sequence is recognized.
920" This must be after other tests, because it has side effects to xterm
921" properties.
922func Test_xx01_term_style_response()
923  " Termresponse is only parsed when t_RV is not empty.
924  set t_RV=x
925
926  " send the termresponse to trigger requesting the XT codes
927  let seq = "\<Esc>[>41;337;0c"
928  call feedkeys(seq, 'Lx!')
929  call assert_equal(seq, v:termresponse)
930
931  let seq = "\<Esc>P1$r2 q\<Esc>\\"
932  call feedkeys(seq, 'Lx!')
933  call assert_equal(seq, v:termstyleresp)
934
935  set t_RV=
936endfunc
937
938" This checks the iTerm2 version response.
939" This must be after other tests, because it has side effects to xterm
940" properties.
941func Test_xx02_iTerm2_response()
942  " Termresponse is only parsed when t_RV is not empty.
943  set t_RV=x
944
945  " Old versions of iTerm2 used a different style term response.
946  set ttymouse=xterm
947  call test_option_not_set('ttymouse')
948  let seq = "\<Esc>[>0;95;c"
949  call feedkeys(seq, 'Lx!')
950  call assert_equal(seq, v:termresponse)
951  call assert_equal('xterm', &ttymouse)
952
953  set ttymouse=xterm
954  call test_option_not_set('ttymouse')
955  let seq = "\<Esc>[>0;95;0c"
956  call feedkeys(seq, 'Lx!')
957  call assert_equal(seq, v:termresponse)
958  call assert_equal('sgr', &ttymouse)
959
960  set t_RV=
961endfunc
962
963" This checks the libvterm version response.
964" This must be after other tests, because it has side effects to xterm
965" properties.
966func Test_xx03_libvterm_response()
967  " Termresponse is only parsed when t_RV is not empty.
968  set t_RV=x
969
970  set ttymouse=xterm
971  call test_option_not_set('ttymouse')
972  let seq = "\<Esc>[>0;100;0c"
973  call feedkeys(seq, 'Lx!')
974  call assert_equal(seq, v:termresponse)
975  call assert_equal('sgr', &ttymouse)
976
977  set t_RV=
978endfunc
979
980" This checks the Mac Terminal.app version response.
981" This must be after other tests, because it has side effects to xterm
982" properties.
983func Test_xx04_Mac_Terminal_response()
984  " Termresponse is only parsed when t_RV is not empty.
985  set t_RV=x
986
987  set ttymouse=xterm
988  call test_option_not_set('ttymouse')
989  let seq = "\<Esc>[>1;95;0c"
990  call feedkeys(seq, 'Lx!')
991  call assert_equal(seq, v:termresponse)
992  call assert_equal('sgr', &ttymouse)
993
994  " Reset is_not_xterm and is_mac_terminal.
995  set t_RV=
996  set term=xterm
997  set t_RV=x
998endfunc
999
1000" This checks the mintty version response.
1001" This must be after other tests, because it has side effects to xterm
1002" properties.
1003func Test_xx05_mintty_response()
1004  " Termresponse is only parsed when t_RV is not empty.
1005  set t_RV=x
1006
1007  set ttymouse=xterm
1008  call test_option_not_set('ttymouse')
1009  let seq = "\<Esc>[>77;20905;0c"
1010  call feedkeys(seq, 'Lx!')
1011  call assert_equal(seq, v:termresponse)
1012  call assert_equal('sgr', &ttymouse)
1013
1014  set t_RV=
1015endfunc
1016
1017" This checks the screen version response.
1018" This must be after other tests, because it has side effects to xterm
1019" properties.
1020func Test_xx06_screen_response()
1021  " Termresponse is only parsed when t_RV is not empty.
1022  set t_RV=x
1023
1024  " Old versions of screen don't support SGR mouse mode.
1025  set ttymouse=xterm
1026  call test_option_not_set('ttymouse')
1027  let seq = "\<Esc>[>83;40500;0c"
1028  call feedkeys(seq, 'Lx!')
1029  call assert_equal(seq, v:termresponse)
1030  call assert_equal('xterm', &ttymouse)
1031
1032  " screen supports SGR mouse mode starting in version 4.7.
1033  set ttymouse=xterm
1034  call test_option_not_set('ttymouse')
1035  let seq = "\<Esc>[>83;40700;0c"
1036  call feedkeys(seq, 'Lx!')
1037  call assert_equal(seq, v:termresponse)
1038  call assert_equal('sgr', &ttymouse)
1039
1040  set t_RV=
1041endfunc
1042
1043" This checks the xterm version response.
1044" This must be after other tests, because it has side effects to xterm
1045" properties.
1046func Test_xx07_xterm_response()
1047  " Termresponse is only parsed when t_RV is not empty.
1048  set t_RV=x
1049
1050  " Do Terminal.app first to check that is_mac_terminal is reset.
1051  set ttymouse=xterm
1052  call test_option_not_set('ttymouse')
1053  let seq = "\<Esc>[>1;95;0c"
1054  call feedkeys(seq, 'Lx!')
1055  call assert_equal(seq, v:termresponse)
1056  call assert_equal('sgr', &ttymouse)
1057
1058  " xterm < 95: "xterm" (actually unmodified)
1059  set t_RV=
1060  set term=xterm
1061  set t_RV=x
1062  set ttymouse=xterm
1063  call test_option_not_set('ttymouse')
1064  let seq = "\<Esc>[>0;94;0c"
1065  call feedkeys(seq, 'Lx!')
1066  call assert_equal(seq, v:termresponse)
1067  call assert_equal('xterm', &ttymouse)
1068
1069  " xterm >= 95 < 277 "xterm2"
1070  set ttymouse=xterm
1071  call test_option_not_set('ttymouse')
1072  let seq = "\<Esc>[>0;267;0c"
1073  call feedkeys(seq, 'Lx!')
1074  call assert_equal(seq, v:termresponse)
1075  call assert_equal('xterm2', &ttymouse)
1076
1077  " xterm >= 277: "sgr"
1078  set ttymouse=xterm
1079  call test_option_not_set('ttymouse')
1080  let seq = "\<Esc>[>0;277;0c"
1081  call feedkeys(seq, 'Lx!')
1082  call assert_equal(seq, v:termresponse)
1083  call assert_equal('sgr', &ttymouse)
1084
1085  set t_RV=
1086endfunc
1087
1088func Test_get_termcode()
1089  try
1090    let k1 = &t_k1
1091  catch /E113/
1092    throw 'Skipped: Unable to query termcodes'
1093  endtry
1094  set t_k1=
1095  set t_k1&
1096  call assert_equal(k1, &t_k1)
1097
1098  " use external termcap first
1099  set nottybuiltin
1100  set t_k1=
1101  set t_k1&
1102  " when using external termcap may get something else, but it must not be
1103  " empty, since we would fallback to the builtin one.
1104  call assert_notequal('', &t_k1)
1105
1106  if &term =~ 'xterm'
1107    " use internal termcap first
1108    let term_save = &term
1109    let &term = 'builtin_' .. &term
1110    set t_k1=
1111    set t_k1&
1112    call assert_equal(k1, &t_k1)
1113    let &term = term_save
1114  endif
1115
1116  set ttybuiltin
1117endfunc
1118
1119func GetEscCodeCSI27(key, modifier)
1120  let key = printf("%d", char2nr(a:key))
1121  let mod = printf("%d", a:modifier)
1122  return "\<Esc>[27;" .. mod .. ';' .. key .. '~'
1123endfunc
1124
1125func GetEscCodeCSIu(key, modifier)
1126  let key = printf("%d", char2nr(a:key))
1127  let mod = printf("%d", a:modifier)
1128  return "\<Esc>[" .. key .. ';' .. mod .. 'u'
1129endfunc
1130
1131" This checks the CSI sequences when in modifyOtherKeys mode.
1132" The mode doesn't need to be enabled, the codes are always detected.
1133func RunTest_modifyOtherKeys(func)
1134  new
1135  set timeoutlen=10
1136
1137  " Shift-X is sent as 'X' with the shift modifier
1138  call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!')
1139  call assert_equal('X', getline(1))
1140
1141  " Ctrl-i is Tab
1142  call setline(1, '')
1143  call feedkeys('a' .. a:func('i', 5) .. "\<Esc>", 'Lx!')
1144  call assert_equal("\t", getline(1))
1145
1146  " Ctrl-I is also Tab
1147  call setline(1, '')
1148  call feedkeys('a' .. a:func('I', 5) .. "\<Esc>", 'Lx!')
1149  call assert_equal("\t", getline(1))
1150
1151  " Alt-x is ø
1152  call setline(1, '')
1153  call feedkeys('a' .. a:func('x', 3) .. "\<Esc>", 'Lx!')
1154  call assert_equal("ø", getline(1))
1155
1156  " Meta-x is also ø
1157  call setline(1, '')
1158  call feedkeys('a' .. a:func('x', 9) .. "\<Esc>", 'Lx!')
1159  call assert_equal("ø", getline(1))
1160
1161  " Alt-X is Ø
1162  call setline(1, '')
1163  call feedkeys('a' .. a:func('X', 3) .. "\<Esc>", 'Lx!')
1164  call assert_equal("Ø", getline(1))
1165
1166  " Meta-X is ø
1167  call setline(1, '')
1168  call feedkeys('a' .. a:func('X', 9) .. "\<Esc>", 'Lx!')
1169  call assert_equal("Ø", getline(1))
1170
1171  " Ctrl-6 is Ctrl-^
1172  split aaa
1173  edit bbb
1174  call feedkeys(a:func('6', 5), 'Lx!')
1175  call assert_equal("aaa", bufname())
1176  bwipe aaa
1177  bwipe bbb
1178
1179  bwipe!
1180  set timeoutlen&
1181endfunc
1182
1183func Test_modifyOtherKeys_basic()
1184  call RunTest_modifyOtherKeys(function('GetEscCodeCSI27'))
1185  call RunTest_modifyOtherKeys(function('GetEscCodeCSIu'))
1186endfunc
1187
1188func Test_modifyOtherKeys_no_mapping()
1189  set timeoutlen=10
1190
1191  let @a = 'aaa'
1192  call feedkeys(":let x = '" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a'\<CR>", 'Lx!')
1193  call assert_equal("let x = 'aaa'", @:)
1194
1195  new
1196  call feedkeys("a" .. GetEscCodeCSI27('R', 5) .. GetEscCodeCSI27('R', 5) .. "a\<Esc>", 'Lx!')
1197  call assert_equal("aaa", getline(1))
1198  bwipe!
1199
1200  new
1201  call feedkeys("axx\<CR>yy" .. GetEscCodeCSI27('G', 5) .. GetEscCodeCSI27('K', 5) .. "a\<Esc>", 'Lx!')
1202  call assert_equal("axx", getline(1))
1203  call assert_equal("yy", getline(2))
1204  bwipe!
1205
1206  set timeoutlen&
1207endfunc
1208
1209func RunTest_mapping_shift(key, func)
1210  call setline(1, '')
1211  if a:key == '|'
1212    exe 'inoremap \| xyz'
1213  else
1214    exe 'inoremap ' .. a:key .. ' xyz'
1215  endif
1216  call feedkeys('a' .. a:func(a:key, 2) .. "\<Esc>", 'Lx!')
1217  call assert_equal("xyz", getline(1))
1218  if a:key == '|'
1219    exe 'iunmap \|'
1220  else
1221    exe 'iunmap ' .. a:key
1222  endif
1223endfunc
1224
1225func RunTest_mapping_works_with_shift(func)
1226  new
1227  set timeoutlen=10
1228
1229  call RunTest_mapping_shift('@', a:func)
1230  call RunTest_mapping_shift('A', a:func)
1231  call RunTest_mapping_shift('Z', a:func)
1232  call RunTest_mapping_shift('^', a:func)
1233  call RunTest_mapping_shift('_', a:func)
1234  call RunTest_mapping_shift('{', a:func)
1235  call RunTest_mapping_shift('|', a:func)
1236  call RunTest_mapping_shift('}', a:func)
1237  call RunTest_mapping_shift('~', a:func)
1238
1239  bwipe!
1240  set timeoutlen&
1241endfunc
1242
1243func Test_mapping_works_with_shift_plain()
1244  call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27'))
1245  call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu'))
1246endfunc
1247
1248func RunTest_mapping_mods(map, key, func, code)
1249  call setline(1, '')
1250  exe 'inoremap ' .. a:map .. ' xyz'
1251  call feedkeys('a' .. a:func(a:key, a:code) .. "\<Esc>", 'Lx!')
1252  call assert_equal("xyz", getline(1))
1253  exe 'iunmap ' .. a:map
1254endfunc
1255
1256func RunTest_mapping_works_with_mods(func, mods, code)
1257  new
1258  set timeoutlen=10
1259
1260  if a:mods !~ 'S'
1261    " Shift by itself has no effect
1262    call RunTest_mapping_mods('<' .. a:mods .. '-@>', '@', a:func, a:code)
1263  endif
1264  call RunTest_mapping_mods('<' .. a:mods .. '-A>', 'A', a:func, a:code)
1265  call RunTest_mapping_mods('<' .. a:mods .. '-Z>', 'Z', a:func, a:code)
1266  if a:mods !~ 'S'
1267    " with Shift code is always upper case
1268    call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'a', a:func, a:code)
1269    call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'z', a:func, a:code)
1270  endif
1271  if a:mods != 'A'
1272    " with Alt code is not in upper case
1273    call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'A', a:func, a:code)
1274    call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'Z', a:func, a:code)
1275  endif
1276  call RunTest_mapping_mods('<' .. a:mods .. '-á>', 'á', a:func, a:code)
1277  if a:mods !~ 'S'
1278    " Shift by itself has no effect
1279    call RunTest_mapping_mods('<' .. a:mods .. '-^>', '^', a:func, a:code)
1280    call RunTest_mapping_mods('<' .. a:mods .. '-_>', '_', a:func, a:code)
1281    call RunTest_mapping_mods('<' .. a:mods .. '-{>', '{', a:func, a:code)
1282    call RunTest_mapping_mods('<' .. a:mods .. '-\|>', '|', a:func, a:code)
1283    call RunTest_mapping_mods('<' .. a:mods .. '-}>', '}', a:func, a:code)
1284    call RunTest_mapping_mods('<' .. a:mods .. '-~>', '~', a:func, a:code)
1285  endif
1286
1287  bwipe!
1288  set timeoutlen&
1289endfunc
1290
1291func Test_mapping_works_with_shift()
1292  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S', 2)
1293  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S', 2)
1294endfunc
1295
1296func Test_mapping_works_with_ctrl()
1297  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5)
1298  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5)
1299endfunc
1300
1301func Test_mapping_works_with_shift_ctrl()
1302  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6)
1303  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6)
1304endfunc
1305
1306" Below we also test the "u" code with Alt, This works, but libvterm would not
1307" send the Alt key like this but by prefixing an Esc.
1308
1309func Test_mapping_works_with_alt()
1310  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'A', 3)
1311  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'A', 3)
1312endfunc
1313
1314func Test_mapping_works_with_shift_alt()
1315  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S-A', 4)
1316  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S-A', 4)
1317endfunc
1318
1319func Test_mapping_works_with_ctrl_alt()
1320  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-A', 7)
1321  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-A', 7)
1322endfunc
1323
1324func Test_mapping_works_with_shift_ctrl_alt()
1325  call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A', 8)
1326  call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
1327endfunc
1328
1329func Test_insert_literal()
1330  set timeoutlen=10
1331  new
1332  " CTRL-V CTRL-X inserts a ^X
1333  call feedkeys('a' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
1334  call assert_equal("\<C-X>", getline(1))
1335
1336  call setline(1, '')
1337  call feedkeys('a' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
1338  call assert_equal("\<C-X>", getline(1))
1339
1340  " CTRL-SHIFT-V CTRL-X inserts escape sequence
1341  call setline(1, '')
1342  call feedkeys('a' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('X', '5') .. "\<Esc>", 'Lx!')
1343  call assert_equal("\<Esc>[88;5u", getline(1))
1344
1345  call setline(1, '')
1346  call feedkeys('a' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('X', '5') .. "\<Esc>", 'Lx!')
1347  call assert_equal("\<Esc>[27;5;88~", getline(1))
1348
1349  bwipe!
1350  set timeoutlen&
1351endfunc
1352
1353func Test_cmdline_literal()
1354  set timeoutlen=10
1355
1356  " CTRL-V CTRL-Y inserts a ^Y
1357  call feedkeys(':' .. GetEscCodeCSIu('V', '5') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
1358  call assert_equal("\"\<C-Y>", @:)
1359
1360  call feedkeys(':' .. GetEscCodeCSI27('V', '5') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
1361  call assert_equal("\"\<C-Y>", @:)
1362
1363  " CTRL-SHIFT-V CTRL-Y inserts escape sequence
1364  call feedkeys(':' .. GetEscCodeCSIu('V', '6') .. GetEscCodeCSIu('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
1365  call assert_equal("\"\<Esc>[89;5u", @:)
1366
1367  call setline(1, '')
1368  call feedkeys(':' .. GetEscCodeCSI27('V', '6') .. GetEscCodeCSI27('Y', '5') .. "\<C-B>\"\<CR>", 'Lx!')
1369  call assert_equal("\"\<Esc>[27;5;89~", @:)
1370
1371  set timeoutlen&
1372endfunc
1373
1374" Test for translation of special key codes (<xF1>, <xF2>, etc.)
1375func Test_Keycode_Tranlsation()
1376  let keycodes = [
1377        \ ["<xUp>", "<Up>"],
1378        \ ["<xDown>", "<Down>"],
1379        \ ["<xLeft>", "<Left>"],
1380        \ ["<xRight>", "<Right>"],
1381        \ ["<xHome>", "<Home>"],
1382        \ ["<xEnd>", "<End>"],
1383        \ ["<zHome>", "<Home>"],
1384        \ ["<zEnd>", "<End>"],
1385        \ ["<xF1>", "<F1>"],
1386        \ ["<xF2>", "<F2>"],
1387        \ ["<xF3>", "<F3>"],
1388        \ ["<xF4>", "<F4>"],
1389        \ ["<S-xF1>", "<S-F1>"],
1390        \ ["<S-xF2>", "<S-F2>"],
1391        \ ["<S-xF3>", "<S-F3>"],
1392        \ ["<S-xF4>", "<S-F4>"]]
1393  for [k1, k2] in keycodes
1394    exe "nnoremap " .. k1 .. " 2wx"
1395    call assert_true(maparg(k1, 'n', 0, 1).lhs == k2)
1396    exe "nunmap " .. k1
1397  endfor
1398endfunc
1399
1400" vim: shiftwidth=2 sts=2 expandtab
1401