mirror of
https://github.com/zoriya/vim.git
synced 2025-12-12 18:26:16 +00:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26e8558e74 | ||
|
|
c4da113ef9 | ||
|
|
a92522fbf3 | ||
|
|
0daf843b4c | ||
|
|
1b0675caec | ||
|
|
74675a666b | ||
|
|
85dad2c815 | ||
|
|
8603356bf4 | ||
|
|
8327d1df17 | ||
|
|
292eff0c5a | ||
|
|
f1d13478e3 | ||
|
|
5a15b6aa0a | ||
|
|
cae24be4a8 | ||
|
|
163095f088 | ||
|
|
faf29d7f91 | ||
|
|
c577d813b7 | ||
|
|
11e79bb04e | ||
|
|
0ea5070d79 | ||
|
|
710b4a1646 | ||
|
|
c4f833808a | ||
|
|
8858498516 | ||
|
|
cce1cf12eb | ||
|
|
e5ae108ab8 | ||
|
|
a34293ae0a | ||
|
|
e4f25e4a8d | ||
|
|
da5116da45 | ||
|
|
a83fe75ca7 | ||
|
|
c2226845eb | ||
|
|
a693d0584b | ||
|
|
9c4fefffb6 | ||
|
|
86f100dc09 | ||
|
|
9f5f7bf4d5 | ||
|
|
e6bf655bc4 | ||
|
|
28b238225a | ||
|
|
2e147caa14 | ||
|
|
0b2eef24bc | ||
|
|
18d90b95c4 | ||
|
|
07ecfa64a1 | ||
|
|
41cc038ff8 | ||
|
|
8eeeba8c02 | ||
|
|
1814183b86 | ||
|
|
182a17b1e8 | ||
|
|
774e5a9673 | ||
|
|
5d7be4f0fa | ||
|
|
ea20de8146 | ||
|
|
cc0750dc6e | ||
|
|
4eb6531b03 | ||
|
|
1e8e14552e | ||
|
|
24a9e348aa | ||
|
|
a1bd86e0f2 | ||
|
|
53564f7c1a | ||
|
|
5fe691240b | ||
|
|
090209bfbd | ||
|
|
6d006f9e95 | ||
|
|
f8be461d02 | ||
|
|
4670490673 | ||
|
|
a529ce068b | ||
|
|
a1fed064d1 | ||
|
|
4d785895d1 | ||
|
|
d2c061d24c | ||
|
|
6a8958db25 | ||
|
|
6f9a476b2f | ||
|
|
d6abcd154c | ||
|
|
663bb23316 | ||
|
|
c768a208ca | ||
|
|
383aa84c0d | ||
|
|
157069b04e | ||
|
|
868831f122 | ||
|
|
9049298f8d | ||
|
|
fadacf01d0 | ||
|
|
06f1ed2f78 |
72
Filelist
72
Filelist
@@ -85,6 +85,7 @@ SRC_ALL = \
|
||||
src/syntax.c \
|
||||
src/tag.c \
|
||||
src/term.c \
|
||||
src/terminal.c \
|
||||
src/term.h \
|
||||
src/termlib.c \
|
||||
src/ui.c \
|
||||
@@ -187,6 +188,7 @@ SRC_ALL = \
|
||||
src/proto/syntax.pro \
|
||||
src/proto/tag.pro \
|
||||
src/proto/term.pro \
|
||||
src/proto/terminal.pro \
|
||||
src/proto/termlib.pro \
|
||||
src/proto/ui.pro \
|
||||
src/proto/undo.pro \
|
||||
@@ -194,6 +196,76 @@ SRC_ALL = \
|
||||
src/proto/version.pro \
|
||||
src/proto/winclip.pro \
|
||||
src/proto/window.pro \
|
||||
src/libvterm/.bzrignore \
|
||||
src/libvterm/.gitignore \
|
||||
src/libvterm/LICENSE \
|
||||
src/libvterm/Makefile \
|
||||
src/libvterm/README \
|
||||
src/libvterm/tbl2inc_c.pl \
|
||||
src/libvterm/vterm.pc.in \
|
||||
src/libvterm/bin/unterm.c \
|
||||
src/libvterm/bin/vterm-ctrl.c \
|
||||
src/libvterm/bin/vterm-dump.c \
|
||||
src/libvterm/doc/URLs \
|
||||
src/libvterm/doc/seqs.txt \
|
||||
src/libvterm/include/vterm.h \
|
||||
src/libvterm/include/vterm_keycodes.h \
|
||||
src/libvterm/src/encoding.c \
|
||||
src/libvterm/src/encoding/DECdrawing.inc \
|
||||
src/libvterm/src/encoding/DECdrawing.tbl \
|
||||
src/libvterm/src/encoding/uk.inc \
|
||||
src/libvterm/src/encoding/uk.tbl \
|
||||
src/libvterm/src/keyboard.c \
|
||||
src/libvterm/src/mouse.c \
|
||||
src/libvterm/src/parser.c \
|
||||
src/libvterm/src/pen.c \
|
||||
src/libvterm/src/rect.h \
|
||||
src/libvterm/src/screen.c \
|
||||
src/libvterm/src/state.c \
|
||||
src/libvterm/src/unicode.c \
|
||||
src/libvterm/src/utf8.h \
|
||||
src/libvterm/src/vterm.c \
|
||||
src/libvterm/src/vterm_internal.h \
|
||||
src/libvterm/t/02parser.test \
|
||||
src/libvterm/t/03encoding_utf8.test \
|
||||
src/libvterm/t/10state_putglyph.test \
|
||||
src/libvterm/t/11state_movecursor.test \
|
||||
src/libvterm/t/12state_scroll.test \
|
||||
src/libvterm/t/13state_edit.test \
|
||||
src/libvterm/t/14state_encoding.test \
|
||||
src/libvterm/t/15state_mode.test \
|
||||
src/libvterm/t/16state_resize.test \
|
||||
src/libvterm/t/17state_mouse.test \
|
||||
src/libvterm/t/18state_termprops.test \
|
||||
src/libvterm/t/20state_wrapping.test \
|
||||
src/libvterm/t/21state_tabstops.test \
|
||||
src/libvterm/t/22state_save.test \
|
||||
src/libvterm/t/25state_input.test \
|
||||
src/libvterm/t/26state_query.test \
|
||||
src/libvterm/t/27state_reset.test \
|
||||
src/libvterm/t/28state_dbl_wh.test \
|
||||
src/libvterm/t/29state_fallback.test \
|
||||
src/libvterm/t/30pen.test \
|
||||
src/libvterm/t/40screen_ascii.test \
|
||||
src/libvterm/t/41screen_unicode.test \
|
||||
src/libvterm/t/42screen_damage.test \
|
||||
src/libvterm/t/43screen_resize.test \
|
||||
src/libvterm/t/44screen_pen.test \
|
||||
src/libvterm/t/45screen_protect.test \
|
||||
src/libvterm/t/46screen_extent.test \
|
||||
src/libvterm/t/47screen_dbl_wh.test \
|
||||
src/libvterm/t/48screen_termprops.test \
|
||||
src/libvterm/t/90vttest_01-movement-1.test \
|
||||
src/libvterm/t/90vttest_01-movement-2.test \
|
||||
src/libvterm/t/90vttest_01-movement-3.test \
|
||||
src/libvterm/t/90vttest_01-movement-4.test \
|
||||
src/libvterm/t/90vttest_02-screen-1.test \
|
||||
src/libvterm/t/90vttest_02-screen-2.test \
|
||||
src/libvterm/t/90vttest_02-screen-3.test \
|
||||
src/libvterm/t/90vttest_02-screen-4.test \
|
||||
src/libvterm/t/92lp1640917.test \
|
||||
src/libvterm/t/harness.c \
|
||||
src/libvterm/t/run-test.pl \
|
||||
|
||||
|
||||
# source files for Unix only
|
||||
|
||||
@@ -87,6 +87,7 @@ UninstPage instfiles
|
||||
Function .onInit
|
||||
MessageBox MB_YESNO|MB_ICONQUESTION \
|
||||
"This will install Vim ${VER_MAJOR}.${VER_MINOR} on your computer.$\n Continue?" \
|
||||
/SD IDYES \
|
||||
IDYES NoAbort
|
||||
Abort ; causes installer to quit.
|
||||
NoAbort:
|
||||
|
||||
@@ -101,6 +101,7 @@ DOCS = \
|
||||
tabpage.txt \
|
||||
tagsrch.txt \
|
||||
term.txt \
|
||||
terminal.txt \
|
||||
tips.txt \
|
||||
todo.txt \
|
||||
uganda.txt \
|
||||
@@ -236,6 +237,7 @@ HTMLS = \
|
||||
tabpage.html \
|
||||
tagsrch.html \
|
||||
term.html \
|
||||
terminal.html \
|
||||
tips.html \
|
||||
todo.html \
|
||||
uganda.html \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*autocmd.txt* For Vim version 8.0. Last change: 2017 Apr 07
|
||||
*autocmd.txt* For Vim version 8.0. Last change: 2017 Jul 14
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -651,7 +651,8 @@ FileType When the 'filetype' option has been set. The
|
||||
pattern is matched against the filetype.
|
||||
<afile> can be used for the name of the file
|
||||
where this option was set, and <amatch> for
|
||||
the new value of 'filetype'.
|
||||
the new value of 'filetype'. Navigating to
|
||||
another window or buffer is not allowed.
|
||||
See |filetypes|.
|
||||
*FileWriteCmd*
|
||||
FileWriteCmd Before writing to a file, when not writing the
|
||||
|
||||
@@ -518,7 +518,7 @@ By default this reads the whole buffer. This can be changed with the "in_top"
|
||||
and "in_bot" options.
|
||||
|
||||
A special mode is when "in_top" is set to zero and "in_bot" is not set: Every
|
||||
time a line is added to the buffer, the last-but-one line will be send to the
|
||||
time a line is added to the buffer, the last-but-one line will be sent to the
|
||||
job stdin. This allows for editing the last line and sending it when pressing
|
||||
Enter.
|
||||
*channel-close-in*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*cmdline.txt* For Vim version 8.0. Last change: 2016 Sep 27
|
||||
*cmdline.txt* For Vim version 8.0. Last change: 2017 Jul 11
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -455,6 +455,9 @@ matches exactly one character.
|
||||
|
||||
The 'wildignorecase' option can be set to ignore case in filenames.
|
||||
|
||||
The 'wildmenu' option can be set to show the matches just above the command
|
||||
line.
|
||||
|
||||
If you like tcsh's autolist completion, you can use this mapping:
|
||||
:cnoremap X <C-L><C-D>
|
||||
(Where X is the command key to use, <C-L> is CTRL-L and <C-D> is CTRL-D)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*debug.txt* For Vim version 8.0. Last change: 2012 Feb 11
|
||||
*debug.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -53,7 +53,7 @@ Use this command to start Vim:
|
||||
valgrind --log-file=valgrind.log --leak-check=full ./vim
|
||||
|
||||
Note: Vim will run much slower. If your .vimrc is big or you have several
|
||||
plugins you need to be patient for startup, or run with the "-u NONE"
|
||||
plugins you need to be patient for startup, or run with the "--clean"
|
||||
argument.
|
||||
|
||||
There are often a few leaks from libraries, such as getpwuid() and
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*editing.txt* For Vim version 8.0. Last change: 2017 Apr 10
|
||||
*editing.txt* For Vim version 8.0. Last change: 2017 Jun 20
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -1328,9 +1328,11 @@ present in 'cpoptions' and "!" is not used in the command.
|
||||
:chd[ir][!] [path] Same as |:cd|.
|
||||
|
||||
*:lc* *:lcd*
|
||||
:lc[d][!] {path} Like |:cd|, but only set the current directory for the
|
||||
current window. The current directory for other
|
||||
windows is not changed. {not in Vi}
|
||||
:lc[d][!] {path} Like |:cd|, but only set the current directory when
|
||||
the cursor is in the current window. The current
|
||||
directory for other windows is not changed, switching
|
||||
to another window will stop using {path}.
|
||||
{not in Vi}
|
||||
|
||||
*:lch* *:lchdir*
|
||||
:lch[dir][!] Same as |:lcd|. {not in Vi}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*eval.txt* For Vim version 8.0. Last change: 2017 Jun 13
|
||||
*eval.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -2369,6 +2369,12 @@ tagfiles() List tags files used
|
||||
tan({expr}) Float tangent of {expr}
|
||||
tanh({expr}) Float hyperbolic tangent of {expr}
|
||||
tempname() String name for a temporary file
|
||||
term_getsize() Dict get the size of a terminal
|
||||
term_open() Job open a terminal window and run a job
|
||||
term_scrape() List inspect terminal screen
|
||||
term_sendkeys() Number send keystrokes to a terminal
|
||||
term_setsize() Number set the size of a terminal
|
||||
term_wait() Number wait for screen to be updated
|
||||
test_alloc_fail({id}, {countdown}, {repeat})
|
||||
none make memory allocation fail
|
||||
test_autochdir() none enable 'autochdir' during startup
|
||||
@@ -4189,14 +4195,14 @@ getchar([expr]) *getchar()*
|
||||
not consumed. Return zero if no character available.
|
||||
|
||||
Without [expr] and when [expr] is 0 a whole character or
|
||||
special key is returned. If it is an 8-bit character, the
|
||||
special key is returned. If it is a single character, the
|
||||
result is a number. Use nr2char() to convert it to a String.
|
||||
Otherwise a String is returned with the encoded character.
|
||||
For a special key it's a sequence of bytes starting with 0x80
|
||||
(decimal: 128). This is the same value as the string
|
||||
"\<Key>", e.g., "\<Left>". The returned value is also a
|
||||
String when a modifier (shift, control, alt) was used that is
|
||||
not included in the character.
|
||||
For a special key it's a String with a sequence of bytes
|
||||
starting with 0x80 (decimal: 128). This is the same value as
|
||||
the String "\<Key>", e.g., "\<Left>". The returned value is
|
||||
also a String when a modifier (shift, control, alt) was used
|
||||
that is not included in the character.
|
||||
|
||||
When [expr] is 0 and Esc is typed, there will be a short delay
|
||||
while Vim waits to see if this is the start of an escape
|
||||
@@ -4586,6 +4592,7 @@ getqflist([{what}]) *getqflist()*
|
||||
returns only the items listed in {what} as a dictionary. The
|
||||
following string items are supported in {what}:
|
||||
context get the context stored with |setqflist()|
|
||||
items quickfix list entries
|
||||
nr get information for this quickfix list; zero
|
||||
means the current quickfix list and '$' means
|
||||
the last quickfix list
|
||||
@@ -4602,6 +4609,7 @@ getqflist([{what}]) *getqflist()*
|
||||
|
||||
The returned dictionary contains the following entries:
|
||||
context context information stored with |setqflist()|
|
||||
items quickfix list entries
|
||||
nr quickfix list number
|
||||
title quickfix list title text
|
||||
winid quickfix |window-ID| (if opened)
|
||||
@@ -6998,13 +7006,16 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
|
||||
argument is ignored. The following items can be specified in
|
||||
{what}:
|
||||
context any Vim type can be stored as a context
|
||||
items list of quickfix entries. Same as the {list}
|
||||
argument.
|
||||
nr list number in the quickfix stack; zero
|
||||
means the current quickfix list and '$' means
|
||||
the last quickfix list
|
||||
title quickfix list title text
|
||||
Unsupported keys in {what} are ignored.
|
||||
If the "nr" item is not present, then the current quickfix list
|
||||
is modified.
|
||||
is modified. When creating a new quickfix list, "nr" can be
|
||||
set to a value one greater than the quickfix stack size.
|
||||
|
||||
Examples: >
|
||||
:call setqflist([], 'r', {'title': 'My search'})
|
||||
@@ -7651,17 +7662,29 @@ synIDtrans({synID}) *synIDtrans()*
|
||||
":highlight link" are followed.
|
||||
|
||||
synconcealed({lnum}, {col}) *synconcealed()*
|
||||
The result is a List. The first item in the list is 0 if the
|
||||
character at the position {lnum} and {col} is not part of a
|
||||
concealable region, 1 if it is. The second item in the list is
|
||||
a string. If the first item is 1, the second item contains the
|
||||
text which will be displayed in place of the concealed text,
|
||||
depending on the current setting of 'conceallevel'. The third
|
||||
and final item in the list is a unique number representing the
|
||||
specific syntax region matched. This allows detection of the
|
||||
beginning of a new concealable region if there are two
|
||||
consecutive regions with the same replacement character.
|
||||
For an example use see $VIMRUNTIME/syntax/2html.vim .
|
||||
The result is a List with currently three items:
|
||||
1. The first item in the list is 0 if the character at the
|
||||
position {lnum} and {col} is not part of a concealable
|
||||
region, 1 if it is.
|
||||
2. The second item in the list is a string. If the first item
|
||||
is 1, the second item contains the text which will be
|
||||
displayed in place of the concealed text, depending on the
|
||||
current setting of 'conceallevel' and 'listchars'.
|
||||
3. The third and final item in the list is a number
|
||||
representing the specific syntax region matched in the
|
||||
line. When the character is not concealed the value is
|
||||
zero. This allows detection of the beginning of a new
|
||||
concealable region if there are two consecutive regions
|
||||
with the same replacement character. For an example, if
|
||||
the text is "123456" and both "23" and "45" are concealed
|
||||
and replace by the character "X", then:
|
||||
call returns ~
|
||||
synconcealed(lnum, 1) [0, '', 0]
|
||||
synconcealed(lnum, 2) [1, 'X', 1]
|
||||
synconcealed(lnum, 3) [1, 'X', 1]
|
||||
synconcealed(lnum, 4) [1, 'X', 2]
|
||||
synconcealed(lnum, 5) [1, 'X', 2]
|
||||
synconcealed(lnum, 6) [0, '', 0]
|
||||
|
||||
|
||||
synstack({lnum}, {col}) *synstack()*
|
||||
@@ -7870,6 +7893,23 @@ tempname() *tempname()* *temp-file-name*
|
||||
For MS-Windows forward slashes are used when the 'shellslash'
|
||||
option is set or when 'shellcmdflag' starts with '-'.
|
||||
|
||||
term_getsize() *term_getsize()*
|
||||
Get the size of a terminal. NOT IMPLEMENTED YET
|
||||
|
||||
term_open() *term_open()*
|
||||
Open a terminal window and run a job. NOT IMPLEMENTED YET
|
||||
|
||||
term_scrape() *term_scrape()*
|
||||
Inspect terminal screen. NOT IMPLEMENTED YET
|
||||
|
||||
term_sendkeys() *term_sendkeys()*
|
||||
Send keystrokes to a terminal. NOT IMPLEMENTED YET
|
||||
|
||||
term_setsize() *term_setsize()*
|
||||
Set the size of a terminal. NOT IMPLEMENTED YET
|
||||
|
||||
term_wait() *term_wait()*
|
||||
Wait for screen to be updated. NOT IMPLEMENTED YET
|
||||
|
||||
test_alloc_fail({id}, {countdown}, {repeat}) *test_alloc_fail()*
|
||||
This is for testing: If the memory allocation with {id} is
|
||||
@@ -7926,8 +7966,19 @@ test_override({name}, {val}) *test_override()*
|
||||
name effect when {val} is non-zero ~
|
||||
redraw disable the redrawing() function
|
||||
char_avail disable the char_avail() function
|
||||
starting reset the "starting" variable, see below
|
||||
ALL clear all overrides ({val} is not used)
|
||||
|
||||
"starting" is to be used when a test should behave like
|
||||
startup was done. Since the tests are run by sourcing a
|
||||
script the "starting" variable is non-zero. This is usually a
|
||||
good thing (tests run faster), but sometimes changes behavior
|
||||
in a way that the test doesn't work properly.
|
||||
When using: >
|
||||
call test_override('starting', 1)
|
||||
< The value of "starting" is saved. It is restored by: >
|
||||
call test_override('starting', 0)
|
||||
|
||||
test_settime({expr}) *test_settime()*
|
||||
Set the time Vim uses internally. Currently only used for
|
||||
timestamps in the history, as they are used in viminfo, and
|
||||
@@ -7989,6 +8040,10 @@ timer_start({time}, {callback} [, {options}])
|
||||
"repeat" Number of times to repeat calling the
|
||||
callback. -1 means forever. When not present
|
||||
the callback will be called once.
|
||||
If the timer causes an error three times in a
|
||||
row the repeat is cancelled. This avoids that
|
||||
Vim becomes unusable because of all the error
|
||||
messages.
|
||||
|
||||
Example: >
|
||||
func MyHandler(timer)
|
||||
@@ -8715,6 +8770,9 @@ See |:verbose-cmd| for more information.
|
||||
not used an error message is given. When [!] is used,
|
||||
an existing function is silently replaced. Unless it
|
||||
is currently being executed, that is an error.
|
||||
NOTE: Use ! wisely. If used without care it can cause
|
||||
an existing function to be replaced unexpectedly,
|
||||
which is hard to debug.
|
||||
|
||||
For the {arguments} see |function-argument|.
|
||||
|
||||
@@ -8764,18 +8822,36 @@ See |:verbose-cmd| for more information.
|
||||
implies that the effect of |:nohlsearch| is undone
|
||||
when the function returns.
|
||||
|
||||
*:endf* *:endfunction* *E126* *E193*
|
||||
:endf[unction] The end of a function definition. Must be on a line
|
||||
by its own, without other commands.
|
||||
*:endf* *:endfunction* *E126* *E193* *W22*
|
||||
:endf[unction] [argument]
|
||||
The end of a function definition. Best is to put it
|
||||
on a line by its own, without [argument].
|
||||
|
||||
[argument] can be:
|
||||
| command command to execute next
|
||||
\n command command to execute next
|
||||
" comment always ignored
|
||||
anything else ignored, warning given when
|
||||
'verbose' is non-zero
|
||||
The support for a following command was added in Vim
|
||||
8.0.0654, before that any argument was silently
|
||||
ignored.
|
||||
|
||||
To be able to define a function inside an `:execute`
|
||||
command, use line breaks instead of |:bar|: >
|
||||
:exe "func Foo()\necho 'foo'\nendfunc"
|
||||
<
|
||||
*:delf* *:delfunction* *E130* *E131* *E933*
|
||||
:delf[unction] {name} Delete function {name}.
|
||||
:delf[unction][!] {name}
|
||||
Delete function {name}.
|
||||
{name} can also be a |Dictionary| entry that is a
|
||||
|Funcref|: >
|
||||
:delfunc dict.init
|
||||
< This will remove the "init" entry from "dict". The
|
||||
function is deleted if there are no more references to
|
||||
it.
|
||||
With the ! there is no error if the function does not
|
||||
exist.
|
||||
*:retu* *:return* *E133*
|
||||
:retu[rn] [expr] Return from a function. When "[expr]" is given, it is
|
||||
evaluated and returned as the result of the function.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*gui_x11.txt* For Vim version 8.0. Last change: 2016 Sep 12
|
||||
*gui_x11.txt* For Vim version 8.0. Last change: 2017 Jun 27
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -279,8 +279,9 @@ For CDE "dtwm" (a derivative of Motif) add this line in the .Xdefaults: >
|
||||
For "mwm" (Motif window manager) the line would be: >
|
||||
Mwm*Vim*iconImage: /usr/local/share/vim/vim32x32.xpm
|
||||
|
||||
Mouse Pointers Available in X11 *X11_mouse_shapes*
|
||||
|
||||
Mouse Pointers Available in X11 ~
|
||||
*X11_mouse_shapes*
|
||||
By using the |'mouseshape'| option, the mouse pointer can be automatically
|
||||
changed whenever Vim enters one of its various modes (e.g., Insert or
|
||||
Command). Currently, the available pointers are:
|
||||
@@ -354,6 +355,8 @@ to the GTK documentation, however little there is, on how to do this.
|
||||
See http://developer.gnome.org/doc/API/2.0/gtk/gtk-Resource-Files.html
|
||||
for more information.
|
||||
|
||||
|
||||
Tooltip Colors ~
|
||||
*gtk-tooltip-colors*
|
||||
Example, which sets the tooltip colors to black on light-yellow: >
|
||||
|
||||
@@ -372,15 +375,122 @@ distribution.
|
||||
For GTK+ 3, an effect similar to the above can be obtained by adding the
|
||||
following snippet of CSS code to $XDG_HOME_DIR/gtk-3.0/gtk.css (usually,
|
||||
$HOME/.config/gtk-3.0/gtk.css):
|
||||
>
|
||||
|
||||
For GTK+ 3 < 3.20: >
|
||||
|
||||
.tooltip {
|
||||
background-color: #ffffcc;
|
||||
color: #000000;
|
||||
}
|
||||
<
|
||||
For GTK+ 3 >= 3.20: >
|
||||
|
||||
Using Vim as a GTK+ plugin *gui-gtk-socketid*
|
||||
tooltip {
|
||||
background-color: #ffffcc;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
tooltip label {
|
||||
color: #2e3436;
|
||||
}
|
||||
<
|
||||
|
||||
A Quick Look at GTK+ CSS ~
|
||||
*gtk-css*
|
||||
The contents of this subsection apply to GTK+ 3.20 or later which provides
|
||||
stable support for GTK+ CSS:
|
||||
|
||||
https://developer.gnome.org/gtk3/stable/theming.html
|
||||
|
||||
GTK+ uses CSS for styling and layout of widgets. In this subsection, we'll
|
||||
have a quick look at GTK+ CSS through simple, illustrative examples.
|
||||
|
||||
Example 1. Empty Space Adjustment ~
|
||||
|
||||
By default, the toolbar and the tabline of the GTK+ 3 GUI are somewhat larger
|
||||
than those of the GTK+ 2 GUI. Some people may want to make them look similar
|
||||
to the GTK+ 2 GUI in size.
|
||||
|
||||
To do that, we'll try reducing empty space around icons and labels that looks
|
||||
apparently superfluous.
|
||||
|
||||
Add the following lines to $XDG_HOME_DIR/gtk-3.0/gtk.css (usually,
|
||||
$HOME/.config/gtk-3.0/gtk.css): >
|
||||
|
||||
toolbar button {
|
||||
margin-top: -2px;
|
||||
margin-right: 0px;
|
||||
margin-bottom: -2px;
|
||||
margin-left: 0px;
|
||||
|
||||
padding-top: 0px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
padding-left: 0px
|
||||
}
|
||||
|
||||
notebook tab {
|
||||
margin-top: -1px;
|
||||
margin-right: 3px;
|
||||
margin-bottom: -1px;
|
||||
margin-left: 3px;
|
||||
|
||||
padding-top: 0px;
|
||||
padding-right: 0px;
|
||||
padding-bottom: 0px;
|
||||
padding-left: 0px
|
||||
}
|
||||
<
|
||||
Since it's a CSS, they can be rewritten using shorthand: >
|
||||
|
||||
toolbar button {
|
||||
margin: -2px 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
notebook tab {
|
||||
margin: -1px 3px;
|
||||
padding: 0px
|
||||
}
|
||||
<
|
||||
Note: You might want to use 'toolbariconsize' to adjust the icon size, too.
|
||||
|
||||
Note: Depending on the icon theme and/or the font in use, some extra tweaks
|
||||
may be needed for a satisfactory result.
|
||||
|
||||
Note: In addition to margin and padding, you can use border. For details,
|
||||
refer to the box model of CSS, e.g.,
|
||||
|
||||
https://www.w3schools.com/css/css_boxmodel.asp
|
||||
|
||||
Example 2. More Than Just Colors ~
|
||||
|
||||
GTK+ CSS supports gradients as well: >
|
||||
|
||||
tooltip {
|
||||
background-image: -gtk-gradient(linear,
|
||||
0 0, 0 1,
|
||||
color-stop(0, #344752),
|
||||
color-stop(0.5, #546772),
|
||||
color-stop(1, #243742));
|
||||
}
|
||||
|
||||
tooltip label {
|
||||
color: #f3f3f3;
|
||||
}
|
||||
<
|
||||
Gradients can be used to make a GUI element visually distinguishable from
|
||||
others without relying on high contrast. Accordingly, effective use of them is
|
||||
a useful technique to give a theme a sense of unity in color and luminance.
|
||||
|
||||
Note: Theming can be difficult since it must make every application look
|
||||
equally good; making a single application more charming often gets others
|
||||
unexpectedly less attractive or even deteriorates their usability. Keep this
|
||||
in mind always when you try improving a theme.
|
||||
|
||||
|
||||
Using Vim as a GTK+ plugin ~
|
||||
*gui-gtk-socketid*
|
||||
When the GTK+ version of Vim starts up normally, it creates its own top level
|
||||
window (technically, a 'GtkWindow'). GTK+ provides an embedding facility with
|
||||
its GtkSocket and GtkPlug widgets. If one GTK+ application creates a
|
||||
@@ -425,8 +535,8 @@ Note: Avoid use of --enable-gnome-check with GTK+ 3 GUI build. The
|
||||
functionality mentioned above is consolidated in GTK+ 3.
|
||||
|
||||
|
||||
GNOME session support *gui-gnome-session* *gnome-session*
|
||||
|
||||
GNOME session support ~
|
||||
*gui-gnome-session* *gnome-session*
|
||||
On logout, Vim shows the well-known exit confirmation dialog if any buffers
|
||||
are modified. Clicking [Cancel] will stop the logout process. Otherwise the
|
||||
current session is stored to disk by using the |:mksession| command, and
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*if_cscop.txt* For Vim version 8.0. Last change: 2011 Jun 12
|
||||
*if_cscop.txt* For Vim version 8.0. Last change: 2017 Jun 14
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Andy Kahn
|
||||
@@ -91,9 +91,10 @@ suggested use.)
|
||||
2. Cscope related commands *cscope-commands*
|
||||
|
||||
*:cscope* *:cs* *:scs* *:scscope* *E259* *E262* *E561* *E560*
|
||||
All cscope commands are accessed through suboptions to the main cscope
|
||||
command ":cscope". The shortest abbreviation is ":cs". The ":scscope"
|
||||
command does the same and also splits the window (short: "scs").
|
||||
All cscope commands are accessed through suboptions to the cscope commands.
|
||||
`:cscope` or `:cs` is the main command
|
||||
`:scscope` or `:scs` does the same and splits the window
|
||||
`:lcscope` or `:lcs` uses the location list, see |:lcscope|
|
||||
|
||||
The available subcommands are:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*index.txt* For Vim version 8.0. Last change: 2017 Apr 22
|
||||
*index.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -1573,6 +1573,7 @@ tag command action ~
|
||||
|:tcldo| :tcld[o] execute Tcl command for each line
|
||||
|:tclfile| :tclf[ile] execute Tcl script file
|
||||
|:tearoff| :te[aroff] tear-off a menu
|
||||
|:terminal| :ter[minal] open a terminal window
|
||||
|:tfirst| :tf[irst] jump to first matching tag
|
||||
|:throw| :th[row] throw an exception
|
||||
|:tjump| :tj[ump] like ":tselect", but jump directly when there
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*options.txt* For Vim version 8.0. Last change: 2017 Jun 13
|
||||
*options.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -4966,8 +4966,8 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
When on the plugin scripts are loaded when starting up |load-plugins|.
|
||||
This option can be reset in your |vimrc| file to disable the loading
|
||||
of plugins.
|
||||
Note that using the "-u NONE" and "--noplugin" command line arguments
|
||||
reset this option. |-u| |--noplugin|
|
||||
Note that using the "-u NONE", "-u DEFAULTS" and "--noplugin" command
|
||||
line arguments reset this option. See |-u| and |--noplugin|.
|
||||
|
||||
*'luadll'*
|
||||
'luadll' string (default depends on the build)
|
||||
@@ -5945,10 +5945,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
{only available when compiled with the |+reltime|
|
||||
feature}
|
||||
The time in milliseconds for redrawing the display. This applies to
|
||||
searching for patterns for 'hlsearch' and |:match| highlighting.
|
||||
searching for patterns for 'hlsearch', |:match| highlighting an syntax
|
||||
highlighting.
|
||||
When redrawing takes more than this many milliseconds no further
|
||||
matches will be highlighted. This is used to avoid that Vim hangs
|
||||
when using a very complicated pattern.
|
||||
matches will be highlighted.
|
||||
For syntax highlighting the time applies per window. When over the
|
||||
limit syntax highlighting is disabled until |CTRL-L| is used.
|
||||
This is used to avoid that Vim hangs when using a very complicated
|
||||
pattern.
|
||||
|
||||
*'regexpengine'* *'re'*
|
||||
'regexpengine' 're' number (default 0)
|
||||
@@ -7326,7 +7330,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
|
||||
Watch out for errors in expressions. They may render Vim unusable!
|
||||
If you are stuck, hold down ':' or 'Q' to get a prompt, then quit and
|
||||
edit your .vimrc or whatever with "vim -u NONE" to get it right.
|
||||
edit your .vimrc or whatever with "vim --clean" to get it right.
|
||||
|
||||
Examples:
|
||||
Emulate standard status line with 'ruler' set >
|
||||
@@ -7750,6 +7754,26 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
Note that the "cterm" attributes are still used, not the "gui" ones.
|
||||
NOTE: This option is reset when 'compatible' is set.
|
||||
|
||||
*'termkey'* *'tk'*
|
||||
'termkey' 'tk' string (default "CTRL-W")
|
||||
local to window
|
||||
{not in Vi}
|
||||
The key that precedes a Vim command in a terminal window. Other keys
|
||||
are sent to the job running in the window.
|
||||
The string must be one key stroke.
|
||||
NOT IMPLEMENTED YET
|
||||
|
||||
|
||||
*'thesaurus'* *'tsr'*
|
||||
'termsize' 'tms' string (default "")
|
||||
local to window
|
||||
{not in Vi}
|
||||
Size of the |terminal| window. Format: {rows}x{columns}.
|
||||
- When empty the terminal gets the size from the window.
|
||||
- When set (e.g., "24x80") the terminal size is fixed. If the window
|
||||
is smaller only the top-left part is displayed.
|
||||
NOT IMPLEMENTED YET
|
||||
|
||||
*'terse'* *'noterse'*
|
||||
'terse' boolean (default off)
|
||||
global
|
||||
@@ -8309,13 +8333,14 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
{not available when compiled without the |+viminfo|
|
||||
feature}
|
||||
When non-empty, the viminfo file is read upon startup and written
|
||||
when exiting Vim (see |viminfo-file|). The string should be a comma
|
||||
separated list of parameters, each consisting of a single character
|
||||
identifying the particular parameter, followed by a number or string
|
||||
which specifies the value of that parameter. If a particular
|
||||
character is left out, then the default value is used for that
|
||||
parameter. The following is a list of the identifying characters and
|
||||
the effect of their value.
|
||||
when exiting Vim (see |viminfo-file|). Except when 'viminfofile' is
|
||||
"NONE".
|
||||
The string should be a comma separated list of parameters, each
|
||||
consisting of a single character identifying the particular parameter,
|
||||
followed by a number or string which specifies the value of that
|
||||
parameter. If a particular character is left out, then the default
|
||||
value is used for that parameter. The following is a list of the
|
||||
identifying characters and the effect of their value.
|
||||
CHAR VALUE ~
|
||||
*viminfo-!*
|
||||
! When included, save and restore global variables that start
|
||||
@@ -8375,9 +8400,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
has been used since the last search command.
|
||||
*viminfo-n*
|
||||
n Name of the viminfo file. The name must immediately follow
|
||||
the 'n'. Must be at the end of the option! If the "-i"
|
||||
argument was given when starting Vim, that file name overrides
|
||||
the one given here with 'viminfo'. Environment variables are
|
||||
the 'n'. Must be at the end of the option! If the
|
||||
'viminfofile' option is set, that file name overrides the one
|
||||
given here with 'viminfo'. Environment variables are
|
||||
expanded when opening the file, not when setting the option.
|
||||
*viminfo-r*
|
||||
r Removable media. The argument is a string (up to the next
|
||||
@@ -8418,6 +8443,17 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
NOTE: This option is set to the Vim default value when 'compatible'
|
||||
is reset.
|
||||
|
||||
*'viminfofile'* *'vif'*
|
||||
'viminfofile' 'vif' string (default: "")
|
||||
global
|
||||
{not in Vi}
|
||||
{not available when compiled without the |+viminfo|
|
||||
feature}
|
||||
When non-empty, overrides the file name used for viminfo.
|
||||
When equal to "NONE" no viminfo file will be read or written.
|
||||
This option can be set with the |-i| command line flag. The |--clean|
|
||||
command line flag sets it to "NONE".
|
||||
|
||||
*'virtualedit'* *'ve'*
|
||||
'virtualedit' 've' string (default "")
|
||||
global
|
||||
@@ -8451,14 +8487,27 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
'visualbell' 'vb' boolean (default off)
|
||||
global
|
||||
{not in Vi}
|
||||
Use visual bell instead of beeping. The terminal code to display the
|
||||
Use a visual bell instead of beeping. The terminal code to display the
|
||||
visual bell is given with 't_vb'. When no beep or flash is wanted,
|
||||
use ":set vb t_vb=".
|
||||
Note: When the GUI starts, 't_vb' is reset to its default value. You
|
||||
might want to set it again in your |gvimrc|.
|
||||
use: >
|
||||
:set vb t_vb=
|
||||
< If you want a short flash, you can use this on many terminals: >
|
||||
:set vb t_vb=[?5h$<100>[?5l
|
||||
< Here $<100> specifies the time, you can use a smaller or bigger value
|
||||
to get a shorter or longer flash.
|
||||
|
||||
Note: Vim will limit the bell to once per half a second. This avoids
|
||||
having to wait for the flashing to finish when there are lots of
|
||||
bells, e.g. on key repeat. This also happens without 'visualbell'
|
||||
set.
|
||||
|
||||
In the GUI, 't_vb' defaults to "<Esc>|f", which inverts the display
|
||||
for 20 msec. If you want to use a different time, use "<Esc>|40f",
|
||||
where 40 is the time in msec.
|
||||
|
||||
Note: When the GUI starts, 't_vb' is reset to its default value. You
|
||||
might want to set it again in your |gvimrc|.
|
||||
|
||||
Does not work on the Amiga, you always get a screen flash.
|
||||
Also see 'errorbells'.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*quickref.txt* For Vim version 8.0. Last change: 2016 Dec 16
|
||||
*quickref.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -920,6 +920,8 @@ Short explanation of each option: *option-list*
|
||||
'termbidi' 'tbidi' terminal takes care of bi-directionality
|
||||
'termencoding' 'tenc' character encoding used by the terminal
|
||||
'termguicolors' 'tgc' use GUI colors for the terminal
|
||||
'termkey' 'tk' key that precedes a Vim command in a terminal
|
||||
'termsize' 'tms' size of a terminal window
|
||||
'terse' shorten some messages
|
||||
'textauto' 'ta' obsolete, use 'fileformats'
|
||||
'textmode' 'tx' obsolete, use 'fileformat'
|
||||
@@ -1309,6 +1311,7 @@ Context-sensitive completion on the command-line:
|
||||
|
||||
|:sfind| :sf[ind] {file} split window, find {file} in 'path'
|
||||
and edit it
|
||||
|:terminal| :terminal {cmd} open a terminal window
|
||||
|CTRL-W_]| CTRL-W ] split window and jump to tag under
|
||||
cursor
|
||||
|CTRL-W_f| CTRL-W f split window and edit file name under
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*starting.txt* For Vim version 8.0. Last change: 2017 Jan 15
|
||||
*starting.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -140,11 +140,12 @@ a slash. Thus "-R" means recovery and "-/R" readonly.
|
||||
--noplugin Skip loading plugins. Resets the 'loadplugins' option.
|
||||
{not in Vi}
|
||||
Note that the |-u| argument may also disable loading plugins:
|
||||
argument load vimrc files load plugins ~
|
||||
(nothing) yes yes
|
||||
-u NONE no no
|
||||
-u NORC no yes
|
||||
--noplugin yes no
|
||||
argument load: vimrc files plugins defaults.vim ~
|
||||
(nothing) yes yes yes
|
||||
-u NONE no no no
|
||||
-u DEFAULTS no no yes
|
||||
-u NORC no yes no
|
||||
--noplugin yes no yes
|
||||
|
||||
--startuptime {fname} *--startuptime*
|
||||
During startup write timing messages to the file {fname}.
|
||||
@@ -465,21 +466,30 @@ a slash. Thus "-R" means recovery and "-/R" readonly.
|
||||
--nofork GUI: Do not fork. Same as |-f|.
|
||||
*-u* *E282*
|
||||
-u {vimrc} The file {vimrc} is read for initializations. Most other
|
||||
initializations are skipped; see |initialization|. This can
|
||||
be used to start Vim in a special mode, with special
|
||||
initializations are skipped; see |initialization|.
|
||||
|
||||
This can be used to start Vim in a special mode, with special
|
||||
mappings and settings. A shell alias can be used to make
|
||||
this easy to use. For example: >
|
||||
alias vimc vim -u ~/.c_vimrc !*
|
||||
< Also consider using autocommands; see |autocommand|.
|
||||
|
||||
When {vimrc} is equal to "NONE" (all uppercase), all
|
||||
initializations from files and environment variables are
|
||||
skipped, including reading the |gvimrc| file when the GUI
|
||||
starts. Loading plugins is also skipped.
|
||||
|
||||
When {vimrc} is equal to "NORC" (all uppercase), this has the
|
||||
same effect as "NONE", but loading plugins is not skipped.
|
||||
Using the "-u" argument has the side effect that the
|
||||
'compatible' option will be on by default. This can have
|
||||
unexpected effects. See |'compatible'|.
|
||||
|
||||
When {vimrc} is equal to "DEFAULTS" (all uppercase), this has
|
||||
the same effect as "NONE", but the |defaults.vim| script is
|
||||
loaded, which will also set 'nocompatible'.
|
||||
|
||||
Using the "-u" argument with another argument than DEFAULTS
|
||||
has the side effect that the 'compatible' option will be on by
|
||||
default. This can have unexpected effects. See
|
||||
|'compatible'|.
|
||||
{not in Vi}
|
||||
|
||||
*-U* *E230*
|
||||
@@ -497,6 +507,13 @@ a slash. Thus "-R" means recovery and "-/R" readonly.
|
||||
":rv" or ":wv" are used. See also |viminfo-file|.
|
||||
{not in Vi}
|
||||
|
||||
*--clean*
|
||||
--clean Equal to "-u DEFAULTS -i NONE":
|
||||
- initializations from files and environment variables is
|
||||
skipped
|
||||
- the |defaults.vim| script is loaded, which implies
|
||||
'nocompatible': use Vim defaults
|
||||
- no viminfo file is read or written
|
||||
*-x*
|
||||
-x Use encryption to read/write files. Will prompt for a key,
|
||||
which is then stored in the 'key' option. All writes will
|
||||
@@ -868,6 +885,7 @@ accordingly. Vim proceeds in this order:
|
||||
Loading plugins won't be done when:
|
||||
- The 'loadplugins' option was reset in a vimrc file.
|
||||
- The |--noplugin| command line argument is used.
|
||||
- The |--clean| command line argument is used.
|
||||
- The "-u NONE" command line argument is used |-u|.
|
||||
- When Vim was compiled without the |+eval| feature.
|
||||
Note that using "-c 'set noloadplugins'" doesn't work, because the
|
||||
@@ -990,6 +1008,7 @@ starts its initializations. But as soon as:
|
||||
- a vimrc file in the current directory, or
|
||||
- the "VIMINIT" environment variable is set, or
|
||||
- the "-N" command line argument is given, or
|
||||
- the "--clean" command line argument is given, or
|
||||
even when no vimrc file exists.
|
||||
- the |defaults.vim| script is loaded, or
|
||||
- gvimrc file was found,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*syntax.txt* For Vim version 8.0. Last change: 2017 Jun 04
|
||||
*syntax.txt* For Vim version 8.0. Last change: 2017 Jul 14
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -4982,10 +4982,11 @@ PmenuSbar Popup menu: scrollbar.
|
||||
PmenuThumb Popup menu: Thumb of the scrollbar.
|
||||
*hl-Question*
|
||||
Question |hit-enter| prompt and yes/no questions
|
||||
*hl-QuickFixLine*
|
||||
QuickFixLine Current |quickfix| item in the quickfix window.
|
||||
*hl-Search*
|
||||
Search Last search pattern highlighting (see 'hlsearch').
|
||||
Also used for highlighting the current line in the quickfix
|
||||
window and similar items that need to stand out.
|
||||
Also used for similar items that need to stand out.
|
||||
*hl-SpecialKey*
|
||||
SpecialKey Meta and special keys listed with ":map", also for text used
|
||||
to show unprintable characters in the text, 'listchars'.
|
||||
|
||||
@@ -3098,6 +3098,8 @@ $VIM_POSIX vi_diff.txt /*$VIM_POSIX*
|
||||
:tclfile if_tcl.txt /*:tclfile*
|
||||
:te gui_w32.txt /*:te*
|
||||
:tearoff gui_w32.txt /*:tearoff*
|
||||
:ter terminal.txt /*:ter*
|
||||
:terminal terminal.txt /*:terminal*
|
||||
:tf tagsrch.txt /*:tf*
|
||||
:tfirst tagsrch.txt /*:tfirst*
|
||||
:th eval.txt /*:th*
|
||||
@@ -4802,6 +4804,7 @@ W18 syntax.txt /*W18*
|
||||
W19 autocmd.txt /*W19*
|
||||
W20 if_pyth.txt /*W20*
|
||||
W21 if_pyth.txt /*W21*
|
||||
W22 eval.txt /*W22*
|
||||
WORD motion.txt /*WORD*
|
||||
WWW intro.txt /*WWW*
|
||||
Win32 os_win32.txt /*Win32*
|
||||
@@ -6571,6 +6574,7 @@ gs various.txt /*gs*
|
||||
gsp.vim syntax.txt /*gsp.vim*
|
||||
gstar pattern.txt /*gstar*
|
||||
gt tabpage.txt /*gt*
|
||||
gtk-css gui_x11.txt /*gtk-css*
|
||||
gtk-tooltip-colors gui_x11.txt /*gtk-tooltip-colors*
|
||||
gu change.txt /*gu*
|
||||
gugu change.txt /*gugu*
|
||||
@@ -6740,6 +6744,7 @@ hl-PmenuSbar syntax.txt /*hl-PmenuSbar*
|
||||
hl-PmenuSel syntax.txt /*hl-PmenuSel*
|
||||
hl-PmenuThumb syntax.txt /*hl-PmenuThumb*
|
||||
hl-Question syntax.txt /*hl-Question*
|
||||
hl-QuickFixLine syntax.txt /*hl-QuickFixLine*
|
||||
hl-Scrollbar syntax.txt /*hl-Scrollbar*
|
||||
hl-Search syntax.txt /*hl-Search*
|
||||
hl-SignColumn syntax.txt /*hl-SignColumn*
|
||||
@@ -8778,6 +8783,12 @@ tempname() eval.txt /*tempname()*
|
||||
term-dependent-settings term.txt /*term-dependent-settings*
|
||||
term-list syntax.txt /*term-list*
|
||||
term.txt term.txt /*term.txt*
|
||||
term_getsize() eval.txt /*term_getsize()*
|
||||
term_open() eval.txt /*term_open()*
|
||||
term_scrape() eval.txt /*term_scrape()*
|
||||
term_sendkeys() eval.txt /*term_sendkeys()*
|
||||
term_setsize() eval.txt /*term_setsize()*
|
||||
term_wait() eval.txt /*term_wait()*
|
||||
termcap term.txt /*termcap*
|
||||
termcap-changed version4.txt /*termcap-changed*
|
||||
termcap-colors term.txt /*termcap-colors*
|
||||
@@ -8785,11 +8796,16 @@ termcap-cursor-color term.txt /*termcap-cursor-color*
|
||||
termcap-cursor-shape term.txt /*termcap-cursor-shape*
|
||||
termcap-options term.txt /*termcap-options*
|
||||
termcap-title term.txt /*termcap-title*
|
||||
terminal terminal.txt /*terminal*
|
||||
terminal-colors os_unix.txt /*terminal-colors*
|
||||
terminal-debug terminal.txt /*terminal-debug*
|
||||
terminal-info term.txt /*terminal-info*
|
||||
terminal-key-codes term.txt /*terminal-key-codes*
|
||||
terminal-options term.txt /*terminal-options*
|
||||
terminal-output-codes term.txt /*terminal-output-codes*
|
||||
terminal-testing terminal.txt /*terminal-testing*
|
||||
terminal-use terminal.txt /*terminal-use*
|
||||
terminal.txt terminal.txt /*terminal.txt*
|
||||
terminfo term.txt /*terminfo*
|
||||
termresponse-variable eval.txt /*termresponse-variable*
|
||||
test-functions usr_41.txt /*test-functions*
|
||||
|
||||
126
runtime/doc/terminal.txt
Normal file
126
runtime/doc/terminal.txt
Normal file
@@ -0,0 +1,126 @@
|
||||
*terminal.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
|
||||
|
||||
Terminal window support *terminal*
|
||||
|
||||
|
||||
WARNING: THIS IS ONLY PARTLY IMPLEMENTED, ANYTHING CAN STILL CHANGE
|
||||
|
||||
|
||||
1. Basic use |terminal-use|
|
||||
2. Remote testing |terminal-testing|
|
||||
3. Debugging |terminal-debug|
|
||||
|
||||
{Vi does not have any of these commands}
|
||||
|
||||
==============================================================================
|
||||
1. Basic use *terminal-use*
|
||||
|
||||
This feature is for running a terminal emulator in a Vim window. A job can be
|
||||
started connected to the terminal emulator. For example, to run a shell: >
|
||||
:term bash
|
||||
|
||||
Or to run a debugger: >
|
||||
:term gdb vim
|
||||
|
||||
The job runs asynchronously from Vim, the window will be updated to show
|
||||
output from the job, also while editing in any other window.
|
||||
|
||||
When the keyboard focus is in the terminal window, typed keys will be send to
|
||||
the job. This uses a pty when possible.
|
||||
|
||||
Navigate between windows with CTRL-W commands (and mouse).
|
||||
E.g. CTRL-W CTRL-W moves focus to the next window.
|
||||
|
||||
See option 'termkey' for specifying the key that precedes a Vim command.
|
||||
Default is CTRL-W.
|
||||
|
||||
See option 'termsize' for controlling the size of the terminal window.
|
||||
(TODO: scrolling when the terminal is larger than the window)
|
||||
|
||||
Syntax ~
|
||||
*:ter* *:terminal*
|
||||
:terminal[!] [command] Open a new terminal window.
|
||||
|
||||
If [command] is provided run it as a job and connect
|
||||
the input and output to the terminal.
|
||||
If [command] is not given the 'shell' option is used.
|
||||
|
||||
A new buffer will be created, using [command] or
|
||||
'shell' as the name. If a buffer by this name already
|
||||
exists a number is added in parenthesis.
|
||||
E.g. if "gdb" exists the second terminal buffer will
|
||||
use "gdb (1)".
|
||||
|
||||
The window can be closed, in which case the buffer
|
||||
becomes hidden. The command will not be stopped. The
|
||||
`:buffer` command can be used to turn the current
|
||||
window into a terminal window, using the existing
|
||||
buffer. If there are unsaved changes this fails, use
|
||||
! to force, as usual.
|
||||
|
||||
Resizing ~
|
||||
|
||||
The size of the terminal can be in one of three modes:
|
||||
|
||||
1. The 'termsize' option is empty: The terminal size follows the window size.
|
||||
The minimal size is 2 screen lines with 10 cells.
|
||||
|
||||
2. The 'termsize' option is "rows*cols", where "rows" is the minimal number of
|
||||
screen rows and "cols" is the minial number of cells.
|
||||
|
||||
3. The 'termsize' option is "rowsXcols" (where the x is upper or lower case).
|
||||
The terminal size is fixed to the specified number of screen lines and
|
||||
cells. If the window is bigger there will be unused empty space.
|
||||
|
||||
If the window is smaller than the terminal size, only part of the terminal can
|
||||
be seen (the lower-left part).
|
||||
|
||||
The |term_getsize()| function can be used to get the current size of the
|
||||
terminal. |term_setsize()| can be used only when in the first or second mode,
|
||||
not when 'termsize' is "rowsXcols".
|
||||
|
||||
==============================================================================
|
||||
2. Remote testing *terminal-testing*
|
||||
|
||||
Most Vim tests execute a script inside Vim. For some tests this does not
|
||||
work, running the test interferes with the code being tested. To avoid this
|
||||
Vim is executed in a terminal window. The test sends keystrokes to it and
|
||||
inspects the resulting screen state.
|
||||
|
||||
Functions ~
|
||||
|
||||
term_sendkeys() send keystrokes to a terminal
|
||||
term_wait() wait for screen to be updated
|
||||
term_scrape() inspect terminal screen
|
||||
|
||||
|
||||
==============================================================================
|
||||
3. Debugging *terminal-debug*
|
||||
|
||||
The Terminal debugging plugin can be used to debug a program with gdb and view
|
||||
the source code in a Vim window. For example: >
|
||||
|
||||
:TermDebug vim
|
||||
|
||||
This opens three windows:
|
||||
- A terminal window in which "gdb vim" is executed. Here you can directly
|
||||
interact with gdb.
|
||||
- A terminal window for the executed program. When "run" is used in gdb the
|
||||
program I/O will happen in this window, so that it does not interfere with
|
||||
controlling gdb.
|
||||
- A normal Vim window used to show the source code. When gdb jumps to a
|
||||
source file location this window will display the code, if possible. Values
|
||||
of variables can be inspected, breakpoints set and cleared, etc.
|
||||
|
||||
This uses two terminal windows. To open the gdb window: >
|
||||
:term gdb [arguments]
|
||||
To open the terminal to run the tested program |term_open()| is used.
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
@@ -1,4 +1,4 @@
|
||||
*todo.txt* For Vim version 8.0. Last change: 2017 Jun 13
|
||||
*todo.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@@ -35,9 +35,39 @@ entered there will not be repeated below, unless there is extra information.
|
||||
*known-bugs*
|
||||
-------------------- Known bugs and current work -----------------------
|
||||
|
||||
+channel:
|
||||
- When redrawing for the channel buffer, command line completion is cleared.
|
||||
When redrawing for the channel buffer, command line completion is cleared.
|
||||
(Ramel Eshed, 2017 May 4)
|
||||
When a timer triggers the command completion disappears. (Dominique Pelle,
|
||||
2017 Jun 13, #1768)
|
||||
Caused by 8.0.0592.
|
||||
Check if anything was output? Don't redraw when scrolled. (#1820)
|
||||
When redrawing the command line a pending CTRL-R shows ", which is removed.
|
||||
|
||||
No maintainer for German translations.
|
||||
No maintainer for Vietnamese translations.
|
||||
No maintainer for Simplified Chinese translations.
|
||||
|
||||
|
||||
Terminal emulator window:
|
||||
- Lots of stuff to implement, see src/terminal.c
|
||||
- Windows implementation (WiP): https://github.com/mattn/vim/tree/terminal
|
||||
Using winpty ?
|
||||
- Running a shell command from the GUI still has limitations. Look into how
|
||||
the terminal emulator of the Vim shell project can help:
|
||||
http://vimshell.wana.at
|
||||
- Add debugger interface. Implementation for gdb by Xavier de Gaye.
|
||||
Should work like an IDE. Try to keep it generic. Now found here:
|
||||
http://clewn.sf.net.
|
||||
- Look into the idevim plugin/script.
|
||||
- Related wishes for NetBeans commands:
|
||||
- make it possible to have 'defineAnnoType' also handle terminal colors.
|
||||
- send 'balloonText' events for the cursor position (using CursorHold ?)
|
||||
in terminal mode.
|
||||
- Feature: switch between "running job" and a normal buffer (possibly
|
||||
read-only) to allow for searching, copy/paste, etc. (Domnique). Having a
|
||||
(large) scrollback would be useful.
|
||||
|
||||
+channel:
|
||||
- Try out background make plugin:
|
||||
https://github.com/AndrewVos/vim-make-background
|
||||
- Problem with stderr on Windows? (Vincent Rischmann, 2016 Aug 31, #1026)
|
||||
@@ -101,14 +131,14 @@ Regexp problems:
|
||||
col and vcol when moving to another line.
|
||||
- this doesn't work: "syntax match ErrorMsg /.\%9l\%>20c\&\%<28c/". Leaving
|
||||
out the \& works. Seems any column check after \& fails.
|
||||
- The pattern "\1" with the old engine gives E65, with the new engine it
|
||||
matches the empty string. (Dominique Pelle, 2015 Oct 2, Nov 24)
|
||||
had_endbrace[] is set but not initialized or used.
|
||||
- Difference between two engines: ".*\zs\/\@>\/" on text "///"
|
||||
(Chris Paul, 2016 Nov 13) New engine not greedy enough?
|
||||
Another one: echom matchstr(" sdfsfsf\n sfdsdfsdf",'[^\n]*')
|
||||
(2017 May 15, #1252)
|
||||
|
||||
Patch to update b:changedtick in the quickfix window. (Yegappan Lakshmanan,
|
||||
2017 Jul 13)
|
||||
|
||||
With foldmethod=syntax and nofoldenable comment highlighting isn't removed.
|
||||
(Marcin Szewczyk, 2017 Apr 26)
|
||||
|
||||
@@ -119,13 +149,38 @@ ml_get errors with buggy script. (Dominique, 2017 Apr 30)
|
||||
|
||||
Error in emsg with buggy script. (Dominique, 2017 Apr 30)
|
||||
|
||||
Better detection of strace file. (Steven Fernandez, 2017 Jul 12, #1837)
|
||||
|
||||
To reproduce problems "vim -u NONE -N" is often used, but this still uses
|
||||
'viminfo'. Add "-I" to not use 'viminfo'?
|
||||
Or use "vim -B" for "bug reproduction"?
|
||||
|
||||
Bug with conceal mode: 3rd element returned by synconcealed() differs for
|
||||
every call. (Dominique Pelle, 2017 Jun 18)
|
||||
|
||||
Add options_default() / options_restore() to set several options to Vim
|
||||
defaults for a plugin. Comments from Zyx, 2017 May 10.
|
||||
Perhaps use a vimcontext / endvimcontext command block.
|
||||
|
||||
Using freed memory with "qf" FileType autocommand that does :cclose.
|
||||
(Lemonboy, 2017 May 28, #1730, fix in 1734, with test that doesn't fail, but
|
||||
it fails when run manually) Add "starting" to test_override()?
|
||||
Patch to trigger OptionSet when entering diff mode. (Christian Brabandt, 2017
|
||||
Jul 7)
|
||||
|
||||
Illegal memory access, requires ASAN to see. (Dominique Pelle, 2015 Jul 28)
|
||||
Still happens (2017 Jul 9)
|
||||
|
||||
Memory leak in test_arabic.
|
||||
|
||||
Refactored HTML indent file. (Michael Lee, #1821)
|
||||
|
||||
Using uninitialzed value in test_crypt.
|
||||
|
||||
X11: Putting more than about 262040 characters of text on the clipboard and
|
||||
pasting it in another Vim doesn't work. (Dominique Pelle, 2008 Aug 21-23)
|
||||
clip_x11_request_selection_cb() is called with zero value and length.
|
||||
Also: Get an error message from free() in the process that owns the selection.
|
||||
Seems to happen when the selection is requested the second time, but before
|
||||
clip_x11_convert_selection_cb() is invoked, thus in X library code.
|
||||
Patch to fix this by Kiichi, 2017 Jul 11, #1822)
|
||||
|
||||
Problem with three-piece comment. (Michael Lee, 2017 May 11, #1696)
|
||||
|
||||
@@ -134,15 +189,24 @@ case of :bwipe followed by :new.
|
||||
|
||||
Files for Latvian language. (Vitolins, 2017 May 3, #1675)
|
||||
|
||||
MS-Windows: Opening same file in a second gvim hangs. (Sven Bruggemann, 2017
|
||||
Jul 4)
|
||||
|
||||
Setting 'clipboard' to "unnamed" makes a global command very slow (Daniel
|
||||
Drucker, 2017 May 8).
|
||||
This was supposed to be fixed, did it break again somehow?
|
||||
Christian cannot reproduce it.
|
||||
|
||||
Using composing char in mapping does not work properly. maparg() shows the
|
||||
wrong thing. (Nikolai Pavlov, 2017 Jul 8, #1827)
|
||||
Or is this not an actual problem?
|
||||
|
||||
Better TeX indent file. (Christian Brabandt, 2017 May 3)
|
||||
|
||||
Openhab syntax file (mueller, #1678)
|
||||
|
||||
Patch to use a separate code for BS on Windows. (Linwei, #1823)
|
||||
|
||||
Use gvimext.dll from the nightly build? (Issue #249)
|
||||
|
||||
'synmaxcol' works with bytes instead of screen cells. (Llandon, 2017 May 31,
|
||||
@@ -151,18 +215,17 @@ Use gvimext.dll from the nightly build? (Issue #249)
|
||||
Problem with using :cd when remotely editing a file. (Gerd Wachsmuth, 2017 May
|
||||
8, #1690)
|
||||
|
||||
'equalalways' only works for one column. (Glacambre, 2017 May 15, #1707)
|
||||
|
||||
Include solarized color scheme?
|
||||
|
||||
Updates to GTK help. (Kazunobu Kuriyama, 2017 May 4)
|
||||
|
||||
Running test_gui and test_gui_init with Motif sometimes kills the window
|
||||
manager. Problem with Motif?
|
||||
|
||||
Bogus characters inserted when triggering indent while changing text.
|
||||
(Vitor Antunes, 2016 Nov 22, #1269)
|
||||
|
||||
Using "wviminfo /tmp/viminfo" does not store file marks that Vim knows about,
|
||||
it only works when merging with an existing file. (Shougo, 2017 Jun 19, #1781)
|
||||
|
||||
Segmentation fault with complete(). (Lifepillar, 2017 Apr 29, #1668)
|
||||
Check for "pat" to be NULL in search_for_exact_line()?
|
||||
How did it get NULL? Comment by Christian, Apr 30.
|
||||
@@ -172,6 +235,9 @@ Is it possible to keep the complete menu open when calling complete()?
|
||||
|
||||
Memory leak in test97? The string is actually freed. Weird.
|
||||
|
||||
assert_fails() can only check for the first error. Make it possible to have
|
||||
it catch multiple errors and check all of them.
|
||||
|
||||
New value "uselast" for 'switchbuf'. (Lemonboy, 2017 Apr 23, #1652)
|
||||
|
||||
Add a toolbar in the terminal. Can be global, above all windows, or specific
|
||||
@@ -187,6 +253,11 @@ Perhaps simpler: actually delete the mappings. Use maplist() to list matching
|
||||
mappings (with a lhs prefix, like maparg()), mapdelete() to delete,
|
||||
maprestore() to restore (using the output of maplist().
|
||||
|
||||
Patch to add setbufline(). (email from Yasuhiro Matsumoto, patch by Ozaki
|
||||
Kiichi, 2016 Feb 28)
|
||||
Update Mar 8: https://gist.github.com/mattn/23c1f50999084992ca98
|
||||
Update Mar 13: https://gist.github.com/mattn/23c1f50999084992ca98
|
||||
|
||||
Add an argument to :mkvimrc (or add aother command) to skip mappings from
|
||||
plugins (source is a Vim script). No need to put these in a .vimrc, they will
|
||||
be defined when the plugin is loaded.
|
||||
@@ -200,6 +271,9 @@ What if there is an invalid character?
|
||||
|
||||
Json string with trailing \u should be an error. (Lcd)
|
||||
|
||||
import can't be used in define option when include matches too.
|
||||
(Romain Lafourcade, 2017 Jun 18, #1519)
|
||||
|
||||
When session file has name in argument list but the buffer was deleted, the
|
||||
buffer is not deleted when using the session file. (#1393)
|
||||
Should add the buffer in hidden state.
|
||||
@@ -211,10 +285,6 @@ Wrong diff highlighting with three files. (2016 Oct 20, #1186)
|
||||
Also get E749 on exit.
|
||||
Another example in #1309
|
||||
|
||||
Patch to change all use of &sw to shiftwidth(). (Tyru, 2017 Feb 19)
|
||||
Takuya Fujiwara
|
||||
Wait until maintainers integrate it.
|
||||
|
||||
When deleting a mark or register, leave a tombstone, so that it's also deleted
|
||||
when writing viminfo (and the delete was the most recent action). #1339
|
||||
|
||||
@@ -244,6 +314,12 @@ highlighting for both stl and stlnc. Patch by Ken Hamada (itchyny, 2016 Dec 11)
|
||||
Using CTRL-G_U in InsertCharPre causes trouble for redo. (Israel Chauca
|
||||
Fuentes, 2017 Feb 12, #1470)
|
||||
|
||||
Add a "keytrans()" function, which turns the internal byte representation of a
|
||||
key into a form that can be used for :map. E.g.
|
||||
let xx = "\<C-Home>"
|
||||
echo keytrans(xx)
|
||||
<C-Home>
|
||||
|
||||
Check for errors E704 and E705 only does VAR_FUNC, should also do VAR_PARTIAL.
|
||||
(Nikolai Pavlov, 2017 Mar 13, #1557)
|
||||
Make a function to check for function-like type?
|
||||
@@ -257,9 +333,6 @@ Implement optional arguments for functions.
|
||||
call Foo(12, all = 0)
|
||||
call Foo(12, 15, 0)
|
||||
|
||||
writefile() does not abort as soon as an error is found. (Nikolai Pavlov,
|
||||
2017 Feb 14, #1476)
|
||||
|
||||
Patch to support on-the-spot and over-the-spot input method. (Ken Takata, 2017
|
||||
Feb 14).
|
||||
|
||||
@@ -273,6 +346,10 @@ somewhere else. :{range}copy {dest} !cmd
|
||||
Patch to fix that empty first tab is not in session.
|
||||
(Hirohito Higashi, 2016 Nov 25, #1282)
|
||||
|
||||
Patch to add random number generator. (Hong Xu, 2010 Nov 8, update Nov 10)
|
||||
Alternative from Christian Brabandt. (2010 Sep 19)
|
||||
New one from Yasuhiro Matsumoto, #1277.
|
||||
|
||||
Patch for restoring wide characters in the console buffer.
|
||||
(Ken Takata, 2016 Jun 7)
|
||||
|
||||
@@ -286,9 +363,6 @@ The TermResponse event is not triggered when a plugin has set 'eventignore' to
|
||||
"all". Netrw does this. (Gary Johnson, 2017 Jan 24)
|
||||
Postpone the event until 'eventignore' is reset.
|
||||
|
||||
Patch to make urxvt mouse work better, recognize Esc[*M termcap code.
|
||||
(Maurice Bos, 2017 Feb 17, #1486)
|
||||
|
||||
Expanding /**/ is slow. Idea by Luc Hermitte, 2017 Apr 14.
|
||||
|
||||
Once .exe with updated installer is available: Add remark to download page
|
||||
@@ -324,11 +398,24 @@ Does this also fix #1408 ?
|
||||
|
||||
Patch to add "module" to quickfix entries. (Coot, 2017 Jun 8, #1757)
|
||||
|
||||
'cursorline' and match interfere. (Ozaki Kiichi, 2017 Jun 23, #1792)
|
||||
|
||||
Patch for 'cursorlinenr' option. (Ozaki Kiichi, 2016 Nov 30)
|
||||
|
||||
Patch to be able to separately map CTRL-H and BS on Windows.
|
||||
(Linwei, 2017 Jul 11, #1833)
|
||||
|
||||
When 'completeopt' has "noselect" does not insert a newline. (Lifepillar, 2017
|
||||
Apr 23, #1653)
|
||||
|
||||
Using an external diff is inefficient. Not all systems have a good diff
|
||||
program available (esp. MS-Windows). Would be nice to have in internal diff
|
||||
implementation. Can then also use this for displaying changes within a line.
|
||||
Olaf Dabrunz is working on this. (10 Jan 2016)
|
||||
9 Instead invoking an external diff program, use builtin code. One can be
|
||||
found here: http://www.ioplex.com/~miallen/libmba/dl/src/diff.c
|
||||
It's complicated and badly documented.
|
||||
|
||||
Window resizing with 'winfixheight': With a vertical split the height changes
|
||||
anyway. (Tommy allen, 2017 Feb 21, #1502)
|
||||
|
||||
@@ -385,9 +472,6 @@ Include the test.
|
||||
Patch to add tagfunc(). Cleaned up by Christian Brabandt, 2013 Jun 22.
|
||||
New update 2017 Apr 10, #1628
|
||||
|
||||
Unnamed register only contains the last deleted text when appending deleted
|
||||
text to a register. (Wolfgang Jeltsch, reproduced by Ben Fritz, 2017 Apr 10)
|
||||
|
||||
When 'keywordprg' starts with ":" the argument is still escaped as a shell
|
||||
command argument. (Romain Lafourcade, 2016 Oct 16, #1175)
|
||||
|
||||
@@ -405,6 +489,8 @@ execute() cannot be used with command completeion. (Daniel Hahler, 2016 Oct 1,
|
||||
|
||||
cmap using execute() has side effects. (Killthemule, 2016 Aug 17, #983)
|
||||
|
||||
:map X may print invalid data. (Nikolay Pavlov, 2017 Jul 3, #1816)
|
||||
|
||||
Patch to order results from taglist(). (Duncan McDougall, 2016 Oct 25)
|
||||
|
||||
patch for 'spellcamelcase' option: spellcheck each CamelCased word.
|
||||
@@ -502,9 +588,6 @@ Because of using the initial buffer? (Dun Peal, 2016 May 12)
|
||||
Patch to add the :bvimgrep command. (Christian Brabandt, 2014 Nov 12)
|
||||
Updated 2016 Jun 10, #858 Update 2017 Mar 28: use <buffer>
|
||||
|
||||
Patch to fix that an encoding conversion failure results in a corrupted or
|
||||
empty file. (Christian Brabandt, #1765, https://github.com/chrisbra/vim-mq-patches/blob/master/conversion_error)
|
||||
|
||||
Add redrawtabline command. (Naruhiko Nishino, 2016 Jun 11)
|
||||
|
||||
Neovim patch for utfc_ptr2char_len() https://github.com/neovim/neovim/pull/4574
|
||||
@@ -522,11 +605,6 @@ Possibly include the needed code so that it can be build everywhere.
|
||||
Add a way to restart a timer. It's similar to timer_stop() and timer_start(),
|
||||
but the reference remains valid.
|
||||
|
||||
Patch to add setbufline(). (email from Yasuhiro Matsumoto, patch by Ozaki
|
||||
Kiichi, 2016 Feb 28)
|
||||
Update Mar 8: https://gist.github.com/mattn/23c1f50999084992ca98
|
||||
Update Mar 13: https://gist.github.com/mattn/23c1f50999084992ca98
|
||||
|
||||
Need to try out instructions in INSSTALLpc.txt about how to install all
|
||||
interfaces and how to build Vim with them.
|
||||
Appveyor build with self-installing executable, includes getting most
|
||||
@@ -639,8 +717,6 @@ Patch to add TagNotFound autocommand. (Anton Lindqvist, 2016 Feb 3)
|
||||
Patch to add Error autocommand. (Anton Lindqvist, 2016 Feb 17)
|
||||
Only remembers one error.
|
||||
|
||||
Illegal memory access, requires ASAN to see. (Dominique Pelle, 2015 Jul 28)
|
||||
|
||||
Gvim: when both Tab and CTRL-I are mapped, use CTRL-I not for Tab.
|
||||
|
||||
Unexpected delay when using CTRL-O u. It's not timeoutlen.
|
||||
@@ -708,11 +784,6 @@ Patch to use two highlight groups for relative numbers. (Shaun Brady, 2016 Jan
|
||||
MS-Windows: Crash opening very long file name starting with "\\".
|
||||
(Christian Brock, 2012 Jun 29)
|
||||
|
||||
Using an external diff is inefficient. Not all systems have a good diff
|
||||
program available (esp. MS-Windows). Would be nice to have in internal diff
|
||||
implementation. Can then also use this for displaying changes within a line.
|
||||
Olaf Dabrunz is working on this.
|
||||
|
||||
The OptionSet autocommand event is not always triggered. (Rick Howe, 2015 Sep
|
||||
24): :diffthis, :diffoff.
|
||||
|
||||
@@ -1408,9 +1479,6 @@ New esperanto spell file can't be processed. (Dominique Pelle, 2011 Jan 30)
|
||||
Editing a file with a ^M with 'ff' set to "mac", opening a help file, then the
|
||||
^M is displayed as ^J sometimes. Getting 'ff' value from wrong window/buffer?
|
||||
|
||||
'colorcolumn' has higher priority than hlsearch. Should probably be the other
|
||||
way around. (Nazri Ramliy, 2013 Feb 19)
|
||||
|
||||
When Vim is put in the background (SIGTSTP) and then gets a SIGHUP it doesn't
|
||||
exit. It exists as soon as back in the foreground. (Stephen Liang, 2011 Jan
|
||||
9) Caused by vim_handle_signal(SIGNAL_BLOCK); in ui.c.
|
||||
@@ -1459,14 +1527,13 @@ setpos() does not restore cursor position after :normal. (Tyru, 2010 Aug 11)
|
||||
7 The 'directory' option supports changing path separators to "%" to make
|
||||
file names unique, also support this for 'backupdir'. (Mikolaj Machowski)
|
||||
Patch by Christian Brabandt, 2010 Oct 21.
|
||||
Is this an update: related to: #179
|
||||
https://github.com/chrisbra/vim-mq-patches/blob/master/backupdir
|
||||
Fixed patch 2017 Jul 1.
|
||||
|
||||
With "tw=55 fo+=a" typing space before ) doesn't work well. (Scott Mcdermott,
|
||||
2010 Oct 24)
|
||||
|
||||
Patch to add random number generator. (Hong Xu, 2010 Nov 8, update Nov 10)
|
||||
Alternative from Christian Brabandt. (2010 Sep 19)
|
||||
New one from Yasuhiro Matsumoto, #1277.
|
||||
|
||||
Messages in message.txt are highlighted as examples.
|
||||
|
||||
When using cp850 the NBSP (0xff) is not drawn correctly. (Brett Stahlman, 2010
|
||||
@@ -2406,13 +2473,6 @@ respond to selection requests. Invoking XtDisownSelection() before executing
|
||||
the shell doesn't help. Would require forking and doing a message loop, like
|
||||
what happens for the GUI.
|
||||
|
||||
X11: Putting more than about 262040 characters of text on the clipboard and
|
||||
pasting it in another Vim doesn't work. (Dominique Pelle, 2008 Aug 21-23)
|
||||
clip_x11_request_selection_cb() is called with zero value and length.
|
||||
Also: Get an error message from free() in the process that owns the selection.
|
||||
Seems to happen when the selection is requested the second time, but before
|
||||
clip_x11_convert_selection_cb() is invoked, thus in X library code.
|
||||
|
||||
":vimgrep" does not recognize a recursive symlink. Is it possible to detect
|
||||
this, at least for Unix (using device/inode)?
|
||||
|
||||
@@ -3275,18 +3335,6 @@ Most interesting new features to be added when all bugs have been fixed:
|
||||
Alternative: Make a function for Ex commands: cmd_edit().
|
||||
- Add COLUMN NUMBERS to ":" commands ":line1,line2[col1,col2]cmd". Block
|
||||
can be selected with CTRL-V. Allow '$' (end of line) for col2.
|
||||
- Add DEBUGGER INTERFACE. Implementation for gdb by Xavier de Gaye.
|
||||
Should work like an IDE. Try to keep it generic. Now found here:
|
||||
http://clewn.sf.net.
|
||||
And the idevim plugin/script.
|
||||
To be able to start the debugger from inside Vim: For GUI run a program
|
||||
with a netbeans connection; for console: start a program that splits the
|
||||
terminal, runs the debugger in one window and reconnect Vim I/O to the
|
||||
other window.
|
||||
Wishes for NetBeans commands:
|
||||
- make it possible to have 'defineAnnoType' also handle terminal colors.
|
||||
- send 'balloonText' events for the cursor position (using CursorHold ?)
|
||||
in terminal mode.
|
||||
- ECLIPSE plugin. Problem is: the interface is very complicated. Need to
|
||||
implement part in Java and then connect to Vim. Some hints from Alexandru
|
||||
Roman, 2004 Dec 15. Should then also work with Oracle Jdeveloper, see JSR
|
||||
@@ -3299,9 +3347,6 @@ Most interesting new features to be added when all bugs have been fixed:
|
||||
scrolls back to where the cursor is.
|
||||
- Scroll commands by screen line. g CTRL-E and g CTRL-Y ? Requires the
|
||||
first line to be able to start halfway.
|
||||
- Running a shell command from the GUI still has limitations. Look into how
|
||||
the terminal emulator of the Vim shell project can help:
|
||||
http://vimshell.wana.at
|
||||
8 Add a command to jump to a certain kind of tag. Allow the user to specify
|
||||
values for the optional fields. E.g., ":tag size type=m".
|
||||
Also allow specifying the file and command, so that the result of
|
||||
@@ -3490,9 +3535,6 @@ Spell checking:
|
||||
Diff mode:
|
||||
9 When making small changes, e.g. deleting a character, update the diff.
|
||||
Possibly without running diff.
|
||||
9 Instead invoking an external diff program, use builtin code. One can be
|
||||
found here: http://www.ioplex.com/~miallen/libmba/dl/src/diff.c
|
||||
It's quite big and badly documented though.
|
||||
8 Also show difference with the file when editing started? Should show what
|
||||
can be undone. (Tom Popovich)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
*usr_01.txt* For Vim version 8.0. Last change: 2010 Nov 03
|
||||
*usr_01.txt* For Vim version 8.0. Last change: 2017 Jul 15
|
||||
|
||||
VIM USER MANUAL - by Bram Moolenaar
|
||||
|
||||
@@ -140,19 +140,19 @@ On other systems, you have to do a little work:
|
||||
|
||||
1. Copy the tutor file. You can do this with Vim (it knows where to find it):
|
||||
>
|
||||
vim -u NONE -c 'e $VIMRUNTIME/tutor/tutor' -c 'w! TUTORCOPY' -c 'q'
|
||||
vim --clean -c 'e $VIMRUNTIME/tutor/tutor' -c 'w! TUTORCOPY' -c 'q'
|
||||
<
|
||||
This will write the file "TUTORCOPY" in the current directory. To use a
|
||||
translated version of the tutor, append the two-letter language code to the
|
||||
filename. For French:
|
||||
>
|
||||
vim -u NONE -c 'e $VIMRUNTIME/tutor/tutor.fr' -c 'w! TUTORCOPY' -c 'q'
|
||||
vim --clean -c 'e $VIMRUNTIME/tutor/tutor.fr' -c 'w! TUTORCOPY' -c 'q'
|
||||
<
|
||||
2. Edit the copied file with Vim:
|
||||
>
|
||||
vim -u NONE -c "set nocp" TUTORCOPY
|
||||
vim --clean TUTORCOPY
|
||||
<
|
||||
The extra arguments make sure Vim is started in a good mood.
|
||||
The --clean argument makes sure Vim is started with nice defaults.
|
||||
|
||||
3. Delete the copied file when you are finished with it:
|
||||
>
|
||||
|
||||
@@ -16827,7 +16827,7 @@ Patch 8.0.0388
|
||||
Problem: filtering lines through "cat", without changing the line count,
|
||||
changes manual folds.
|
||||
Solution: Change how marks and folds are adjusted. (Matthew Malcomson, from
|
||||
neovim #6194.
|
||||
neovim #6194).
|
||||
Files: src/fold.c, src/testdir/test_fold.vim
|
||||
|
||||
Patch 8.0.0389
|
||||
@@ -17499,7 +17499,7 @@ Files: src/evalfunc.c, src/if_xcmdsrv.c, src/proto/if_xcmdsrv.pro,
|
||||
|
||||
Patch 8.0.0493
|
||||
Problem: Crash with cd command with very long argument.
|
||||
Solution: Check for running out of space. (Dominique pending, closes #1576)
|
||||
Solution: Check for running out of space. (Dominique Pelle, closes #1576)
|
||||
Files: src/testdir/test_alot.vim, src/testdir/test_cd.vim, src/Makefile,
|
||||
src/misc2.c
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
" Vim support file to detect file types
|
||||
"
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2017 Jun 12
|
||||
" Last Change: 2017 Jul 11
|
||||
|
||||
" Listen very carefully, I will say this only once
|
||||
if exists("did_load_filetypes")
|
||||
@@ -48,6 +48,9 @@ func! s:StarSetf(ft)
|
||||
endif
|
||||
endfunc
|
||||
|
||||
" Vim help file
|
||||
au BufNewFile,BufRead $VIMRUNTIME/doc/*.txt setf help
|
||||
|
||||
" Abaqus or Trasys
|
||||
au BufNewFile,BufRead *.inp call s:Check_inp()
|
||||
|
||||
@@ -632,7 +635,13 @@ au BufNewFile,BufRead dict.conf,.dictrc setf dictconf
|
||||
au BufNewFile,BufRead dictd.conf setf dictdconf
|
||||
|
||||
" Diff files
|
||||
au BufNewFile,BufRead *.diff,*.rej,*.patch setf diff
|
||||
au BufNewFile,BufRead *.diff,*.rej setf diff
|
||||
au BufNewFile,BufRead *.patch
|
||||
\ if getline(1) =~ '^From [0-9a-f]\{40\} Mon Sep 17 00:00:00 2001$' |
|
||||
\ setf gitsendemail |
|
||||
\ else |
|
||||
\ setf diff |
|
||||
\ endif
|
||||
|
||||
" Dircolors
|
||||
au BufNewFile,BufRead .dir_colors,.dircolors,*/etc/DIR_COLORS setf dircolors
|
||||
@@ -801,6 +810,7 @@ if !empty($XDG_CONFIG_HOME)
|
||||
au BufNewFile,BufRead $XDG_CONFIG_HOME/git/config setf gitconfig
|
||||
endif
|
||||
au BufNewFile,BufRead git-rebase-todo setf gitrebase
|
||||
au BufRead,BufNewFile .gitsendemail.msg.?????? setf gitsendemail
|
||||
au BufNewFile,BufRead .msg.[0-9]*
|
||||
\ if getline(1) =~ '^From.*# This line is ignored.$' |
|
||||
\ setf gitsendemail |
|
||||
@@ -2786,7 +2796,13 @@ au BufNewFile,BufRead zsh*,zlog* call s:StarSetf('zsh')
|
||||
|
||||
" Plain text files, needs to be far down to not override others. This avoids
|
||||
" the "conf" type being used if there is a line starting with '#'.
|
||||
au BufNewFile,BufRead *.txt,*.text,README setf text
|
||||
au BufNewFile,BufRead *.text,README setf text
|
||||
|
||||
" Help files match *.txt but should have a last line that is a modeline.
|
||||
au BufNewFile,BufRead *.txt
|
||||
\ if getline('$') !~ 'vim:.*ft=help'
|
||||
\| setf text
|
||||
\| endif
|
||||
|
||||
|
||||
" Use the filetype detect plugins. They may overrule any of the previously
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
" These commands create the option window.
|
||||
"
|
||||
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
||||
" Last Change: 2017 Mar 06
|
||||
" Last Change: 2017 Jul 15
|
||||
|
||||
" If there already is an option window, jump to that one.
|
||||
if bufwinnr("option-window") > 0
|
||||
@@ -506,6 +506,14 @@ if has("cursorbind")
|
||||
call append("$", "\t(local to window)")
|
||||
call <SID>BinOptionL("crb")
|
||||
endif
|
||||
if has("terminal")
|
||||
call append("$", "termsize\tsize of a terminal window")
|
||||
call append("$", "\t(local to window)")
|
||||
call <SID>OptionL("tms")
|
||||
call append("$", "termkey\tkey that precedes Vim commands in a terminal window")
|
||||
call append("$", "\t(local to window)")
|
||||
call <SID>OptionL("tk")
|
||||
endif
|
||||
|
||||
|
||||
call <SID>Header("multiple tab pages")
|
||||
|
||||
127
runtime/syntax/murphi.vim
Normal file
127
runtime/syntax/murphi.vim
Normal file
@@ -0,0 +1,127 @@
|
||||
" Vim syntax file
|
||||
" Language: Murphi model checking language
|
||||
" Maintainer: Matthew Fernandez <matthew.fernandez@gmail.com>
|
||||
" Last Change: 2017 May 3
|
||||
" Version: 2
|
||||
" Remark: Originally authored by Diego Ongaro <ongaro@cs.stanford.edu>
|
||||
|
||||
if version < 600
|
||||
syntax clear
|
||||
elseif exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
" Keywords are case insensitive.
|
||||
" Keep these in alphabetical order.
|
||||
syntax case ignore
|
||||
syn keyword murphiKeyword alias
|
||||
syn keyword murphiStructure array
|
||||
syn keyword murphiKeyword assert
|
||||
syn keyword murphiKeyword begin
|
||||
syn keyword murphiType boolean
|
||||
syn keyword murphiKeyword by
|
||||
syn keyword murphiLabel case
|
||||
syn keyword murphiKeyword clear
|
||||
syn keyword murphiLabel const
|
||||
syn keyword murphiRepeat do
|
||||
syn keyword murphiConditional else
|
||||
syn keyword murphiConditional elsif
|
||||
syn keyword murphiKeyword end
|
||||
syn keyword murphiKeyword endalias
|
||||
syn keyword murphiRepeat endexists
|
||||
syn keyword murphiRepeat endfor
|
||||
syn keyword murphiRepeat endforall
|
||||
syn keyword murphiKeyword endfunction
|
||||
syn keyword murphiConditional endif
|
||||
syn keyword murphiKeyword endprocedure
|
||||
syn keyword murphiStructure endrecord
|
||||
syn keyword murphiKeyword endrule
|
||||
syn keyword murphiKeyword endruleset
|
||||
syn keyword murphiKeyword endstartstate
|
||||
syn keyword murphiConditional endswitch
|
||||
syn keyword murphiRepeat endwhile
|
||||
syn keyword murphiStructure enum
|
||||
syn keyword murphiKeyword error
|
||||
syn keyword murphiRepeat exists
|
||||
syn keyword murphiBoolean false
|
||||
syn keyword murphiRepeat for
|
||||
syn keyword murphiRepeat forall
|
||||
syn keyword murphiKeyword function
|
||||
syn keyword murphiConditional if
|
||||
syn keyword murphiKeyword in
|
||||
syn keyword murphiKeyword interleaved
|
||||
syn keyword murphiLabel invariant
|
||||
syn keyword murphiFunction ismember
|
||||
syn keyword murphiFunction isundefined
|
||||
syn keyword murphiKeyword log
|
||||
syn keyword murphiStructure of
|
||||
syn keyword murphiType multiset
|
||||
syn keyword murphiFunction multisetadd
|
||||
syn keyword murphiFunction multisetcount
|
||||
syn keyword murphiFunction multisetremove
|
||||
syn keyword murphiFunction multisetremovepred
|
||||
syn keyword murphiKeyword procedure
|
||||
syn keyword murphiKeyword process
|
||||
syn keyword murphiKeyword program
|
||||
syn keyword murphiKeyword put
|
||||
syn keyword murphiStructure record
|
||||
syn keyword murphiKeyword return
|
||||
syn keyword murphiLabel rule
|
||||
syn keyword murphiLabel ruleset
|
||||
syn keyword murphiType scalarset
|
||||
syn keyword murphiLabel startstate
|
||||
syn keyword murphiConditional switch
|
||||
syn keyword murphiConditional then
|
||||
syn keyword murphiRepeat to
|
||||
syn keyword murphiKeyword traceuntil
|
||||
syn keyword murphiBoolean true
|
||||
syn keyword murphiLabel type
|
||||
syn keyword murphiKeyword undefine
|
||||
syn keyword murphiStructure union
|
||||
syn keyword murphiLabel var
|
||||
syn keyword murphiRepeat while
|
||||
|
||||
syn keyword murphiTodo contained todo xxx fixme
|
||||
syntax case match
|
||||
|
||||
" Integers.
|
||||
syn match murphiNumber "\<\d\+\>"
|
||||
|
||||
" Operators and special characters.
|
||||
syn match murphiOperator "[\+\-\*\/%&|=!<>:\?]\|\."
|
||||
syn match murphiDelimiter "\(:[^=]\|[;,]\)"
|
||||
syn match murphiSpecial "[()\[\]]"
|
||||
|
||||
" Double equal sign is a common error: use one equal sign for equality testing.
|
||||
syn match murphiError "==[^>]"he=e-1
|
||||
" Double && and || are errors.
|
||||
syn match murphiError "&&\|||"
|
||||
|
||||
" Strings. This is defined so late so that it overrides previous matches.
|
||||
syn region murphiString start=+"+ end=+"+
|
||||
|
||||
" Comments. This is defined so late so that it overrides previous matches.
|
||||
syn region murphiComment start="--" end="$" contains=murphiTodo
|
||||
syn region murphiComment start="/\*" end="\*/" contains=murphiTodo
|
||||
|
||||
" Link the rules to some groups.
|
||||
highlight link murphiComment Comment
|
||||
highlight link murphiString String
|
||||
highlight link murphiNumber Number
|
||||
highlight link murphiBoolean Boolean
|
||||
highlight link murphiIdentifier Identifier
|
||||
highlight link murphiFunction Function
|
||||
highlight link murphiStatement Statement
|
||||
highlight link murphiConditional Conditional
|
||||
highlight link murphiRepeat Repeat
|
||||
highlight link murphiLabel Label
|
||||
highlight link murphiOperator Operator
|
||||
highlight link murphiKeyword Keyword
|
||||
highlight link murphiType Type
|
||||
highlight link murphiStructure Structure
|
||||
highlight link murphiSpecial Special
|
||||
highlight link murphiDelimiter Delimiter
|
||||
highlight link murphiError Error
|
||||
highlight link murphiTodo Todo
|
||||
|
||||
let b:current_syntax = "murphi"
|
||||
@@ -1,15 +1,15 @@
|
||||
" Vim syntax file
|
||||
" Language: php PHP 3/4/5/7
|
||||
" Maintainer: Jason Woofenden <jason@jasonwoof.com>
|
||||
" Last Change: Jun 09, 2017
|
||||
" Last Change: Jul 14, 2017
|
||||
" URL: https://jasonwoof.com/gitweb/?p=vim-syntax.git;a=blob;f=php.vim;hb=HEAD
|
||||
" Former Maintainers: Peter Hodge <toomuchphp-vim@yahoo.com>
|
||||
" Debian VIM Maintainers <pkg-vim-maintainers@lists.alioth.debian.org>
|
||||
"
|
||||
" Note: If you are using a colour terminal with dark background, you will probably find
|
||||
" the 'elflord' colorscheme is much better for PHP's syntax than the default
|
||||
" colourscheme, because elflord's colours will better highlight the break-points
|
||||
" (Statements) in your code.
|
||||
" Note: If you are using a colour terminal with dark background, you will
|
||||
" probably find the 'elflord' colorscheme is much better for PHP's syntax
|
||||
" than the default colourscheme, because elflord's colours will better
|
||||
" highlight the break-points (Statements) in your code.
|
||||
"
|
||||
" Options:
|
||||
" Set to anything to enable:
|
||||
@@ -112,7 +112,7 @@ syn keyword phpCoreConstant E_ALL E_COMPILE_ERROR E_COMPILE_WARNING E_CORE_ERROR
|
||||
|
||||
syn case ignore
|
||||
|
||||
syn keyword phpConstant __LINE__ __FILE__ __FUNCTION__ __METHOD__ __CLASS__ __DIR__ __NAMESPACE__ contained
|
||||
syn keyword phpConstant __LINE__ __FILE__ __FUNCTION__ __METHOD__ __CLASS__ __DIR__ __NAMESPACE__ __TRAIT__ contained
|
||||
|
||||
|
||||
" Function and Methods ripped from php_manual_de.tar.gz Jan 2003
|
||||
@@ -255,13 +255,13 @@ syn keyword phpRepeat as do endfor endforeach endwhile for foreach while contai
|
||||
syn keyword phpLabel case default switch contained
|
||||
|
||||
" Statement
|
||||
syn keyword phpStatement return break continue exit goto contained
|
||||
syn keyword phpStatement return break continue exit goto yield contained
|
||||
|
||||
" Keyword
|
||||
syn keyword phpKeyword var const contained
|
||||
|
||||
" Type
|
||||
syn keyword phpType bool boolean int integer real double float string array object NULL contained
|
||||
syn keyword phpType bool boolean int integer real double float string array object NULL callable iterable contained
|
||||
|
||||
" Structure
|
||||
syn keyword phpStructure namespace extends implements instanceof parent self contained
|
||||
@@ -320,7 +320,6 @@ syn match phpMethodsVar "->\h\w*" contained contains=phpMethods,phpMemberSelecto
|
||||
" Include
|
||||
syn keyword phpInclude include require include_once require_once use contained
|
||||
|
||||
" Peter Hodge - added 'clone' keyword
|
||||
" Define
|
||||
syn keyword phpDefine new clone contained
|
||||
|
||||
@@ -441,38 +440,32 @@ if exists("php_folding") && php_folding==1
|
||||
syn keyword phpFCKeyword function contained
|
||||
syn keyword phpStorageClass global contained
|
||||
syn match phpDefine "\(\s\|^\)\(abstract\s\+\|final\s\+\|private\s\+\|protected\s\+\|public\s\+\|static\s\+\)*function\(\s\+.*[;}]\)\@=" contained contains=phpSCKeyword
|
||||
syn match phpStructure "\(\s\|^\)\(abstract\s\+\|final\s\+\)*class\(\s\+.*}\)\@=" contained
|
||||
syn match phpStructure "\(\s\|^\)\(abstract\s\+\|final\s\+\)*\(trait\|class\)\(\s\+.*}\)\@=" contained
|
||||
syn match phpStructure "\(\s\|^\)interface\(\s\+.*}\)\@=" contained
|
||||
syn match phpException "\(\s\|^\)try\(\s\+.*}\)\@=" contained
|
||||
syn match phpException "\(\s\|^\)catch\(\s\+.*}\)\@=" contained
|
||||
syn match phpException "\(\s\|^\)finally\(\s\+.*}\)\@=" contained
|
||||
|
||||
set foldmethod=syntax
|
||||
syn region phpFoldHtmlInside matchgroup=Delimiter start="?>" end="<?\(php\)\=" contained transparent contains=@htmlTop
|
||||
syn region phpFoldFunction matchgroup=Storageclass start="^\z(\s*\)\(abstract\s\+\|final\s\+\|private\s\+\|protected\s\+\|public\s\+\|static\s\+\)*function\s\([^};]*$\)\@="rs=e-9 matchgroup=Delimiter end="^\z1}" contains=@phpClFunction,phpFoldHtmlInside,phpFCKeyword contained transparent fold extend
|
||||
syn region phpFoldFunction matchgroup=Define start="^function\s\([^};]*$\)\@=" matchgroup=Delimiter end="^}" contains=@phpClFunction,phpFoldHtmlInside contained transparent fold extend
|
||||
syn region phpFoldClass matchgroup=Structure start="^\z(\s*\)\(abstract\s\+\|final\s\+\)*class\s\+\([^}]*$\)\@=" matchgroup=Delimiter end="^\z1}" contains=@phpClFunction,phpFoldFunction,phpSCKeyword contained transparent fold extend
|
||||
syn region phpFoldClass matchgroup=Structure start="^\z(\s*\)\(abstract\s\+\|final\s\+\)*\(trait\|class\)\s\+\([^}]*$\)\@=" matchgroup=Delimiter end="^\z1}" contains=@phpClFunction,phpFoldFunction,phpSCKeyword contained transparent fold extend
|
||||
syn region phpFoldInterface matchgroup=Structure start="^\z(\s*\)interface\s\+\([^}]*$\)\@=" matchgroup=Delimiter end="^\z1}" contains=@phpClFunction,phpFoldFunction contained transparent fold extend
|
||||
syn region phpFoldCatch matchgroup=Exception start="^\z(\s*\)catch\s\+\([^}]*$\)\@=" matchgroup=Delimiter end="^\z1}" contains=@phpClFunction,phpFoldFunction contained transparent fold extend
|
||||
syn region phpFoldTry matchgroup=Exception start="^\z(\s*\)try\s\+\([^}]*$\)\@=" matchgroup=Delimiter end="^\z1}" contains=@phpClFunction,phpFoldFunction contained transparent fold extend
|
||||
elseif exists("php_folding") && php_folding==2
|
||||
else
|
||||
syn keyword phpDefine function contained
|
||||
syn keyword phpStructure abstract class interface contained
|
||||
syn keyword phpException catch throw try contained
|
||||
syn keyword phpStructure abstract class trait interface contained
|
||||
syn keyword phpException catch throw try finally contained
|
||||
syn keyword phpStorageClass final global private protected public static contained
|
||||
|
||||
if exists("php_folding") && php_folding==2
|
||||
set foldmethod=syntax
|
||||
syn region phpFoldHtmlInside matchgroup=Delimiter start="?>" end="<?\(php\)\=" contained transparent contains=@htmlTop
|
||||
syn region phpParent matchgroup=Delimiter start="{" end="}" contained contains=@phpClFunction,phpFoldHtmlInside transparent fold
|
||||
else
|
||||
syn keyword phpDefine function contained
|
||||
syn keyword phpStructure abstract class interface contained
|
||||
syn keyword phpException catch throw try contained
|
||||
syn keyword phpStorageClass final global private protected public static contained
|
||||
endif
|
||||
endif
|
||||
|
||||
" TODO: fold on "trait". For now just make sure it gets colored:
|
||||
syn keyword phpStructure trait
|
||||
|
||||
" ================================================================
|
||||
" Peter Hodge - June 9, 2006
|
||||
" Some of these changes (highlighting isset/unset/echo etc) are not so
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
" SiSU Vim syntax file
|
||||
" SiSU Maintainer: Ralph Amissah <ralph.amissah@gmail.com>
|
||||
" SiSU Markup: SiSU (sisu-5.6.7)
|
||||
" Last Change: 2014-09-14
|
||||
" Last Change: 2017 Jun 22
|
||||
" URL: <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=blob;f=data/sisu/conf/editor-syntax-etc/vim/syntax/sisu.vim;hb=HEAD>
|
||||
" <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=blob_plain;f=data/sisu/conf/editor-syntax-etc/vim/syntax/sisu.vim;hb=HEAD>
|
||||
"(originally looked at Ruby Vim by Mirko Nasato)
|
||||
@@ -102,7 +102,7 @@ syn region sisu_content_alt contains=sisu_strikeout,sisu_number,sisu_bold,sisu_c
|
||||
syn region sisu_content_alt contains=sisu_strikeout,sisu_number,sisu_bold,sisu_control,sisu_identifier,sisu_error matchgroup=sisu_contain start="^```\s\+table" end="^```\(\s\|$\)"
|
||||
syn region sisu_content_alt contains=sisu_strikeout,sisu_number,sisu_bold,sisu_control,sisu_identifier,sisu_error matchgroup=sisu_contain start="^{\(t\|table\)\(\~h\)\?\(\sc[0-9]\+;\)\?[0-9; ]*}" end="\n$"
|
||||
" block, group, poem, alt
|
||||
syn region sisu_content_alt contains=sisu_mark_endnote,sisu_content_endnote,sisu_link,sisu_mark,sisu_strikeout,sisu_number,sisu_control,sisu_identifier,sisu_error matchgroup=sisu_contain start="^\(block\|group\|poem\|alt\){" end="^}\1"
|
||||
syn region sisu_content_alt contains=sisu_mark_endnote,sisu_content_endnote,sisu_link,sisu_mark,sisu_strikeout,sisu_number,sisu_control,sisu_identifier,sisu_error matchgroup=sisu_contain start="^\z(block\|group\|poem\|alt\){" end="^}\z1"
|
||||
syn region sisu_content_alt contains=sisu_mark_endnote,sisu_content_endnote,sisu_link,sisu_mark,sisu_strikeout,sisu_number,sisu_control,sisu_identifier,sisu_error matchgroup=sisu_contain start="^```\s\+\(block\|group\|poem\|alt\)" end="^```\(\s\|$\)"
|
||||
" box
|
||||
syn region sisu_content_alt contains=sisu_mark_endnote,sisu_content_endnote,sisu_link,sisu_mark,sisu_strikeout,sisu_number,sisu_control,sisu_identifier,sisu_error matchgroup=sisu_contain start="^box\(\.[a-z]\+\)\?{" end="^}box"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
" http://www.unicode.org/Public/5.1.0/ucd/UCD.html
|
||||
" For the other files see the header.
|
||||
"
|
||||
" Might need to update the URL to the emoji-data.txt
|
||||
" Usage: Vim -S <this-file>
|
||||
"
|
||||
" Author: Bram Moolenaar
|
||||
@@ -382,8 +383,9 @@ let s:ambitable = []
|
||||
call BuildWidthTable('A', 'ambiguous')
|
||||
|
||||
" Edit the emoji text file. Requires the netrw plugin.
|
||||
edit http://www.unicode.org/Public/emoji/3.0/emoji-data.txt
|
||||
edit http://unicode.org/Public/emoji/5.0/emoji-data.txt
|
||||
"edit http://www.unicode.org/Public/emoji/latest/emoji-data.txt
|
||||
|
||||
" Build the emoji table. Ver. 1.0 - 6.0
|
||||
" Must come after the "ambiguous" table
|
||||
call BuildEmojiTable('; Emoji\s\+# [1-6]\.[0-9]', 'emoji')
|
||||
call BuildEmojiTable('; Emoji\s\+#\s\+\d\+\.\d', 'emoji')
|
||||
|
||||
@@ -88,7 +88,7 @@ NOTE : :q! <Entrée> annule tous les changements que vous avez faits. Dans
|
||||
|
||||
4. Répétez les étapes 2 à 4 jusqu'à ce que la phrase soit correcte.
|
||||
|
||||
---> La vvache à sautéé au-ddessus dde la luune.
|
||||
---> La vvache a sautéé au-ddessus dde la luune.
|
||||
|
||||
5. Maintenant que la ligne est correcte, passez à la Leçon 1.4.
|
||||
|
||||
@@ -1034,5 +1034,5 @@ NOTE : Le complètement fonctionne pour de nombreuses commandes. Essayez
|
||||
Dernières mises à jour par Dominique Pellé.
|
||||
|
||||
E-mail : dominique.pelle@gmail.com
|
||||
Last Change : 2017 Jan 16
|
||||
Last Change : 2017 Jun 30
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -904,7 +904,7 @@ NOTA: Se quiser ignorar a diferen
|
||||
:e $VIM/_vimrc para MS-Windows
|
||||
|
||||
2. Agora, leia o conte<74>do do arquivo "vimrc" de exemplo:
|
||||
:r $VIM/vimrc_example.vim
|
||||
:r $VIMRUNTIME/vimrc_example.vim
|
||||
|
||||
3. Salve o arquivo com:
|
||||
:w
|
||||
|
||||
@@ -904,7 +904,7 @@ NOTA: Se quiser ignorar a diferença entre maiúsculas e minúsculas em apenas
|
||||
:e $VIM/_vimrc para MS-Windows
|
||||
|
||||
2. Agora, leia o conteúdo do arquivo "vimrc" de exemplo:
|
||||
:r $VIM/vimrc_example.vim
|
||||
:r $VIMRUNTIME/vimrc_example.vim
|
||||
|
||||
3. Salve o arquivo com:
|
||||
:w
|
||||
|
||||
93
src/Makefile
93
src/Makefile
@@ -482,6 +482,11 @@ CClink = $(CC)
|
||||
# Uncomment this when you do not want inter process communication.
|
||||
#CONF_OPT_CHANNEL = --disable-channel
|
||||
|
||||
# TERMINAL - Terminal emulator support, :terminal command. Requires the
|
||||
# channel feature.
|
||||
# Uncomment this when you want terminal emulator support.
|
||||
#CONF_OPT_TERMINAL = --enable-terminal
|
||||
|
||||
# MULTIBYTE - To edit multi-byte characters.
|
||||
# Uncomment this when you want to edit a multibyte language.
|
||||
# It's automatically enabled with normal features, GTK or IME support.
|
||||
@@ -598,6 +603,9 @@ CClink = $(CC)
|
||||
|
||||
# Use this with GCC to check for mistakes, unused arguments, etc.
|
||||
#CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
|
||||
# Add -Wpedantic to find // comments and other C99 constructs.
|
||||
# Better disable Perl and Python to avoid a lot of warnings.
|
||||
#CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wpedantic -Wunreachable-code -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
|
||||
#CFLAGS = -g -O2 -Wall -Wextra -Wmissing-prototypes -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -DU_DEBUG
|
||||
#PYTHON_CFLAGS_EXTRA = -Wno-missing-field-initializers
|
||||
#MZSCHEME_CFLAGS_EXTRA = -Wno-unreachable-code -Wno-unused-parameter
|
||||
@@ -1371,6 +1379,13 @@ ALL_GUI_PRO = gui.pro gui_gtk.pro gui_motif.pro gui_xmdlg.pro gui_athena.pro gu
|
||||
|
||||
# }}}
|
||||
|
||||
TERM_DEPS = \
|
||||
libvterm/include/vterm.h \
|
||||
libvterm/include/vterm_keycodes.h \
|
||||
libvterm/src/rect.h \
|
||||
libvterm/src/utf8.h \
|
||||
libvterm/src/vterm_internal.h
|
||||
|
||||
### Command to create dependencies based on #include "..."
|
||||
### prototype headers are ignored due to -DPROTO, system
|
||||
### headers #include <...> are ignored if we use the -MM option, as
|
||||
@@ -1560,6 +1575,7 @@ BASIC_SRC = \
|
||||
syntax.c \
|
||||
tag.c \
|
||||
term.c \
|
||||
terminal.c \
|
||||
ui.c \
|
||||
undo.c \
|
||||
userfunc.c \
|
||||
@@ -1569,6 +1585,7 @@ BASIC_SRC = \
|
||||
|
||||
SRC = $(BASIC_SRC) \
|
||||
$(GUI_SRC) \
|
||||
$(TERM_SRC) \
|
||||
$(HANGULIN_SRC) \
|
||||
$(LUA_SRC) \
|
||||
$(MZSCHEME_SRC) \
|
||||
@@ -1610,7 +1627,7 @@ ALL_SRC = $(BASIC_SRC) $(ALL_GUI_SRC) $(UNITTEST_SRC) $(EXTRA_SRC)
|
||||
LINT_SRC = $(BASIC_SRC) $(GUI_SRC) $(HANGULIN_SRC) \
|
||||
$(PYTHON_SRC) $(PYTHON3_SRC) $(TCL_SRC) \
|
||||
$(WORKSHOP_SRC) $(WSDEBUG_SRC) \
|
||||
$(NETBEANS_SRC) $(CHANNEL_SRC)
|
||||
$(NETBEANS_SRC) $(CHANNEL_SRC) $(TERM_SRC)
|
||||
#LINT_SRC = $(SRC)
|
||||
#LINT_SRC = $(ALL_SRC)
|
||||
#LINT_SRC = $(BASIC_SRC)
|
||||
@@ -1665,12 +1682,14 @@ OBJ_COMMON = \
|
||||
objects/syntax.o \
|
||||
objects/tag.o \
|
||||
objects/term.o \
|
||||
objects/terminal.o \
|
||||
objects/ui.o \
|
||||
objects/undo.o \
|
||||
objects/userfunc.o \
|
||||
objects/version.o \
|
||||
objects/window.o \
|
||||
$(GUI_OBJ) \
|
||||
$(TERM_OBJ) \
|
||||
$(LUA_OBJ) \
|
||||
$(MZSCHEME_OBJ) \
|
||||
$(PERL_OBJ) \
|
||||
@@ -1795,6 +1814,7 @@ PRO_AUTO = \
|
||||
syntax.pro \
|
||||
tag.pro \
|
||||
term.pro \
|
||||
terminal.pro \
|
||||
termlib.pro \
|
||||
ui.pro \
|
||||
undo.pro \
|
||||
@@ -1848,7 +1868,7 @@ config auto/config.mk: auto/configure config.mk.in config.h.in
|
||||
$(CONF_OPT_OUTPUT) $(CONF_OPT_GPM) $(CONF_OPT_WORKSHOP) \
|
||||
$(CONF_OPT_FEAT) $(CONF_TERM_LIB) \
|
||||
$(CONF_OPT_COMPBY) $(CONF_OPT_ACL) $(CONF_OPT_NETBEANS) \
|
||||
$(CONF_OPT_CHANNEL) \
|
||||
$(CONF_OPT_CHANNEL) $(CONF_OPT_TERMINAL) \
|
||||
$(CONF_ARGS) $(CONF_OPT_MZSCHEME) $(CONF_OPT_PLTHOME) \
|
||||
$(CONF_OPT_LUA) $(CONF_OPT_LUA_PREFIX) \
|
||||
$(CONF_OPT_SYSMOUSE); \
|
||||
@@ -2072,25 +2092,23 @@ test1 \
|
||||
test_autoformat_join \
|
||||
test_changelist \
|
||||
test_close_count \
|
||||
test_comparators \
|
||||
test_erasebackword \
|
||||
test_eval \
|
||||
test_fixeol \
|
||||
test_getcwd \
|
||||
test_insertcount \
|
||||
test_listchars \
|
||||
test_search_mbyte \
|
||||
test_wordcount \
|
||||
test3 test4 test5 test6 test7 test8 test9 \
|
||||
test11 test12 test14 test15 test17 test18 test19 \
|
||||
test20 test21 test22 test23 test24 test25 test26 test27 test28 test29 \
|
||||
test20 test21 test22 test25 test27 test28 test29 \
|
||||
test30 test31 test32 test33 test34 test36 test37 test38 test39 \
|
||||
test40 test41 test42 test43 test44 test45 test48 test49 \
|
||||
test50 test51 test52 test53 test54 test55 test56 test57 test58 test59 \
|
||||
test60 test64 test66 test67 test68 test69 \
|
||||
test70 test72 test73 test74 test75 test77 test78 test79 \
|
||||
test80 test82 test83 test84 test85 test86 test87 test88 \
|
||||
test90 test91 test94 test95 test97 test98 test99 \
|
||||
test50 test51 test52 test53 test54 test55 test56 test57 test59 \
|
||||
test60 test64 test66 test68 test69 \
|
||||
test70 test72 test73 test74 test77 test78 test79 \
|
||||
test80 test83 test84 test85 test86 test87 test88 \
|
||||
test91 test94 test95 test98 test99 \
|
||||
test100 test101 test103 test104 test107 test108:
|
||||
cd testdir; rm -f $@.out; $(MAKE) -f Makefile $@.out VIMPROG=../$(VIMTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE)
|
||||
|
||||
@@ -2114,6 +2132,7 @@ test_arglist \
|
||||
test_clientserver \
|
||||
test_cmdline \
|
||||
test_command_count \
|
||||
test_comparators \
|
||||
test_crypt \
|
||||
test_cscope \
|
||||
test_cursor_func \
|
||||
@@ -2122,9 +2141,12 @@ test_arglist \
|
||||
test_digraph \
|
||||
test_display \
|
||||
test_edit \
|
||||
test_escaped_glob \
|
||||
test_ex_undo \
|
||||
test_ex_z \
|
||||
test_exec_while_if \
|
||||
test_execute_func \
|
||||
test_exists_autocmd \
|
||||
test_expand \
|
||||
test_expand_dllpath \
|
||||
test_expr \
|
||||
@@ -2143,6 +2165,7 @@ test_arglist \
|
||||
test_fold \
|
||||
test_functions \
|
||||
test_ga \
|
||||
test_getcwd \
|
||||
test_gf \
|
||||
test_glob2regpat \
|
||||
test_global \
|
||||
@@ -2171,6 +2194,7 @@ test_arglist \
|
||||
test_lua \
|
||||
test_makeencoding \
|
||||
test_man \
|
||||
test_maparg \
|
||||
test_mapping \
|
||||
test_marks \
|
||||
test_match \
|
||||
@@ -2189,6 +2213,7 @@ test_arglist \
|
||||
test_partial \
|
||||
test_paste \
|
||||
test_perl \
|
||||
test_plus_arg_edit \
|
||||
test_popup \
|
||||
test_profile \
|
||||
test_put \
|
||||
@@ -2199,6 +2224,7 @@ test_arglist \
|
||||
test_quickfix \
|
||||
test_quotestar \
|
||||
test_recover \
|
||||
test_regex_char_classes \
|
||||
test_regexp_latin \
|
||||
test_regexp_utf8 \
|
||||
test_reltime \
|
||||
@@ -2207,6 +2233,7 @@ test_arglist \
|
||||
test_search \
|
||||
test_searchpos \
|
||||
test_set \
|
||||
test_sha256 \
|
||||
test_signs \
|
||||
test_smartindent \
|
||||
test_sort \
|
||||
@@ -2233,6 +2260,7 @@ test_arglist \
|
||||
test_unlet \
|
||||
test_usercommands \
|
||||
test_utf8 \
|
||||
test_utf8_comparisons \
|
||||
test_viminfo \
|
||||
test_vimscript \
|
||||
test_visual \
|
||||
@@ -2788,7 +2816,7 @@ SHADOWDIR = shadow
|
||||
|
||||
shadow: runtime pixmaps
|
||||
$(MKDIR_P) $(SHADOWDIR)
|
||||
cd $(SHADOWDIR); ln -s ../*.[chm] ../*.in ../*.sh ../*.xs ../*.xbm ../gui_gtk_res.xml ../toolcheck ../proto ../vimtutor ../gvimtutor ../install-sh .
|
||||
cd $(SHADOWDIR); ln -s ../*.[chm] ../*.in ../*.sh ../*.xs ../*.xbm ../gui_gtk_res.xml ../toolcheck ../proto ../libvterm ../vimtutor ../gvimtutor ../install-sh .
|
||||
mkdir $(SHADOWDIR)/auto
|
||||
cd $(SHADOWDIR)/auto; ln -s ../../auto/configure .
|
||||
$(MKDIR_P) $(SHADOWDIR)/po
|
||||
@@ -3226,6 +3254,9 @@ objects/tag.o: tag.c
|
||||
objects/term.o: term.c
|
||||
$(CCC) -o $@ term.c
|
||||
|
||||
objects/terminal.o: terminal.c $(TERM_DEPS)
|
||||
$(CCC) -o $@ terminal.c
|
||||
|
||||
objects/ui.o: ui.c
|
||||
$(CCC) -o $@ ui.c
|
||||
|
||||
@@ -3253,6 +3284,34 @@ objects/channel.o: channel.c
|
||||
Makefile:
|
||||
@echo The name of the makefile MUST be "Makefile" (with capital M)!!!!
|
||||
|
||||
CCCTERM = $(CCC) -Ilibvterm/include -DINLINE="" -DVSNPRINTF=vim_vsnprintf
|
||||
objects/term_encoding.o: libvterm/src/encoding.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/encoding.c
|
||||
|
||||
objects/term_keyboard.o: libvterm/src/keyboard.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/keyboard.c
|
||||
|
||||
objects/term_mouse.o: libvterm/src/mouse.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/mouse.c
|
||||
|
||||
objects/term_parser.o: libvterm/src/parser.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/parser.c
|
||||
|
||||
objects/term_pen.o: libvterm/src/pen.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/pen.c
|
||||
|
||||
objects/term_screen.o: libvterm/src/screen.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/screen.c
|
||||
|
||||
objects/term_state.o: libvterm/src/state.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/state.c
|
||||
|
||||
objects/term_unicode.o: libvterm/src/unicode.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/unicode.c
|
||||
|
||||
objects/term_vterm.o: libvterm/src/vterm.c $(TERM_DEPS)
|
||||
$(CCCTERM) -o $@ libvterm/src/vterm.c
|
||||
|
||||
###############################################################################
|
||||
### MacOS X installation
|
||||
###
|
||||
@@ -3397,7 +3456,7 @@ objects/ex_cmds2.o: ex_cmds2.c vim.h auto/config.h feature.h os_unix.h \
|
||||
objects/ex_docmd.o: ex_docmd.c vim.h auto/config.h feature.h os_unix.h \
|
||||
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
|
||||
regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h \
|
||||
proto.h globals.h farsi.h arabic.h
|
||||
proto.h globals.h farsi.h arabic.h ex_cmdidxs.h
|
||||
objects/ex_eval.o: ex_eval.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
|
||||
ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
|
||||
gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h proto.h \
|
||||
@@ -3501,7 +3560,7 @@ objects/option.o: option.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h
|
||||
objects/os_unix.o: os_unix.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
|
||||
ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
|
||||
gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h proto.h \
|
||||
globals.h farsi.h arabic.h if_mzsch.h os_unixx.h
|
||||
globals.h farsi.h arabic.h os_unixx.h
|
||||
objects/pathdef.o: auto/pathdef.c vim.h auto/config.h feature.h os_unix.h \
|
||||
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
|
||||
regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h \
|
||||
@@ -3550,6 +3609,10 @@ objects/term.o: term.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h \
|
||||
ascii.h keymap.h term.h macros.h option.h structs.h regexp.h gui.h \
|
||||
gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h proto.h \
|
||||
globals.h farsi.h arabic.h
|
||||
objects/terminal.o: terminal.c vim.h auto/config.h feature.h os_unix.h \
|
||||
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
|
||||
regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h \
|
||||
proto.h globals.h farsi.h arabic.h
|
||||
objects/ui.o: ui.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h ascii.h \
|
||||
keymap.h term.h macros.h option.h structs.h regexp.h gui.h gui_beval.h \
|
||||
proto/gui_beval.pro alloc.h ex_cmds.h spell.h proto.h globals.h farsi.h \
|
||||
@@ -3659,7 +3722,7 @@ objects/json_test.o: json_test.c main.c vim.h auto/config.h feature.h os_unix.h
|
||||
objects/kword_test.o: kword_test.c main.c vim.h auto/config.h feature.h os_unix.h \
|
||||
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
|
||||
regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h \
|
||||
proto.h globals.h farsi.h arabic.h charset.c mbyte.c
|
||||
proto.h globals.h farsi.h arabic.h charset.c
|
||||
objects/memfile_test.o: memfile_test.c main.c vim.h auto/config.h feature.h \
|
||||
os_unix.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h \
|
||||
structs.h regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h \
|
||||
@@ -3679,7 +3742,7 @@ objects/if_lua.o: if_lua.c vim.h auto/config.h feature.h os_unix.h auto/osdef.h
|
||||
objects/if_mzsch.o: if_mzsch.c vim.h auto/config.h feature.h os_unix.h \
|
||||
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
|
||||
regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h \
|
||||
proto.h globals.h farsi.h arabic.h if_mzsch.h mzscheme_base.c
|
||||
proto.h globals.h farsi.h arabic.h if_mzsch.h
|
||||
objects/if_perl.o: auto/if_perl.c vim.h auto/config.h feature.h os_unix.h \
|
||||
auto/osdef.h ascii.h keymap.h term.h macros.h option.h structs.h \
|
||||
regexp.h gui.h gui_beval.h proto/gui_beval.pro alloc.h ex_cmds.h spell.h \
|
||||
|
||||
33
src/auto/configure
vendored
33
src/auto/configure
vendored
@@ -655,6 +655,8 @@ X_PRE_LIBS
|
||||
X_CFLAGS
|
||||
XMKMF
|
||||
xmkmfpath
|
||||
TERM_OBJ
|
||||
TERM_SRC
|
||||
CHANNEL_OBJ
|
||||
CHANNEL_SRC
|
||||
NETBEANS_OBJ
|
||||
@@ -814,6 +816,7 @@ enable_cscope
|
||||
enable_workshop
|
||||
enable_netbeans
|
||||
enable_channel
|
||||
enable_terminal
|
||||
enable_multibyte
|
||||
enable_hangulinput
|
||||
enable_xim
|
||||
@@ -1491,6 +1494,7 @@ Optional Features:
|
||||
--enable-workshop Include Sun Visual Workshop support.
|
||||
--disable-netbeans Disable NetBeans integration support.
|
||||
--disable-channel Disable process communication support.
|
||||
--enable-terminal Disable terminal emulation support.
|
||||
--enable-multibyte Include multibyte editing support.
|
||||
--enable-hangulinput Include Hangul input support.
|
||||
--enable-xim Include XIM input support.
|
||||
@@ -7464,6 +7468,35 @@ if test "$enable_channel" = "yes"; then
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-terminal argument" >&5
|
||||
$as_echo_n "checking --enable-terminal argument... " >&6; }
|
||||
# Check whether --enable-terminal was given.
|
||||
if test "${enable_terminal+set}" = set; then :
|
||||
enableval=$enable_terminal; enable_terminal="yes"
|
||||
fi
|
||||
|
||||
if test "$enable_terminal" = "yes"; then
|
||||
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use terminal emulator with tiny or small features" >&5
|
||||
$as_echo "cannot use terminal emulator with tiny or small features" >&6; }
|
||||
enable_terminal="no"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
if test "$enable_terminal" = "yes"; then
|
||||
$as_echo "#define FEAT_TERMINAL 1" >>confdefs.h
|
||||
|
||||
TERM_SRC="libvterm/src/encoding.c libvterm/src/keyboard.c libvterm/src/mouse.c libvterm/src/parser.c libvterm/src/pen.c libvterm/src/screen.c libvterm/src/state.c libvterm/src/unicode.c libvterm/src/vterm.c"
|
||||
|
||||
TERM_OBJ="objects/term_encoding.o objects/term_keyboard.o objects/term_mouse.o objects/term_parser.o objects/term_pen.o objects/term_screen.o objects/term_state.o objects/term_unicode.o objects/term_vterm.o"
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking --enable-multibyte argument" >&5
|
||||
$as_echo_n "checking --enable-multibyte argument... " >&6; }
|
||||
# Check whether --enable-multibyte was given.
|
||||
|
||||
@@ -372,7 +372,7 @@ open_buffer(
|
||||
set_bufref(bufref_T *bufref, buf_T *buf)
|
||||
{
|
||||
bufref->br_buf = buf;
|
||||
bufref->br_fnum = buf->b_fnum;
|
||||
bufref->br_fnum = buf == NULL ? 0 : buf->b_fnum;
|
||||
bufref->br_buf_free_count = buf_free_count;
|
||||
}
|
||||
|
||||
|
||||
@@ -1438,6 +1438,7 @@ channel_write_in(channel_T *channel)
|
||||
if (!bufref_valid(&in_part->ch_bufref) || buf->b_ml.ml_mfp == NULL)
|
||||
{
|
||||
/* buffer was wiped out or unloaded */
|
||||
ch_log(channel, "input buffer has been wiped out");
|
||||
in_part->ch_bufref.br_buf = NULL;
|
||||
return;
|
||||
}
|
||||
@@ -2338,7 +2339,7 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
|
||||
int save_write_to = buffer->b_write_to_channel;
|
||||
chanpart_T *ch_part = &channel->ch_part[part];
|
||||
int save_p_ma = buffer->b_p_ma;
|
||||
int empty = (buffer->b_ml.ml_flags & ML_EMPTY);
|
||||
int empty = (buffer->b_ml.ml_flags & ML_EMPTY) ? 1 : 0;
|
||||
|
||||
if (!buffer->b_p_ma && !ch_part->ch_nomodifiable)
|
||||
{
|
||||
@@ -2359,13 +2360,14 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
|
||||
}
|
||||
|
||||
/* Append to the buffer */
|
||||
ch_logn(channel, "appending line %d to buffer", (int)lnum + 1);
|
||||
ch_logn(channel, "appending line %d to buffer", (int)lnum + 1 - empty);
|
||||
|
||||
buffer->b_p_ma = TRUE;
|
||||
curbuf = buffer;
|
||||
curwin->w_buffer = curbuf;
|
||||
u_sync(TRUE);
|
||||
/* ignore undo failure, undo is not very useful here */
|
||||
ignored = u_save(lnum, lnum + 1 + (empty ? 1 : 0));
|
||||
ignored = u_save(lnum - empty, lnum + 1);
|
||||
|
||||
if (empty)
|
||||
{
|
||||
@@ -2377,6 +2379,7 @@ append_to_buffer(buf_T *buffer, char_u *msg, channel_T *channel, ch_part_T part)
|
||||
ml_append(lnum, msg, 0, FALSE);
|
||||
appended_lines_mark(lnum, 1L);
|
||||
curbuf = save_curbuf;
|
||||
curwin->w_buffer = curbuf;
|
||||
if (ch_part->ch_nomodifiable)
|
||||
buffer->b_p_ma = FALSE;
|
||||
else
|
||||
@@ -2483,9 +2486,11 @@ may_invoke_callback(channel_T *channel, ch_part_T part)
|
||||
}
|
||||
|
||||
buffer = ch_part->ch_bufref.br_buf;
|
||||
if (buffer != NULL && !bufref_valid(&ch_part->ch_bufref))
|
||||
if (buffer != NULL && (!bufref_valid(&ch_part->ch_bufref)
|
||||
|| buffer->b_ml.ml_mfp == NULL))
|
||||
{
|
||||
/* buffer was wiped out */
|
||||
/* buffer was wiped out or unloaded */
|
||||
ch_logs(channel, "%s buffer has been wiped out", part_names[part]);
|
||||
ch_part->ch_bufref.br_buf = NULL;
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
@@ -431,6 +431,9 @@
|
||||
/* Define if you want to include process communication. */
|
||||
#undef FEAT_JOB_CHANNEL
|
||||
|
||||
/* Define if you want to include terminal emulator support. */
|
||||
#undef FEAT_TERMINAL
|
||||
|
||||
/* Define default global runtime path */
|
||||
#undef RUNTIME_GLOBAL
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ NETBEANS_SRC = @NETBEANS_SRC@
|
||||
NETBEANS_OBJ = @NETBEANS_OBJ@
|
||||
CHANNEL_SRC = @CHANNEL_SRC@
|
||||
CHANNEL_OBJ = @CHANNEL_OBJ@
|
||||
TERM_SRC = @TERM_SRC@
|
||||
TERM_OBJ = @TERM_OBJ@
|
||||
|
||||
RUBY = @vi_cv_path_ruby@
|
||||
RUBY_SRC = @RUBY_SRC@
|
||||
|
||||
@@ -2028,6 +2028,28 @@ if test "$enable_channel" = "yes"; then
|
||||
AC_SUBST(CHANNEL_OBJ)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(--enable-terminal argument)
|
||||
AC_ARG_ENABLE(terminal,
|
||||
[ --enable-terminal Disable terminal emulation support.],
|
||||
[enable_terminal="yes"], )
|
||||
if test "$enable_terminal" = "yes"; then
|
||||
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
|
||||
AC_MSG_RESULT([cannot use terminal emulator with tiny or small features])
|
||||
enable_terminal="no"
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
if test "$enable_terminal" = "yes"; then
|
||||
AC_DEFINE(FEAT_TERMINAL)
|
||||
TERM_SRC="libvterm/src/encoding.c libvterm/src/keyboard.c libvterm/src/mouse.c libvterm/src/parser.c libvterm/src/pen.c libvterm/src/screen.c libvterm/src/state.c libvterm/src/unicode.c libvterm/src/vterm.c"
|
||||
AC_SUBST(TERM_SRC)
|
||||
TERM_OBJ="objects/term_encoding.o objects/term_keyboard.o objects/term_mouse.o objects/term_parser.o objects/term_pen.o objects/term_screen.o objects/term_state.o objects/term_unicode.o objects/term_vterm.o"
|
||||
AC_SUBST(TERM_OBJ)
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(--enable-multibyte argument)
|
||||
AC_ARG_ENABLE(multibyte,
|
||||
[ --enable-multibyte Include multibyte editing support.], ,
|
||||
|
||||
16
src/edit.c
16
src/edit.c
@@ -4308,9 +4308,17 @@ ins_compl_get_exp(pos_T *ini)
|
||||
{
|
||||
ins_buf = curbuf;
|
||||
first_match_pos = *ini;
|
||||
/* So that ^N can match word immediately after cursor */
|
||||
if (ctrl_x_mode == 0)
|
||||
dec(&first_match_pos);
|
||||
/* Move the cursor back one character so that ^N can match the
|
||||
* word immediately after the cursor. */
|
||||
if (ctrl_x_mode == 0 && dec(&first_match_pos) < 0)
|
||||
{
|
||||
/* Move the cursor to after the last character in the
|
||||
* buffer, so that word at start of buffer is found
|
||||
* correctly. */
|
||||
first_match_pos.lnum = ins_buf->b_ml.ml_line_count;
|
||||
first_match_pos.col =
|
||||
(colnr_T)STRLEN(ml_get(first_match_pos.lnum));
|
||||
}
|
||||
last_match_pos = first_match_pos;
|
||||
type = 0;
|
||||
|
||||
@@ -7321,7 +7329,9 @@ oneleft(void)
|
||||
#ifdef FEAT_VIRTUALEDIT
|
||||
if (virtual_active())
|
||||
{
|
||||
# ifdef FEAT_LINEBREAK
|
||||
int width;
|
||||
# endif
|
||||
int v = getviscol();
|
||||
|
||||
if (v == 0)
|
||||
|
||||
@@ -3191,7 +3191,11 @@ f_feedkeys(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
|
||||
insert ? 0 : typebuf.tb_len, !typed, FALSE);
|
||||
vim_free(keys_esc);
|
||||
if (vgetc_busy)
|
||||
if (vgetc_busy
|
||||
#ifdef FEAT_TIMERS
|
||||
|| timer_busy
|
||||
#endif
|
||||
)
|
||||
typebuf_was_filled = TRUE;
|
||||
if (execute)
|
||||
{
|
||||
@@ -5866,6 +5870,9 @@ f_has(typval_T *argvars, typval_T *rettv)
|
||||
#ifdef FEAT_TERMGUICOLORS
|
||||
"termguicolors",
|
||||
#endif
|
||||
#ifdef FEAT_TERMINAL
|
||||
"terminal",
|
||||
#endif
|
||||
#ifdef TERMINFO
|
||||
"terminfo",
|
||||
#endif
|
||||
@@ -8036,14 +8043,15 @@ f_printf(typval_T *argvars, typval_T *rettv)
|
||||
/* Get the required length, allocate the buffer and do it for real. */
|
||||
did_emsg = FALSE;
|
||||
fmt = (char *)get_tv_string_buf(&argvars[0], buf);
|
||||
len = vim_vsnprintf(NULL, 0, fmt, ap, argvars + 1);
|
||||
len = vim_vsnprintf_typval(NULL, 0, fmt, ap, argvars + 1);
|
||||
if (!did_emsg)
|
||||
{
|
||||
s = alloc(len + 1);
|
||||
if (s != NULL)
|
||||
{
|
||||
rettv->vval.v_string = s;
|
||||
(void)vim_vsnprintf((char *)s, len + 1, fmt, ap, argvars + 1);
|
||||
(void)vim_vsnprintf_typval((char *)s, len + 1, fmt,
|
||||
ap, argvars + 1);
|
||||
}
|
||||
}
|
||||
did_emsg |= saved_did_emsg;
|
||||
@@ -11841,8 +11849,8 @@ f_synconcealed(typval_T *argvars UNUSED, typval_T *rettv)
|
||||
if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3)
|
||||
{
|
||||
cchar = syn_get_sub_char();
|
||||
if (cchar == NUL && curwin->w_p_cole == 1 && lcs_conceal != NUL)
|
||||
cchar = lcs_conceal;
|
||||
if (cchar == NUL && curwin->w_p_cole == 1)
|
||||
cchar = (lcs_conceal == NUL) ? ' ' : lcs_conceal;
|
||||
if (cchar != NUL)
|
||||
{
|
||||
# ifdef FEAT_MBYTE
|
||||
@@ -12394,6 +12402,7 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
{
|
||||
char_u *name = (char_u *)"";
|
||||
int val;
|
||||
static int save_starting = -1;
|
||||
|
||||
if (argvars[0].v_type != VAR_STRING
|
||||
|| (argvars[1].v_type) != VAR_NUMBER)
|
||||
@@ -12407,10 +12416,29 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
|
||||
disable_redraw_for_testing = val;
|
||||
else if (STRCMP(name, (char_u *)"char_avail") == 0)
|
||||
disable_char_avail_for_testing = val;
|
||||
else if (STRCMP(name, (char_u *)"starting") == 0)
|
||||
{
|
||||
if (val)
|
||||
{
|
||||
if (save_starting < 0)
|
||||
save_starting = starting;
|
||||
starting = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
starting = save_starting;
|
||||
save_starting = -1;
|
||||
}
|
||||
}
|
||||
else if (STRCMP(name, (char_u *)"ALL") == 0)
|
||||
{
|
||||
disable_char_avail_for_testing = FALSE;
|
||||
disable_redraw_for_testing = FALSE;
|
||||
if (save_starting >= 0)
|
||||
{
|
||||
starting = save_starting;
|
||||
save_starting = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
EMSG2(_(e_invarg2), name);
|
||||
|
||||
@@ -25,12 +25,12 @@ static const unsigned short cmdidxs1[26] =
|
||||
/* r */ 351,
|
||||
/* s */ 370,
|
||||
/* t */ 437,
|
||||
/* u */ 472,
|
||||
/* v */ 483,
|
||||
/* w */ 501,
|
||||
/* x */ 516,
|
||||
/* y */ 525,
|
||||
/* z */ 526
|
||||
/* u */ 473,
|
||||
/* v */ 484,
|
||||
/* w */ 502,
|
||||
/* x */ 517,
|
||||
/* y */ 526,
|
||||
/* z */ 527
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -60,7 +60,7 @@ static const unsigned char cmdidxs2[26][26] =
|
||||
/* q */ { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* r */ { 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 18, 0, 0, 0, 0 },
|
||||
/* s */ { 2, 6, 15, 0, 18, 22, 0, 24, 25, 0, 0, 28, 30, 34, 38, 40, 0, 48, 0, 49, 0, 61, 62, 0, 63, 0 },
|
||||
/* t */ { 2, 0, 19, 0, 22, 23, 0, 24, 0, 25, 0, 26, 27, 28, 29, 30, 0, 31, 33, 0, 34, 0, 0, 0, 0, 0 },
|
||||
/* t */ { 2, 0, 19, 0, 22, 24, 0, 25, 0, 26, 0, 27, 28, 29, 30, 31, 0, 32, 34, 0, 35, 0, 0, 0, 0, 0 },
|
||||
/* u */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* v */ { 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 9, 12, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0 },
|
||||
/* w */ { 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 8, 0, 9, 10, 0, 12, 0, 13, 14, 0, 0, 0, 0 },
|
||||
@@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][26] =
|
||||
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static const int command_count = 539;
|
||||
static const int command_count = 540;
|
||||
|
||||
@@ -1743,7 +1743,7 @@ static int viminfo_errcnt;
|
||||
no_viminfo(void)
|
||||
{
|
||||
/* "vim -i NONE" does not read or write a viminfo file */
|
||||
return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
|
||||
return STRCMP(p_viminfofile, "NONE") == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2093,8 +2093,8 @@ viminfo_filename(char_u *file)
|
||||
{
|
||||
if (file == NULL || *file == NUL)
|
||||
{
|
||||
if (use_viminfo != NULL)
|
||||
file = use_viminfo;
|
||||
if (*p_viminfofile != NUL)
|
||||
file = p_viminfofile;
|
||||
else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
|
||||
{
|
||||
#ifdef VIMINFO_FILE2
|
||||
@@ -3968,8 +3968,8 @@ do_ecmd(
|
||||
* <VN> We could instead free the synblock
|
||||
* and re-attach to buffer, perhaps.
|
||||
*/
|
||||
if (curwin->w_buffer != NULL
|
||||
&& curwin->w_s == &(curwin->w_buffer->b_s))
|
||||
if (curwin->w_buffer == NULL
|
||||
|| curwin->w_s == &(curwin->w_buffer->b_s))
|
||||
curwin->w_s = &(buf->b_s);
|
||||
#endif
|
||||
curwin->w_buffer = buf;
|
||||
@@ -6832,8 +6832,15 @@ fix_help_buffer(void)
|
||||
char_u *rt;
|
||||
int mustfree;
|
||||
|
||||
/* set filetype to "help". */
|
||||
#ifdef FEAT_AUTOCMD
|
||||
/* Set filetype to "help" if still needed. */
|
||||
if (STRCMP(curbuf->b_p_ft, "help") != 0)
|
||||
{
|
||||
++curbuf_lock;
|
||||
set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
|
||||
--curbuf_lock;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_SYN_HL
|
||||
if (!syntax_present(curwin))
|
||||
|
||||
@@ -51,7 +51,9 @@
|
||||
#define BUFUNL 0x20000L /* accepts unlisted buffer too */
|
||||
#define ARGOPT 0x40000L /* allow "++opt=val" argument */
|
||||
#define SBOXOK 0x80000L /* allowed in the sandbox */
|
||||
#define CMDWIN 0x100000L /* allowed in cmdline window */
|
||||
#define CMDWIN 0x100000L /* allowed in cmdline window; when missing
|
||||
* disallows editing another buffer when
|
||||
* curbuf_lock is set */
|
||||
#define MODIFY 0x200000L /* forbidden in non-'modifiable' buffer */
|
||||
#define EXFLAGS 0x400000L /* allow flags after count in argument */
|
||||
#define FILES (XFILE | EXTRA) /* multiple extra files allowed */
|
||||
@@ -426,7 +428,7 @@ EX(CMD_delcommand, "delcommand", ex_delcommand,
|
||||
NEEDARG|WORD1|TRLBAR|CMDWIN,
|
||||
ADDR_LINES),
|
||||
EX(CMD_delfunction, "delfunction", ex_delfunction,
|
||||
NEEDARG|WORD1|CMDWIN,
|
||||
BANG|NEEDARG|WORD1|CMDWIN,
|
||||
ADDR_LINES),
|
||||
EX(CMD_display, "display", ex_display,
|
||||
EXTRA|NOTRLCOM|TRLBAR|SBOXOK|CMDWIN,
|
||||
@@ -1176,7 +1178,7 @@ EX(CMD_registers, "registers", ex_display,
|
||||
EXTRA|NOTRLCOM|TRLBAR|CMDWIN,
|
||||
ADDR_LINES),
|
||||
EX(CMD_resize, "resize", ex_resize,
|
||||
RANGE|NOTADR|TRLBAR|WORD1,
|
||||
RANGE|NOTADR|TRLBAR|WORD1|CMDWIN,
|
||||
ADDR_LINES),
|
||||
EX(CMD_retab, "retab", ex_retab,
|
||||
TRLBAR|RANGE|WHOLEFOLD|DFLALL|BANG|WORD1|CMDWIN|MODIFY,
|
||||
@@ -1481,6 +1483,9 @@ EX(CMD_tclfile, "tclfile", ex_tclfile,
|
||||
EX(CMD_tearoff, "tearoff", ex_tearoff,
|
||||
NEEDARG|EXTRA|TRLBAR|NOTRLCOM|CMDWIN,
|
||||
ADDR_LINES),
|
||||
EX(CMD_terminal, "terminal", ex_terminal,
|
||||
RANGE|NOTADR|EXTRA|TRLBAR|CMDWIN,
|
||||
ADDR_OTHER),
|
||||
EX(CMD_tfirst, "tfirst", ex_tag,
|
||||
RANGE|NOTADR|BANG|TRLBAR|ZEROR,
|
||||
ADDR_LINES),
|
||||
@@ -1620,7 +1625,7 @@ EX(CMD_winsize, "winsize", ex_winsize,
|
||||
EXTRA|NEEDARG|TRLBAR,
|
||||
ADDR_LINES),
|
||||
EX(CMD_wincmd, "wincmd", ex_wincmd,
|
||||
NEEDARG|WORD1|RANGE|NOTADR,
|
||||
NEEDARG|WORD1|RANGE|NOTADR|CMDWIN,
|
||||
ADDR_WINDOWS),
|
||||
EX(CMD_windo, "windo", ex_listdo,
|
||||
NEEDARG|EXTRA|NOTRLCOM|RANGE|NOTADR|DFLALL,
|
||||
|
||||
@@ -1183,6 +1183,7 @@ timer_callback(timer_T *timer)
|
||||
/*
|
||||
* Call timers that are due.
|
||||
* Return the time in msec until the next timer is due.
|
||||
* Returns -1 if there are no pending timers.
|
||||
*/
|
||||
long
|
||||
check_due_timer(void)
|
||||
@@ -1196,7 +1197,13 @@ check_due_timer(void)
|
||||
long current_id = last_timer_id;
|
||||
# ifdef WIN3264
|
||||
LARGE_INTEGER fr;
|
||||
# endif
|
||||
|
||||
/* Don't run any timers while exiting or dealing with an error. */
|
||||
if (exiting || aborting())
|
||||
return next_due;
|
||||
|
||||
# ifdef WIN3264
|
||||
QueryPerformanceFrequency(&fr);
|
||||
# endif
|
||||
profile_start(&now);
|
||||
@@ -1209,15 +1216,35 @@ check_due_timer(void)
|
||||
this_due = GET_TIMEDIFF(timer, now);
|
||||
if (this_due <= 1)
|
||||
{
|
||||
int save_timer_busy = timer_busy;
|
||||
int save_vgetc_busy = vgetc_busy;
|
||||
int did_emsg_save = did_emsg;
|
||||
int called_emsg_save = called_emsg;
|
||||
int did_throw_save = did_throw;
|
||||
|
||||
timer_busy = timer_busy > 0 || vgetc_busy > 0;
|
||||
vgetc_busy = 0;
|
||||
called_emsg = FALSE;
|
||||
timer->tr_firing = TRUE;
|
||||
timer_callback(timer);
|
||||
timer->tr_firing = FALSE;
|
||||
timer_next = timer->tr_next;
|
||||
did_one = TRUE;
|
||||
timer_busy = save_timer_busy;
|
||||
vgetc_busy = save_vgetc_busy;
|
||||
if (called_emsg)
|
||||
{
|
||||
++timer->tr_emsg_count;
|
||||
if (!did_throw_save && did_throw && current_exception != NULL)
|
||||
discard_current_exception();
|
||||
}
|
||||
did_emsg = did_emsg_save;
|
||||
called_emsg = called_emsg_save;
|
||||
|
||||
/* Only fire the timer again if it repeats and stop_timer() wasn't
|
||||
* called while inside the callback (tr_id == -1). */
|
||||
if (timer->tr_repeat != 0 && timer->tr_id != -1)
|
||||
if (timer->tr_repeat != 0 && timer->tr_id != -1
|
||||
&& timer->tr_emsg_count < 3)
|
||||
{
|
||||
profile_setlimit(timer->tr_interval, &timer->tr_due);
|
||||
this_due = GET_TIMEDIFF(timer, now);
|
||||
@@ -3278,19 +3305,6 @@ source_callback(char_u *fname, void *cookie UNUSED)
|
||||
(void)do_source(fname, FALSE, DOSO_NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Source the file "name" from all directories in 'runtimepath'.
|
||||
* "name" can contain wildcards.
|
||||
* When "flags" has DIP_ALL: source all files, otherwise only the first one.
|
||||
*
|
||||
* return FAIL when no file could be sourced, OK otherwise.
|
||||
*/
|
||||
int
|
||||
source_runtime(char_u *name, int flags)
|
||||
{
|
||||
return do_in_runtimepath(name, flags, source_callback, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the file "name" in all directories in "path" and invoke
|
||||
* "callback(fname, cookie)".
|
||||
@@ -3428,18 +3442,19 @@ do_in_path(
|
||||
}
|
||||
|
||||
/*
|
||||
* Find "name" in 'runtimepath'. When found, invoke the callback function for
|
||||
* Find "name" in "path". When found, invoke the callback function for
|
||||
* it: callback(fname, "cookie")
|
||||
* When "flags" has DIP_ALL repeat for all matches, otherwise only the first
|
||||
* one is used.
|
||||
* Returns OK when at least one match found, FAIL otherwise.
|
||||
*
|
||||
* If "name" is NULL calls callback for each entry in runtimepath. Cookie is
|
||||
* If "name" is NULL calls callback for each entry in "path". Cookie is
|
||||
* passed by reference in this case, setting it to NULL indicates that callback
|
||||
* has done its job.
|
||||
*/
|
||||
int
|
||||
do_in_runtimepath(
|
||||
static int
|
||||
do_in_path_and_pp(
|
||||
char_u *path,
|
||||
char_u *name,
|
||||
int flags,
|
||||
void (*callback)(char_u *fname, void *ck),
|
||||
@@ -3452,7 +3467,7 @@ do_in_runtimepath(
|
||||
char *opt_dir = "pack/*/opt/*/%s";
|
||||
|
||||
if ((flags & DIP_NORTP) == 0)
|
||||
done = do_in_path(p_rtp, name, flags, callback, cookie);
|
||||
done = do_in_path(path, name, flags, callback, cookie);
|
||||
|
||||
if ((done == FAIL || (flags & DIP_ALL)) && (flags & DIP_START))
|
||||
{
|
||||
@@ -3479,6 +3494,42 @@ do_in_runtimepath(
|
||||
return done;
|
||||
}
|
||||
|
||||
/*
|
||||
* Just like do_in_path_and_pp(), using 'runtimepath' for "path".
|
||||
*/
|
||||
int
|
||||
do_in_runtimepath(
|
||||
char_u *name,
|
||||
int flags,
|
||||
void (*callback)(char_u *fname, void *ck),
|
||||
void *cookie)
|
||||
{
|
||||
return do_in_path_and_pp(p_rtp, name, flags, callback, cookie);
|
||||
}
|
||||
|
||||
/*
|
||||
* Source the file "name" from all directories in 'runtimepath'.
|
||||
* "name" can contain wildcards.
|
||||
* When "flags" has DIP_ALL: source all files, otherwise only the first one.
|
||||
*
|
||||
* return FAIL when no file could be sourced, OK otherwise.
|
||||
*/
|
||||
int
|
||||
source_runtime(char_u *name, int flags)
|
||||
{
|
||||
return source_in_path(p_rtp, name, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just like source_runtime(), but use "path" instead of 'runtimepath'.
|
||||
*/
|
||||
int
|
||||
source_in_path(char_u *path, char_u *name, int flags)
|
||||
{
|
||||
return do_in_path_and_pp(path, name, flags, source_callback, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Expand wildcards in "pat" and invoke do_source() for each match.
|
||||
*/
|
||||
|
||||
@@ -488,6 +488,9 @@ static void ex_folddo(exarg_T *eap);
|
||||
#ifndef FEAT_PROFILE
|
||||
# define ex_profile ex_ni
|
||||
#endif
|
||||
#ifndef FEAT_TERMINAL
|
||||
# define ex_terminal ex_ni
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Declare cmdnames[].
|
||||
@@ -2370,7 +2373,8 @@ do_one_cmd(
|
||||
goto doend;
|
||||
}
|
||||
/* Check for wrong commands. */
|
||||
if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78)
|
||||
if (*p == '!' && ea.cmd[1] == 0151 && ea.cmd[0] == 78
|
||||
&& !IS_USER_CMDIDX(ea.cmdidx))
|
||||
{
|
||||
errormsg = uc_fun_cmd();
|
||||
goto doend;
|
||||
@@ -7267,8 +7271,11 @@ ex_quit(exarg_T *eap)
|
||||
apply_autocmds(EVENT_QUITPRE, NULL, NULL, FALSE, curbuf);
|
||||
/* Refuse to quit when locked or when the buffer in the last window is
|
||||
* being closed (can only happen in autocommands). */
|
||||
if (curbuf_locked() || (wp->w_buffer->b_nwindows == 1
|
||||
&& wp->w_buffer->b_locked > 0))
|
||||
if (curbuf_locked()
|
||||
# ifdef FEAT_WINDOWS
|
||||
|| !win_valid(wp)
|
||||
# endif
|
||||
|| (wp->w_buffer->b_nwindows == 1 && wp->w_buffer->b_locked > 0))
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -640,8 +640,11 @@ discard_exception(except_T *excp, int was_finished)
|
||||
void
|
||||
discard_current_exception(void)
|
||||
{
|
||||
if (current_exception != NULL)
|
||||
{
|
||||
discard_exception(current_exception, FALSE);
|
||||
current_exception = NULL;
|
||||
}
|
||||
did_throw = FALSE;
|
||||
need_rethrow = FALSE;
|
||||
}
|
||||
@@ -1978,7 +1981,10 @@ enter_cleanup(cleanup_T *csp)
|
||||
* there is an extra instance for every call of do_cmdline(), anyway.
|
||||
*/
|
||||
if (did_throw || need_rethrow)
|
||||
{
|
||||
csp->exception = current_exception;
|
||||
current_exception = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
csp->exception = NULL;
|
||||
|
||||
@@ -52,6 +52,8 @@ static int cmd_showtail; /* Only show path tail in lists ? */
|
||||
static int new_cmdpos; /* position set by set_cmdline_pos() */
|
||||
#endif
|
||||
|
||||
static int extra_char = NUL; /* extra character to display when redrawing
|
||||
* the command line */
|
||||
#ifdef FEAT_CMDHIST
|
||||
typedef struct hist_entry
|
||||
{
|
||||
@@ -1173,12 +1175,14 @@ getcmdline(
|
||||
dont_scroll = TRUE; /* disallow scrolling here */
|
||||
#endif
|
||||
putcmdline('"', TRUE);
|
||||
extra_char = '"';
|
||||
++no_mapping;
|
||||
i = c = plain_vgetc(); /* CTRL-R <char> */
|
||||
if (i == Ctrl_O)
|
||||
i = Ctrl_R; /* CTRL-R CTRL-O == CTRL-R CTRL-R */
|
||||
if (i == Ctrl_R)
|
||||
c = plain_vgetc(); /* CTRL-R CTRL-R <char> */
|
||||
extra_char = NUL;
|
||||
--no_mapping;
|
||||
#ifdef FEAT_EVAL
|
||||
/*
|
||||
@@ -1492,7 +1496,7 @@ getcmdline(
|
||||
if (c != NUL)
|
||||
{
|
||||
if (c == firstc || vim_strchr((char_u *)(
|
||||
p_magic ? "\\^$.*[" : "\\^$"), c)
|
||||
p_magic ? "\\~^$.*[" : "\\^$"), c)
|
||||
!= NULL)
|
||||
{
|
||||
/* put a backslash before special
|
||||
@@ -1708,6 +1712,14 @@ getcmdline(
|
||||
search_start = t;
|
||||
(void)decl(&search_start);
|
||||
}
|
||||
else if (c == Ctrl_G && firstc == '?')
|
||||
{
|
||||
/* move just after the current match, so that
|
||||
* when nv_search finishes the cursor will be
|
||||
* put back on the match */
|
||||
search_start = t;
|
||||
(void)incl(&search_start);
|
||||
}
|
||||
if (LT_POS(t, search_start) && c == Ctrl_G)
|
||||
{
|
||||
/* wrap around */
|
||||
@@ -1747,8 +1759,10 @@ getcmdline(
|
||||
ignore_drag_release = TRUE;
|
||||
#endif
|
||||
putcmdline('^', TRUE);
|
||||
extra_char = '^';
|
||||
c = get_literal(); /* get next (two) character(s) */
|
||||
do_abbr = FALSE; /* don't do abbreviation now */
|
||||
extra_char = NUL;
|
||||
#ifdef FEAT_MBYTE
|
||||
/* may need to remove ^ when composing char was typed */
|
||||
if (enc_utf8 && utf_iscomposing(c) && !cmd_silent)
|
||||
@@ -1766,10 +1780,12 @@ getcmdline(
|
||||
ignore_drag_release = TRUE;
|
||||
#endif
|
||||
putcmdline('?', TRUE);
|
||||
extra_char = '?';
|
||||
#ifdef USE_ON_FLY_SCROLL
|
||||
dont_scroll = TRUE; /* disallow scrolling here */
|
||||
#endif
|
||||
c = get_digraph(TRUE);
|
||||
extra_char = NUL;
|
||||
if (c != NUL)
|
||||
break;
|
||||
|
||||
@@ -3401,6 +3417,8 @@ redrawcmd(void)
|
||||
msg_no_more = FALSE;
|
||||
|
||||
set_cmdspos_cursor();
|
||||
if (extra_char != NUL)
|
||||
putcmdline(extra_char, TRUE);
|
||||
|
||||
/*
|
||||
* An emsg() before may have set msg_scroll. This is used in normal mode,
|
||||
@@ -6878,6 +6896,8 @@ open_cmdwin(void)
|
||||
# ifdef FEAT_AUTOCMD
|
||||
/* Do execute autocommands for setting the filetype (load syntax). */
|
||||
unblock_autocmds();
|
||||
/* But don't allow switching to another buffer. */
|
||||
++curbuf_lock;
|
||||
# endif
|
||||
|
||||
/* Showing the prompt may have set need_wait_return, reset it. */
|
||||
@@ -6893,6 +6913,9 @@ open_cmdwin(void)
|
||||
}
|
||||
set_option_value((char_u *)"ft", 0L, (char_u *)"vim", OPT_LOCAL);
|
||||
}
|
||||
# ifdef FEAT_AUTOCMD
|
||||
--curbuf_lock;
|
||||
# endif
|
||||
|
||||
/* Reset 'textwidth' after setting 'filetype' (the Vim filetype plugin
|
||||
* sets 'textwidth' to 78). */
|
||||
@@ -7029,7 +7052,13 @@ open_cmdwin(void)
|
||||
else
|
||||
ccline.cmdbuff = vim_strsave(ml_get_curline());
|
||||
if (ccline.cmdbuff == NULL)
|
||||
{
|
||||
ccline.cmdbuff = vim_strsave((char_u *)"");
|
||||
ccline.cmdlen = 0;
|
||||
ccline.cmdbufflen = 1;
|
||||
ccline.cmdpos = 0;
|
||||
cmdwin_result = Ctrl_C;
|
||||
}
|
||||
else
|
||||
{
|
||||
ccline.cmdlen = (int)STRLEN(ccline.cmdbuff);
|
||||
|
||||
@@ -1267,6 +1267,13 @@
|
||||
# undef FEAT_JOB_CHANNEL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* +terminal ":terminal" command. Runs a terminal in a window.
|
||||
*/
|
||||
#if !defined(FEAT_JOB_CHANNEL) && defined(FEAT_TERMINAL)
|
||||
# undef FEAT_TERMINAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* +signs Allow signs to be displayed to the left of text lines.
|
||||
* Adds the ":sign" command.
|
||||
|
||||
168
src/fileio.c
168
src/fileio.c
@@ -3166,6 +3166,7 @@ buf_write(
|
||||
int device = FALSE; /* writing to a device */
|
||||
stat_T st_old;
|
||||
int prev_got_int = got_int;
|
||||
int checking_conversion;
|
||||
int file_readonly = FALSE; /* overwritten file is read-only */
|
||||
static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
|
||||
#if defined(UNIX) /*XXX fix me sometime? */
|
||||
@@ -4343,13 +4344,41 @@ buf_write(
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If conversion is taking place, we may first pretend to write and check
|
||||
* for conversion errors. Then loop again to write for real.
|
||||
* When not doing conversion this writes for real right away.
|
||||
*/
|
||||
for (checking_conversion = TRUE; ; checking_conversion = FALSE)
|
||||
{
|
||||
/*
|
||||
* There is no need to check conversion when:
|
||||
* - there is no conversion
|
||||
* - we make a backup file, that can be restored in case of conversion
|
||||
* failure.
|
||||
*/
|
||||
#ifdef FEAT_MBYTE
|
||||
if (!converted || dobackup)
|
||||
#endif
|
||||
checking_conversion = FALSE;
|
||||
|
||||
if (checking_conversion)
|
||||
{
|
||||
/* Make sure we don't write anything. */
|
||||
fd = -1;
|
||||
write_info.bw_fd = fd;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Open the file "wfname" for writing.
|
||||
* We may try to open the file twice: If we can't write to the
|
||||
* file and forceit is TRUE we delete the existing file and try to create
|
||||
* a new one. If this still fails we may have lost the original file!
|
||||
* (this may happen when the user reached his quotum for number of files).
|
||||
* Appending will fail if the file does not exist and forceit is FALSE.
|
||||
* We may try to open the file twice: If we can't write to the file
|
||||
* and forceit is TRUE we delete the existing file and try to
|
||||
* create a new one. If this still fails we may have lost the
|
||||
* original file! (this may happen when the user reached his
|
||||
* quotum for number of files).
|
||||
* Appending will fail if the file does not exist and forceit is
|
||||
* FALSE.
|
||||
*/
|
||||
while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
|
||||
? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
|
||||
@@ -4357,16 +4386,17 @@ buf_write(
|
||||
, perm < 0 ? 0666 : (perm & 0777))) < 0)
|
||||
{
|
||||
/*
|
||||
* A forced write will try to create a new file if the old one is
|
||||
* still readonly. This may also happen when the directory is
|
||||
* read-only. In that case the mch_remove() will fail.
|
||||
* A forced write will try to create a new file if the old one
|
||||
* is still readonly. This may also happen when the directory
|
||||
* is read-only. In that case the mch_remove() will fail.
|
||||
*/
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
#ifdef UNIX
|
||||
stat_T st;
|
||||
|
||||
/* Don't delete the file when it's a hard or symbolic link. */
|
||||
/* Don't delete the file when it's a hard or symbolic link.
|
||||
*/
|
||||
if ((!newfile && st_old.st_nlink > 1)
|
||||
|| (mch_lstat((char *)fname, &st) == 0
|
||||
&& (st.st_dev != st_old.st_dev
|
||||
@@ -4385,7 +4415,8 @@ buf_write(
|
||||
if (!(perm & 0200))
|
||||
made_writable = TRUE;
|
||||
perm |= 0200;
|
||||
if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
|
||||
if (st_old.st_uid != getuid()
|
||||
|| st_old.st_gid != getgid())
|
||||
perm &= 0777;
|
||||
#endif
|
||||
if (!append) /* don't remove when appending */
|
||||
@@ -4400,24 +4431,26 @@ restore_backup:
|
||||
stat_T st;
|
||||
|
||||
/*
|
||||
* If we failed to open the file, we don't need a backup. Throw it
|
||||
* away. If we moved or removed the original file try to put the
|
||||
* backup in its place.
|
||||
* If we failed to open the file, we don't need a backup.
|
||||
* Throw it away. If we moved or removed the original file
|
||||
* try to put the backup in its place.
|
||||
*/
|
||||
if (backup != NULL && wfname == fname)
|
||||
{
|
||||
if (backup_copy)
|
||||
{
|
||||
/*
|
||||
* There is a small chance that we removed the original,
|
||||
* try to move the copy in its place.
|
||||
* There is a small chance that we removed the
|
||||
* original, try to move the copy in its place.
|
||||
* This may not work if the vim_rename() fails.
|
||||
* In that case we leave the copy around.
|
||||
*/
|
||||
/* If file does not exist, put the copy in its place */
|
||||
/* If file does not exist, put the copy in its
|
||||
* place */
|
||||
if (mch_stat((char *)fname, &st) < 0)
|
||||
vim_rename(backup, fname);
|
||||
/* if original file does exist throw away the copy */
|
||||
/* if original file does exist throw away the copy
|
||||
*/
|
||||
if (mch_stat((char *)fname, &st) >= 0)
|
||||
mch_remove(backup);
|
||||
}
|
||||
@@ -4428,7 +4461,8 @@ restore_backup:
|
||||
}
|
||||
}
|
||||
|
||||
/* if original file no longer exists give an extra warning */
|
||||
/* if original file no longer exists give an extra warning
|
||||
*/
|
||||
if (!newfile && mch_stat((char *)fname, &st) < 0)
|
||||
end = 0;
|
||||
}
|
||||
@@ -4439,7 +4473,7 @@ restore_backup:
|
||||
#endif
|
||||
goto fail;
|
||||
}
|
||||
errmsg = NULL;
|
||||
write_info.bw_fd = fd;
|
||||
|
||||
#if defined(MACOS_CLASSIC) || defined(WIN3264)
|
||||
/* TODO: Is it need for MACOS_X? (Dany) */
|
||||
@@ -4464,15 +4498,14 @@ restore_backup:
|
||||
}
|
||||
#endif
|
||||
|
||||
write_info.bw_fd = fd;
|
||||
|
||||
#ifdef FEAT_CRYPT
|
||||
if (*buf->b_p_key != NUL && !filtering)
|
||||
{
|
||||
char_u *header;
|
||||
int header_len;
|
||||
|
||||
buf->b_cryptstate = crypt_create_for_writing(crypt_get_method_nr(buf),
|
||||
buf->b_cryptstate = crypt_create_for_writing(
|
||||
crypt_get_method_nr(buf),
|
||||
buf->b_p_key, &header, &header_len);
|
||||
if (buf->b_cryptstate == NULL || header == NULL)
|
||||
end = 0;
|
||||
@@ -4490,6 +4523,8 @@ restore_backup:
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
errmsg = NULL;
|
||||
|
||||
write_info.bw_buf = buffer;
|
||||
nchars = 0;
|
||||
@@ -4503,8 +4538,8 @@ restore_backup:
|
||||
#ifdef FEAT_MBYTE
|
||||
/*
|
||||
* The BOM is written just after the encryption magic number.
|
||||
* Skip it when appending and the file already existed, the BOM only makes
|
||||
* sense at the start of the file.
|
||||
* Skip it when appending and the file already existed, the BOM only
|
||||
* makes sense at the start of the file.
|
||||
*/
|
||||
if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
|
||||
{
|
||||
@@ -4523,8 +4558,12 @@ restore_backup:
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_PERSISTENT_UNDO
|
||||
write_undo_file = (buf->b_p_udf && overwriting && !append
|
||||
&& !filtering && reset_changed);
|
||||
write_undo_file = (buf->b_p_udf
|
||||
&& overwriting
|
||||
&& !append
|
||||
&& !filtering
|
||||
&& reset_changed
|
||||
&& !checking_conversion);
|
||||
if (write_undo_file)
|
||||
/* Prepare for computing the hash value of the text. */
|
||||
sha256_start(&sha_ctx);
|
||||
@@ -4546,7 +4585,8 @@ restore_backup:
|
||||
ptr = ml_get_buf(buf, lnum, FALSE) - 1;
|
||||
#ifdef FEAT_PERSISTENT_UNDO
|
||||
if (write_undo_file)
|
||||
sha256_update(&sha_ctx, ptr + 1, (UINT32_T)(STRLEN(ptr + 1) + 1));
|
||||
sha256_update(&sha_ctx, ptr + 1,
|
||||
(UINT32_T)(STRLEN(ptr + 1) + 1));
|
||||
#endif
|
||||
while ((c = *++ptr) != NUL)
|
||||
{
|
||||
@@ -4576,7 +4616,8 @@ restore_backup:
|
||||
|| (lnum == end
|
||||
&& (write_bin || !buf->b_p_fixeol)
|
||||
&& (lnum == buf->b_no_eol_lnum
|
||||
|| (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
|
||||
|| (lnum == buf->b_ml.ml_line_count
|
||||
&& !buf->b_p_eol))))
|
||||
{
|
||||
++lnum; /* written the line, count it */
|
||||
no_eol = TRUE;
|
||||
@@ -4623,12 +4664,12 @@ restore_backup:
|
||||
}
|
||||
#ifdef VMS
|
||||
/*
|
||||
* On VMS there is a problem: newlines get added when writing blocks
|
||||
* at a time. Fix it by writing a line at a time.
|
||||
* On VMS there is a problem: newlines get added when writing
|
||||
* blocks at a time. Fix it by writing a line at a time.
|
||||
* This is much slower!
|
||||
* Explanation: VAX/DECC RTL insists that records in some RMS
|
||||
* structures end with a newline (carriage return) character, and if
|
||||
* they don't it adds one.
|
||||
* structures end with a newline (carriage return) character, and
|
||||
* if they don't it adds one.
|
||||
* With other RMS structures it works perfect without this fix.
|
||||
*/
|
||||
if (buf->b_fab_rfm == FAB$C_VFC
|
||||
@@ -4666,15 +4707,29 @@ restore_backup:
|
||||
nchars += len;
|
||||
}
|
||||
|
||||
/* Stop when writing done or an error was encountered. */
|
||||
if (!checking_conversion || end == 0)
|
||||
break;
|
||||
|
||||
/* If no error happened until now, writing should be ok, so loop to
|
||||
* really write the buffer. */
|
||||
}
|
||||
|
||||
/* If we started writing, finish writing. Also when an error was
|
||||
* encountered. */
|
||||
if (!checking_conversion)
|
||||
{
|
||||
#if defined(UNIX) && defined(HAVE_FSYNC)
|
||||
/* On many journalling file systems there is a bug that causes both the
|
||||
* original and the backup file to be lost when halting the system right
|
||||
* after writing the file. That's because only the meta-data is
|
||||
* journalled. Syncing the file slows down the system, but assures it has
|
||||
* been written to disk and we don't lose it.
|
||||
* For a device do try the fsync() but don't complain if it does not work
|
||||
* (could be a pipe).
|
||||
* If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. */
|
||||
/*
|
||||
* On many journalling file systems there is a bug that causes both the
|
||||
* original and the backup file to be lost when halting the system
|
||||
* right after writing the file. That's because only the meta-data is
|
||||
* journalled. Syncing the file slows down the system, but assures it
|
||||
* has been written to disk and we don't lose it.
|
||||
* For a device do try the fsync() but don't complain if it does not
|
||||
* work (could be a pipe).
|
||||
* If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
|
||||
*/
|
||||
if (p_fs && fsync(fd) != 0 && !device)
|
||||
{
|
||||
errmsg = (char_u *)_("E667: Fsync failed");
|
||||
@@ -4689,8 +4744,8 @@ restore_backup:
|
||||
#endif
|
||||
|
||||
#ifdef UNIX
|
||||
/* When creating a new file, set its owner/group to that of the original
|
||||
* file. Get the new device and inode number. */
|
||||
/* When creating a new file, set its owner/group to that of the
|
||||
* original file. Get the new device and inode number. */
|
||||
if (backup != NULL && !backup_copy)
|
||||
{
|
||||
# ifdef HAVE_FCHOWN
|
||||
@@ -4731,9 +4786,9 @@ restore_backup:
|
||||
* Probably need to set the ACL before changing the user (can't set the
|
||||
* ACL on a file the user doesn't own).
|
||||
* On Solaris, with ZFS and the aclmode property set to "discard" (the
|
||||
* default), chmod() discards all part of a file's ACL that don't represent
|
||||
* the mode of the file. It's non-trivial for us to discover whether we're
|
||||
* in that situation, so we simply always re-set the ACL.
|
||||
* default), chmod() discards all part of a file's ACL that don't
|
||||
* represent the mode of the file. It's non-trivial for us to discover
|
||||
* whether we're in that situation, so we simply always re-set the ACL.
|
||||
*/
|
||||
# ifndef HAVE_SOLARIS_ZFS_ACL
|
||||
if (!backup_copy)
|
||||
@@ -4752,13 +4807,13 @@ restore_backup:
|
||||
if (wfname != fname)
|
||||
{
|
||||
/*
|
||||
* The file was written to a temp file, now it needs to be converted
|
||||
* with 'charconvert' to (overwrite) the output file.
|
||||
* The file was written to a temp file, now it needs to be
|
||||
* converted with 'charconvert' to (overwrite) the output file.
|
||||
*/
|
||||
if (end != 0)
|
||||
{
|
||||
if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
|
||||
wfname, fname) == FAIL)
|
||||
if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc,
|
||||
fenc, wfname, fname) == FAIL)
|
||||
{
|
||||
write_info.bw_conv_error = TRUE;
|
||||
end = 0;
|
||||
@@ -4768,9 +4823,13 @@ restore_backup:
|
||||
vim_free(wfname);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (end == 0)
|
||||
{
|
||||
/*
|
||||
* Error encountered.
|
||||
*/
|
||||
if (errmsg == NULL)
|
||||
{
|
||||
#ifdef FEAT_MBYTE
|
||||
@@ -5690,6 +5749,10 @@ buf_write_bytes(struct bw_info *ip)
|
||||
}
|
||||
#endif /* FEAT_MBYTE */
|
||||
|
||||
if (ip->bw_fd < 0)
|
||||
/* Only checking conversion, which is OK if we get here. */
|
||||
return OK;
|
||||
|
||||
#ifdef FEAT_CRYPT
|
||||
if (flags & FIO_ENCRYPTED)
|
||||
{
|
||||
@@ -8800,7 +8863,7 @@ do_doautocmd(
|
||||
/*
|
||||
* Loop over the events.
|
||||
*/
|
||||
while (*arg && !VIM_ISWHITE(*arg))
|
||||
while (*arg && !ends_excmd(*arg) && !VIM_ISWHITE(*arg))
|
||||
if (apply_autocmds_group(event_name2nr(arg, &arg),
|
||||
fname, NULL, TRUE, group, curbuf, NULL))
|
||||
nothing_done = FALSE;
|
||||
@@ -9322,7 +9385,8 @@ apply_autocmds_group(
|
||||
* Quickly return if there are no autocommands for this event or
|
||||
* autocommands are blocked.
|
||||
*/
|
||||
if (first_autopat[(int)event] == NULL || autocmd_blocked > 0)
|
||||
if (event == NUM_EVENTS || first_autopat[(int)event] == NULL
|
||||
|| autocmd_blocked > 0)
|
||||
goto BYPASS_AU;
|
||||
|
||||
/*
|
||||
@@ -9395,7 +9459,7 @@ apply_autocmds_group(
|
||||
{
|
||||
if (event == EVENT_COLORSCHEME || event == EVENT_OPTIONSET)
|
||||
autocmd_fname = NULL;
|
||||
else if (fname != NULL && *fname != NUL)
|
||||
else if (fname != NULL && !ends_excmd(*fname))
|
||||
autocmd_fname = fname;
|
||||
else if (buf != NULL)
|
||||
autocmd_fname = buf->b_ffname;
|
||||
|
||||
@@ -467,6 +467,11 @@ flush_buffers(int flush_typeahead)
|
||||
;
|
||||
typebuf.tb_off = MAXMAPLEN;
|
||||
typebuf.tb_len = 0;
|
||||
#if defined(FEAT_CLIENTSERVER) || defined(FEAT_EVAL)
|
||||
/* Reset the flag that text received from a client or from feedkeys()
|
||||
* was inserted in the typeahead buffer. */
|
||||
typebuf_was_filled = FALSE;
|
||||
#endif
|
||||
}
|
||||
else /* remove mapped characters at the start only */
|
||||
{
|
||||
|
||||
@@ -1036,7 +1036,6 @@ EXTERN int skip_redraw INIT(= FALSE); /* skip redraw once */
|
||||
EXTERN int do_redraw INIT(= FALSE); /* extra redraw once */
|
||||
|
||||
EXTERN int need_highlight_changed INIT(= TRUE);
|
||||
EXTERN char_u *use_viminfo INIT(= NULL); /* name of viminfo file to use */
|
||||
|
||||
#define NSCRIPT 15
|
||||
EXTERN FILE *scriptin[NSCRIPT]; /* streams to read script from */
|
||||
@@ -1659,6 +1658,7 @@ EXTERN int in_free_unref_items INIT(= FALSE);
|
||||
|
||||
#ifdef FEAT_TIMERS
|
||||
EXTERN int did_add_timer INIT(= FALSE);
|
||||
EXTERN int timer_busy INIT(= 0); /* when timer is inside vgetc() then > 0 */
|
||||
#endif
|
||||
|
||||
#ifdef FEAT_EVAL
|
||||
|
||||
@@ -779,6 +779,7 @@ get_exceptions(void)
|
||||
|
||||
static int initialised = 0;
|
||||
#define PYINITIALISED initialised
|
||||
static int python_end_called = FALSE;
|
||||
|
||||
#define DESTRUCTOR_FINISH(self) self->ob_type->tp_free((PyObject*)self);
|
||||
|
||||
@@ -878,6 +879,7 @@ python_end(void)
|
||||
if (recurse != 0)
|
||||
return;
|
||||
|
||||
python_end_called = TRUE;
|
||||
++recurse;
|
||||
|
||||
#ifdef DYNAMIC_PYTHON
|
||||
@@ -1040,6 +1042,8 @@ DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg)
|
||||
}
|
||||
++recursive;
|
||||
#endif
|
||||
if (python_end_called)
|
||||
return;
|
||||
|
||||
#if defined(MACOS) && !defined(MACOS_X_UNIX)
|
||||
GetPort(&oldPort);
|
||||
@@ -1568,7 +1572,7 @@ do_pyeval (char_u *str, typval_T *rettv)
|
||||
(rangeinitializer) init_range_eval,
|
||||
(runner) run_eval,
|
||||
(void *) rettv);
|
||||
switch(rettv->v_type)
|
||||
switch (rettv->v_type)
|
||||
{
|
||||
case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break;
|
||||
case VAR_LIST: ++rettv->vval.v_list->lv_refcount; break;
|
||||
|
||||
@@ -733,8 +733,8 @@ get_py3_exceptions(void)
|
||||
#endif /* DYNAMIC_PYTHON3 */
|
||||
|
||||
static int py3initialised = 0;
|
||||
|
||||
#define PYINITIALISED py3initialised
|
||||
static int python_end_called = FALSE;
|
||||
|
||||
#define DESTRUCTOR_FINISH(self) Py_TYPE(self)->tp_free((PyObject*)self)
|
||||
|
||||
@@ -817,6 +817,7 @@ python3_end(void)
|
||||
if (recurse != 0)
|
||||
return;
|
||||
|
||||
python_end_called = TRUE;
|
||||
++recurse;
|
||||
|
||||
#ifdef DYNAMIC_PYTHON3
|
||||
@@ -938,6 +939,9 @@ DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg)
|
||||
PyObject *cmdbytes;
|
||||
PyGILState_STATE pygilstate;
|
||||
|
||||
if (python_end_called)
|
||||
goto theend;
|
||||
|
||||
#if defined(MACOS) && !defined(MACOS_X_UNIX)
|
||||
GetPort(&oldPort);
|
||||
/* Check if the Python library is available */
|
||||
|
||||
195
src/keymap.h
195
src/keymap.h
@@ -112,6 +112,7 @@
|
||||
|
||||
/* Used for the sgr mouse. */
|
||||
#define KS_SGR_MOUSE 237
|
||||
#define KS_SGR_MOUSE_RELEASE 236
|
||||
|
||||
/*
|
||||
* Filler used after KS_SPECIAL and others
|
||||
@@ -139,6 +140,8 @@
|
||||
|
||||
/*
|
||||
* Codes for keys that do not have a termcap name.
|
||||
* The numbers are fixed to make sure that recorded key sequences remain valid.
|
||||
* Add new entries at the end, not halfway.
|
||||
*
|
||||
* K_SPECIAL KS_EXTRA KE_xxx
|
||||
*/
|
||||
@@ -146,125 +149,126 @@ enum key_extra
|
||||
{
|
||||
KE_NAME = 3 /* name of this terminal entry */
|
||||
|
||||
, KE_S_UP /* shift-up */
|
||||
, KE_S_DOWN /* shift-down */
|
||||
, KE_S_UP = 4 /* shift-up */
|
||||
, KE_S_DOWN = 5 /* shift-down */
|
||||
|
||||
, KE_S_F1 /* shifted function keys */
|
||||
, KE_S_F2
|
||||
, KE_S_F3
|
||||
, KE_S_F4
|
||||
, KE_S_F5
|
||||
, KE_S_F6
|
||||
, KE_S_F7
|
||||
, KE_S_F8
|
||||
, KE_S_F9
|
||||
, KE_S_F10
|
||||
, KE_S_F1 = 6 /* shifted function keys */
|
||||
, KE_S_F2 = 7
|
||||
, KE_S_F3 = 8
|
||||
, KE_S_F4 = 9
|
||||
, KE_S_F5 = 10
|
||||
, KE_S_F6 = 11
|
||||
, KE_S_F7 = 12
|
||||
, KE_S_F8 = 13
|
||||
, KE_S_F9 = 14
|
||||
, KE_S_F10 = 15
|
||||
|
||||
, KE_S_F11
|
||||
, KE_S_F12
|
||||
, KE_S_F13
|
||||
, KE_S_F14
|
||||
, KE_S_F15
|
||||
, KE_S_F16
|
||||
, KE_S_F17
|
||||
, KE_S_F18
|
||||
, KE_S_F19
|
||||
, KE_S_F20
|
||||
, KE_S_F11 = 16
|
||||
, KE_S_F12 = 17
|
||||
, KE_S_F13 = 18
|
||||
, KE_S_F14 = 19
|
||||
, KE_S_F15 = 20
|
||||
, KE_S_F16 = 21
|
||||
, KE_S_F17 = 22
|
||||
, KE_S_F18 = 23
|
||||
, KE_S_F19 = 24
|
||||
, KE_S_F20 = 25
|
||||
|
||||
, KE_S_F21
|
||||
, KE_S_F22
|
||||
, KE_S_F23
|
||||
, KE_S_F24
|
||||
, KE_S_F25
|
||||
, KE_S_F26
|
||||
, KE_S_F27
|
||||
, KE_S_F28
|
||||
, KE_S_F29
|
||||
, KE_S_F30
|
||||
, KE_S_F21 = 26
|
||||
, KE_S_F22 = 27
|
||||
, KE_S_F23 = 28
|
||||
, KE_S_F24 = 29
|
||||
, KE_S_F25 = 30
|
||||
, KE_S_F26 = 31
|
||||
, KE_S_F27 = 32
|
||||
, KE_S_F28 = 33
|
||||
, KE_S_F29 = 34
|
||||
, KE_S_F30 = 35
|
||||
|
||||
, KE_S_F31
|
||||
, KE_S_F32
|
||||
, KE_S_F33
|
||||
, KE_S_F34
|
||||
, KE_S_F35
|
||||
, KE_S_F36
|
||||
, KE_S_F37
|
||||
, KE_S_F31 = 36
|
||||
, KE_S_F32 = 37
|
||||
, KE_S_F33 = 38
|
||||
, KE_S_F34 = 39
|
||||
, KE_S_F35 = 40
|
||||
, KE_S_F36 = 41
|
||||
, KE_S_F37 = 42
|
||||
|
||||
, KE_MOUSE /* mouse event start */
|
||||
, KE_MOUSE = 43 /* mouse event start */
|
||||
|
||||
/*
|
||||
* Symbols for pseudo keys which are translated from the real key symbols
|
||||
* above.
|
||||
*/
|
||||
, KE_LEFTMOUSE /* Left mouse button click */
|
||||
, KE_LEFTDRAG /* Drag with left mouse button down */
|
||||
, KE_LEFTRELEASE /* Left mouse button release */
|
||||
, KE_MIDDLEMOUSE /* Middle mouse button click */
|
||||
, KE_MIDDLEDRAG /* Drag with middle mouse button down */
|
||||
, KE_MIDDLERELEASE /* Middle mouse button release */
|
||||
, KE_RIGHTMOUSE /* Right mouse button click */
|
||||
, KE_RIGHTDRAG /* Drag with right mouse button down */
|
||||
, KE_RIGHTRELEASE /* Right mouse button release */
|
||||
, KE_LEFTMOUSE = 44 /* Left mouse button click */
|
||||
, KE_LEFTDRAG = 45 /* Drag with left mouse button down */
|
||||
, KE_LEFTRELEASE = 46 /* Left mouse button release */
|
||||
, KE_MIDDLEMOUSE = 47 /* Middle mouse button click */
|
||||
, KE_MIDDLEDRAG = 48 /* Drag with middle mouse button down */
|
||||
, KE_MIDDLERELEASE = 49 /* Middle mouse button release */
|
||||
, KE_RIGHTMOUSE = 50 /* Right mouse button click */
|
||||
, KE_RIGHTDRAG = 51 /* Drag with right mouse button down */
|
||||
, KE_RIGHTRELEASE = 52 /* Right mouse button release */
|
||||
|
||||
, KE_IGNORE /* Ignored mouse drag/release */
|
||||
, KE_IGNORE = 53 /* Ignored mouse drag/release */
|
||||
|
||||
, KE_TAB /* unshifted TAB key */
|
||||
, KE_S_TAB_OLD /* shifted TAB key (no longer used) */
|
||||
, KE_TAB = 54 /* unshifted TAB key */
|
||||
, KE_S_TAB_OLD = 55 /* shifted TAB key (no longer used) */
|
||||
|
||||
, KE_XF1 /* extra vt100 function keys for xterm */
|
||||
, KE_XF2
|
||||
, KE_XF3
|
||||
, KE_XF4
|
||||
, KE_XEND /* extra (vt100) end key for xterm */
|
||||
, KE_ZEND /* extra (vt100) end key for xterm */
|
||||
, KE_XHOME /* extra (vt100) home key for xterm */
|
||||
, KE_ZHOME /* extra (vt100) home key for xterm */
|
||||
, KE_XUP /* extra vt100 cursor keys for xterm */
|
||||
, KE_XDOWN
|
||||
, KE_XLEFT
|
||||
, KE_XRIGHT
|
||||
, KE_SNIFF_UNUSED = 56 /* obsolete */
|
||||
, KE_XF1 = 57 /* extra vt100 function keys for xterm */
|
||||
, KE_XF2 = 58
|
||||
, KE_XF3 = 59
|
||||
, KE_XF4 = 60
|
||||
, KE_XEND = 61 /* extra (vt100) end key for xterm */
|
||||
, KE_ZEND = 62 /* extra (vt100) end key for xterm */
|
||||
, KE_XHOME = 63 /* extra (vt100) home key for xterm */
|
||||
, KE_ZHOME = 64 /* extra (vt100) home key for xterm */
|
||||
, KE_XUP = 65 /* extra vt100 cursor keys for xterm */
|
||||
, KE_XDOWN = 66
|
||||
, KE_XLEFT = 67
|
||||
, KE_XRIGHT = 68
|
||||
|
||||
, KE_LEFTMOUSE_NM /* non-mappable Left mouse button click */
|
||||
, KE_LEFTRELEASE_NM /* non-mappable left mouse button release */
|
||||
, KE_LEFTMOUSE_NM = 69 /* non-mappable Left mouse button click */
|
||||
, KE_LEFTRELEASE_NM = 70 /* non-mappable left mouse button release */
|
||||
|
||||
, KE_S_XF1 /* extra vt100 shifted function keys for xterm */
|
||||
, KE_S_XF2
|
||||
, KE_S_XF3
|
||||
, KE_S_XF4
|
||||
, KE_S_XF1 = 71 /* vt100 shifted function keys for xterm */
|
||||
, KE_S_XF2 = 72
|
||||
, KE_S_XF3 = 73
|
||||
, KE_S_XF4 = 74
|
||||
|
||||
/* NOTE: The scroll wheel events are inverted: i.e. UP is the same as
|
||||
* moving the actual scroll wheel down, LEFT is the same as moving the
|
||||
* scroll wheel right. */
|
||||
, KE_MOUSEDOWN /* scroll wheel pseudo-button Down */
|
||||
, KE_MOUSEUP /* scroll wheel pseudo-button Up */
|
||||
, KE_MOUSELEFT /* scroll wheel pseudo-button Left */
|
||||
, KE_MOUSERIGHT /* scroll wheel pseudo-button Right */
|
||||
, KE_MOUSEDOWN = 75 /* scroll wheel pseudo-button Down */
|
||||
, KE_MOUSEUP = 76 /* scroll wheel pseudo-button Up */
|
||||
, KE_MOUSELEFT = 77 /* scroll wheel pseudo-button Left */
|
||||
, KE_MOUSERIGHT = 78 /* scroll wheel pseudo-button Right */
|
||||
|
||||
, KE_KINS /* keypad Insert key */
|
||||
, KE_KDEL /* keypad Delete key */
|
||||
, KE_KINS = 79 /* keypad Insert key */
|
||||
, KE_KDEL = 80 /* keypad Delete key */
|
||||
|
||||
, KE_CSI /* CSI typed directly */
|
||||
, KE_SNR /* <SNR> */
|
||||
, KE_PLUG /* <Plug> */
|
||||
, KE_CMDWIN /* open command-line window from Command-line Mode */
|
||||
, KE_CSI = 81 /* CSI typed directly */
|
||||
, KE_SNR = 82 /* <SNR> */
|
||||
, KE_PLUG = 83 /* <Plug> */
|
||||
, KE_CMDWIN = 84 /* open command-line window from Command-line Mode */
|
||||
|
||||
, KE_C_LEFT /* control-left */
|
||||
, KE_C_RIGHT /* control-right */
|
||||
, KE_C_HOME /* control-home */
|
||||
, KE_C_END /* control-end */
|
||||
, KE_C_LEFT = 85 /* control-left */
|
||||
, KE_C_RIGHT = 86 /* control-right */
|
||||
, KE_C_HOME = 87 /* control-home */
|
||||
, KE_C_END = 88 /* control-end */
|
||||
|
||||
, KE_X1MOUSE /* X1/X2 mouse-buttons */
|
||||
, KE_X1DRAG
|
||||
, KE_X1RELEASE
|
||||
, KE_X2MOUSE
|
||||
, KE_X2DRAG
|
||||
, KE_X2RELEASE
|
||||
, KE_X1MOUSE = 89 /* X1/X2 mouse-buttons */
|
||||
, KE_X1DRAG = 90
|
||||
, KE_X1RELEASE = 91
|
||||
, KE_X2MOUSE = 92
|
||||
, KE_X2DRAG = 93
|
||||
, KE_X2RELEASE = 94
|
||||
|
||||
, KE_DROP /* DnD data is available */
|
||||
, KE_CURSORHOLD /* CursorHold event */
|
||||
, KE_NOP /* doesn't do something */
|
||||
, KE_FOCUSGAINED /* focus gained */
|
||||
, KE_FOCUSLOST /* focus lost */
|
||||
, KE_DROP = 95 /* DnD data is available */
|
||||
, KE_CURSORHOLD = 96 /* CursorHold event */
|
||||
, KE_NOP = 97 /* doesn't do something */
|
||||
, KE_FOCUSGAINED = 98 /* focus gained */
|
||||
, KE_FOCUSLOST = 99 /* focus lost */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -416,6 +420,7 @@ enum key_extra
|
||||
#define K_PTERM_MOUSE TERMCAP2KEY(KS_PTERM_MOUSE, KE_FILLER)
|
||||
#define K_URXVT_MOUSE TERMCAP2KEY(KS_URXVT_MOUSE, KE_FILLER)
|
||||
#define K_SGR_MOUSE TERMCAP2KEY(KS_SGR_MOUSE, KE_FILLER)
|
||||
#define K_SGR_MOUSERELEASE TERMCAP2KEY(KS_SGR_MOUSE_RELEASE, KE_FILLER)
|
||||
|
||||
#define K_SELECT TERMCAP2KEY(KS_SELECT, KE_FILLER)
|
||||
#define K_TEAROFF TERMCAP2KEY(KS_TEAROFF, KE_FILLER)
|
||||
|
||||
13
src/libvterm/.bzrignore
Normal file
13
src/libvterm/.bzrignore
Normal file
@@ -0,0 +1,13 @@
|
||||
.libs
|
||||
*.lo
|
||||
*.la
|
||||
|
||||
bin/*
|
||||
!bin/*.c
|
||||
|
||||
pangoterm
|
||||
t/test
|
||||
t/suites.h
|
||||
t/externs.h
|
||||
t/harness
|
||||
src/encoding/*.inc
|
||||
17
src/libvterm/.gitignore
vendored
Normal file
17
src/libvterm/.gitignore
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
*~
|
||||
*.swp
|
||||
|
||||
tags
|
||||
src/*.o
|
||||
src/*.lo
|
||||
|
||||
libvterm.la
|
||||
bin/unterm
|
||||
bin/vterm-ctrl
|
||||
bin/vterm-dump
|
||||
|
||||
t/harness
|
||||
t/harness.lo
|
||||
t/harness.o
|
||||
|
||||
.libs/
|
||||
23
src/libvterm/LICENSE
Normal file
23
src/libvterm/LICENSE
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2008 Paul Evans <leonerd@leonerd.org.uk>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
145
src/libvterm/Makefile
Normal file
145
src/libvterm/Makefile
Normal file
@@ -0,0 +1,145 @@
|
||||
ifeq ($(shell uname),Darwin)
|
||||
LIBTOOL ?= glibtool
|
||||
else
|
||||
LIBTOOL ?= libtool
|
||||
endif
|
||||
|
||||
ifneq ($(VERBOSE),1)
|
||||
LIBTOOL +=--quiet
|
||||
endif
|
||||
|
||||
# override CFLAGS +=-Wall -Iinclude -std=c99 -DINLINE="static inline" -DUSE_INLINE
|
||||
override CFLAGS +=-Wall -Iinclude -std=c90 -Wpedantic -DINLINE=""
|
||||
|
||||
ifeq ($(shell uname),SunOS)
|
||||
override CFLAGS +=-D__EXTENSIONS__ -D_XPG6 -D__XOPEN_OR_POSIX
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),1)
|
||||
override CFLAGS +=-ggdb -DDEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(PROFILE),1)
|
||||
override CFLAGS +=-pg
|
||||
override LDFLAGS+=-pg
|
||||
endif
|
||||
|
||||
CFILES=$(sort $(wildcard src/*.c))
|
||||
HFILES=$(sort $(wildcard include/*.h))
|
||||
OBJECTS=$(CFILES:.c=.lo)
|
||||
LIBRARY=libvterm.la
|
||||
|
||||
BINFILES_SRC=$(sort $(wildcard bin/*.c))
|
||||
BINFILES=$(BINFILES_SRC:.c=)
|
||||
|
||||
TBLFILES=$(sort $(wildcard src/encoding/*.tbl))
|
||||
INCFILES=$(TBLFILES:.tbl=.inc)
|
||||
|
||||
HFILES_INT=$(sort $(wildcard src/*.h)) $(HFILES)
|
||||
|
||||
VERSION_MAJOR=0
|
||||
VERSION_MINOR=0
|
||||
|
||||
VERSION_CURRENT=0
|
||||
VERSION_REVISION=0
|
||||
VERSION_AGE=0
|
||||
|
||||
VERSION=0
|
||||
|
||||
PREFIX=/usr/local
|
||||
BINDIR=$(PREFIX)/bin
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
INCDIR=$(PREFIX)/include
|
||||
MANDIR=$(PREFIX)/share/man
|
||||
MAN3DIR=$(MANDIR)/man3
|
||||
|
||||
all: $(LIBRARY) $(BINFILES)
|
||||
|
||||
$(LIBRARY): $(OBJECTS)
|
||||
@echo LINK $@
|
||||
@$(LIBTOOL) --mode=link --tag=CC $(CC) -rpath $(LIBDIR) -version-info $(VERSION_CURRENT):$(VERSION_REVISION):$(VERSION_AGE) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
src/%.lo: src/%.c $(HFILES_INT)
|
||||
@echo CC $<
|
||||
@$(LIBTOOL) --mode=compile --tag=CC $(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
src/encoding/%.inc: src/encoding/%.tbl
|
||||
@echo TBL $<
|
||||
@perl -CSD tbl2inc_c.pl $< >$@
|
||||
|
||||
src/encoding.lo: $(INCFILES)
|
||||
|
||||
bin/%: bin/%.c $(LIBRARY)
|
||||
@echo CC $<
|
||||
@$(LIBTOOL) --mode=link --tag=CC $(CC) $(CFLAGS) -o $@ $< -lvterm $(LDFLAGS)
|
||||
|
||||
t/harness.lo: t/harness.c $(HFILES)
|
||||
@echo CC $<
|
||||
@$(LIBTOOL) --mode=compile --tag=CC $(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
t/harness: t/harness.lo $(LIBRARY)
|
||||
@echo LINK $@
|
||||
@$(LIBTOOL) --mode=link --tag=CC $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
.PHONY: test
|
||||
test: $(LIBRARY) t/harness
|
||||
for T in `ls t/[0-9]*.test`; do echo "** $$T **"; perl t/run-test.pl $$T $(if $(VALGRIND),--valgrind) || exit 1; done
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(LIBTOOL) --mode=clean rm -f $(OBJECTS) $(INCFILES)
|
||||
$(LIBTOOL) --mode=clean rm -f t/harness.lo t/harness
|
||||
$(LIBTOOL) --mode=clean rm -f $(LIBRARY) $(BINFILES)
|
||||
|
||||
.PHONY: install
|
||||
install: install-inc install-lib install-bin
|
||||
|
||||
install-inc:
|
||||
install -d $(DESTDIR)$(INCDIR)
|
||||
install -m644 $(HFILES) $(DESTDIR)$(INCDIR)
|
||||
install -d $(DESTDIR)$(LIBDIR)/pkgconfig
|
||||
sed -e "s,@PREFIX@,$(PREFIX)," -e "s,@LIBDIR@,$(LIBDIR)," -e "s,@VERSION@,$(VERSION)," <vterm.pc.in >$(DESTDIR)$(LIBDIR)/pkgconfig/vterm.pc
|
||||
|
||||
install-lib: $(LIBRARY)
|
||||
install -d $(DESTDIR)$(LIBDIR)
|
||||
$(LIBTOOL) --mode=install install $(LIBRARY) $(DESTDIR)$(LIBDIR)/$(LIBRARY)
|
||||
$(LIBTOOL) --mode=finish $(DESTDIR)$(LIBDIR)
|
||||
|
||||
install-bin: $(BINFILES)
|
||||
install -d $(DESTDIR)$(BINDIR)
|
||||
$(LIBTOOL) --mode=install install $(BINFILES) $(DESTDIR)$(BINDIR)/
|
||||
|
||||
# DIST CUT
|
||||
|
||||
VERSION=$(VERSION_MAJOR).$(VERSION_MINOR)
|
||||
|
||||
DISTDIR=libvterm-$(VERSION)
|
||||
|
||||
distdir: $(INCFILES)
|
||||
mkdir __distdir
|
||||
cp LICENSE __distdir
|
||||
mkdir __distdir/src
|
||||
cp src/*.c src/*.h __distdir/src
|
||||
mkdir __distdir/src/encoding
|
||||
cp src/encoding/*.inc __distdir/src/encoding
|
||||
mkdir __distdir/include
|
||||
cp include/*.h __distdir/include
|
||||
mkdir __distdir/bin
|
||||
cp bin/*.c __distdir/bin
|
||||
mkdir __distdir/t
|
||||
cp t/*.test t/harness.c t/run-test.pl __distdir/t
|
||||
sed "s,@VERSION@,$(VERSION)," <vterm.pc.in >__distdir/vterm.pc.in
|
||||
sed "/^# DIST CUT/Q" <Makefile >__distdir/Makefile
|
||||
mv __distdir $(DISTDIR)
|
||||
|
||||
TARBALL=$(DISTDIR).tar.gz
|
||||
|
||||
dist: distdir
|
||||
tar -czf $(TARBALL) $(DISTDIR)
|
||||
rm -rf $(DISTDIR)
|
||||
|
||||
dist+bzr:
|
||||
$(MAKE) dist VERSION=$(VERSION)+bzr`bzr revno`
|
||||
|
||||
distdir+bzr:
|
||||
$(MAKE) distdir VERSION=$(VERSION)+bzr`bzr revno`
|
||||
13
src/libvterm/README
Normal file
13
src/libvterm/README
Normal file
@@ -0,0 +1,13 @@
|
||||
This is a MODIFIED version of libvterm.
|
||||
|
||||
The original can be found:
|
||||
On the original site (tar archive and Bazaar repository):
|
||||
http://www.leonerd.org.uk/code/libvterm/
|
||||
Cloned on Github:
|
||||
https://github.com/neovim/libvterm
|
||||
|
||||
Modifications:
|
||||
- Add a .gitignore file.
|
||||
- Convert from C99 to C90.
|
||||
- Other changes to support embedding in Vim.
|
||||
-
|
||||
287
src/libvterm/bin/unterm.c
Normal file
287
src/libvterm/bin/unterm.c
Normal file
@@ -0,0 +1,287 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "vterm.h"
|
||||
|
||||
#define DEFINE_INLINES
|
||||
#include "../src/utf8.h" /* fill_utf8 */
|
||||
|
||||
#define streq(a,b) (!strcmp(a,b))
|
||||
|
||||
static VTerm *vt;
|
||||
static VTermScreen *vts;
|
||||
|
||||
static int cols;
|
||||
static int rows;
|
||||
|
||||
static enum {
|
||||
FORMAT_PLAIN,
|
||||
FORMAT_SGR
|
||||
} format = FORMAT_PLAIN;
|
||||
|
||||
static int col2index(VTermColor target)
|
||||
{
|
||||
int index;
|
||||
|
||||
for(index = 0; index < 256; index++) {
|
||||
VTermColor col;
|
||||
vterm_state_get_palette_color(NULL, index, &col);
|
||||
if(col.red == target.red && col.green == target.green && col.blue == target.blue)
|
||||
return index;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void dump_cell(const VTermScreenCell *cell, const VTermScreenCell *prevcell)
|
||||
{
|
||||
switch(format) {
|
||||
case FORMAT_PLAIN:
|
||||
break;
|
||||
case FORMAT_SGR:
|
||||
{
|
||||
/* If all 7 attributes change, that means 7 SGRs max */
|
||||
/* Each colour could consume up to 3 */
|
||||
int sgr[7 + 2*3]; int sgri = 0;
|
||||
|
||||
if(!prevcell->attrs.bold && cell->attrs.bold)
|
||||
sgr[sgri++] = 1;
|
||||
if(prevcell->attrs.bold && !cell->attrs.bold)
|
||||
sgr[sgri++] = 22;
|
||||
|
||||
if(!prevcell->attrs.underline && cell->attrs.underline)
|
||||
sgr[sgri++] = 4;
|
||||
if(prevcell->attrs.underline && !cell->attrs.underline)
|
||||
sgr[sgri++] = 24;
|
||||
|
||||
if(!prevcell->attrs.italic && cell->attrs.italic)
|
||||
sgr[sgri++] = 3;
|
||||
if(prevcell->attrs.italic && !cell->attrs.italic)
|
||||
sgr[sgri++] = 23;
|
||||
|
||||
if(!prevcell->attrs.blink && cell->attrs.blink)
|
||||
sgr[sgri++] = 5;
|
||||
if(prevcell->attrs.blink && !cell->attrs.blink)
|
||||
sgr[sgri++] = 25;
|
||||
|
||||
if(!prevcell->attrs.reverse && cell->attrs.reverse)
|
||||
sgr[sgri++] = 7;
|
||||
if(prevcell->attrs.reverse && !cell->attrs.reverse)
|
||||
sgr[sgri++] = 27;
|
||||
|
||||
if(!prevcell->attrs.strike && cell->attrs.strike)
|
||||
sgr[sgri++] = 9;
|
||||
if(prevcell->attrs.strike && !cell->attrs.strike)
|
||||
sgr[sgri++] = 29;
|
||||
|
||||
if(!prevcell->attrs.font && cell->attrs.font)
|
||||
sgr[sgri++] = 10 + cell->attrs.font;
|
||||
if(prevcell->attrs.font && !cell->attrs.font)
|
||||
sgr[sgri++] = 10;
|
||||
|
||||
if(prevcell->fg.red != cell->fg.red ||
|
||||
prevcell->fg.green != cell->fg.green ||
|
||||
prevcell->fg.blue != cell->fg.blue) {
|
||||
int index = col2index(cell->fg);
|
||||
if(index == -1)
|
||||
sgr[sgri++] = 39;
|
||||
else if(index < 8)
|
||||
sgr[sgri++] = 30 + index;
|
||||
else if(index < 16)
|
||||
sgr[sgri++] = 90 + (index - 8);
|
||||
else {
|
||||
sgr[sgri++] = 38;
|
||||
sgr[sgri++] = 5 | (1<<31);
|
||||
sgr[sgri++] = index | (1<<31);
|
||||
}
|
||||
}
|
||||
|
||||
if(prevcell->bg.red != cell->bg.red ||
|
||||
prevcell->bg.green != cell->bg.green ||
|
||||
prevcell->bg.blue != cell->bg.blue) {
|
||||
int index = col2index(cell->bg);
|
||||
if(index == -1)
|
||||
sgr[sgri++] = 49;
|
||||
else if(index < 8)
|
||||
sgr[sgri++] = 40 + index;
|
||||
else if(index < 16)
|
||||
sgr[sgri++] = 100 + (index - 8);
|
||||
else {
|
||||
sgr[sgri++] = 48;
|
||||
sgr[sgri++] = 5 | (1<<31);
|
||||
sgr[sgri++] = index | (1<<31);
|
||||
}
|
||||
}
|
||||
|
||||
if(!sgri)
|
||||
break;
|
||||
|
||||
printf("\x1b[");
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < sgri; i++)
|
||||
printf(!i ? "%d" :
|
||||
sgr[i] & (1<<31) ? ":%d" :
|
||||
";%d",
|
||||
sgr[i] & ~(1<<31));
|
||||
}
|
||||
printf("m");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && cell->chars[i]; i++) {
|
||||
char bytes[6];
|
||||
bytes[fill_utf8(cell->chars[i], bytes)] = 0;
|
||||
printf("%s", bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_eol(const VTermScreenCell *prevcell)
|
||||
{
|
||||
switch(format) {
|
||||
case FORMAT_PLAIN:
|
||||
break;
|
||||
case FORMAT_SGR:
|
||||
if(prevcell->attrs.bold || prevcell->attrs.underline || prevcell->attrs.italic ||
|
||||
prevcell->attrs.blink || prevcell->attrs.reverse || prevcell->attrs.strike ||
|
||||
prevcell->attrs.font)
|
||||
printf("\x1b[m");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void dump_row(int row)
|
||||
{
|
||||
VTermPos pos;
|
||||
VTermScreenCell prevcell;
|
||||
pos.row = row;
|
||||
pos.col = 0;
|
||||
memset(&prevcell, 0, sizeof(prevcell));
|
||||
vterm_state_get_default_colors(vterm_obtain_state(vt), &prevcell.fg, &prevcell.bg);
|
||||
|
||||
while(pos.col < cols) {
|
||||
VTermScreenCell cell;
|
||||
vterm_screen_get_cell(vts, pos, &cell);
|
||||
|
||||
dump_cell(&cell, &prevcell);
|
||||
|
||||
pos.col += cell.width;
|
||||
prevcell = cell;
|
||||
}
|
||||
|
||||
dump_eol(&prevcell);
|
||||
}
|
||||
|
||||
static int screen_sb_pushline(int cols, const VTermScreenCell *cells, void *user)
|
||||
{
|
||||
VTermScreenCell prevcell;
|
||||
int col;
|
||||
|
||||
memset(&prevcell, 0, sizeof(prevcell));
|
||||
vterm_state_get_default_colors(vterm_obtain_state(vt), &prevcell.fg, &prevcell.bg);
|
||||
|
||||
for(col = 0; col < cols; col++) {
|
||||
dump_cell(cells + col, &prevcell);
|
||||
prevcell = cells[col];
|
||||
}
|
||||
|
||||
dump_eol(&prevcell);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int screen_resize(int new_rows, int new_cols, void *user)
|
||||
{
|
||||
rows = new_rows;
|
||||
cols = new_cols;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static VTermScreenCallbacks cb_screen = {
|
||||
NULL, /* damage */
|
||||
NULL, /* moverect */
|
||||
NULL, /* movecursor */
|
||||
NULL, /* settermprop */
|
||||
NULL, /* bell */
|
||||
&screen_resize, /* resize */
|
||||
&screen_sb_pushline, /* sb_pushline */
|
||||
NULL, /* popline */
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int opt;
|
||||
const char *file;
|
||||
int fd;
|
||||
int len;
|
||||
char buffer[1024];
|
||||
int row;
|
||||
|
||||
rows = 25;
|
||||
cols = 80;
|
||||
|
||||
while((opt = getopt(argc, argv, "f:l:c:")) != -1) {
|
||||
switch(opt) {
|
||||
case 'f':
|
||||
if(streq(optarg, "plain"))
|
||||
format = FORMAT_PLAIN;
|
||||
else if(streq(optarg, "sgr"))
|
||||
format = FORMAT_SGR;
|
||||
else {
|
||||
fprintf(stderr, "Unrecognised format '%s'\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
rows = atoi(optarg);
|
||||
if(!rows)
|
||||
rows = 25;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
cols = atoi(optarg);
|
||||
if(!cols)
|
||||
cols = 80;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file = argv[optind++];
|
||||
fd = open(file, O_RDONLY);
|
||||
if(fd == -1) {
|
||||
fprintf(stderr, "Cannot open %s - %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
vt = vterm_new(rows, cols);
|
||||
vterm_set_utf8(vt, true);
|
||||
|
||||
vts = vterm_obtain_screen(vt);
|
||||
vterm_screen_set_callbacks(vts, &cb_screen, NULL);
|
||||
|
||||
vterm_screen_reset(vts, 1);
|
||||
|
||||
while((len = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
vterm_input_write(vt, buffer, len);
|
||||
}
|
||||
|
||||
for(row = 0; row < rows; row++) {
|
||||
dump_row(row);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
vterm_free(vt);
|
||||
return 0;
|
||||
}
|
||||
362
src/libvterm/bin/vterm-ctrl.c
Normal file
362
src/libvterm/bin/vterm-ctrl.c
Normal file
@@ -0,0 +1,362 @@
|
||||
#define _XOPEN_SOURCE 500 /* strdup */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#define streq(a,b) (strcmp(a,b)==0)
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
static char *getvalue(int *argip, int argc, char *argv[])
|
||||
{
|
||||
if(*argip >= argc) {
|
||||
fprintf(stderr, "Expected an option value\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return argv[(*argip)++];
|
||||
}
|
||||
|
||||
static int getchoice(int *argip, int argc, char *argv[], const char *options[])
|
||||
{
|
||||
const char *arg = getvalue(argip, argc, argv);
|
||||
|
||||
int value = -1;
|
||||
while(options[++value])
|
||||
if(streq(arg, options[value]))
|
||||
return value;
|
||||
|
||||
fprintf(stderr, "Unrecognised option value %s\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
OFF,
|
||||
ON,
|
||||
QUERY
|
||||
} BoolQuery;
|
||||
|
||||
static BoolQuery getboolq(int *argip, int argc, char *argv[])
|
||||
{
|
||||
const char *choices[] = {"off", "on", "query", NULL};
|
||||
return getchoice(argip, argc, argv, choices);
|
||||
}
|
||||
|
||||
static char *helptext[] = {
|
||||
"reset",
|
||||
"s8c1t [off|on]",
|
||||
"keypad [app|num]",
|
||||
"screen [off|on|query]",
|
||||
"cursor [off|on|query]",
|
||||
"curblink [off|on|query]",
|
||||
"curshape [block|under|bar|query]",
|
||||
"mouse [off|click|clickdrag|motion]",
|
||||
"altscreen [off|on|query]",
|
||||
"bracketpaste [off|on|query]",
|
||||
"icontitle [STR]",
|
||||
"icon [STR]",
|
||||
"title [STR]",
|
||||
NULL
|
||||
};
|
||||
|
||||
static bool seticanon(bool icanon, bool echo)
|
||||
{
|
||||
struct termios termios;
|
||||
|
||||
tcgetattr(0, &termios);
|
||||
|
||||
bool ret = (termios.c_lflag & ICANON);
|
||||
|
||||
if(icanon) termios.c_lflag |= ICANON;
|
||||
else termios.c_lflag &= ~ICANON;
|
||||
|
||||
if(echo) termios.c_lflag |= ECHO;
|
||||
else termios.c_lflag &= ~ECHO;
|
||||
|
||||
tcsetattr(0, TCSANOW, &termios);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void await_c1(int c1)
|
||||
{
|
||||
int c;
|
||||
|
||||
/* await CSI - 8bit or 2byte 7bit form */
|
||||
bool in_esc = false;
|
||||
while((c = getchar())) {
|
||||
if(c == c1)
|
||||
break;
|
||||
if(in_esc && c == (char)(c1 - 0x40))
|
||||
break;
|
||||
if(!in_esc && c == 0x1b)
|
||||
in_esc = true;
|
||||
else
|
||||
in_esc = false;
|
||||
}
|
||||
}
|
||||
|
||||
static char *read_csi()
|
||||
{
|
||||
unsigned char csi[32];
|
||||
int i = 0;
|
||||
|
||||
await_c1(0x9B); /* CSI */
|
||||
|
||||
/* TODO: This really should be a more robust CSI parser
|
||||
*/
|
||||
for(; i < sizeof(csi)-1; i++) {
|
||||
int c = csi[i] = getchar();
|
||||
if(c >= 0x40 && c <= 0x7e)
|
||||
break;
|
||||
}
|
||||
csi[++i] = 0;
|
||||
|
||||
/* TODO: returns longer than 32? */
|
||||
|
||||
return strdup((char *)csi);
|
||||
}
|
||||
|
||||
static char *read_dcs()
|
||||
{
|
||||
unsigned char dcs[32];
|
||||
bool in_esc = false;
|
||||
int i;
|
||||
|
||||
await_c1(0x90);
|
||||
|
||||
for(i = 0; i < sizeof(dcs)-1; ) {
|
||||
char c = getchar();
|
||||
if(c == 0x9c) /* ST */
|
||||
break;
|
||||
if(in_esc && c == 0x5c)
|
||||
break;
|
||||
if(!in_esc && c == 0x1b)
|
||||
in_esc = true;
|
||||
else {
|
||||
dcs[i++] = c;
|
||||
in_esc = false;
|
||||
}
|
||||
}
|
||||
dcs[++i] = 0;
|
||||
|
||||
return strdup((char *)dcs);
|
||||
}
|
||||
|
||||
static void usage(int exitcode)
|
||||
{
|
||||
char **p;
|
||||
|
||||
fprintf(stderr, "Control a libvterm-based terminal\n"
|
||||
"\n"
|
||||
"Options:\n");
|
||||
|
||||
for(p = helptext; *p; p++)
|
||||
fprintf(stderr, " %s\n", *p);
|
||||
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
static bool query_dec_mode(int mode)
|
||||
{
|
||||
char *s = NULL;
|
||||
|
||||
printf("\x1b[?%d$p", mode);
|
||||
|
||||
do {
|
||||
int reply_mode, reply_value;
|
||||
char reply_cmd;
|
||||
|
||||
if(s)
|
||||
free(s);
|
||||
s = read_csi();
|
||||
|
||||
/* expect "?" mode ";" value "$y" */
|
||||
|
||||
/* If the sscanf format string ends in a literal, we can't tell from
|
||||
* its return value if it matches. Hence we'll %c the cmd and check it
|
||||
* explicitly
|
||||
*/
|
||||
if(sscanf(s, "?%d;%d$%c", &reply_mode, &reply_value, &reply_cmd) < 3)
|
||||
continue;
|
||||
if(reply_cmd != 'y')
|
||||
continue;
|
||||
|
||||
if(reply_mode != mode)
|
||||
continue;
|
||||
|
||||
free(s);
|
||||
|
||||
if(reply_value == 1 || reply_value == 3)
|
||||
return true;
|
||||
if(reply_value == 2 || reply_value == 4)
|
||||
return false;
|
||||
|
||||
printf("Unrecognised reply to DECRQM: %d\n", reply_value);
|
||||
return false;
|
||||
} while(1);
|
||||
}
|
||||
|
||||
static void do_dec_mode(int mode, BoolQuery val, const char *name)
|
||||
{
|
||||
switch(val) {
|
||||
case OFF:
|
||||
case ON:
|
||||
printf("\x1b[?%d%c", mode, val == ON ? 'h' : 'l');
|
||||
break;
|
||||
|
||||
case QUERY:
|
||||
if(query_dec_mode(mode))
|
||||
printf("%s on\n", name);
|
||||
else
|
||||
printf("%s off\n", name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int query_rqss_numeric(char *cmd)
|
||||
{
|
||||
char *s = NULL;
|
||||
|
||||
printf("\x1bP$q%s\x1b\\", cmd);
|
||||
|
||||
do {
|
||||
int num;
|
||||
|
||||
if(s)
|
||||
free(s);
|
||||
s = read_dcs();
|
||||
|
||||
if(!s)
|
||||
return -1;
|
||||
if(strlen(s) < strlen(cmd))
|
||||
return -1;
|
||||
if(strcmp(s + strlen(s) - strlen(cmd), cmd) != 0) {
|
||||
printf("No match\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(s[0] != '1' || s[1] != '$' || s[2] != 'r')
|
||||
return -1;
|
||||
|
||||
if(sscanf(s + 3, "%d", &num) != 1)
|
||||
return -1;
|
||||
|
||||
return num;
|
||||
} while(1);
|
||||
}
|
||||
|
||||
bool wasicanon;
|
||||
|
||||
void restoreicanon(void)
|
||||
{
|
||||
seticanon(wasicanon, true);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int argi = 1;
|
||||
|
||||
if(argc == 1)
|
||||
usage(0);
|
||||
|
||||
wasicanon = seticanon(false, false);
|
||||
atexit(restoreicanon);
|
||||
|
||||
while(argi < argc) {
|
||||
const char *arg = argv[argi++];
|
||||
|
||||
if(streq(arg, "reset")) {
|
||||
printf("\x1b" "c");
|
||||
}
|
||||
else if(streq(arg, "s8c1t")) {
|
||||
const char *choices[] = {"off", "on", NULL};
|
||||
switch(getchoice(&argi, argc, argv, choices)) {
|
||||
case 0:
|
||||
printf("\x1b F"); break;
|
||||
case 1:
|
||||
printf("\x1b G"); break;
|
||||
}
|
||||
}
|
||||
else if(streq(arg, "keypad")) {
|
||||
const char *choices[] = {"app", "num", NULL};
|
||||
switch(getchoice(&argi, argc, argv, choices)) {
|
||||
case 0:
|
||||
printf("\x1b="); break;
|
||||
case 1:
|
||||
printf("\x1b>"); break;
|
||||
}
|
||||
}
|
||||
else if(streq(arg, "screen")) {
|
||||
do_dec_mode(5, getboolq(&argi, argc, argv), "screen");
|
||||
}
|
||||
else if(streq(arg, "cursor")) {
|
||||
do_dec_mode(25, getboolq(&argi, argc, argv), "cursor");
|
||||
}
|
||||
else if(streq(arg, "curblink")) {
|
||||
do_dec_mode(12, getboolq(&argi, argc, argv), "curblink");
|
||||
}
|
||||
else if(streq(arg, "curshape")) {
|
||||
/* TODO: This ought to query the current value of DECSCUSR because it */
|
||||
/* may need blinking on or off */
|
||||
const char *choices[] = {"block", "under", "bar", "query", NULL};
|
||||
int shape = getchoice(&argi, argc, argv, choices);
|
||||
switch(shape) {
|
||||
case 3: /* query */
|
||||
shape = query_rqss_numeric(" q");
|
||||
switch(shape) {
|
||||
case 1: case 2:
|
||||
printf("curshape block\n");
|
||||
break;
|
||||
case 3: case 4:
|
||||
printf("curshape under\n");
|
||||
break;
|
||||
case 5: case 6:
|
||||
printf("curshape bar\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
printf("\x1b[%d q", 1 + (shape * 2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(streq(arg, "mouse")) {
|
||||
const char *choices[] = {"off", "click", "clickdrag", "motion", NULL};
|
||||
switch(getchoice(&argi, argc, argv, choices)) {
|
||||
case 0:
|
||||
printf("\x1b[?1000l"); break;
|
||||
case 1:
|
||||
printf("\x1b[?1000h"); break;
|
||||
case 2:
|
||||
printf("\x1b[?1002h"); break;
|
||||
case 3:
|
||||
printf("\x1b[?1003h"); break;
|
||||
}
|
||||
}
|
||||
else if(streq(arg, "altscreen")) {
|
||||
do_dec_mode(1049, getboolq(&argi, argc, argv), "altscreen");
|
||||
}
|
||||
else if(streq(arg, "bracketpaste")) {
|
||||
do_dec_mode(2004, getboolq(&argi, argc, argv), "bracketpaste");
|
||||
}
|
||||
else if(streq(arg, "icontitle")) {
|
||||
printf("\x1b]0;%s\a", getvalue(&argi, argc, argv));
|
||||
}
|
||||
else if(streq(arg, "icon")) {
|
||||
printf("\x1b]1;%s\a", getvalue(&argi, argc, argv));
|
||||
}
|
||||
else if(streq(arg, "title")) {
|
||||
printf("\x1b]2;%s\a", getvalue(&argi, argc, argv));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Unrecognised command %s\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
231
src/libvterm/bin/vterm-dump.c
Normal file
231
src/libvterm/bin/vterm-dump.c
Normal file
@@ -0,0 +1,231 @@
|
||||
/* Require getopt(3) */
|
||||
#define _XOPEN_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#define streq(a,b) (strcmp(a,b)==0)
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "vterm.h"
|
||||
|
||||
static const char *special_begin = "{";
|
||||
static const char *special_end = "}";
|
||||
|
||||
static int parser_text(const char bytes[], size_t len, void *user)
|
||||
{
|
||||
unsigned char *b = (unsigned char *)bytes;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < len; /* none */) {
|
||||
if(b[i] < 0x20) /* C0 */
|
||||
break;
|
||||
else if(b[i] < 0x80) /* ASCII */
|
||||
i++;
|
||||
else if(b[i] < 0xa0) /* C1 */
|
||||
break;
|
||||
else if(b[i] < 0xc0) /* UTF-8 continuation */
|
||||
break;
|
||||
else if(b[i] < 0xe0) { /* UTF-8 2-byte */
|
||||
/* 2-byte UTF-8 */
|
||||
if(len < i+2) break;
|
||||
i += 2;
|
||||
}
|
||||
else if(b[i] < 0xf0) { /* UTF-8 3-byte */
|
||||
if(len < i+3) break;
|
||||
i += 3;
|
||||
}
|
||||
else if(b[i] < 0xf8) { /* UTF-8 4-byte */
|
||||
if(len < i+4) break;
|
||||
i += 4;
|
||||
}
|
||||
else /* otherwise invalid */
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%.*s", i, b);
|
||||
return i;
|
||||
}
|
||||
|
||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||
static const char *name_c0[] = {
|
||||
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "LS0", "LS1",
|
||||
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US",
|
||||
};
|
||||
static const char *name_c1[] = {
|
||||
NULL, NULL, "BPH", "NBH", NULL, "NEL", "SSA", "ESA", "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
|
||||
"DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA", "SOS", NULL, "SCI", "CSI", "ST", "OSC", "PM", "APC",
|
||||
};
|
||||
|
||||
static int parser_control(unsigned char control, void *user)
|
||||
{
|
||||
if(control < 0x20)
|
||||
printf("%s%s%s", special_begin, name_c0[control], special_end);
|
||||
else if(control >= 0x80 && control < 0xa0 && name_c1[control - 0x80])
|
||||
printf("%s%s%s", special_begin, name_c1[control - 0x80], special_end);
|
||||
else
|
||||
printf("%sCONTROL 0x%02x%s", special_begin, control, special_end);
|
||||
|
||||
if(control == 0x0a)
|
||||
printf("\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_escape(const char bytes[], size_t len, void *user)
|
||||
{
|
||||
if(bytes[0] >= 0x20 && bytes[0] < 0x30) {
|
||||
if(len < 2)
|
||||
return -1;
|
||||
len = 2;
|
||||
}
|
||||
else {
|
||||
len = 1;
|
||||
}
|
||||
|
||||
printf("%sESC %.*s%s", special_begin, (int)len, bytes, special_end);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||
static const char *name_csi_plain[] = {
|
||||
"ICH", "CUU", "CUD", "CUF", "CUB", "CNL", "CPL", "CHA", "CUP", "CHT", "ED", "EL", "IL", "DL", "EF", "EA",
|
||||
"DCH", "SSE", "CPR", "SU", "SD", "NP", "PP", "CTC", "ECH", "CVT", "CBT", "SRS", "PTX", "SDS", "SIMD",NULL,
|
||||
"HPA", "HPR", "REP", "DA", "VPA", "VPR", "HVP", "TBC", "SM", "MC", "HPB", "VPB", "RM", "SGR", "DSR", "DAQ",
|
||||
};
|
||||
|
||||
/*0 4 8 B */
|
||||
static const int newline_csi_plain[] = {
|
||||
0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
};
|
||||
|
||||
static int parser_csi(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user)
|
||||
{
|
||||
const char *name = NULL;
|
||||
if(!leader && !intermed && command < 0x70)
|
||||
name = name_csi_plain[command - 0x40];
|
||||
else if(leader && streq(leader, "?") && !intermed) {
|
||||
/* DEC */
|
||||
switch(command) {
|
||||
case 'h': name = "DECSM"; break;
|
||||
case 'l': name = "DECRM"; break;
|
||||
}
|
||||
if(name)
|
||||
leader = NULL;
|
||||
}
|
||||
|
||||
if(!leader && !intermed && command < 0x70 && newline_csi_plain[command - 0x40])
|
||||
printf("\n");
|
||||
|
||||
if(name)
|
||||
printf("%s%s", special_begin, name);
|
||||
else
|
||||
printf("%sCSI", special_begin);
|
||||
|
||||
if(leader && leader[0])
|
||||
printf(" %s", leader);
|
||||
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < argcount; i++) {
|
||||
printf(i ? "," : " ");
|
||||
}
|
||||
|
||||
if(args[i] == CSI_ARG_MISSING)
|
||||
printf("*");
|
||||
else {
|
||||
while(CSI_ARG_HAS_MORE(args[i]))
|
||||
printf("%ld+", CSI_ARG(args[i++]));
|
||||
printf("%ld", CSI_ARG(args[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if(intermed && intermed[0])
|
||||
printf(" %s", intermed);
|
||||
|
||||
if(name)
|
||||
printf("%s", special_end);
|
||||
else
|
||||
printf(" %c%s", command, special_end);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_osc(const char *command, size_t cmdlen, void *user)
|
||||
{
|
||||
printf("%sOSC %.*s%s", special_begin, (int)cmdlen, command, special_end);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parser_dcs(const char *command, size_t cmdlen, void *user)
|
||||
{
|
||||
printf("%sDCS %.*s%s", special_begin, (int)cmdlen, command, special_end);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static VTermParserCallbacks parser_cbs = {
|
||||
&parser_text, /* text */
|
||||
&parser_control, /* control */
|
||||
&parser_escape, /* escape */
|
||||
&parser_csi, /* csi */
|
||||
&parser_osc, /* osc */
|
||||
&parser_dcs, /* dcs */
|
||||
NULL /* resize */
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int use_colour = isatty(1);
|
||||
const char *file;
|
||||
int fd;
|
||||
VTerm *vt;
|
||||
int len;
|
||||
char buffer[1024];
|
||||
|
||||
int opt;
|
||||
while((opt = getopt(argc, argv, "c")) != -1) {
|
||||
switch(opt) {
|
||||
case 'c': use_colour = 1; break;
|
||||
}
|
||||
}
|
||||
|
||||
file = argv[optind++];
|
||||
|
||||
if(!file || streq(file, "-"))
|
||||
fd = 0; /* stdin */
|
||||
else {
|
||||
fd = open(file, O_RDONLY);
|
||||
if(fd == -1) {
|
||||
fprintf(stderr, "Cannot open %s - %s\n", file, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if(use_colour) {
|
||||
special_begin = "\x1b[7m{";
|
||||
special_end = "}\x1b[m";
|
||||
}
|
||||
|
||||
/* Size matters not for the parser */
|
||||
vt = vterm_new(25, 80);
|
||||
vterm_set_utf8(vt, 1);
|
||||
vterm_parser_set_callbacks(vt, &parser_cbs, NULL);
|
||||
|
||||
while((len = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
vterm_input_write(vt, buffer, len);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
close(fd);
|
||||
vterm_free(vt);
|
||||
return 0;
|
||||
}
|
||||
11
src/libvterm/doc/URLs
Normal file
11
src/libvterm/doc/URLs
Normal file
@@ -0,0 +1,11 @@
|
||||
ECMA-48:
|
||||
http://www.ecma-international.org/publications/standards/Ecma-048.htm
|
||||
|
||||
Xterm Control Sequences:
|
||||
http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
|
||||
Digital VT100 User Guide:
|
||||
http://vt100.net/docs/vt100-ug/
|
||||
|
||||
Digital VT220 Programmer Reference Manual
|
||||
http://vt100.net/docs/vt220-rm/
|
||||
226
src/libvterm/doc/seqs.txt
Normal file
226
src/libvterm/doc/seqs.txt
Normal file
@@ -0,0 +1,226 @@
|
||||
Sequences documented in parens are implicit ones from parser.c, which move
|
||||
between states.
|
||||
|
||||
1 = VT100
|
||||
2 = VT220
|
||||
3 = VT320
|
||||
|
||||
C0 controls
|
||||
|
||||
123 0x00 = NUL
|
||||
123 0x07 = BEL
|
||||
123 0x08 = BS
|
||||
123 0x09 = HT
|
||||
123 0x0A = LF
|
||||
123 0x0B = VT
|
||||
123 0x0C = FF
|
||||
123 0x0D = CR
|
||||
123 0x0E = LS1
|
||||
123 0x0F = LS0
|
||||
(0x18 = CAN)
|
||||
(0x1A = SUB)
|
||||
(0x1B = ESC)
|
||||
|
||||
123 0x7f = DEL (ignored)
|
||||
|
||||
C1 controls
|
||||
|
||||
123 0x84 = IND
|
||||
123 0x85 = NEL
|
||||
123 0x88 = HTS
|
||||
123 0x8D = RI
|
||||
23 0x8e = SS2
|
||||
23 0x8f = SS3
|
||||
(0x90 = DCS)
|
||||
(0x9B = CSI)
|
||||
(0x9C = ST)
|
||||
(0x9D = OSC)
|
||||
|
||||
Escape sequences
|
||||
- excluding sequences that are C1 aliases
|
||||
|
||||
123 ESC () = SCS, select character set (G0, G1)
|
||||
23 ESC *+ = SCS, select character set (G2, G3)
|
||||
123 ESC 7 = DECSC - save cursor
|
||||
123 ESC 8 = DECRC - restore cursor
|
||||
123 ESC # 3 = DECDHL, double-height line (top half)
|
||||
123 ESC # 4 = DECDHL, double-height line (bottom half)
|
||||
123 ESC # 5 = DECSWL, single-width single-height line
|
||||
123 ESC # 6 = DECDWL, double-width single-height line
|
||||
123 ESC # 8 = DECALN
|
||||
123 ESC < = Ignored (used by VT100 to exit VT52 mode)
|
||||
123 ESC = = DECKPAM, keypad application mode
|
||||
123 ESC > = DECKPNM, keypad numeric mode
|
||||
23 ESC Sp F = S7C1T
|
||||
23 ESC Sp G = S8C1T
|
||||
(ESC P = DCS)
|
||||
(ESC [ = CSI)
|
||||
(ESC \ = ST)
|
||||
(ESC ] = OSC)
|
||||
123 ESC c = RIS, reset initial state
|
||||
3 ESC n = LS2
|
||||
3 ESC o = LS3
|
||||
3 ESC ~ = LS1R
|
||||
3 ESC } = LS2R
|
||||
3 ESC | = LS3R
|
||||
|
||||
DCSes
|
||||
|
||||
3 DCS $ q ST = DECRQSS
|
||||
3 m = Request SGR
|
||||
Sp q = Request DECSCUSR
|
||||
3 " q = Request DECSCA
|
||||
3 r = Request DECSTBM
|
||||
s = Request DECSLRM
|
||||
|
||||
CSIs
|
||||
23 CSI @ = ICH
|
||||
123 CSI A = CUU
|
||||
123 CSI B = CUD
|
||||
123 CSI C = CUF
|
||||
123 CSI D = CUB
|
||||
CSI E = CNL
|
||||
CSI F = CPL
|
||||
CSI G = CHA
|
||||
123 CSI H = CUP
|
||||
CSI I = CHT
|
||||
123 CSI J = ED
|
||||
23 CSI ? J = DECSED, selective erase in display
|
||||
123 CSI K = EL
|
||||
23 CSI ? K = DECSEL, selective erase in line
|
||||
23 CSI L = IL
|
||||
23 CSI M = DL
|
||||
23 CSI P = DCH
|
||||
CSI S = SU
|
||||
CSI T = SD
|
||||
23 CSI X = ECH
|
||||
CSI Z = CBT
|
||||
CSI ` = HPA
|
||||
CSI a = HPR
|
||||
123 CSI c = DA, device attributes
|
||||
123 0 = DA
|
||||
23 CSI > c = DECSDA
|
||||
23 0 = SDA
|
||||
CSI d = VPA
|
||||
CSI e = VPR
|
||||
123 CSI f = HVP
|
||||
123 CSI g = TBC
|
||||
123 CSI h = SM, Set mode
|
||||
123 CSI ? h = DECSM, DEC set mode
|
||||
CSI j = HPB
|
||||
CSI k = VPB
|
||||
123 CSI l = RM, Reset mode
|
||||
123 CSI ? l = DECRM, DEC reset mode
|
||||
123 CSI m = SGR, Set Graphic Rendition
|
||||
123 CSI n = DSR, Device Status Report
|
||||
23 5 = operating status
|
||||
23 6 = CPR = cursor position
|
||||
23 CSI ? n = DECDSR; behaves as DSR but uses CSI ? instead of CSI to respond
|
||||
23 CSI ! p = DECSTR, soft terminal reset
|
||||
3 CSI ? $ p = DECRQM, request mode
|
||||
CSI Sp q = DECSCUSR (odd numbers blink, even numbers solid)
|
||||
1 or 2 = block
|
||||
3 or 4 = underline
|
||||
5 or 6 = I-beam to left
|
||||
23 CSI " q = DECSCA, select character attributes
|
||||
123 CSI r = DECSTBM
|
||||
CSI s = DECSLRM
|
||||
CSI ' } = DECIC
|
||||
CSI ' ~ = DECDC
|
||||
|
||||
OSCs
|
||||
|
||||
OSC 0; = Set icon name and title
|
||||
OSC 1; = Set icon name
|
||||
OSC 2; = Set title
|
||||
|
||||
Standard modes
|
||||
|
||||
23 SM 4 = IRM
|
||||
123 SM 20 = NLM, linefeed/newline
|
||||
|
||||
DEC modes
|
||||
|
||||
123 DECSM 1 = DECCKM, cursor keys
|
||||
123 DECSM 5 = DECSCNM, screen
|
||||
123 DECSM 6 = DECOM, origin
|
||||
123 DECSM 7 = DECAWM, autowrap
|
||||
DECSM 12 = Cursor blink
|
||||
23 DECSM 25 = DECTCEM, text cursor enable
|
||||
DECSM 69 = DECVSSM, vertical screen split
|
||||
DECSM 1000 = Mouse click/release tracking
|
||||
DECSM 1002 = Mouse click/release/drag tracking
|
||||
DECSM 1003 = Mouse all movements tracking
|
||||
DECSM 1005 = Mouse protocol extended (UTF-8) - not recommended
|
||||
DECSM 1006 = Mouse protocol SGR
|
||||
DECSM 1015 = Mouse protocol rxvt
|
||||
DECSM 1047 = Altscreen
|
||||
DECSM 1048 = Save cursor
|
||||
DECSM 1049 = 1047 + 1048
|
||||
DECSM 2004 = Bracketed paste
|
||||
|
||||
Graphic Renditions
|
||||
|
||||
123 SGR 0 = Reset
|
||||
123 SGR 1 = Bold on
|
||||
SGR 3 = Italic on
|
||||
123 SGR 4 = Underline single
|
||||
123 SGR 5 = Blink on
|
||||
123 SGR 7 = Reverse on
|
||||
SGR 9 = Strikethrough on
|
||||
SGR 10-19 = Select font
|
||||
SGR 21 = Underline double
|
||||
23 SGR 22 = Bold off
|
||||
SGR 23 = Italic off
|
||||
23 SGR 24 = Underline off
|
||||
23 SGR 25 = Blink off
|
||||
23 SGR 27 = Reverse off
|
||||
SGR 29 = Strikethrough off
|
||||
SGR 30-37 = Foreground ANSI
|
||||
SGR 38 = Foreground alternative palette
|
||||
SGR 39 = Foreground default
|
||||
SGR 40-47 = Background ANSI
|
||||
SGR 48 = Background alternative palette
|
||||
SGR 49 = Background default
|
||||
SGR 90-97 = Foreground ANSI high-intensity
|
||||
SGR 100-107 = Background ANSI high-intensity
|
||||
|
||||
The state storage used by ESC 7 and DECSM 1048/1049 is shared.
|
||||
|
||||
Unimplemented sequences:
|
||||
|
||||
The following sequences are not recognised by libvterm.
|
||||
|
||||
123 0x05 = ENQ
|
||||
3 0x11 = DC1 (XON)
|
||||
3 0x13 = DC3 (XOFF)
|
||||
12 ESC Z = DECID, identify terminal
|
||||
DCS $ q = [DECRQSS]
|
||||
3 " p = Request DECSCL
|
||||
3 $ } = Request DECSASD
|
||||
3 $ ~ = Request DECSSDT
|
||||
23 DCS { = DECDLD, down-line-loadable character set
|
||||
23 DCS | = DECUDK, user-defined key
|
||||
23 CSI i = DEC printer control
|
||||
23 CSI " p = DECSCL, set compatibility level
|
||||
1 CSI q = DECLL, load LEDs
|
||||
3 CSI $ u = DECRQTSR, request terminal state report
|
||||
3 1 = terminal state report
|
||||
3 CSI & u = DECRQUPSS, request user-preferred supplemental set
|
||||
3 CSI $ w = DECRQPSR, request presentation state report
|
||||
3 1 = cursor information report
|
||||
3 2 = tab stop report
|
||||
1 CSI x = DECREQTPARM, request terminal parameters
|
||||
123 CSI y = DECTST, invoke confidence test
|
||||
3 CSI $ } = DECSASD, select active status display
|
||||
3 CSI $ ~ = DECSSDT, select status line type
|
||||
23 SM 2 = KAM, keyboard action
|
||||
123 SM 12 = SRM, send/receive
|
||||
123 DECSM 2 = DECANM, ANSI/VT52
|
||||
123 DECSM 3 = DECCOLM, 132 column
|
||||
123 DECSM 4 = DECSCLM, scrolling
|
||||
123 DECSM 8 = DECARM, auto-repeat
|
||||
12 DECSM 9 = DECINLM, interlace
|
||||
23 DECSM 18 = DECPFF, print form feed
|
||||
23 DECSM 19 = DECPEX, print extent
|
||||
23 DECSM 42 = DECNRCM, national/multinational character
|
||||
370
src/libvterm/include/vterm.h
Normal file
370
src/libvterm/include/vterm.h
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* NOTE: This is a MODIFIED version of libvterm, see the README file.
|
||||
*/
|
||||
#ifndef __VTERM_H__
|
||||
#define __VTERM_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "vterm_keycodes.h"
|
||||
|
||||
typedef struct VTerm VTerm;
|
||||
typedef struct VTermState VTermState;
|
||||
typedef struct VTermScreen VTermScreen;
|
||||
|
||||
/* Specifies a screen point. */
|
||||
typedef struct {
|
||||
int row;
|
||||
int col;
|
||||
} VTermPos;
|
||||
|
||||
/*
|
||||
* Some small utility functions; we can just keep these static here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Order points by on-screen flow order:
|
||||
* Return < 0 if "a" is before "b"
|
||||
* Return 0 if "a" and "b" are equal
|
||||
* Return > 0 if "a" is after "b".
|
||||
*/
|
||||
int vterm_pos_cmp(VTermPos a, VTermPos b);
|
||||
|
||||
#if defined(DEFINE_INLINES) || USE_INLINE
|
||||
INLINE int vterm_pos_cmp(VTermPos a, VTermPos b)
|
||||
{
|
||||
return (a.row == b.row) ? a.col - b.col : a.row - b.row;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Specifies a rectangular screen area. */
|
||||
typedef struct {
|
||||
int start_row;
|
||||
int end_row;
|
||||
int start_col;
|
||||
int end_col;
|
||||
} VTermRect;
|
||||
|
||||
/* Return true if the rect "r" contains the point "p". */
|
||||
int vterm_rect_contains(VTermRect r, VTermPos p);
|
||||
|
||||
#if defined(DEFINE_INLINES) || USE_INLINE
|
||||
INLINE int vterm_rect_contains(VTermRect r, VTermPos p)
|
||||
{
|
||||
return p.row >= r.start_row && p.row < r.end_row &&
|
||||
p.col >= r.start_col && p.col < r.end_col;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Move "rect" "row_delta" down and "col_delta" right.
|
||||
* Does not check boundaries. */
|
||||
void vterm_rect_move(VTermRect *rect, int row_delta, int col_delta);
|
||||
|
||||
#if defined(DEFINE_INLINES) || USE_INLINE
|
||||
INLINE void vterm_rect_move(VTermRect *rect, int row_delta, int col_delta)
|
||||
{
|
||||
rect->start_row += row_delta; rect->end_row += row_delta;
|
||||
rect->start_col += col_delta; rect->end_col += col_delta;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint8_t red, green, blue;
|
||||
} VTermColor;
|
||||
|
||||
typedef enum {
|
||||
/* VTERM_VALUETYPE_NONE = 0 */
|
||||
VTERM_VALUETYPE_BOOL = 1,
|
||||
VTERM_VALUETYPE_INT,
|
||||
VTERM_VALUETYPE_STRING,
|
||||
VTERM_VALUETYPE_COLOR
|
||||
} VTermValueType;
|
||||
|
||||
typedef union {
|
||||
int boolean;
|
||||
int number;
|
||||
char *string;
|
||||
VTermColor color;
|
||||
} VTermValue;
|
||||
|
||||
typedef enum {
|
||||
/* VTERM_ATTR_NONE = 0 */
|
||||
VTERM_ATTR_BOLD = 1, /* bool: 1, 22 */
|
||||
VTERM_ATTR_UNDERLINE, /* number: 4, 21, 24 */
|
||||
VTERM_ATTR_ITALIC, /* bool: 3, 23 */
|
||||
VTERM_ATTR_BLINK, /* bool: 5, 25 */
|
||||
VTERM_ATTR_REVERSE, /* bool: 7, 27 */
|
||||
VTERM_ATTR_STRIKE, /* bool: 9, 29 */
|
||||
VTERM_ATTR_FONT, /* number: 10-19 */
|
||||
VTERM_ATTR_FOREGROUND, /* color: 30-39 90-97 */
|
||||
VTERM_ATTR_BACKGROUND /* color: 40-49 100-107 */
|
||||
} VTermAttr;
|
||||
|
||||
typedef enum {
|
||||
/* VTERM_PROP_NONE = 0 */
|
||||
VTERM_PROP_CURSORVISIBLE = 1, /* bool */
|
||||
VTERM_PROP_CURSORBLINK, /* bool */
|
||||
VTERM_PROP_ALTSCREEN, /* bool */
|
||||
VTERM_PROP_TITLE, /* string */
|
||||
VTERM_PROP_ICONNAME, /* string */
|
||||
VTERM_PROP_REVERSE, /* bool */
|
||||
VTERM_PROP_CURSORSHAPE, /* number */
|
||||
VTERM_PROP_MOUSE /* number */
|
||||
} VTermProp;
|
||||
|
||||
enum {
|
||||
VTERM_PROP_CURSORSHAPE_BLOCK = 1,
|
||||
VTERM_PROP_CURSORSHAPE_UNDERLINE,
|
||||
VTERM_PROP_CURSORSHAPE_BAR_LEFT
|
||||
};
|
||||
|
||||
enum {
|
||||
VTERM_PROP_MOUSE_NONE = 0,
|
||||
VTERM_PROP_MOUSE_CLICK,
|
||||
VTERM_PROP_MOUSE_DRAG,
|
||||
VTERM_PROP_MOUSE_MOVE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const uint32_t *chars;
|
||||
int width;
|
||||
unsigned int protected_cell:1; /* DECSCA-protected against DECSEL/DECSED */
|
||||
unsigned int dwl:1; /* DECDWL or DECDHL double-width line */
|
||||
unsigned int dhl:2; /* DECDHL double-height line (1=top 2=bottom) */
|
||||
} VTermGlyphInfo;
|
||||
|
||||
typedef struct {
|
||||
unsigned int doublewidth:1; /* DECDWL or DECDHL line */
|
||||
unsigned int doubleheight:2; /* DECDHL line (1=top 2=bottom) */
|
||||
} VTermLineInfo;
|
||||
|
||||
typedef struct {
|
||||
/* libvterm relies on the allocated memory to be zeroed out before it is
|
||||
* returned by the allocator. */
|
||||
void *(*malloc)(size_t size, void *allocdata);
|
||||
void (*free)(void *ptr, void *allocdata);
|
||||
} VTermAllocatorFunctions;
|
||||
|
||||
/* Allocate and initialize a new terminal with default allocators. */
|
||||
VTerm *vterm_new(int rows, int cols);
|
||||
|
||||
/* Allocate and initialize a new terminal with specified allocators. */
|
||||
VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata);
|
||||
|
||||
/* Free and cleanup a terminal and all its data. */
|
||||
void vterm_free(VTerm* vt);
|
||||
|
||||
void vterm_get_size(const VTerm *vt, int *rowsp, int *colsp);
|
||||
void vterm_set_size(VTerm *vt, int rows, int cols);
|
||||
|
||||
int vterm_get_utf8(const VTerm *vt);
|
||||
void vterm_set_utf8(VTerm *vt, int is_utf8);
|
||||
|
||||
size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len);
|
||||
|
||||
size_t vterm_output_get_buffer_size(const VTerm *vt);
|
||||
size_t vterm_output_get_buffer_current(const VTerm *vt);
|
||||
size_t vterm_output_get_buffer_remaining(const VTerm *vt);
|
||||
|
||||
size_t vterm_output_read(VTerm *vt, char *buffer, size_t len);
|
||||
|
||||
void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod);
|
||||
void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod);
|
||||
|
||||
void vterm_keyboard_start_paste(VTerm *vt);
|
||||
void vterm_keyboard_end_paste(VTerm *vt);
|
||||
|
||||
void vterm_mouse_move(VTerm *vt, int row, int col, VTermModifier mod);
|
||||
void vterm_mouse_button(VTerm *vt, int button, bool pressed, VTermModifier mod);
|
||||
|
||||
/* ------------
|
||||
* Parser layer
|
||||
* ------------ */
|
||||
|
||||
/* Flag to indicate non-final subparameters in a single CSI parameter.
|
||||
* Consider
|
||||
* CSI 1;2:3:4;5a
|
||||
* 1 4 and 5 are final.
|
||||
* 2 and 3 are non-final and will have this bit set
|
||||
*
|
||||
* Don't confuse this with the final byte of the CSI escape; 'a' in this case.
|
||||
*/
|
||||
#define CSI_ARG_FLAG_MORE (1<<31)
|
||||
#define CSI_ARG_MASK (~(1<<31))
|
||||
|
||||
#define CSI_ARG_HAS_MORE(a) ((a) & CSI_ARG_FLAG_MORE)
|
||||
#define CSI_ARG(a) ((a) & CSI_ARG_MASK)
|
||||
|
||||
/* Can't use -1 to indicate a missing argument; use this instead */
|
||||
#define CSI_ARG_MISSING ((1UL<<31)-1)
|
||||
|
||||
#define CSI_ARG_IS_MISSING(a) (CSI_ARG(a) == CSI_ARG_MISSING)
|
||||
#define CSI_ARG_OR(a,def) (CSI_ARG(a) == CSI_ARG_MISSING ? (def) : CSI_ARG(a))
|
||||
#define CSI_ARG_COUNT(a) (CSI_ARG(a) == CSI_ARG_MISSING || CSI_ARG(a) == 0 ? 1 : CSI_ARG(a))
|
||||
|
||||
typedef struct {
|
||||
int (*text)(const char *bytes, size_t len, void *user);
|
||||
int (*control)(unsigned char control, void *user);
|
||||
int (*escape)(const char *bytes, size_t len, void *user);
|
||||
int (*csi)(const char *leader, const long args[], int argcount, const char *intermed, char command, void *user);
|
||||
int (*osc)(const char *command, size_t cmdlen, void *user);
|
||||
int (*dcs)(const char *command, size_t cmdlen, void *user);
|
||||
int (*resize)(int rows, int cols, void *user);
|
||||
} VTermParserCallbacks;
|
||||
|
||||
void vterm_parser_set_callbacks(VTerm *vt, const VTermParserCallbacks *callbacks, void *user);
|
||||
void *vterm_parser_get_cbdata(VTerm *vt);
|
||||
|
||||
/* -----------
|
||||
* State layer
|
||||
* ----------- */
|
||||
|
||||
typedef struct {
|
||||
int (*putglyph)(VTermGlyphInfo *info, VTermPos pos, void *user);
|
||||
int (*movecursor)(VTermPos pos, VTermPos oldpos, int visible, void *user);
|
||||
int (*scrollrect)(VTermRect rect, int downward, int rightward, void *user);
|
||||
int (*moverect)(VTermRect dest, VTermRect src, void *user);
|
||||
int (*erase)(VTermRect rect, int selective, void *user);
|
||||
int (*initpen)(void *user);
|
||||
int (*setpenattr)(VTermAttr attr, VTermValue *val, void *user);
|
||||
int (*settermprop)(VTermProp prop, VTermValue *val, void *user);
|
||||
int (*bell)(void *user);
|
||||
int (*resize)(int rows, int cols, VTermPos *delta, void *user);
|
||||
int (*setlineinfo)(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user);
|
||||
} VTermStateCallbacks;
|
||||
|
||||
VTermState *vterm_obtain_state(VTerm *vt);
|
||||
|
||||
void vterm_state_set_callbacks(VTermState *state, const VTermStateCallbacks *callbacks, void *user);
|
||||
void *vterm_state_get_cbdata(VTermState *state);
|
||||
|
||||
/* Only invokes control, csi, osc, dcs */
|
||||
void vterm_state_set_unrecognised_fallbacks(VTermState *state, const VTermParserCallbacks *fallbacks, void *user);
|
||||
void *vterm_state_get_unrecognised_fbdata(VTermState *state);
|
||||
|
||||
void vterm_state_reset(VTermState *state, int hard);
|
||||
void vterm_state_get_cursorpos(const VTermState *state, VTermPos *cursorpos);
|
||||
void vterm_state_get_default_colors(const VTermState *state, VTermColor *default_fg, VTermColor *default_bg);
|
||||
void vterm_state_get_palette_color(const VTermState *state, int index, VTermColor *col);
|
||||
void vterm_state_set_default_colors(VTermState *state, const VTermColor *default_fg, const VTermColor *default_bg);
|
||||
void vterm_state_set_palette_color(VTermState *state, int index, const VTermColor *col);
|
||||
void vterm_state_set_bold_highbright(VTermState *state, int bold_is_highbright);
|
||||
int vterm_state_get_penattr(const VTermState *state, VTermAttr attr, VTermValue *val);
|
||||
int vterm_state_set_termprop(VTermState *state, VTermProp prop, VTermValue *val);
|
||||
const VTermLineInfo *vterm_state_get_lineinfo(const VTermState *state, int row);
|
||||
|
||||
/* ------------
|
||||
* Screen layer
|
||||
* ------------ */
|
||||
|
||||
typedef struct {
|
||||
unsigned int bold : 1;
|
||||
unsigned int underline : 2;
|
||||
unsigned int italic : 1;
|
||||
unsigned int blink : 1;
|
||||
unsigned int reverse : 1;
|
||||
unsigned int strike : 1;
|
||||
unsigned int font : 4; /* 0 to 9 */
|
||||
unsigned int dwl : 1; /* On a DECDWL or DECDHL line */
|
||||
unsigned int dhl : 2; /* On a DECDHL line (1=top 2=bottom) */
|
||||
} VTermScreenCellAttrs;
|
||||
|
||||
typedef struct {
|
||||
#define VTERM_MAX_CHARS_PER_CELL 6
|
||||
uint32_t chars[VTERM_MAX_CHARS_PER_CELL];
|
||||
char width;
|
||||
VTermScreenCellAttrs attrs;
|
||||
VTermColor fg, bg;
|
||||
} VTermScreenCell;
|
||||
|
||||
/* All fields are optional, NULL when not used. */
|
||||
typedef struct {
|
||||
int (*damage)(VTermRect rect, void *user);
|
||||
int (*moverect)(VTermRect dest, VTermRect src, void *user);
|
||||
int (*movecursor)(VTermPos pos, VTermPos oldpos, int visible, void *user);
|
||||
int (*settermprop)(VTermProp prop, VTermValue *val, void *user);
|
||||
int (*bell)(void *user);
|
||||
int (*resize)(int rows, int cols, void *user);
|
||||
int (*sb_pushline)(int cols, const VTermScreenCell *cells, void *user);
|
||||
int (*sb_popline)(int cols, VTermScreenCell *cells, void *user);
|
||||
} VTermScreenCallbacks;
|
||||
|
||||
VTermScreen *vterm_obtain_screen(VTerm *vt);
|
||||
|
||||
/*
|
||||
* Install screen callbacks. These are invoked when the screen contents is
|
||||
* changed. "user" is passed into to the callback.
|
||||
*/
|
||||
void vterm_screen_set_callbacks(VTermScreen *screen, const VTermScreenCallbacks *callbacks, void *user);
|
||||
void *vterm_screen_get_cbdata(VTermScreen *screen);
|
||||
|
||||
/* Only invokes control, csi, osc, dcs */
|
||||
void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermParserCallbacks *fallbacks, void *user);
|
||||
void *vterm_screen_get_unrecognised_fbdata(VTermScreen *screen);
|
||||
|
||||
void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen);
|
||||
|
||||
typedef enum {
|
||||
VTERM_DAMAGE_CELL, /* every cell */
|
||||
VTERM_DAMAGE_ROW, /* entire rows */
|
||||
VTERM_DAMAGE_SCREEN, /* entire screen */
|
||||
VTERM_DAMAGE_SCROLL /* entire screen + scrollrect */
|
||||
} VTermDamageSize;
|
||||
|
||||
void vterm_screen_flush_damage(VTermScreen *screen);
|
||||
void vterm_screen_set_damage_merge(VTermScreen *screen, VTermDamageSize size);
|
||||
|
||||
void vterm_screen_reset(VTermScreen *screen, int hard);
|
||||
|
||||
/* Neither of these functions NUL-terminate the buffer */
|
||||
size_t vterm_screen_get_chars(const VTermScreen *screen, uint32_t *chars, size_t len, const VTermRect rect);
|
||||
size_t vterm_screen_get_text(const VTermScreen *screen, char *str, size_t len, const VTermRect rect);
|
||||
|
||||
typedef enum {
|
||||
VTERM_ATTR_BOLD_MASK = 1 << 0,
|
||||
VTERM_ATTR_UNDERLINE_MASK = 1 << 1,
|
||||
VTERM_ATTR_ITALIC_MASK = 1 << 2,
|
||||
VTERM_ATTR_BLINK_MASK = 1 << 3,
|
||||
VTERM_ATTR_REVERSE_MASK = 1 << 4,
|
||||
VTERM_ATTR_STRIKE_MASK = 1 << 5,
|
||||
VTERM_ATTR_FONT_MASK = 1 << 6,
|
||||
VTERM_ATTR_FOREGROUND_MASK = 1 << 7,
|
||||
VTERM_ATTR_BACKGROUND_MASK = 1 << 8
|
||||
} VTermAttrMask;
|
||||
|
||||
int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect *extent, VTermPos pos, VTermAttrMask attrs);
|
||||
|
||||
int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCell *cell);
|
||||
|
||||
int vterm_screen_is_eol(const VTermScreen *screen, VTermPos pos);
|
||||
|
||||
/* ---------
|
||||
* Utilities
|
||||
* --------- */
|
||||
|
||||
VTermValueType vterm_get_attr_type(VTermAttr attr);
|
||||
VTermValueType vterm_get_prop_type(VTermProp prop);
|
||||
|
||||
void vterm_scroll_rect(VTermRect rect,
|
||||
int downward,
|
||||
int rightward,
|
||||
int (*moverect)(VTermRect src, VTermRect dest, void *user),
|
||||
int (*eraserect)(VTermRect rect, int selective, void *user),
|
||||
void *user);
|
||||
|
||||
void vterm_copy_cells(VTermRect dest,
|
||||
VTermRect src,
|
||||
void (*copycell)(VTermPos dest, VTermPos src, void *user),
|
||||
void *user);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
58
src/libvterm/include/vterm_keycodes.h
Normal file
58
src/libvterm/include/vterm_keycodes.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef __VTERM_INPUT_H__
|
||||
#define __VTERM_INPUT_H__
|
||||
|
||||
typedef enum {
|
||||
VTERM_MOD_NONE = 0x00,
|
||||
VTERM_MOD_SHIFT = 0x01,
|
||||
VTERM_MOD_ALT = 0x02,
|
||||
VTERM_MOD_CTRL = 0x04
|
||||
} VTermModifier;
|
||||
|
||||
typedef enum {
|
||||
VTERM_KEY_NONE,
|
||||
|
||||
VTERM_KEY_ENTER,
|
||||
VTERM_KEY_TAB,
|
||||
VTERM_KEY_BACKSPACE,
|
||||
VTERM_KEY_ESCAPE,
|
||||
|
||||
VTERM_KEY_UP,
|
||||
VTERM_KEY_DOWN,
|
||||
VTERM_KEY_LEFT,
|
||||
VTERM_KEY_RIGHT,
|
||||
|
||||
VTERM_KEY_INS,
|
||||
VTERM_KEY_DEL,
|
||||
VTERM_KEY_HOME,
|
||||
VTERM_KEY_END,
|
||||
VTERM_KEY_PAGEUP,
|
||||
VTERM_KEY_PAGEDOWN,
|
||||
|
||||
VTERM_KEY_FUNCTION_0 = 256,
|
||||
VTERM_KEY_FUNCTION_MAX = VTERM_KEY_FUNCTION_0 + 255,
|
||||
|
||||
VTERM_KEY_KP_0,
|
||||
VTERM_KEY_KP_1,
|
||||
VTERM_KEY_KP_2,
|
||||
VTERM_KEY_KP_3,
|
||||
VTERM_KEY_KP_4,
|
||||
VTERM_KEY_KP_5,
|
||||
VTERM_KEY_KP_6,
|
||||
VTERM_KEY_KP_7,
|
||||
VTERM_KEY_KP_8,
|
||||
VTERM_KEY_KP_9,
|
||||
VTERM_KEY_KP_MULT,
|
||||
VTERM_KEY_KP_PLUS,
|
||||
VTERM_KEY_KP_COMMA,
|
||||
VTERM_KEY_KP_MINUS,
|
||||
VTERM_KEY_KP_PERIOD,
|
||||
VTERM_KEY_KP_DIVIDE,
|
||||
VTERM_KEY_KP_ENTER,
|
||||
VTERM_KEY_KP_EQUAL,
|
||||
|
||||
VTERM_KEY_MAX /* Must be last */
|
||||
} VTermKey;
|
||||
|
||||
#define VTERM_KEY_FUNCTION(n) (VTERM_KEY_FUNCTION_0+(n))
|
||||
|
||||
#endif
|
||||
232
src/libvterm/src/encoding.c
Normal file
232
src/libvterm/src/encoding.c
Normal file
@@ -0,0 +1,232 @@
|
||||
#include "vterm_internal.h"
|
||||
|
||||
#define UNICODE_INVALID 0xFFFD
|
||||
|
||||
#if defined(DEBUG) && DEBUG > 1
|
||||
# define DEBUG_PRINT_UTF8
|
||||
#endif
|
||||
|
||||
struct UTF8DecoderData {
|
||||
/* number of bytes remaining in this codepoint */
|
||||
int bytes_remaining;
|
||||
|
||||
/* number of bytes total in this codepoint once it's finished
|
||||
(for detecting overlongs) */
|
||||
int bytes_total;
|
||||
|
||||
int this_cp;
|
||||
};
|
||||
|
||||
static void init_utf8(VTermEncoding *enc UNUSED, void *data_)
|
||||
{
|
||||
struct UTF8DecoderData *data = data_;
|
||||
|
||||
data->bytes_remaining = 0;
|
||||
data->bytes_total = 0;
|
||||
}
|
||||
|
||||
static void decode_utf8(VTermEncoding *enc UNUSED, void *data_,
|
||||
uint32_t cp[], int *cpi, int cplen,
|
||||
const char bytes[], size_t *pos, size_t bytelen)
|
||||
{
|
||||
struct UTF8DecoderData *data = data_;
|
||||
|
||||
#ifdef DEBUG_PRINT_UTF8
|
||||
printf("BEGIN UTF-8\n");
|
||||
#endif
|
||||
|
||||
for(; *pos < bytelen && *cpi < cplen; (*pos)++) {
|
||||
unsigned char c = bytes[*pos];
|
||||
|
||||
#ifdef DEBUG_PRINT_UTF8
|
||||
printf(" pos=%zd c=%02x rem=%d\n", *pos, c, data->bytes_remaining);
|
||||
#endif
|
||||
|
||||
if(c < 0x20) /* C0 */
|
||||
return;
|
||||
|
||||
else if(c >= 0x20 && c < 0x7f) {
|
||||
if(data->bytes_remaining)
|
||||
cp[(*cpi)++] = UNICODE_INVALID;
|
||||
|
||||
cp[(*cpi)++] = c;
|
||||
#ifdef DEBUG_PRINT_UTF8
|
||||
printf(" UTF-8 char: U+%04x\n", c);
|
||||
#endif
|
||||
data->bytes_remaining = 0;
|
||||
}
|
||||
|
||||
else if(c == 0x7f) /* DEL */
|
||||
return;
|
||||
|
||||
else if(c >= 0x80 && c < 0xc0) {
|
||||
if(!data->bytes_remaining) {
|
||||
cp[(*cpi)++] = UNICODE_INVALID;
|
||||
continue;
|
||||
}
|
||||
|
||||
data->this_cp <<= 6;
|
||||
data->this_cp |= c & 0x3f;
|
||||
data->bytes_remaining--;
|
||||
|
||||
if(!data->bytes_remaining) {
|
||||
#ifdef DEBUG_PRINT_UTF8
|
||||
printf(" UTF-8 raw char U+%04x bytelen=%d ", data->this_cp, data->bytes_total);
|
||||
#endif
|
||||
/* Check for overlong sequences */
|
||||
switch(data->bytes_total) {
|
||||
case 2:
|
||||
if(data->this_cp < 0x0080) data->this_cp = UNICODE_INVALID;
|
||||
break;
|
||||
case 3:
|
||||
if(data->this_cp < 0x0800) data->this_cp = UNICODE_INVALID;
|
||||
break;
|
||||
case 4:
|
||||
if(data->this_cp < 0x10000) data->this_cp = UNICODE_INVALID;
|
||||
break;
|
||||
case 5:
|
||||
if(data->this_cp < 0x200000) data->this_cp = UNICODE_INVALID;
|
||||
break;
|
||||
case 6:
|
||||
if(data->this_cp < 0x4000000) data->this_cp = UNICODE_INVALID;
|
||||
break;
|
||||
}
|
||||
/* Now look for plain invalid ones */
|
||||
if((data->this_cp >= 0xD800 && data->this_cp <= 0xDFFF) ||
|
||||
data->this_cp == 0xFFFE ||
|
||||
data->this_cp == 0xFFFF)
|
||||
data->this_cp = UNICODE_INVALID;
|
||||
#ifdef DEBUG_PRINT_UTF8
|
||||
printf(" char: U+%04x\n", data->this_cp);
|
||||
#endif
|
||||
cp[(*cpi)++] = data->this_cp;
|
||||
}
|
||||
}
|
||||
|
||||
else if(c >= 0xc0 && c < 0xe0) {
|
||||
if(data->bytes_remaining)
|
||||
cp[(*cpi)++] = UNICODE_INVALID;
|
||||
|
||||
data->this_cp = c & 0x1f;
|
||||
data->bytes_total = 2;
|
||||
data->bytes_remaining = 1;
|
||||
}
|
||||
|
||||
else if(c >= 0xe0 && c < 0xf0) {
|
||||
if(data->bytes_remaining)
|
||||
cp[(*cpi)++] = UNICODE_INVALID;
|
||||
|
||||
data->this_cp = c & 0x0f;
|
||||
data->bytes_total = 3;
|
||||
data->bytes_remaining = 2;
|
||||
}
|
||||
|
||||
else if(c >= 0xf0 && c < 0xf8) {
|
||||
if(data->bytes_remaining)
|
||||
cp[(*cpi)++] = UNICODE_INVALID;
|
||||
|
||||
data->this_cp = c & 0x07;
|
||||
data->bytes_total = 4;
|
||||
data->bytes_remaining = 3;
|
||||
}
|
||||
|
||||
else if(c >= 0xf8 && c < 0xfc) {
|
||||
if(data->bytes_remaining)
|
||||
cp[(*cpi)++] = UNICODE_INVALID;
|
||||
|
||||
data->this_cp = c & 0x03;
|
||||
data->bytes_total = 5;
|
||||
data->bytes_remaining = 4;
|
||||
}
|
||||
|
||||
else if(c >= 0xfc && c < 0xfe) {
|
||||
if(data->bytes_remaining)
|
||||
cp[(*cpi)++] = UNICODE_INVALID;
|
||||
|
||||
data->this_cp = c & 0x01;
|
||||
data->bytes_total = 6;
|
||||
data->bytes_remaining = 5;
|
||||
}
|
||||
|
||||
else {
|
||||
cp[(*cpi)++] = UNICODE_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static VTermEncoding encoding_utf8 = {
|
||||
&init_utf8, /* init */
|
||||
&decode_utf8 /* decode */
|
||||
};
|
||||
|
||||
static void decode_usascii(VTermEncoding *enc UNUSED, void *data UNUSED,
|
||||
uint32_t cp[], int *cpi, int cplen,
|
||||
const char bytes[], size_t *pos, size_t bytelen)
|
||||
{
|
||||
int is_gr = bytes[*pos] & 0x80;
|
||||
|
||||
for(; *pos < bytelen && *cpi < cplen; (*pos)++) {
|
||||
unsigned char c = bytes[*pos] ^ is_gr;
|
||||
|
||||
if(c < 0x20 || c == 0x7f || c >= 0x80)
|
||||
return;
|
||||
|
||||
cp[(*cpi)++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
static VTermEncoding encoding_usascii = {
|
||||
NULL, /* init */
|
||||
&decode_usascii /* decode */
|
||||
};
|
||||
|
||||
struct StaticTableEncoding {
|
||||
const VTermEncoding enc;
|
||||
const uint32_t chars[128];
|
||||
};
|
||||
|
||||
static void decode_table(VTermEncoding *enc, void *data UNUSED,
|
||||
uint32_t cp[], int *cpi, int cplen,
|
||||
const char bytes[], size_t *pos, size_t bytelen)
|
||||
{
|
||||
struct StaticTableEncoding *table = (struct StaticTableEncoding *)enc;
|
||||
int is_gr = bytes[*pos] & 0x80;
|
||||
|
||||
for(; *pos < bytelen && *cpi < cplen; (*pos)++) {
|
||||
unsigned char c = bytes[*pos] ^ is_gr;
|
||||
|
||||
if(c < 0x20 || c == 0x7f || c >= 0x80)
|
||||
return;
|
||||
|
||||
if(table->chars[c])
|
||||
cp[(*cpi)++] = table->chars[c];
|
||||
else
|
||||
cp[(*cpi)++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
#include "encoding/DECdrawing.inc"
|
||||
#include "encoding/uk.inc"
|
||||
|
||||
static struct {
|
||||
VTermEncodingType type;
|
||||
char designation;
|
||||
VTermEncoding *enc;
|
||||
}
|
||||
encodings[] = {
|
||||
{ ENC_UTF8, 'u', &encoding_utf8 },
|
||||
{ ENC_SINGLE_94, '0', (VTermEncoding*)&encoding_DECdrawing },
|
||||
{ ENC_SINGLE_94, 'A', (VTermEncoding*)&encoding_uk },
|
||||
{ ENC_SINGLE_94, 'B', &encoding_usascii },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
/* This ought to be INTERNAL but isn't because it's used by unit testing */
|
||||
VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; encodings[i].designation; i++)
|
||||
if(encodings[i].type == type && encodings[i].designation == designation)
|
||||
return encodings[i].enc;
|
||||
return NULL;
|
||||
}
|
||||
136
src/libvterm/src/encoding/DECdrawing.inc
Normal file
136
src/libvterm/src/encoding/DECdrawing.inc
Normal file
@@ -0,0 +1,136 @@
|
||||
static const struct StaticTableEncoding encoding_DECdrawing = {
|
||||
{
|
||||
NULL, /* init */
|
||||
&decode_table /* decode */
|
||||
},
|
||||
{
|
||||
0x0, /* 0 */
|
||||
0x0, /* 1 */
|
||||
0x0, /* 2 */
|
||||
0x0, /* 3 */
|
||||
0x0, /* 4 */
|
||||
0x0, /* 5 */
|
||||
0x0, /* 6 */
|
||||
0x0, /* 7 */
|
||||
0x0, /* 8 */
|
||||
0x0, /* 9 */
|
||||
0x0, /* 10 */
|
||||
0x0, /* 11 */
|
||||
0x0, /* 12 */
|
||||
0x0, /* 13 */
|
||||
0x0, /* 14 */
|
||||
0x0, /* 15 */
|
||||
0x0, /* 16 */
|
||||
0x0, /* 17 */
|
||||
0x0, /* 18 */
|
||||
0x0, /* 19 */
|
||||
0x0, /* 20 */
|
||||
0x0, /* 21 */
|
||||
0x0, /* 22 */
|
||||
0x0, /* 23 */
|
||||
0x0, /* 24 */
|
||||
0x0, /* 25 */
|
||||
0x0, /* 26 */
|
||||
0x0, /* 27 */
|
||||
0x0, /* 28 */
|
||||
0x0, /* 29 */
|
||||
0x0, /* 30 */
|
||||
0x0, /* 31 */
|
||||
0x0, /* 32 */
|
||||
0x0, /* 33 */
|
||||
0x0, /* 34 */
|
||||
0x0, /* 35 */
|
||||
0x0, /* 36 */
|
||||
0x0, /* 37 */
|
||||
0x0, /* 38 */
|
||||
0x0, /* 39 */
|
||||
0x0, /* 40 */
|
||||
0x0, /* 41 */
|
||||
0x0, /* 42 */
|
||||
0x0, /* 43 */
|
||||
0x0, /* 44 */
|
||||
0x0, /* 45 */
|
||||
0x0, /* 46 */
|
||||
0x0, /* 47 */
|
||||
0x0, /* 48 */
|
||||
0x0, /* 49 */
|
||||
0x0, /* 50 */
|
||||
0x0, /* 51 */
|
||||
0x0, /* 52 */
|
||||
0x0, /* 53 */
|
||||
0x0, /* 54 */
|
||||
0x0, /* 55 */
|
||||
0x0, /* 56 */
|
||||
0x0, /* 57 */
|
||||
0x0, /* 58 */
|
||||
0x0, /* 59 */
|
||||
0x0, /* 60 */
|
||||
0x0, /* 61 */
|
||||
0x0, /* 62 */
|
||||
0x0, /* 63 */
|
||||
0x0, /* 64 */
|
||||
0x0, /* 65 */
|
||||
0x0, /* 66 */
|
||||
0x0, /* 67 */
|
||||
0x0, /* 68 */
|
||||
0x0, /* 69 */
|
||||
0x0, /* 70 */
|
||||
0x0, /* 71 */
|
||||
0x0, /* 72 */
|
||||
0x0, /* 73 */
|
||||
0x0, /* 74 */
|
||||
0x0, /* 75 */
|
||||
0x0, /* 76 */
|
||||
0x0, /* 77 */
|
||||
0x0, /* 78 */
|
||||
0x0, /* 79 */
|
||||
0x0, /* 80 */
|
||||
0x0, /* 81 */
|
||||
0x0, /* 82 */
|
||||
0x0, /* 83 */
|
||||
0x0, /* 84 */
|
||||
0x0, /* 85 */
|
||||
0x0, /* 86 */
|
||||
0x0, /* 87 */
|
||||
0x0, /* 88 */
|
||||
0x0, /* 89 */
|
||||
0x0, /* 90 */
|
||||
0x0, /* 91 */
|
||||
0x0, /* 92 */
|
||||
0x0, /* 93 */
|
||||
0x0, /* 94 */
|
||||
0x0, /* 95 */
|
||||
0x25C6, /* 96 */
|
||||
0x2592, /* 97 */
|
||||
0x2409, /* 98 */
|
||||
0x240C, /* 99 */
|
||||
0x240D, /* 100 */
|
||||
0x240A, /* 101 */
|
||||
0x00B0, /* 102 */
|
||||
0x00B1, /* 103 */
|
||||
0x2424, /* 104 */
|
||||
0x240B, /* 105 */
|
||||
0x2518, /* 106 */
|
||||
0x2510, /* 107 */
|
||||
0x250C, /* 108 */
|
||||
0x2514, /* 109 */
|
||||
0x253C, /* 110 */
|
||||
0x23BA, /* 111 */
|
||||
0x23BB, /* 112 */
|
||||
0x2500, /* 113 */
|
||||
0x23BC, /* 114 */
|
||||
0x23BD, /* 115 */
|
||||
0x251C, /* 116 */
|
||||
0x2524, /* 117 */
|
||||
0x2534, /* 118 */
|
||||
0x252C, /* 119 */
|
||||
0x2502, /* 120 */
|
||||
0x2A7D, /* 121 */
|
||||
0x2A7E, /* 122 */
|
||||
0x03C0, /* 123 */
|
||||
0x2260, /* 124 */
|
||||
0x00A3, /* 125 */
|
||||
0x00B7, /* 126 */
|
||||
0x0, /* 127 */
|
||||
}
|
||||
};
|
||||
31
src/libvterm/src/encoding/DECdrawing.tbl
Normal file
31
src/libvterm/src/encoding/DECdrawing.tbl
Normal file
@@ -0,0 +1,31 @@
|
||||
6/0 = U+25C6 # BLACK DIAMOND
|
||||
6/1 = U+2592 # MEDIUM SHADE (checkerboard)
|
||||
6/2 = U+2409 # SYMBOL FOR HORIZONTAL TAB
|
||||
6/3 = U+240C # SYMBOL FOR FORM FEED
|
||||
6/4 = U+240D # SYMBOL FOR CARRIAGE RETURN
|
||||
6/5 = U+240A # SYMBOL FOR LINE FEED
|
||||
6/6 = U+00B0 # DEGREE SIGN
|
||||
6/7 = U+00B1 # PLUS-MINUS SIGN (plus or minus)
|
||||
6/8 = U+2424 # SYMBOL FOR NEW LINE
|
||||
6/9 = U+240B # SYMBOL FOR VERTICAL TAB
|
||||
6/10 = U+2518 # BOX DRAWINGS LIGHT UP AND LEFT (bottom-right corner)
|
||||
6/11 = U+2510 # BOX DRAWINGS LIGHT DOWN AND LEFT (top-right corner)
|
||||
6/12 = U+250C # BOX DRAWINGS LIGHT DOWN AND RIGHT (top-left corner)
|
||||
6/13 = U+2514 # BOX DRAWINGS LIGHT UP AND RIGHT (bottom-left corner)
|
||||
6/14 = U+253C # BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL (crossing lines)
|
||||
6/15 = U+23BA # HORIZONTAL SCAN LINE-1
|
||||
7/0 = U+23BB # HORIZONTAL SCAN LINE-3
|
||||
7/1 = U+2500 # BOX DRAWINGS LIGHT HORIZONTAL
|
||||
7/2 = U+23BC # HORIZONTAL SCAN LINE-7
|
||||
7/3 = U+23BD # HORIZONTAL SCAN LINE-9
|
||||
7/4 = U+251C # BOX DRAWINGS LIGHT VERTICAL AND RIGHT
|
||||
7/5 = U+2524 # BOX DRAWINGS LIGHT VERTICAL AND LEFT
|
||||
7/6 = U+2534 # BOX DRAWINGS LIGHT UP AND HORIZONTAL
|
||||
7/7 = U+252C # BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
|
||||
7/8 = U+2502 # BOX DRAWINGS LIGHT VERTICAL
|
||||
7/9 = U+2A7D # LESS-THAN OR SLANTED EQUAL-TO
|
||||
7/10 = U+2A7E # GREATER-THAN OR SLANTED EQUAL-TO
|
||||
7/11 = U+03C0 # GREEK SMALL LETTER PI
|
||||
7/12 = U+2260 # NOT EQUAL TO
|
||||
7/13 = U+00A3 # POUND SIGN
|
||||
7/14 = U+00B7 # MIDDLE DOT
|
||||
136
src/libvterm/src/encoding/uk.inc
Normal file
136
src/libvterm/src/encoding/uk.inc
Normal file
@@ -0,0 +1,136 @@
|
||||
static const struct StaticTableEncoding encoding_uk = {
|
||||
{
|
||||
NULL, /* init */
|
||||
&decode_table /* decode */
|
||||
},
|
||||
{
|
||||
0x0, /* 0 */
|
||||
0x0, /* 1 */
|
||||
0x0, /* 2 */
|
||||
0x0, /* 3 */
|
||||
0x0, /* 4 */
|
||||
0x0, /* 5 */
|
||||
0x0, /* 6 */
|
||||
0x0, /* 7 */
|
||||
0x0, /* 8 */
|
||||
0x0, /* 9 */
|
||||
0x0, /* 10 */
|
||||
0x0, /* 11 */
|
||||
0x0, /* 12 */
|
||||
0x0, /* 13 */
|
||||
0x0, /* 14 */
|
||||
0x0, /* 15 */
|
||||
0x0, /* 16 */
|
||||
0x0, /* 17 */
|
||||
0x0, /* 18 */
|
||||
0x0, /* 19 */
|
||||
0x0, /* 20 */
|
||||
0x0, /* 21 */
|
||||
0x0, /* 22 */
|
||||
0x0, /* 23 */
|
||||
0x0, /* 24 */
|
||||
0x0, /* 25 */
|
||||
0x0, /* 26 */
|
||||
0x0, /* 27 */
|
||||
0x0, /* 28 */
|
||||
0x0, /* 29 */
|
||||
0x0, /* 30 */
|
||||
0x0, /* 31 */
|
||||
0x0, /* 32 */
|
||||
0x0, /* 33 */
|
||||
0x0, /* 34 */
|
||||
0x00a3, /* 35 */
|
||||
0x0, /* 36 */
|
||||
0x0, /* 37 */
|
||||
0x0, /* 38 */
|
||||
0x0, /* 39 */
|
||||
0x0, /* 40 */
|
||||
0x0, /* 41 */
|
||||
0x0, /* 42 */
|
||||
0x0, /* 43 */
|
||||
0x0, /* 44 */
|
||||
0x0, /* 45 */
|
||||
0x0, /* 46 */
|
||||
0x0, /* 47 */
|
||||
0x0, /* 48 */
|
||||
0x0, /* 49 */
|
||||
0x0, /* 50 */
|
||||
0x0, /* 51 */
|
||||
0x0, /* 52 */
|
||||
0x0, /* 53 */
|
||||
0x0, /* 54 */
|
||||
0x0, /* 55 */
|
||||
0x0, /* 56 */
|
||||
0x0, /* 57 */
|
||||
0x0, /* 58 */
|
||||
0x0, /* 59 */
|
||||
0x0, /* 60 */
|
||||
0x0, /* 61 */
|
||||
0x0, /* 62 */
|
||||
0x0, /* 63 */
|
||||
0x0, /* 64 */
|
||||
0x0, /* 65 */
|
||||
0x0, /* 66 */
|
||||
0x0, /* 67 */
|
||||
0x0, /* 68 */
|
||||
0x0, /* 69 */
|
||||
0x0, /* 70 */
|
||||
0x0, /* 71 */
|
||||
0x0, /* 72 */
|
||||
0x0, /* 73 */
|
||||
0x0, /* 74 */
|
||||
0x0, /* 75 */
|
||||
0x0, /* 76 */
|
||||
0x0, /* 77 */
|
||||
0x0, /* 78 */
|
||||
0x0, /* 79 */
|
||||
0x0, /* 80 */
|
||||
0x0, /* 81 */
|
||||
0x0, /* 82 */
|
||||
0x0, /* 83 */
|
||||
0x0, /* 84 */
|
||||
0x0, /* 85 */
|
||||
0x0, /* 86 */
|
||||
0x0, /* 87 */
|
||||
0x0, /* 88 */
|
||||
0x0, /* 89 */
|
||||
0x0, /* 90 */
|
||||
0x0, /* 91 */
|
||||
0x0, /* 92 */
|
||||
0x0, /* 93 */
|
||||
0x0, /* 94 */
|
||||
0x0, /* 95 */
|
||||
0x0, /* 96 */
|
||||
0x0, /* 97 */
|
||||
0x0, /* 98 */
|
||||
0x0, /* 99 */
|
||||
0x0, /* 100 */
|
||||
0x0, /* 101 */
|
||||
0x0, /* 102 */
|
||||
0x0, /* 103 */
|
||||
0x0, /* 104 */
|
||||
0x0, /* 105 */
|
||||
0x0, /* 106 */
|
||||
0x0, /* 107 */
|
||||
0x0, /* 108 */
|
||||
0x0, /* 109 */
|
||||
0x0, /* 110 */
|
||||
0x0, /* 111 */
|
||||
0x0, /* 112 */
|
||||
0x0, /* 113 */
|
||||
0x0, /* 114 */
|
||||
0x0, /* 115 */
|
||||
0x0, /* 116 */
|
||||
0x0, /* 117 */
|
||||
0x0, /* 118 */
|
||||
0x0, /* 119 */
|
||||
0x0, /* 120 */
|
||||
0x0, /* 121 */
|
||||
0x0, /* 122 */
|
||||
0x0, /* 123 */
|
||||
0x0, /* 124 */
|
||||
0x0, /* 125 */
|
||||
0x0, /* 126 */
|
||||
0x0, /* 127 */
|
||||
}
|
||||
};
|
||||
1
src/libvterm/src/encoding/uk.tbl
Normal file
1
src/libvterm/src/encoding/uk.tbl
Normal file
@@ -0,0 +1 @@
|
||||
2/3 = "£"
|
||||
228
src/libvterm/src/keyboard.c
Normal file
228
src/libvterm/src/keyboard.c
Normal file
@@ -0,0 +1,228 @@
|
||||
#include "vterm_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
void vterm_keyboard_unichar(VTerm *vt, uint32_t c, VTermModifier mod)
|
||||
{
|
||||
int needs_CSIu;
|
||||
|
||||
/* The shift modifier is never important for Unicode characters
|
||||
* apart from Space
|
||||
*/
|
||||
if(c != ' ')
|
||||
mod &= ~VTERM_MOD_SHIFT;
|
||||
|
||||
if(mod == 0) {
|
||||
/* Normal text - ignore just shift */
|
||||
char str[6];
|
||||
int seqlen = fill_utf8(c, str);
|
||||
vterm_push_output_bytes(vt, str, seqlen);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(c) {
|
||||
/* Special Ctrl- letters that can't be represented elsewise */
|
||||
case 'i': case 'j': case 'm': case '[':
|
||||
needs_CSIu = 1;
|
||||
break;
|
||||
/* Ctrl-\ ] ^ _ don't need CSUu */
|
||||
case '\\': case ']': case '^': case '_':
|
||||
needs_CSIu = 0;
|
||||
break;
|
||||
/* Shift-space needs CSIu */
|
||||
case ' ':
|
||||
needs_CSIu = !!(mod & VTERM_MOD_SHIFT);
|
||||
break;
|
||||
/* All other characters needs CSIu except for letters a-z */
|
||||
default:
|
||||
needs_CSIu = (c < 'a' || c > 'z');
|
||||
}
|
||||
|
||||
/* ALT we can just prefix with ESC; anything else requires CSI u */
|
||||
if(needs_CSIu && (mod & ~VTERM_MOD_ALT)) {
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", c, mod+1);
|
||||
return;
|
||||
}
|
||||
|
||||
if(mod & VTERM_MOD_CTRL)
|
||||
c &= 0x1f;
|
||||
|
||||
vterm_push_output_sprintf(vt, "%s%c", mod & VTERM_MOD_ALT ? ESC_S : "", c);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
enum {
|
||||
KEYCODE_NONE,
|
||||
KEYCODE_LITERAL,
|
||||
KEYCODE_TAB,
|
||||
KEYCODE_ENTER,
|
||||
KEYCODE_SS3,
|
||||
KEYCODE_CSI,
|
||||
KEYCODE_CSI_CURSOR,
|
||||
KEYCODE_CSINUM,
|
||||
KEYCODE_KEYPAD
|
||||
} type;
|
||||
char literal;
|
||||
int csinum;
|
||||
} keycodes_s;
|
||||
|
||||
static keycodes_s keycodes[] = {
|
||||
{ KEYCODE_NONE, 0, 0 }, /* NONE */
|
||||
|
||||
{ KEYCODE_ENTER, '\r', 0 }, /* ENTER */
|
||||
{ KEYCODE_TAB, '\t', 0 }, /* TAB */
|
||||
{ KEYCODE_LITERAL, '\x7f', 0 }, /* BACKSPACE == ASCII DEL */
|
||||
{ KEYCODE_LITERAL, '\x1b', 0 }, /* ESCAPE */
|
||||
|
||||
{ KEYCODE_CSI_CURSOR, 'A', 0 }, /* UP */
|
||||
{ KEYCODE_CSI_CURSOR, 'B', 0 }, /* DOWN */
|
||||
{ KEYCODE_CSI_CURSOR, 'D', 0 }, /* LEFT */
|
||||
{ KEYCODE_CSI_CURSOR, 'C', 0 }, /* RIGHT */
|
||||
|
||||
{ KEYCODE_CSINUM, '~', 2 }, /* INS */
|
||||
{ KEYCODE_CSINUM, '~', 3 }, /* DEL */
|
||||
{ KEYCODE_CSI_CURSOR, 'H', 0 }, /* HOME */
|
||||
{ KEYCODE_CSI_CURSOR, 'F', 0 }, /* END */
|
||||
{ KEYCODE_CSINUM, '~', 5 }, /* PAGEUP */
|
||||
{ KEYCODE_CSINUM, '~', 6 }, /* PAGEDOWN */
|
||||
};
|
||||
|
||||
static keycodes_s keycodes_fn[] = {
|
||||
{ KEYCODE_NONE, 0, 0 }, /* F0 - shouldn't happen */
|
||||
{ KEYCODE_CSI_CURSOR, 'P', 0 }, /* F1 */
|
||||
{ KEYCODE_CSI_CURSOR, 'Q', 0 }, /* F2 */
|
||||
{ KEYCODE_CSI_CURSOR, 'R', 0 }, /* F3 */
|
||||
{ KEYCODE_CSI_CURSOR, 'S', 0 }, /* F4 */
|
||||
{ KEYCODE_CSINUM, '~', 15 }, /* F5 */
|
||||
{ KEYCODE_CSINUM, '~', 17 }, /* F6 */
|
||||
{ KEYCODE_CSINUM, '~', 18 }, /* F7 */
|
||||
{ KEYCODE_CSINUM, '~', 19 }, /* F8 */
|
||||
{ KEYCODE_CSINUM, '~', 20 }, /* F9 */
|
||||
{ KEYCODE_CSINUM, '~', 21 }, /* F10 */
|
||||
{ KEYCODE_CSINUM, '~', 23 }, /* F11 */
|
||||
{ KEYCODE_CSINUM, '~', 24 }, /* F12 */
|
||||
};
|
||||
|
||||
static keycodes_s keycodes_kp[] = {
|
||||
{ KEYCODE_KEYPAD, '0', 'p' }, /* KP_0 */
|
||||
{ KEYCODE_KEYPAD, '1', 'q' }, /* KP_1 */
|
||||
{ KEYCODE_KEYPAD, '2', 'r' }, /* KP_2 */
|
||||
{ KEYCODE_KEYPAD, '3', 's' }, /* KP_3 */
|
||||
{ KEYCODE_KEYPAD, '4', 't' }, /* KP_4 */
|
||||
{ KEYCODE_KEYPAD, '5', 'u' }, /* KP_5 */
|
||||
{ KEYCODE_KEYPAD, '6', 'v' }, /* KP_6 */
|
||||
{ KEYCODE_KEYPAD, '7', 'w' }, /* KP_7 */
|
||||
{ KEYCODE_KEYPAD, '8', 'x' }, /* KP_8 */
|
||||
{ KEYCODE_KEYPAD, '9', 'y' }, /* KP_9 */
|
||||
{ KEYCODE_KEYPAD, '*', 'j' }, /* KP_MULT */
|
||||
{ KEYCODE_KEYPAD, '+', 'k' }, /* KP_PLUS */
|
||||
{ KEYCODE_KEYPAD, ',', 'l' }, /* KP_COMMA */
|
||||
{ KEYCODE_KEYPAD, '-', 'm' }, /* KP_MINUS */
|
||||
{ KEYCODE_KEYPAD, '.', 'n' }, /* KP_PERIOD */
|
||||
{ KEYCODE_KEYPAD, '/', 'o' }, /* KP_DIVIDE */
|
||||
{ KEYCODE_KEYPAD, '\n', 'M' }, /* KP_ENTER */
|
||||
{ KEYCODE_KEYPAD, '=', 'X' }, /* KP_EQUAL */
|
||||
};
|
||||
|
||||
void vterm_keyboard_key(VTerm *vt, VTermKey key, VTermModifier mod)
|
||||
{
|
||||
keycodes_s k;
|
||||
|
||||
if(key == VTERM_KEY_NONE)
|
||||
return;
|
||||
|
||||
if(key < VTERM_KEY_FUNCTION_0) {
|
||||
if(key >= sizeof(keycodes)/sizeof(keycodes[0]))
|
||||
return;
|
||||
k = keycodes[key];
|
||||
}
|
||||
else if(key >= VTERM_KEY_FUNCTION_0 && key <= VTERM_KEY_FUNCTION_MAX) {
|
||||
if((key - VTERM_KEY_FUNCTION_0) >= sizeof(keycodes_fn)/sizeof(keycodes_fn[0]))
|
||||
return;
|
||||
k = keycodes_fn[key - VTERM_KEY_FUNCTION_0];
|
||||
}
|
||||
else if(key >= VTERM_KEY_KP_0) {
|
||||
if((key - VTERM_KEY_KP_0) >= sizeof(keycodes_kp)/sizeof(keycodes_kp[0]))
|
||||
return;
|
||||
k = keycodes_kp[key - VTERM_KEY_KP_0];
|
||||
}
|
||||
|
||||
switch(k.type) {
|
||||
case KEYCODE_NONE:
|
||||
break;
|
||||
|
||||
case KEYCODE_TAB:
|
||||
/* Shift-Tab is CSI Z but plain Tab is 0x09 */
|
||||
if(mod == VTERM_MOD_SHIFT)
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "Z");
|
||||
else if(mod & VTERM_MOD_SHIFT)
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "1;%dZ", mod+1);
|
||||
else
|
||||
goto case_LITERAL;
|
||||
break;
|
||||
|
||||
case KEYCODE_ENTER:
|
||||
/* Enter is CRLF in newline mode, but just LF in linefeed */
|
||||
if(vt->state->mode.newline)
|
||||
vterm_push_output_sprintf(vt, "\r\n");
|
||||
else
|
||||
goto case_LITERAL;
|
||||
break;
|
||||
|
||||
case KEYCODE_LITERAL: case_LITERAL:
|
||||
if(mod & (VTERM_MOD_SHIFT|VTERM_MOD_CTRL))
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%du", k.literal, mod+1);
|
||||
else
|
||||
vterm_push_output_sprintf(vt, mod & VTERM_MOD_ALT ? ESC_S "%c" : "%c", k.literal);
|
||||
break;
|
||||
|
||||
case KEYCODE_SS3: case_SS3:
|
||||
if(mod == 0)
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_SS3, "%c", k.literal);
|
||||
else
|
||||
goto case_CSI;
|
||||
break;
|
||||
|
||||
case KEYCODE_CSI: case_CSI:
|
||||
if(mod == 0)
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%c", k.literal);
|
||||
else
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "1;%d%c", mod + 1, k.literal);
|
||||
break;
|
||||
|
||||
case KEYCODE_CSINUM:
|
||||
if(mod == 0)
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d%c", k.csinum, k.literal);
|
||||
else
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "%d;%d%c", k.csinum, mod + 1, k.literal);
|
||||
break;
|
||||
|
||||
case KEYCODE_CSI_CURSOR:
|
||||
if(vt->state->mode.cursor)
|
||||
goto case_SS3;
|
||||
else
|
||||
goto case_CSI;
|
||||
|
||||
case KEYCODE_KEYPAD:
|
||||
if(vt->state->mode.keypad) {
|
||||
k.literal = k.csinum;
|
||||
goto case_SS3;
|
||||
}
|
||||
else
|
||||
goto case_LITERAL;
|
||||
}
|
||||
}
|
||||
|
||||
void vterm_keyboard_start_paste(VTerm *vt)
|
||||
{
|
||||
if(vt->state->mode.bracketpaste)
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "200~");
|
||||
}
|
||||
|
||||
void vterm_keyboard_end_paste(VTerm *vt)
|
||||
{
|
||||
if(vt->state->mode.bracketpaste)
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_CSI, "201~");
|
||||
}
|
||||
96
src/libvterm/src/mouse.c
Normal file
96
src/libvterm/src/mouse.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "vterm_internal.h"
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
static void output_mouse(VTermState *state, int code, int pressed, int modifiers, int col, int row)
|
||||
{
|
||||
modifiers <<= 2;
|
||||
|
||||
switch(state->mouse_protocol) {
|
||||
case MOUSE_X10:
|
||||
if(col + 0x21 > 0xff)
|
||||
col = 0xff - 0x21;
|
||||
if(row + 0x21 > 0xff)
|
||||
row = 0xff - 0x21;
|
||||
|
||||
if(!pressed)
|
||||
code = 3;
|
||||
|
||||
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%c%c%c",
|
||||
(code | modifiers) + 0x20, col + 0x21, row + 0x21);
|
||||
break;
|
||||
|
||||
case MOUSE_UTF8:
|
||||
{
|
||||
char utf8[18]; size_t len = 0;
|
||||
|
||||
if(!pressed)
|
||||
code = 3;
|
||||
|
||||
len += fill_utf8((code | modifiers) + 0x20, utf8 + len);
|
||||
len += fill_utf8(col + 0x21, utf8 + len);
|
||||
len += fill_utf8(row + 0x21, utf8 + len);
|
||||
utf8[len] = 0;
|
||||
|
||||
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "M%s", utf8);
|
||||
}
|
||||
break;
|
||||
|
||||
case MOUSE_SGR:
|
||||
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "<%d;%d;%d%c",
|
||||
code | modifiers, col + 1, row + 1, pressed ? 'M' : 'm');
|
||||
break;
|
||||
|
||||
case MOUSE_RXVT:
|
||||
if(!pressed)
|
||||
code = 3;
|
||||
|
||||
vterm_push_output_sprintf_ctrl(state->vt, C1_CSI, "%d;%d;%dM",
|
||||
code | modifiers, col + 1, row + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void vterm_mouse_move(VTerm *vt, int row, int col, VTermModifier mod)
|
||||
{
|
||||
VTermState *state = vt->state;
|
||||
|
||||
if(col == state->mouse_col && row == state->mouse_row)
|
||||
return;
|
||||
|
||||
state->mouse_col = col;
|
||||
state->mouse_row = row;
|
||||
|
||||
if((state->mouse_flags & MOUSE_WANT_DRAG && state->mouse_buttons) ||
|
||||
(state->mouse_flags & MOUSE_WANT_MOVE)) {
|
||||
int button = state->mouse_buttons & 0x01 ? 1 :
|
||||
state->mouse_buttons & 0x02 ? 2 :
|
||||
state->mouse_buttons & 0x04 ? 3 : 4;
|
||||
output_mouse(state, button-1 + 0x20, 1, mod, col, row);
|
||||
}
|
||||
}
|
||||
|
||||
void vterm_mouse_button(VTerm *vt, int button, bool pressed, VTermModifier mod)
|
||||
{
|
||||
VTermState *state = vt->state;
|
||||
|
||||
int old_buttons = state->mouse_buttons;
|
||||
|
||||
if(button > 0 && button <= 3) {
|
||||
if(pressed)
|
||||
state->mouse_buttons |= (1 << (button-1));
|
||||
else
|
||||
state->mouse_buttons &= ~(1 << (button-1));
|
||||
}
|
||||
|
||||
/* Most of the time we don't get button releases from 4/5 */
|
||||
if(state->mouse_buttons == old_buttons && button < 4)
|
||||
return;
|
||||
|
||||
if(button < 4) {
|
||||
output_mouse(state, button-1, pressed, mod, state->mouse_col, state->mouse_row);
|
||||
}
|
||||
else if(button < 6) {
|
||||
output_mouse(state, button-4 + 0x40, pressed, mod, state->mouse_col, state->mouse_row);
|
||||
}
|
||||
}
|
||||
346
src/libvterm/src/parser.c
Normal file
346
src/libvterm/src/parser.c
Normal file
@@ -0,0 +1,346 @@
|
||||
#include "vterm_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CSI_ARGS_MAX 16
|
||||
#define CSI_LEADER_MAX 16
|
||||
#define CSI_INTERMED_MAX 16
|
||||
|
||||
static void do_control(VTerm *vt, unsigned char control)
|
||||
{
|
||||
if(vt->parser_callbacks && vt->parser_callbacks->control)
|
||||
if((*vt->parser_callbacks->control)(control, vt->cbdata))
|
||||
return;
|
||||
|
||||
DEBUG_LOG1("libvterm: Unhandled control 0x%02x\n", control);
|
||||
}
|
||||
|
||||
static void do_string_csi(VTerm *vt, const char *args, size_t arglen, char command)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
int leaderlen = 0;
|
||||
char leader[CSI_LEADER_MAX];
|
||||
int argcount = 1; /* Always at least 1 arg */
|
||||
long csi_args[CSI_ARGS_MAX];
|
||||
int argi;
|
||||
int intermedlen = 0;
|
||||
char intermed[CSI_INTERMED_MAX];
|
||||
|
||||
/* Extract leader bytes 0x3c to 0x3f */
|
||||
for( ; i < (int)arglen; i++) {
|
||||
if(args[i] < 0x3c || args[i] > 0x3f)
|
||||
break;
|
||||
if(leaderlen < CSI_LEADER_MAX-1)
|
||||
leader[leaderlen++] = args[i];
|
||||
}
|
||||
|
||||
leader[leaderlen] = 0;
|
||||
|
||||
for( ; i < (int)arglen; i++)
|
||||
if(args[i] == 0x3b || args[i] == 0x3a) /* ; or : */
|
||||
argcount++;
|
||||
|
||||
/* TODO: Consider if these buffers should live in the VTerm struct itself */
|
||||
if(argcount > CSI_ARGS_MAX)
|
||||
argcount = CSI_ARGS_MAX;
|
||||
|
||||
for(argi = 0; argi < argcount; argi++)
|
||||
csi_args[argi] = CSI_ARG_MISSING;
|
||||
|
||||
argi = 0;
|
||||
for(i = leaderlen; i < (int)arglen && argi < argcount; i++) {
|
||||
switch(args[i]) {
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
|
||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
|
||||
if(csi_args[argi] == CSI_ARG_MISSING)
|
||||
csi_args[argi] = 0;
|
||||
csi_args[argi] *= 10;
|
||||
csi_args[argi] += args[i] - '0';
|
||||
break;
|
||||
case 0x3a:
|
||||
csi_args[argi] |= CSI_ARG_FLAG_MORE;
|
||||
/* FALLTHROUGH */
|
||||
case 0x3b:
|
||||
argi++;
|
||||
break;
|
||||
default:
|
||||
goto done_leader;
|
||||
}
|
||||
}
|
||||
done_leader: ;
|
||||
|
||||
for( ; i < (int)arglen; i++) {
|
||||
if((args[i] & 0xf0) != 0x20)
|
||||
break;
|
||||
|
||||
if(intermedlen < CSI_INTERMED_MAX-1)
|
||||
intermed[intermedlen++] = args[i];
|
||||
}
|
||||
|
||||
intermed[intermedlen] = 0;
|
||||
|
||||
if(i < (int)arglen) {
|
||||
DEBUG_LOG2("libvterm: TODO unhandled CSI bytes \"%.*s\"\n", (int)(arglen - i), args + i);
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("Parsed CSI args %.*s as:\n", arglen, args);
|
||||
printf(" leader: %s\n", leader);
|
||||
for(argi = 0; argi < argcount; argi++) {
|
||||
printf(" %lu", CSI_ARG(csi_args[argi]));
|
||||
if(!CSI_ARG_HAS_MORE(csi_args[argi]))
|
||||
printf("\n");
|
||||
printf(" intermed: %s\n", intermed);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(vt->parser_callbacks && vt->parser_callbacks->csi)
|
||||
if((*vt->parser_callbacks->csi)(leaderlen ? leader : NULL, csi_args, argcount, intermedlen ? intermed : NULL, command, vt->cbdata))
|
||||
return;
|
||||
|
||||
DEBUG_LOG3("libvterm: Unhandled CSI %.*s %c\n", (int)arglen, args, command);
|
||||
}
|
||||
|
||||
static void append_strbuffer(VTerm *vt, const char *str, size_t len)
|
||||
{
|
||||
if(len > vt->strbuffer_len - vt->strbuffer_cur) {
|
||||
len = vt->strbuffer_len - vt->strbuffer_cur;
|
||||
DEBUG_LOG1("Truncating strbuffer preserve to %zd bytes\n", len);
|
||||
}
|
||||
|
||||
if(len > 0) {
|
||||
strncpy(vt->strbuffer + vt->strbuffer_cur, str, len);
|
||||
vt->strbuffer_cur += len;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t do_string(VTerm *vt, const char *str_frag, size_t len)
|
||||
{
|
||||
size_t eaten;
|
||||
|
||||
if(vt->strbuffer_cur) {
|
||||
if(str_frag)
|
||||
append_strbuffer(vt, str_frag, len);
|
||||
|
||||
str_frag = vt->strbuffer;
|
||||
len = vt->strbuffer_cur;
|
||||
}
|
||||
else if(!str_frag) {
|
||||
DEBUG_LOG("parser.c: TODO: No strbuffer _and_ no final fragment???\n");
|
||||
len = 0;
|
||||
}
|
||||
|
||||
vt->strbuffer_cur = 0;
|
||||
|
||||
switch(vt->parser_state) {
|
||||
case NORMAL:
|
||||
if(vt->parser_callbacks && vt->parser_callbacks->text)
|
||||
if((eaten = (*vt->parser_callbacks->text)(str_frag, len, vt->cbdata)))
|
||||
return eaten;
|
||||
|
||||
DEBUG_LOG1("libvterm: Unhandled text (%zu chars)\n", len);
|
||||
return 0;
|
||||
|
||||
case ESC:
|
||||
if(len == 1 && str_frag[0] >= 0x40 && str_frag[0] < 0x60) {
|
||||
/* C1 emulations using 7bit clean */
|
||||
/* ESC 0x40 == 0x80 */
|
||||
do_control(vt, str_frag[0] + 0x40);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(vt->parser_callbacks && vt->parser_callbacks->escape)
|
||||
if((*vt->parser_callbacks->escape)(str_frag, len, vt->cbdata))
|
||||
return 0;
|
||||
|
||||
DEBUG_LOG1("libvterm: Unhandled escape ESC 0x%02x\n", str_frag[len-1]);
|
||||
return 0;
|
||||
|
||||
case CSI:
|
||||
do_string_csi(vt, str_frag, len - 1, str_frag[len - 1]);
|
||||
return 0;
|
||||
|
||||
case OSC:
|
||||
if(vt->parser_callbacks && vt->parser_callbacks->osc)
|
||||
if((*vt->parser_callbacks->osc)(str_frag, len, vt->cbdata))
|
||||
return 0;
|
||||
|
||||
DEBUG_LOG2("libvterm: Unhandled OSC %.*s\n", (int)len, str_frag);
|
||||
return 0;
|
||||
|
||||
case DCS:
|
||||
if(vt->parser_callbacks && vt->parser_callbacks->dcs)
|
||||
if((*vt->parser_callbacks->dcs)(str_frag, len, vt->cbdata))
|
||||
return 0;
|
||||
|
||||
DEBUG_LOG2("libvterm: Unhandled DCS %.*s\n", (int)len, str_frag);
|
||||
return 0;
|
||||
|
||||
case ESC_IN_OSC:
|
||||
case ESC_IN_DCS:
|
||||
DEBUG_LOG("libvterm: ARGH! Should never do_string() in ESC_IN_{OSC,DCS}\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t vterm_input_write(VTerm *vt, const char *bytes, size_t len)
|
||||
{
|
||||
size_t pos = 0;
|
||||
const char *string_start;
|
||||
|
||||
switch(vt->parser_state) {
|
||||
case NORMAL:
|
||||
string_start = NULL;
|
||||
break;
|
||||
case ESC:
|
||||
case ESC_IN_OSC:
|
||||
case ESC_IN_DCS:
|
||||
case CSI:
|
||||
case OSC:
|
||||
case DCS:
|
||||
string_start = bytes;
|
||||
break;
|
||||
}
|
||||
|
||||
#define ENTER_STRING_STATE(st) do { vt->parser_state = st; string_start = bytes + pos + 1; } while(0)
|
||||
#define ENTER_NORMAL_STATE() do { vt->parser_state = NORMAL; string_start = NULL; } while(0)
|
||||
|
||||
for( ; pos < len; pos++) {
|
||||
unsigned char c = bytes[pos];
|
||||
|
||||
if(c == 0x00 || c == 0x7f) { /* NUL, DEL */
|
||||
if(vt->parser_state != NORMAL) {
|
||||
append_strbuffer(vt, string_start, bytes + pos - string_start);
|
||||
string_start = bytes + pos + 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(c == 0x18 || c == 0x1a) { /* CAN, SUB */
|
||||
ENTER_NORMAL_STATE();
|
||||
continue;
|
||||
}
|
||||
else if(c == 0x1b) { /* ESC */
|
||||
if(vt->parser_state == OSC)
|
||||
vt->parser_state = ESC_IN_OSC;
|
||||
else if(vt->parser_state == DCS)
|
||||
vt->parser_state = ESC_IN_DCS;
|
||||
else
|
||||
ENTER_STRING_STATE(ESC);
|
||||
continue;
|
||||
}
|
||||
else if(c == 0x07 && /* BEL, can stand for ST in OSC or DCS state */
|
||||
(vt->parser_state == OSC || vt->parser_state == DCS)) {
|
||||
/* fallthrough */
|
||||
}
|
||||
else if(c < 0x20) { /* other C0 */
|
||||
if(vt->parser_state != NORMAL)
|
||||
append_strbuffer(vt, string_start, bytes + pos - string_start);
|
||||
do_control(vt, c);
|
||||
if(vt->parser_state != NORMAL)
|
||||
string_start = bytes + pos + 1;
|
||||
continue;
|
||||
}
|
||||
/* else fallthrough */
|
||||
|
||||
switch(vt->parser_state) {
|
||||
case ESC_IN_OSC:
|
||||
case ESC_IN_DCS:
|
||||
if(c == 0x5c) { /* ST */
|
||||
switch(vt->parser_state) {
|
||||
case ESC_IN_OSC: vt->parser_state = OSC; break;
|
||||
case ESC_IN_DCS: vt->parser_state = DCS; break;
|
||||
default: break;
|
||||
}
|
||||
do_string(vt, string_start, bytes + pos - string_start - 1);
|
||||
ENTER_NORMAL_STATE();
|
||||
break;
|
||||
}
|
||||
vt->parser_state = ESC;
|
||||
string_start = bytes + pos;
|
||||
/* else fallthrough */
|
||||
|
||||
case ESC:
|
||||
switch(c) {
|
||||
case 0x50: /* DCS */
|
||||
ENTER_STRING_STATE(DCS);
|
||||
break;
|
||||
case 0x5b: /* CSI */
|
||||
ENTER_STRING_STATE(CSI);
|
||||
break;
|
||||
case 0x5d: /* OSC */
|
||||
ENTER_STRING_STATE(OSC);
|
||||
break;
|
||||
default:
|
||||
if(c >= 0x30 && c < 0x7f) {
|
||||
/* +1 to pos because we want to include this command byte as well */
|
||||
do_string(vt, string_start, bytes + pos - string_start + 1);
|
||||
ENTER_NORMAL_STATE();
|
||||
}
|
||||
else if(c >= 0x20 && c < 0x30) {
|
||||
/* intermediate byte */
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG1("TODO: Unhandled byte %02x in Escape\n", c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CSI:
|
||||
if(c >= 0x40 && c <= 0x7f) {
|
||||
/* +1 to pos because we want to include this command byte as well */
|
||||
do_string(vt, string_start, bytes + pos - string_start + 1);
|
||||
ENTER_NORMAL_STATE();
|
||||
}
|
||||
break;
|
||||
|
||||
case OSC:
|
||||
case DCS:
|
||||
if(c == 0x07 || (c == 0x9c && !vt->mode.utf8)) {
|
||||
do_string(vt, string_start, bytes + pos - string_start);
|
||||
ENTER_NORMAL_STATE();
|
||||
}
|
||||
break;
|
||||
|
||||
case NORMAL:
|
||||
if(c >= 0x80 && c < 0xa0 && !vt->mode.utf8) {
|
||||
switch(c) {
|
||||
case 0x90: /* DCS */
|
||||
ENTER_STRING_STATE(DCS);
|
||||
break;
|
||||
case 0x9b: /* CSI */
|
||||
ENTER_STRING_STATE(CSI);
|
||||
break;
|
||||
case 0x9d: /* OSC */
|
||||
ENTER_STRING_STATE(OSC);
|
||||
break;
|
||||
default:
|
||||
do_control(vt, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t text_eaten = do_string(vt, bytes + pos, len - pos);
|
||||
|
||||
if(text_eaten == 0) {
|
||||
string_start = bytes + pos;
|
||||
goto pause;
|
||||
}
|
||||
|
||||
pos += (text_eaten - 1); /* we'll ++ it again in a moment */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pause:
|
||||
if(string_start && string_start < len + bytes) {
|
||||
size_t remaining = len - (string_start - bytes);
|
||||
append_strbuffer(vt, string_start, remaining);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
504
src/libvterm/src/pen.c
Normal file
504
src/libvterm/src/pen.c
Normal file
@@ -0,0 +1,504 @@
|
||||
#include "vterm_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static const VTermColor ansi_colors[] = {
|
||||
/* R G B */
|
||||
{ 0, 0, 0 }, /* black */
|
||||
{ 224, 0, 0 }, /* red */
|
||||
{ 0, 224, 0 }, /* green */
|
||||
{ 224, 224, 0 }, /* yellow */
|
||||
{ 0, 0, 224 }, /* blue */
|
||||
{ 224, 0, 224 }, /* magenta */
|
||||
{ 0, 224, 224 }, /* cyan */
|
||||
{ 224, 224, 224 }, /* white == light grey */
|
||||
|
||||
/* high intensity */
|
||||
{ 128, 128, 128 }, /* black */
|
||||
{ 255, 64, 64 }, /* red */
|
||||
{ 64, 255, 64 }, /* green */
|
||||
{ 255, 255, 64 }, /* yellow */
|
||||
{ 64, 64, 255 }, /* blue */
|
||||
{ 255, 64, 255 }, /* magenta */
|
||||
{ 64, 255, 255 }, /* cyan */
|
||||
{ 255, 255, 255 }, /* white for real */
|
||||
};
|
||||
|
||||
static int ramp6[] = {
|
||||
0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF,
|
||||
};
|
||||
|
||||
static int ramp24[] = {
|
||||
0x00, 0x0B, 0x16, 0x21, 0x2C, 0x37, 0x42, 0x4D, 0x58, 0x63, 0x6E, 0x79,
|
||||
0x85, 0x90, 0x9B, 0xA6, 0xB1, 0xBC, 0xC7, 0xD2, 0xDD, 0xE8, 0xF3, 0xFF,
|
||||
};
|
||||
|
||||
static bool lookup_colour_ansi(const VTermState *state, long index, VTermColor *col)
|
||||
{
|
||||
if(index >= 0 && index < 16) {
|
||||
*col = state->colors[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool lookup_colour_palette(const VTermState *state, long index, VTermColor *col)
|
||||
{
|
||||
if(index >= 0 && index < 16) {
|
||||
/* Normal 8 colours or high intensity - parse as palette 0 */
|
||||
return lookup_colour_ansi(state, index, col);
|
||||
}
|
||||
else if(index >= 16 && index < 232) {
|
||||
/* 216-colour cube */
|
||||
index -= 16;
|
||||
|
||||
col->blue = ramp6[index % 6];
|
||||
col->green = ramp6[index/6 % 6];
|
||||
col->red = ramp6[index/6/6 % 6];
|
||||
|
||||
return true;
|
||||
}
|
||||
else if(index >= 232 && index < 256) {
|
||||
/* 24 greyscales */
|
||||
index -= 232;
|
||||
|
||||
col->blue = ramp24[index];
|
||||
col->green = ramp24[index];
|
||||
col->red = ramp24[index];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int lookup_colour(const VTermState *state, int palette, const long args[], int argcount, VTermColor *col, int *index)
|
||||
{
|
||||
switch(palette) {
|
||||
case 2: /* RGB mode - 3 args contain colour values directly */
|
||||
if(argcount < 3)
|
||||
return argcount;
|
||||
|
||||
col->red = CSI_ARG(args[0]);
|
||||
col->green = CSI_ARG(args[1]);
|
||||
col->blue = CSI_ARG(args[2]);
|
||||
|
||||
return 3;
|
||||
|
||||
case 5: /* XTerm 256-colour mode */
|
||||
if(index)
|
||||
*index = CSI_ARG_OR(args[0], -1);
|
||||
|
||||
lookup_colour_palette(state, argcount ? CSI_ARG_OR(args[0], -1) : -1, col);
|
||||
|
||||
return argcount ? 1 : 0;
|
||||
|
||||
default:
|
||||
DEBUG_LOG1("Unrecognised colour palette %d\n", palette);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Some conveniences */
|
||||
|
||||
static void setpenattr(VTermState *state, VTermAttr attr, VTermValueType type UNUSED, VTermValue *val)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if(type != vterm_get_attr_type(attr)) {
|
||||
DEBUG_LOG("Cannot set attr %d as it has type %d, not type %d\n",
|
||||
attr, vterm_get_attr_type(attr), type);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if(state->callbacks && state->callbacks->setpenattr)
|
||||
(*state->callbacks->setpenattr)(attr, val, state->cbdata);
|
||||
}
|
||||
|
||||
static void setpenattr_bool(VTermState *state, VTermAttr attr, int boolean)
|
||||
{
|
||||
VTermValue val;
|
||||
val.boolean = boolean;
|
||||
setpenattr(state, attr, VTERM_VALUETYPE_BOOL, &val);
|
||||
}
|
||||
|
||||
static void setpenattr_int(VTermState *state, VTermAttr attr, int number)
|
||||
{
|
||||
VTermValue val;
|
||||
val.number = number;
|
||||
setpenattr(state, attr, VTERM_VALUETYPE_INT, &val);
|
||||
}
|
||||
|
||||
static void setpenattr_col(VTermState *state, VTermAttr attr, VTermColor color)
|
||||
{
|
||||
VTermValue val;
|
||||
val.color = color;
|
||||
setpenattr(state, attr, VTERM_VALUETYPE_COLOR, &val);
|
||||
}
|
||||
|
||||
static void set_pen_col_ansi(VTermState *state, VTermAttr attr, long col)
|
||||
{
|
||||
VTermColor *colp = (attr == VTERM_ATTR_BACKGROUND) ? &state->pen.bg : &state->pen.fg;
|
||||
|
||||
lookup_colour_ansi(state, col, colp);
|
||||
|
||||
setpenattr_col(state, attr, *colp);
|
||||
}
|
||||
|
||||
INTERNAL void vterm_state_newpen(VTermState *state)
|
||||
{
|
||||
int col;
|
||||
|
||||
/* 90% grey so that pure white is brighter */
|
||||
state->default_fg.red = state->default_fg.green = state->default_fg.blue = 240;
|
||||
state->default_bg.red = state->default_bg.green = state->default_bg.blue = 0;
|
||||
|
||||
for(col = 0; col < 16; col++)
|
||||
state->colors[col] = ansi_colors[col];
|
||||
}
|
||||
|
||||
INTERNAL void vterm_state_resetpen(VTermState *state)
|
||||
{
|
||||
state->pen.bold = 0; setpenattr_bool(state, VTERM_ATTR_BOLD, 0);
|
||||
state->pen.underline = 0; setpenattr_int( state, VTERM_ATTR_UNDERLINE, 0);
|
||||
state->pen.italic = 0; setpenattr_bool(state, VTERM_ATTR_ITALIC, 0);
|
||||
state->pen.blink = 0; setpenattr_bool(state, VTERM_ATTR_BLINK, 0);
|
||||
state->pen.reverse = 0; setpenattr_bool(state, VTERM_ATTR_REVERSE, 0);
|
||||
state->pen.strike = 0; setpenattr_bool(state, VTERM_ATTR_STRIKE, 0);
|
||||
state->pen.font = 0; setpenattr_int( state, VTERM_ATTR_FONT, 0);
|
||||
|
||||
state->fg_index = -1;
|
||||
state->bg_index = -1;
|
||||
state->pen.fg = state->default_fg; setpenattr_col(state, VTERM_ATTR_FOREGROUND, state->default_fg);
|
||||
state->pen.bg = state->default_bg; setpenattr_col(state, VTERM_ATTR_BACKGROUND, state->default_bg);
|
||||
}
|
||||
|
||||
INTERNAL void vterm_state_savepen(VTermState *state, int save)
|
||||
{
|
||||
if(save) {
|
||||
state->saved.pen = state->pen;
|
||||
}
|
||||
else {
|
||||
state->pen = state->saved.pen;
|
||||
|
||||
setpenattr_bool(state, VTERM_ATTR_BOLD, state->pen.bold);
|
||||
setpenattr_int( state, VTERM_ATTR_UNDERLINE, state->pen.underline);
|
||||
setpenattr_bool(state, VTERM_ATTR_ITALIC, state->pen.italic);
|
||||
setpenattr_bool(state, VTERM_ATTR_BLINK, state->pen.blink);
|
||||
setpenattr_bool(state, VTERM_ATTR_REVERSE, state->pen.reverse);
|
||||
setpenattr_bool(state, VTERM_ATTR_STRIKE, state->pen.strike);
|
||||
setpenattr_int( state, VTERM_ATTR_FONT, state->pen.font);
|
||||
setpenattr_col( state, VTERM_ATTR_FOREGROUND, state->pen.fg);
|
||||
setpenattr_col( state, VTERM_ATTR_BACKGROUND, state->pen.bg);
|
||||
}
|
||||
}
|
||||
|
||||
void vterm_state_get_default_colors(const VTermState *state, VTermColor *default_fg, VTermColor *default_bg)
|
||||
{
|
||||
*default_fg = state->default_fg;
|
||||
*default_bg = state->default_bg;
|
||||
}
|
||||
|
||||
void vterm_state_get_palette_color(const VTermState *state, int index, VTermColor *col)
|
||||
{
|
||||
lookup_colour_palette(state, index, col);
|
||||
}
|
||||
|
||||
void vterm_state_set_default_colors(VTermState *state, const VTermColor *default_fg, const VTermColor *default_bg)
|
||||
{
|
||||
state->default_fg = *default_fg;
|
||||
state->default_bg = *default_bg;
|
||||
}
|
||||
|
||||
void vterm_state_set_palette_color(VTermState *state, int index, const VTermColor *col)
|
||||
{
|
||||
if(index >= 0 && index < 16)
|
||||
state->colors[index] = *col;
|
||||
}
|
||||
|
||||
void vterm_state_set_bold_highbright(VTermState *state, int bold_is_highbright)
|
||||
{
|
||||
state->bold_is_highbright = bold_is_highbright;
|
||||
}
|
||||
|
||||
INTERNAL void vterm_state_setpen(VTermState *state, const long args[], int argcount)
|
||||
{
|
||||
/* SGR - ECMA-48 8.3.117 */
|
||||
|
||||
int argi = 0;
|
||||
int value;
|
||||
|
||||
while(argi < argcount) {
|
||||
/* This logic is easier to do 'done' backwards; set it true, and make it
|
||||
false again in the 'default' case */
|
||||
int done = 1;
|
||||
|
||||
long arg;
|
||||
switch(arg = CSI_ARG(args[argi])) {
|
||||
case CSI_ARG_MISSING:
|
||||
case 0: /* Reset */
|
||||
vterm_state_resetpen(state);
|
||||
break;
|
||||
|
||||
case 1: /* Bold on */
|
||||
state->pen.bold = 1;
|
||||
setpenattr_bool(state, VTERM_ATTR_BOLD, 1);
|
||||
if(state->fg_index > -1 && state->fg_index < 8 && state->bold_is_highbright)
|
||||
set_pen_col_ansi(state, VTERM_ATTR_FOREGROUND, state->fg_index + (state->pen.bold ? 8 : 0));
|
||||
break;
|
||||
|
||||
case 3: /* Italic on */
|
||||
state->pen.italic = 1;
|
||||
setpenattr_bool(state, VTERM_ATTR_ITALIC, 1);
|
||||
break;
|
||||
|
||||
case 4: /* Underline single */
|
||||
state->pen.underline = 1;
|
||||
setpenattr_int(state, VTERM_ATTR_UNDERLINE, 1);
|
||||
break;
|
||||
|
||||
case 5: /* Blink */
|
||||
state->pen.blink = 1;
|
||||
setpenattr_bool(state, VTERM_ATTR_BLINK, 1);
|
||||
break;
|
||||
|
||||
case 7: /* Reverse on */
|
||||
state->pen.reverse = 1;
|
||||
setpenattr_bool(state, VTERM_ATTR_REVERSE, 1);
|
||||
break;
|
||||
|
||||
case 9: /* Strikethrough on */
|
||||
state->pen.strike = 1;
|
||||
setpenattr_bool(state, VTERM_ATTR_STRIKE, 1);
|
||||
break;
|
||||
|
||||
case 10: case 11: case 12: case 13: case 14:
|
||||
case 15: case 16: case 17: case 18: case 19: /* Select font */
|
||||
state->pen.font = CSI_ARG(args[argi]) - 10;
|
||||
setpenattr_int(state, VTERM_ATTR_FONT, state->pen.font);
|
||||
break;
|
||||
|
||||
case 21: /* Underline double */
|
||||
state->pen.underline = 2;
|
||||
setpenattr_int(state, VTERM_ATTR_UNDERLINE, 2);
|
||||
break;
|
||||
|
||||
case 22: /* Bold off */
|
||||
state->pen.bold = 0;
|
||||
setpenattr_bool(state, VTERM_ATTR_BOLD, 0);
|
||||
break;
|
||||
|
||||
case 23: /* Italic and Gothic (currently unsupported) off */
|
||||
state->pen.italic = 0;
|
||||
setpenattr_bool(state, VTERM_ATTR_ITALIC, 0);
|
||||
break;
|
||||
|
||||
case 24: /* Underline off */
|
||||
state->pen.underline = 0;
|
||||
setpenattr_int(state, VTERM_ATTR_UNDERLINE, 0);
|
||||
break;
|
||||
|
||||
case 25: /* Blink off */
|
||||
state->pen.blink = 0;
|
||||
setpenattr_bool(state, VTERM_ATTR_BLINK, 0);
|
||||
break;
|
||||
|
||||
case 27: /* Reverse off */
|
||||
state->pen.reverse = 0;
|
||||
setpenattr_bool(state, VTERM_ATTR_REVERSE, 0);
|
||||
break;
|
||||
|
||||
case 29: /* Strikethrough off */
|
||||
state->pen.strike = 0;
|
||||
setpenattr_bool(state, VTERM_ATTR_STRIKE, 0);
|
||||
break;
|
||||
|
||||
case 30: case 31: case 32: case 33:
|
||||
case 34: case 35: case 36: case 37: /* Foreground colour palette */
|
||||
value = CSI_ARG(args[argi]) - 30;
|
||||
state->fg_index = value;
|
||||
if(state->pen.bold && state->bold_is_highbright)
|
||||
value += 8;
|
||||
set_pen_col_ansi(state, VTERM_ATTR_FOREGROUND, value);
|
||||
break;
|
||||
|
||||
case 38: /* Foreground colour alternative palette */
|
||||
state->fg_index = -1;
|
||||
if(argcount - argi < 1)
|
||||
return;
|
||||
argi += 1 + lookup_colour(state, CSI_ARG(args[argi+1]), args+argi+2, argcount-argi-2, &state->pen.fg, &state->fg_index);
|
||||
setpenattr_col(state, VTERM_ATTR_FOREGROUND, state->pen.fg);
|
||||
break;
|
||||
|
||||
case 39: /* Foreground colour default */
|
||||
state->fg_index = -1;
|
||||
state->pen.fg = state->default_fg;
|
||||
setpenattr_col(state, VTERM_ATTR_FOREGROUND, state->pen.fg);
|
||||
break;
|
||||
|
||||
case 40: case 41: case 42: case 43:
|
||||
case 44: case 45: case 46: case 47: /* Background colour palette */
|
||||
value = CSI_ARG(args[argi]) - 40;
|
||||
state->bg_index = value;
|
||||
set_pen_col_ansi(state, VTERM_ATTR_BACKGROUND, value);
|
||||
break;
|
||||
|
||||
case 48: /* Background colour alternative palette */
|
||||
state->bg_index = -1;
|
||||
if(argcount - argi < 1)
|
||||
return;
|
||||
argi += 1 + lookup_colour(state, CSI_ARG(args[argi+1]), args+argi+2, argcount-argi-2, &state->pen.bg, &state->bg_index);
|
||||
setpenattr_col(state, VTERM_ATTR_BACKGROUND, state->pen.bg);
|
||||
break;
|
||||
|
||||
case 49: /* Default background */
|
||||
state->bg_index = -1;
|
||||
state->pen.bg = state->default_bg;
|
||||
setpenattr_col(state, VTERM_ATTR_BACKGROUND, state->pen.bg);
|
||||
break;
|
||||
|
||||
case 90: case 91: case 92: case 93:
|
||||
case 94: case 95: case 96: case 97: /* Foreground colour high-intensity palette */
|
||||
value = CSI_ARG(args[argi]) - 90 + 8;
|
||||
state->fg_index = value;
|
||||
set_pen_col_ansi(state, VTERM_ATTR_FOREGROUND, value);
|
||||
break;
|
||||
|
||||
case 100: case 101: case 102: case 103:
|
||||
case 104: case 105: case 106: case 107: /* Background colour high-intensity palette */
|
||||
value = CSI_ARG(args[argi]) - 100 + 8;
|
||||
state->bg_index = value;
|
||||
set_pen_col_ansi(state, VTERM_ATTR_BACKGROUND, value);
|
||||
break;
|
||||
|
||||
default:
|
||||
done = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!done)
|
||||
{
|
||||
DEBUG_LOG1("libvterm: Unhandled CSI SGR %lu\n", arg);
|
||||
}
|
||||
|
||||
while(CSI_ARG_HAS_MORE(args[argi++]));
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL int vterm_state_getpen(VTermState *state, long args[], int argcount UNUSED)
|
||||
{
|
||||
int argi = 0;
|
||||
|
||||
if(state->pen.bold)
|
||||
args[argi++] = 1;
|
||||
|
||||
if(state->pen.italic)
|
||||
args[argi++] = 3;
|
||||
|
||||
if(state->pen.underline == 1)
|
||||
args[argi++] = 4;
|
||||
|
||||
if(state->pen.blink)
|
||||
args[argi++] = 5;
|
||||
|
||||
if(state->pen.reverse)
|
||||
args[argi++] = 7;
|
||||
|
||||
if(state->pen.strike)
|
||||
args[argi++] = 9;
|
||||
|
||||
if(state->pen.font)
|
||||
args[argi++] = 10 + state->pen.font;
|
||||
|
||||
if(state->pen.underline == 2)
|
||||
args[argi++] = 21;
|
||||
|
||||
if(state->fg_index >= 0 && state->fg_index < 8)
|
||||
args[argi++] = 30 + state->fg_index;
|
||||
else if(state->fg_index >= 8 && state->fg_index < 16)
|
||||
args[argi++] = 90 + state->fg_index - 8;
|
||||
else if(state->fg_index >= 16 && state->fg_index < 256) {
|
||||
args[argi++] = CSI_ARG_FLAG_MORE|38;
|
||||
args[argi++] = CSI_ARG_FLAG_MORE|5;
|
||||
args[argi++] = state->fg_index;
|
||||
}
|
||||
else if(state->fg_index == -1) {
|
||||
/* Send palette 2 if the actual FG colour is not default */
|
||||
if(state->pen.fg.red != state->default_fg.red ||
|
||||
state->pen.fg.green != state->default_fg.green ||
|
||||
state->pen.fg.blue != state->default_fg.blue ) {
|
||||
args[argi++] = CSI_ARG_FLAG_MORE|38;
|
||||
args[argi++] = CSI_ARG_FLAG_MORE|2;
|
||||
args[argi++] = CSI_ARG_FLAG_MORE | state->pen.fg.red;
|
||||
args[argi++] = CSI_ARG_FLAG_MORE | state->pen.fg.green;
|
||||
args[argi++] = state->pen.fg.blue;
|
||||
}
|
||||
}
|
||||
|
||||
if(state->bg_index >= 0 && state->bg_index < 8)
|
||||
args[argi++] = 40 + state->bg_index;
|
||||
else if(state->bg_index >= 8 && state->bg_index < 16)
|
||||
args[argi++] = 100 + state->bg_index - 8;
|
||||
else if(state->bg_index >= 16 && state->bg_index < 256) {
|
||||
args[argi++] = CSI_ARG_FLAG_MORE|48;
|
||||
args[argi++] = CSI_ARG_FLAG_MORE|5;
|
||||
args[argi++] = state->bg_index;
|
||||
}
|
||||
else if(state->bg_index == -1) {
|
||||
/* Send palette 2 if the actual BG colour is not default */
|
||||
if(state->pen.bg.red != state->default_bg.red ||
|
||||
state->pen.bg.green != state->default_bg.green ||
|
||||
state->pen.bg.blue != state->default_bg.blue ) {
|
||||
args[argi++] = CSI_ARG_FLAG_MORE|48;
|
||||
args[argi++] = CSI_ARG_FLAG_MORE|2;
|
||||
args[argi++] = CSI_ARG_FLAG_MORE | state->pen.bg.red;
|
||||
args[argi++] = CSI_ARG_FLAG_MORE | state->pen.bg.green;
|
||||
args[argi++] = state->pen.bg.blue;
|
||||
}
|
||||
}
|
||||
|
||||
return argi;
|
||||
}
|
||||
|
||||
int vterm_state_get_penattr(const VTermState *state, VTermAttr attr, VTermValue *val)
|
||||
{
|
||||
switch(attr) {
|
||||
case VTERM_ATTR_BOLD:
|
||||
val->boolean = state->pen.bold;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_UNDERLINE:
|
||||
val->number = state->pen.underline;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_ITALIC:
|
||||
val->boolean = state->pen.italic;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_BLINK:
|
||||
val->boolean = state->pen.blink;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_REVERSE:
|
||||
val->boolean = state->pen.reverse;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_STRIKE:
|
||||
val->boolean = state->pen.strike;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_FONT:
|
||||
val->number = state->pen.font;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_FOREGROUND:
|
||||
val->color = state->pen.fg;
|
||||
return 1;
|
||||
|
||||
case VTERM_ATTR_BACKGROUND:
|
||||
val->color = state->pen.bg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
56
src/libvterm/src/rect.h
Normal file
56
src/libvterm/src/rect.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Some utility functions on VTermRect structures
|
||||
*/
|
||||
|
||||
#define STRFrect "(%d,%d-%d,%d)"
|
||||
#define ARGSrect(r) (r).start_row, (r).start_col, (r).end_row, (r).end_col
|
||||
|
||||
/* Expand dst to contain src as well */
|
||||
static void rect_expand(VTermRect *dst, VTermRect *src)
|
||||
{
|
||||
if(dst->start_row > src->start_row) dst->start_row = src->start_row;
|
||||
if(dst->start_col > src->start_col) dst->start_col = src->start_col;
|
||||
if(dst->end_row < src->end_row) dst->end_row = src->end_row;
|
||||
if(dst->end_col < src->end_col) dst->end_col = src->end_col;
|
||||
}
|
||||
|
||||
/* Clip the dst to ensure it does not step outside of bounds */
|
||||
static void rect_clip(VTermRect *dst, VTermRect *bounds)
|
||||
{
|
||||
if(dst->start_row < bounds->start_row) dst->start_row = bounds->start_row;
|
||||
if(dst->start_col < bounds->start_col) dst->start_col = bounds->start_col;
|
||||
if(dst->end_row > bounds->end_row) dst->end_row = bounds->end_row;
|
||||
if(dst->end_col > bounds->end_col) dst->end_col = bounds->end_col;
|
||||
/* Ensure it doesn't end up negatively-sized */
|
||||
if(dst->end_row < dst->start_row) dst->end_row = dst->start_row;
|
||||
if(dst->end_col < dst->start_col) dst->end_col = dst->start_col;
|
||||
}
|
||||
|
||||
/* True if the two rectangles are equal */
|
||||
static int rect_equal(VTermRect *a, VTermRect *b)
|
||||
{
|
||||
return (a->start_row == b->start_row) &&
|
||||
(a->start_col == b->start_col) &&
|
||||
(a->end_row == b->end_row) &&
|
||||
(a->end_col == b->end_col);
|
||||
}
|
||||
|
||||
/* True if small is contained entirely within big */
|
||||
static int rect_contains(VTermRect *big, VTermRect *small)
|
||||
{
|
||||
if(small->start_row < big->start_row) return 0;
|
||||
if(small->start_col < big->start_col) return 0;
|
||||
if(small->end_row > big->end_row) return 0;
|
||||
if(small->end_col > big->end_col) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* True if the rectangles overlap at all */
|
||||
static int rect_intersects(VTermRect *a, VTermRect *b)
|
||||
{
|
||||
if(a->start_row > b->end_row || b->start_row > a->end_row)
|
||||
return 0;
|
||||
if(a->start_col > b->end_col || b->start_col > a->end_col)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
937
src/libvterm/src/screen.c
Normal file
937
src/libvterm/src/screen.c
Normal file
@@ -0,0 +1,937 @@
|
||||
#include "vterm_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rect.h"
|
||||
#include "utf8.h"
|
||||
|
||||
#define UNICODE_SPACE 0x20
|
||||
#define UNICODE_LINEFEED 0x0a
|
||||
|
||||
/* State of the pen at some moment in time, also used in a cell */
|
||||
typedef struct
|
||||
{
|
||||
/* After the bitfield */
|
||||
VTermColor fg, bg;
|
||||
|
||||
unsigned int bold : 1;
|
||||
unsigned int underline : 2;
|
||||
unsigned int italic : 1;
|
||||
unsigned int blink : 1;
|
||||
unsigned int reverse : 1;
|
||||
unsigned int strike : 1;
|
||||
unsigned int font : 4; /* 0 to 9 */
|
||||
|
||||
/* Extra state storage that isn't strictly pen-related */
|
||||
unsigned int protected_cell : 1;
|
||||
unsigned int dwl : 1; /* on a DECDWL or DECDHL line */
|
||||
unsigned int dhl : 2; /* on a DECDHL line (1=top 2=bottom) */
|
||||
} ScreenPen;
|
||||
|
||||
/* Internal representation of a screen cell */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t chars[VTERM_MAX_CHARS_PER_CELL];
|
||||
ScreenPen pen;
|
||||
} ScreenCell;
|
||||
|
||||
static int vterm_screen_set_cell(VTermScreen *screen, VTermPos pos, const VTermScreenCell *cell);
|
||||
|
||||
struct VTermScreen
|
||||
{
|
||||
VTerm *vt;
|
||||
VTermState *state;
|
||||
|
||||
const VTermScreenCallbacks *callbacks;
|
||||
void *cbdata;
|
||||
|
||||
VTermDamageSize damage_merge;
|
||||
/* start_row == -1 => no damage */
|
||||
VTermRect damaged;
|
||||
VTermRect pending_scrollrect;
|
||||
int pending_scroll_downward, pending_scroll_rightward;
|
||||
|
||||
int rows;
|
||||
int cols;
|
||||
int global_reverse;
|
||||
|
||||
/* Primary and Altscreen. buffers[1] is lazily allocated as needed */
|
||||
ScreenCell *buffers[2];
|
||||
|
||||
/* buffer will == buffers[0] or buffers[1], depending on altscreen */
|
||||
ScreenCell *buffer;
|
||||
|
||||
/* buffer for a single screen row used in scrollback storage callbacks */
|
||||
VTermScreenCell *sb_buffer;
|
||||
|
||||
ScreenPen pen;
|
||||
};
|
||||
|
||||
static ScreenCell *getcell(const VTermScreen *screen, int row, int col)
|
||||
{
|
||||
if(row < 0 || row >= screen->rows)
|
||||
return NULL;
|
||||
if(col < 0 || col >= screen->cols)
|
||||
return NULL;
|
||||
return screen->buffer + (screen->cols * row) + col;
|
||||
}
|
||||
|
||||
static ScreenCell *realloc_buffer(VTermScreen *screen, ScreenCell *buffer, int new_rows, int new_cols)
|
||||
{
|
||||
ScreenCell *new_buffer = vterm_allocator_malloc(screen->vt, sizeof(ScreenCell) * new_rows * new_cols);
|
||||
int row, col;
|
||||
|
||||
for(row = 0; row < new_rows; row++) {
|
||||
for(col = 0; col < new_cols; col++) {
|
||||
ScreenCell *new_cell = new_buffer + row*new_cols + col;
|
||||
|
||||
if(buffer && row < screen->rows && col < screen->cols)
|
||||
*new_cell = buffer[row * screen->cols + col];
|
||||
else {
|
||||
new_cell->chars[0] = 0;
|
||||
new_cell->pen = screen->pen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(buffer)
|
||||
vterm_allocator_free(screen->vt, buffer);
|
||||
|
||||
return new_buffer;
|
||||
}
|
||||
|
||||
static void damagerect(VTermScreen *screen, VTermRect rect)
|
||||
{
|
||||
VTermRect emit;
|
||||
|
||||
switch(screen->damage_merge) {
|
||||
case VTERM_DAMAGE_CELL:
|
||||
/* Always emit damage event */
|
||||
emit = rect;
|
||||
break;
|
||||
|
||||
case VTERM_DAMAGE_ROW:
|
||||
/* Emit damage longer than one row. Try to merge with existing damage in
|
||||
* the same row */
|
||||
if(rect.end_row > rect.start_row + 1) {
|
||||
/* Bigger than 1 line - flush existing, emit this */
|
||||
vterm_screen_flush_damage(screen);
|
||||
emit = rect;
|
||||
}
|
||||
else if(screen->damaged.start_row == -1) {
|
||||
/* None stored yet */
|
||||
screen->damaged = rect;
|
||||
return;
|
||||
}
|
||||
else if(rect.start_row == screen->damaged.start_row) {
|
||||
/* Merge with the stored line */
|
||||
if(screen->damaged.start_col > rect.start_col)
|
||||
screen->damaged.start_col = rect.start_col;
|
||||
if(screen->damaged.end_col < rect.end_col)
|
||||
screen->damaged.end_col = rect.end_col;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* Emit the currently stored line, store a new one */
|
||||
emit = screen->damaged;
|
||||
screen->damaged = rect;
|
||||
}
|
||||
break;
|
||||
|
||||
case VTERM_DAMAGE_SCREEN:
|
||||
case VTERM_DAMAGE_SCROLL:
|
||||
/* Never emit damage event */
|
||||
if(screen->damaged.start_row == -1)
|
||||
screen->damaged = rect;
|
||||
else {
|
||||
rect_expand(&screen->damaged, &rect);
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
DEBUG_LOG1("TODO: Maybe merge damage for level %d\n", screen->damage_merge);
|
||||
return;
|
||||
}
|
||||
|
||||
if(screen->callbacks && screen->callbacks->damage)
|
||||
(*screen->callbacks->damage)(emit, screen->cbdata);
|
||||
}
|
||||
|
||||
static void damagescreen(VTermScreen *screen)
|
||||
{
|
||||
VTermRect rect = {0,0,0,0};
|
||||
rect.end_row = screen->rows;
|
||||
rect.end_col = screen->cols;
|
||||
|
||||
damagerect(screen, rect);
|
||||
}
|
||||
|
||||
static int putglyph(VTermGlyphInfo *info, VTermPos pos, void *user)
|
||||
{
|
||||
int i;
|
||||
int col;
|
||||
VTermRect rect;
|
||||
|
||||
VTermScreen *screen = user;
|
||||
ScreenCell *cell = getcell(screen, pos.row, pos.col);
|
||||
|
||||
if(!cell)
|
||||
return 0;
|
||||
|
||||
for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && info->chars[i]; i++) {
|
||||
cell->chars[i] = info->chars[i];
|
||||
cell->pen = screen->pen;
|
||||
}
|
||||
if(i < VTERM_MAX_CHARS_PER_CELL)
|
||||
cell->chars[i] = 0;
|
||||
|
||||
for(col = 1; col < info->width; col++)
|
||||
getcell(screen, pos.row, pos.col + col)->chars[0] = (uint32_t)-1;
|
||||
|
||||
rect.start_row = pos.row;
|
||||
rect.end_row = pos.row+1;
|
||||
rect.start_col = pos.col;
|
||||
rect.end_col = pos.col+info->width;
|
||||
|
||||
cell->pen.protected_cell = info->protected_cell;
|
||||
cell->pen.dwl = info->dwl;
|
||||
cell->pen.dhl = info->dhl;
|
||||
|
||||
damagerect(screen, rect);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int moverect_internal(VTermRect dest, VTermRect src, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
if(screen->callbacks && screen->callbacks->sb_pushline &&
|
||||
dest.start_row == 0 && dest.start_col == 0 && /* starts top-left corner */
|
||||
dest.end_col == screen->cols && /* full width */
|
||||
screen->buffer == screen->buffers[0]) { /* not altscreen */
|
||||
VTermPos pos;
|
||||
for(pos.row = 0; pos.row < src.start_row; pos.row++) {
|
||||
for(pos.col = 0; pos.col < screen->cols; pos.col++)
|
||||
vterm_screen_get_cell(screen, pos, screen->sb_buffer + pos.col);
|
||||
|
||||
(screen->callbacks->sb_pushline)(screen->cols, screen->sb_buffer, screen->cbdata);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int cols = src.end_col - src.start_col;
|
||||
int downward = src.start_row - dest.start_row;
|
||||
int init_row, test_row, inc_row;
|
||||
int row;
|
||||
|
||||
if(downward < 0) {
|
||||
init_row = dest.end_row - 1;
|
||||
test_row = dest.start_row - 1;
|
||||
inc_row = -1;
|
||||
}
|
||||
else {
|
||||
init_row = dest.start_row;
|
||||
test_row = dest.end_row;
|
||||
inc_row = +1;
|
||||
}
|
||||
|
||||
for(row = init_row; row != test_row; row += inc_row)
|
||||
memmove(getcell(screen, row, dest.start_col),
|
||||
getcell(screen, row + downward, src.start_col),
|
||||
cols * sizeof(ScreenCell));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int moverect_user(VTermRect dest, VTermRect src, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
if(screen->callbacks && screen->callbacks->moverect) {
|
||||
if(screen->damage_merge != VTERM_DAMAGE_SCROLL)
|
||||
/* Avoid an infinite loop */
|
||||
vterm_screen_flush_damage(screen);
|
||||
|
||||
if((*screen->callbacks->moverect)(dest, src, screen->cbdata))
|
||||
return 1;
|
||||
}
|
||||
|
||||
damagerect(screen, dest);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int erase_internal(VTermRect rect, int selective, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
int row, col;
|
||||
|
||||
for(row = rect.start_row; row < screen->state->rows && row < rect.end_row; row++) {
|
||||
const VTermLineInfo *info = vterm_state_get_lineinfo(screen->state, row);
|
||||
|
||||
for(col = rect.start_col; col < rect.end_col; col++) {
|
||||
ScreenCell *cell = getcell(screen, row, col);
|
||||
|
||||
if(selective && cell->pen.protected_cell)
|
||||
continue;
|
||||
|
||||
cell->chars[0] = 0;
|
||||
cell->pen = screen->pen;
|
||||
cell->pen.dwl = info->doublewidth;
|
||||
cell->pen.dhl = info->doubleheight;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int erase_user(VTermRect rect, int selective UNUSED, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
damagerect(screen, rect);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int erase(VTermRect rect, int selective, void *user)
|
||||
{
|
||||
erase_internal(rect, selective, user);
|
||||
return erase_user(rect, 0, user);
|
||||
}
|
||||
|
||||
static int scrollrect(VTermRect rect, int downward, int rightward, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
if(screen->damage_merge != VTERM_DAMAGE_SCROLL) {
|
||||
vterm_scroll_rect(rect, downward, rightward,
|
||||
moverect_internal, erase_internal, screen);
|
||||
|
||||
vterm_screen_flush_damage(screen);
|
||||
|
||||
vterm_scroll_rect(rect, downward, rightward,
|
||||
moverect_user, erase_user, screen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(screen->damaged.start_row != -1 &&
|
||||
!rect_intersects(&rect, &screen->damaged)) {
|
||||
vterm_screen_flush_damage(screen);
|
||||
}
|
||||
|
||||
if(screen->pending_scrollrect.start_row == -1) {
|
||||
screen->pending_scrollrect = rect;
|
||||
screen->pending_scroll_downward = downward;
|
||||
screen->pending_scroll_rightward = rightward;
|
||||
}
|
||||
else if(rect_equal(&screen->pending_scrollrect, &rect) &&
|
||||
((screen->pending_scroll_downward == 0 && downward == 0) ||
|
||||
(screen->pending_scroll_rightward == 0 && rightward == 0))) {
|
||||
screen->pending_scroll_downward += downward;
|
||||
screen->pending_scroll_rightward += rightward;
|
||||
}
|
||||
else {
|
||||
vterm_screen_flush_damage(screen);
|
||||
|
||||
screen->pending_scrollrect = rect;
|
||||
screen->pending_scroll_downward = downward;
|
||||
screen->pending_scroll_rightward = rightward;
|
||||
}
|
||||
|
||||
vterm_scroll_rect(rect, downward, rightward,
|
||||
moverect_internal, erase_internal, screen);
|
||||
|
||||
if(screen->damaged.start_row == -1)
|
||||
return 1;
|
||||
|
||||
if(rect_contains(&rect, &screen->damaged)) {
|
||||
/* Scroll region entirely contains the damage; just move it */
|
||||
vterm_rect_move(&screen->damaged, -downward, -rightward);
|
||||
rect_clip(&screen->damaged, &rect);
|
||||
}
|
||||
/* There are a number of possible cases here, but lets restrict this to only
|
||||
* the common case where we might actually gain some performance by
|
||||
* optimising it. Namely, a vertical scroll that neatly cuts the damage
|
||||
* region in half.
|
||||
*/
|
||||
else if(rect.start_col <= screen->damaged.start_col &&
|
||||
rect.end_col >= screen->damaged.end_col &&
|
||||
rightward == 0) {
|
||||
if(screen->damaged.start_row >= rect.start_row &&
|
||||
screen->damaged.start_row < rect.end_row) {
|
||||
screen->damaged.start_row -= downward;
|
||||
if(screen->damaged.start_row < rect.start_row)
|
||||
screen->damaged.start_row = rect.start_row;
|
||||
if(screen->damaged.start_row > rect.end_row)
|
||||
screen->damaged.start_row = rect.end_row;
|
||||
}
|
||||
if(screen->damaged.end_row >= rect.start_row &&
|
||||
screen->damaged.end_row < rect.end_row) {
|
||||
screen->damaged.end_row -= downward;
|
||||
if(screen->damaged.end_row < rect.start_row)
|
||||
screen->damaged.end_row = rect.start_row;
|
||||
if(screen->damaged.end_row > rect.end_row)
|
||||
screen->damaged.end_row = rect.end_row;
|
||||
}
|
||||
}
|
||||
else {
|
||||
DEBUG_LOG2("TODO: Just flush and redo damaged=" STRFrect " rect=" STRFrect "\n",
|
||||
ARGSrect(screen->damaged), ARGSrect(rect));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int movecursor(VTermPos pos, VTermPos oldpos, int visible, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
if(screen->callbacks && screen->callbacks->movecursor)
|
||||
return (*screen->callbacks->movecursor)(pos, oldpos, visible, screen->cbdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setpenattr(VTermAttr attr, VTermValue *val, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
switch(attr) {
|
||||
case VTERM_ATTR_BOLD:
|
||||
screen->pen.bold = val->boolean;
|
||||
return 1;
|
||||
case VTERM_ATTR_UNDERLINE:
|
||||
screen->pen.underline = val->number;
|
||||
return 1;
|
||||
case VTERM_ATTR_ITALIC:
|
||||
screen->pen.italic = val->boolean;
|
||||
return 1;
|
||||
case VTERM_ATTR_BLINK:
|
||||
screen->pen.blink = val->boolean;
|
||||
return 1;
|
||||
case VTERM_ATTR_REVERSE:
|
||||
screen->pen.reverse = val->boolean;
|
||||
return 1;
|
||||
case VTERM_ATTR_STRIKE:
|
||||
screen->pen.strike = val->boolean;
|
||||
return 1;
|
||||
case VTERM_ATTR_FONT:
|
||||
screen->pen.font = val->number;
|
||||
return 1;
|
||||
case VTERM_ATTR_FOREGROUND:
|
||||
screen->pen.fg = val->color;
|
||||
return 1;
|
||||
case VTERM_ATTR_BACKGROUND:
|
||||
screen->pen.bg = val->color;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int settermprop(VTermProp prop, VTermValue *val, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
switch(prop) {
|
||||
case VTERM_PROP_ALTSCREEN:
|
||||
if(val->boolean && !screen->buffers[1])
|
||||
return 0;
|
||||
|
||||
screen->buffer = val->boolean ? screen->buffers[1] : screen->buffers[0];
|
||||
/* only send a damage event on disable; because during enable there's an
|
||||
* erase that sends a damage anyway
|
||||
*/
|
||||
if(!val->boolean)
|
||||
damagescreen(screen);
|
||||
break;
|
||||
case VTERM_PROP_REVERSE:
|
||||
screen->global_reverse = val->boolean;
|
||||
damagescreen(screen);
|
||||
break;
|
||||
default:
|
||||
; /* ignore */
|
||||
}
|
||||
|
||||
if(screen->callbacks && screen->callbacks->settermprop)
|
||||
return (*screen->callbacks->settermprop)(prop, val, screen->cbdata);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bell(void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
if(screen->callbacks && screen->callbacks->bell)
|
||||
return (*screen->callbacks->bell)(screen->cbdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int resize(int new_rows, int new_cols, VTermPos *delta, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
|
||||
int is_altscreen = (screen->buffers[1] && screen->buffer == screen->buffers[1]);
|
||||
|
||||
int old_rows = screen->rows;
|
||||
int old_cols = screen->cols;
|
||||
int first_blank_row;
|
||||
|
||||
if(!is_altscreen && new_rows < old_rows) {
|
||||
/* Fewer rows - determine if we're going to scroll at all, and if so, push
|
||||
those lines to scrollback */
|
||||
VTermPos pos = { 0, 0 };
|
||||
VTermPos cursor = screen->state->pos;
|
||||
/* Find the first blank row after the cursor. */
|
||||
for(pos.row = old_rows - 1; pos.row >= new_rows; pos.row--)
|
||||
if(!vterm_screen_is_eol(screen, pos) || cursor.row == pos.row)
|
||||
break;
|
||||
|
||||
first_blank_row = pos.row + 1;
|
||||
if(first_blank_row > new_rows) {
|
||||
VTermRect rect = {0,0,0,0};
|
||||
rect.end_row = old_rows;
|
||||
rect.end_col = old_cols;
|
||||
scrollrect(rect, first_blank_row - new_rows, 0, user);
|
||||
vterm_screen_flush_damage(screen);
|
||||
|
||||
delta->row -= first_blank_row - new_rows;
|
||||
}
|
||||
}
|
||||
|
||||
screen->buffers[0] = realloc_buffer(screen, screen->buffers[0], new_rows, new_cols);
|
||||
if(screen->buffers[1])
|
||||
screen->buffers[1] = realloc_buffer(screen, screen->buffers[1], new_rows, new_cols);
|
||||
|
||||
screen->buffer = is_altscreen ? screen->buffers[1] : screen->buffers[0];
|
||||
|
||||
screen->rows = new_rows;
|
||||
screen->cols = new_cols;
|
||||
|
||||
if(screen->sb_buffer)
|
||||
vterm_allocator_free(screen->vt, screen->sb_buffer);
|
||||
|
||||
screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * new_cols);
|
||||
|
||||
if(new_cols > old_cols) {
|
||||
VTermRect rect;
|
||||
rect.start_row = 0;
|
||||
rect.end_row = old_rows;
|
||||
rect.start_col = old_cols;
|
||||
rect.end_col = new_cols;
|
||||
damagerect(screen, rect);
|
||||
}
|
||||
|
||||
if(new_rows > old_rows) {
|
||||
if(!is_altscreen && screen->callbacks && screen->callbacks->sb_popline) {
|
||||
int rows = new_rows - old_rows;
|
||||
while(rows) {
|
||||
VTermRect rect = {0,0,0,0};
|
||||
VTermPos pos = { 0, 0 };
|
||||
if(!(screen->callbacks->sb_popline(screen->cols, screen->sb_buffer, screen->cbdata)))
|
||||
break;
|
||||
|
||||
rect.end_row = screen->rows;
|
||||
rect.end_col = screen->cols;
|
||||
scrollrect(rect, -1, 0, user);
|
||||
|
||||
for(pos.col = 0; pos.col < screen->cols; pos.col += screen->sb_buffer[pos.col].width)
|
||||
vterm_screen_set_cell(screen, pos, screen->sb_buffer + pos.col);
|
||||
|
||||
rect.end_row = 1;
|
||||
damagerect(screen, rect);
|
||||
|
||||
vterm_screen_flush_damage(screen);
|
||||
|
||||
rows--;
|
||||
delta->row++;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
VTermRect rect;
|
||||
rect.start_row = old_rows;
|
||||
rect.end_row = new_rows;
|
||||
rect.start_col = 0;
|
||||
rect.end_col = new_cols;
|
||||
damagerect(screen, rect);
|
||||
}
|
||||
}
|
||||
|
||||
if(screen->callbacks && screen->callbacks->resize)
|
||||
return (*screen->callbacks->resize)(new_rows, new_cols, screen->cbdata);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setlineinfo(int row, const VTermLineInfo *newinfo, const VTermLineInfo *oldinfo, void *user)
|
||||
{
|
||||
VTermScreen *screen = user;
|
||||
int col;
|
||||
VTermRect rect;
|
||||
|
||||
if(newinfo->doublewidth != oldinfo->doublewidth ||
|
||||
newinfo->doubleheight != oldinfo->doubleheight) {
|
||||
for(col = 0; col < screen->cols; col++) {
|
||||
ScreenCell *cell = getcell(screen, row, col);
|
||||
cell->pen.dwl = newinfo->doublewidth;
|
||||
cell->pen.dhl = newinfo->doubleheight;
|
||||
}
|
||||
|
||||
rect.start_row = row;
|
||||
rect.end_row = row + 1;
|
||||
rect.start_col = 0;
|
||||
rect.end_col = newinfo->doublewidth ? screen->cols / 2 : screen->cols;
|
||||
damagerect(screen, rect);
|
||||
|
||||
if(newinfo->doublewidth) {
|
||||
rect.start_col = screen->cols / 2;
|
||||
rect.end_col = screen->cols;
|
||||
|
||||
erase_internal(rect, 0, user);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static VTermStateCallbacks state_cbs = {
|
||||
&putglyph, /* putglyph */
|
||||
&movecursor, /* movecursor */
|
||||
&scrollrect, /* scrollrect */
|
||||
NULL, /* moverect */
|
||||
&erase, /* erase */
|
||||
NULL, /* initpen */
|
||||
&setpenattr, /* setpenattr */
|
||||
&settermprop, /* settermprop */
|
||||
&bell, /* bell */
|
||||
&resize, /* resize */
|
||||
&setlineinfo /* setlineinfo */
|
||||
};
|
||||
|
||||
static VTermScreen *screen_new(VTerm *vt)
|
||||
{
|
||||
VTermState *state = vterm_obtain_state(vt);
|
||||
VTermScreen *screen;
|
||||
int rows, cols;
|
||||
|
||||
if(!state)
|
||||
return NULL;
|
||||
|
||||
screen = vterm_allocator_malloc(vt, sizeof(VTermScreen));
|
||||
|
||||
vterm_get_size(vt, &rows, &cols);
|
||||
|
||||
screen->vt = vt;
|
||||
screen->state = state;
|
||||
|
||||
screen->damage_merge = VTERM_DAMAGE_CELL;
|
||||
screen->damaged.start_row = -1;
|
||||
screen->pending_scrollrect.start_row = -1;
|
||||
|
||||
screen->rows = rows;
|
||||
screen->cols = cols;
|
||||
|
||||
screen->callbacks = NULL;
|
||||
screen->cbdata = NULL;
|
||||
|
||||
screen->buffers[0] = realloc_buffer(screen, NULL, rows, cols);
|
||||
|
||||
screen->buffer = screen->buffers[0];
|
||||
|
||||
screen->sb_buffer = vterm_allocator_malloc(screen->vt, sizeof(VTermScreenCell) * cols);
|
||||
|
||||
vterm_state_set_callbacks(screen->state, &state_cbs, screen);
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
INTERNAL void vterm_screen_free(VTermScreen *screen)
|
||||
{
|
||||
vterm_allocator_free(screen->vt, screen->buffers[0]);
|
||||
if(screen->buffers[1])
|
||||
vterm_allocator_free(screen->vt, screen->buffers[1]);
|
||||
|
||||
vterm_allocator_free(screen->vt, screen->sb_buffer);
|
||||
|
||||
vterm_allocator_free(screen->vt, screen);
|
||||
}
|
||||
|
||||
void vterm_screen_reset(VTermScreen *screen, int hard)
|
||||
{
|
||||
screen->damaged.start_row = -1;
|
||||
screen->pending_scrollrect.start_row = -1;
|
||||
vterm_state_reset(screen->state, hard);
|
||||
vterm_screen_flush_damage(screen);
|
||||
}
|
||||
|
||||
static size_t _get_chars(const VTermScreen *screen, const int utf8, void *buffer, size_t len, const VTermRect rect)
|
||||
{
|
||||
size_t outpos = 0;
|
||||
int padding = 0;
|
||||
int row, col;
|
||||
|
||||
#define PUT(c) \
|
||||
if(utf8) { \
|
||||
size_t thislen = utf8_seqlen(c); \
|
||||
if(buffer && outpos + thislen <= len) \
|
||||
outpos += fill_utf8((c), (char *)buffer + outpos); \
|
||||
else \
|
||||
outpos += thislen; \
|
||||
} \
|
||||
else { \
|
||||
if(buffer && outpos + 1 <= len) \
|
||||
((uint32_t*)buffer)[outpos++] = (c); \
|
||||
else \
|
||||
outpos++; \
|
||||
}
|
||||
|
||||
for(row = rect.start_row; row < rect.end_row; row++) {
|
||||
for(col = rect.start_col; col < rect.end_col; col++) {
|
||||
ScreenCell *cell = getcell(screen, row, col);
|
||||
int i;
|
||||
|
||||
if(cell->chars[0] == 0)
|
||||
/* Erased cell, might need a space */
|
||||
padding++;
|
||||
else if(cell->chars[0] == (uint32_t)-1)
|
||||
/* Gap behind a double-width char, do nothing */
|
||||
;
|
||||
else {
|
||||
while(padding) {
|
||||
PUT(UNICODE_SPACE);
|
||||
padding--;
|
||||
}
|
||||
for(i = 0; i < VTERM_MAX_CHARS_PER_CELL && cell->chars[i]; i++) {
|
||||
PUT(cell->chars[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(row < rect.end_row - 1) {
|
||||
PUT(UNICODE_LINEFEED);
|
||||
padding = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return outpos;
|
||||
}
|
||||
|
||||
size_t vterm_screen_get_chars(const VTermScreen *screen, uint32_t *chars, size_t len, const VTermRect rect)
|
||||
{
|
||||
return _get_chars(screen, 0, chars, len, rect);
|
||||
}
|
||||
|
||||
size_t vterm_screen_get_text(const VTermScreen *screen, char *str, size_t len, const VTermRect rect)
|
||||
{
|
||||
return _get_chars(screen, 1, str, len, rect);
|
||||
}
|
||||
|
||||
/* Copy internal to external representation of a screen cell */
|
||||
int vterm_screen_get_cell(const VTermScreen *screen, VTermPos pos, VTermScreenCell *cell)
|
||||
{
|
||||
ScreenCell *intcell = getcell(screen, pos.row, pos.col);
|
||||
int i;
|
||||
|
||||
if(!intcell)
|
||||
return 0;
|
||||
|
||||
for(i = 0; ; i++) {
|
||||
cell->chars[i] = intcell->chars[i];
|
||||
if(!intcell->chars[i])
|
||||
break;
|
||||
}
|
||||
|
||||
cell->attrs.bold = intcell->pen.bold;
|
||||
cell->attrs.underline = intcell->pen.underline;
|
||||
cell->attrs.italic = intcell->pen.italic;
|
||||
cell->attrs.blink = intcell->pen.blink;
|
||||
cell->attrs.reverse = intcell->pen.reverse ^ screen->global_reverse;
|
||||
cell->attrs.strike = intcell->pen.strike;
|
||||
cell->attrs.font = intcell->pen.font;
|
||||
|
||||
cell->attrs.dwl = intcell->pen.dwl;
|
||||
cell->attrs.dhl = intcell->pen.dhl;
|
||||
|
||||
cell->fg = intcell->pen.fg;
|
||||
cell->bg = intcell->pen.bg;
|
||||
|
||||
if(pos.col < (screen->cols - 1) &&
|
||||
getcell(screen, pos.row, pos.col + 1)->chars[0] == (uint32_t)-1)
|
||||
cell->width = 2;
|
||||
else
|
||||
cell->width = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy external to internal representation of a screen cell */
|
||||
/* static because it's only used internally for sb_popline during resize */
|
||||
static int vterm_screen_set_cell(VTermScreen *screen, VTermPos pos, const VTermScreenCell *cell)
|
||||
{
|
||||
ScreenCell *intcell = getcell(screen, pos.row, pos.col);
|
||||
int i;
|
||||
|
||||
if(!intcell)
|
||||
return 0;
|
||||
|
||||
for(i = 0; ; i++) {
|
||||
intcell->chars[i] = cell->chars[i];
|
||||
if(!cell->chars[i])
|
||||
break;
|
||||
}
|
||||
|
||||
intcell->pen.bold = cell->attrs.bold;
|
||||
intcell->pen.underline = cell->attrs.underline;
|
||||
intcell->pen.italic = cell->attrs.italic;
|
||||
intcell->pen.blink = cell->attrs.blink;
|
||||
intcell->pen.reverse = cell->attrs.reverse ^ screen->global_reverse;
|
||||
intcell->pen.strike = cell->attrs.strike;
|
||||
intcell->pen.font = cell->attrs.font;
|
||||
|
||||
intcell->pen.fg = cell->fg;
|
||||
intcell->pen.bg = cell->bg;
|
||||
|
||||
if(cell->width == 2)
|
||||
getcell(screen, pos.row, pos.col + 1)->chars[0] = (uint32_t)-1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vterm_screen_is_eol(const VTermScreen *screen, VTermPos pos)
|
||||
{
|
||||
/* This cell is EOL if this and every cell to the right is black */
|
||||
for(; pos.col < screen->cols; pos.col++) {
|
||||
ScreenCell *cell = getcell(screen, pos.row, pos.col);
|
||||
if(cell->chars[0] != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
VTermScreen *vterm_obtain_screen(VTerm *vt)
|
||||
{
|
||||
VTermScreen *screen;
|
||||
if(vt->screen)
|
||||
return vt->screen;
|
||||
|
||||
screen = screen_new(vt);
|
||||
vt->screen = screen;
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
void vterm_screen_enable_altscreen(VTermScreen *screen, int altscreen)
|
||||
{
|
||||
|
||||
if(!screen->buffers[1] && altscreen) {
|
||||
int rows, cols;
|
||||
vterm_get_size(screen->vt, &rows, &cols);
|
||||
|
||||
screen->buffers[1] = realloc_buffer(screen, NULL, rows, cols);
|
||||
}
|
||||
}
|
||||
|
||||
void vterm_screen_set_callbacks(VTermScreen *screen, const VTermScreenCallbacks *callbacks, void *user)
|
||||
{
|
||||
screen->callbacks = callbacks;
|
||||
screen->cbdata = user;
|
||||
}
|
||||
|
||||
void *vterm_screen_get_cbdata(VTermScreen *screen)
|
||||
{
|
||||
return screen->cbdata;
|
||||
}
|
||||
|
||||
void vterm_screen_set_unrecognised_fallbacks(VTermScreen *screen, const VTermParserCallbacks *fallbacks, void *user)
|
||||
{
|
||||
vterm_state_set_unrecognised_fallbacks(screen->state, fallbacks, user);
|
||||
}
|
||||
|
||||
void *vterm_screen_get_unrecognised_fbdata(VTermScreen *screen)
|
||||
{
|
||||
return vterm_state_get_unrecognised_fbdata(screen->state);
|
||||
}
|
||||
|
||||
void vterm_screen_flush_damage(VTermScreen *screen)
|
||||
{
|
||||
if(screen->pending_scrollrect.start_row != -1) {
|
||||
vterm_scroll_rect(screen->pending_scrollrect, screen->pending_scroll_downward, screen->pending_scroll_rightward,
|
||||
moverect_user, erase_user, screen);
|
||||
|
||||
screen->pending_scrollrect.start_row = -1;
|
||||
}
|
||||
|
||||
if(screen->damaged.start_row != -1) {
|
||||
if(screen->callbacks && screen->callbacks->damage)
|
||||
(*screen->callbacks->damage)(screen->damaged, screen->cbdata);
|
||||
|
||||
screen->damaged.start_row = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void vterm_screen_set_damage_merge(VTermScreen *screen, VTermDamageSize size)
|
||||
{
|
||||
vterm_screen_flush_damage(screen);
|
||||
screen->damage_merge = size;
|
||||
}
|
||||
|
||||
static int attrs_differ(VTermAttrMask attrs, ScreenCell *a, ScreenCell *b)
|
||||
{
|
||||
if((attrs & VTERM_ATTR_BOLD_MASK) && (a->pen.bold != b->pen.bold))
|
||||
return 1;
|
||||
if((attrs & VTERM_ATTR_UNDERLINE_MASK) && (a->pen.underline != b->pen.underline))
|
||||
return 1;
|
||||
if((attrs & VTERM_ATTR_ITALIC_MASK) && (a->pen.italic != b->pen.italic))
|
||||
return 1;
|
||||
if((attrs & VTERM_ATTR_BLINK_MASK) && (a->pen.blink != b->pen.blink))
|
||||
return 1;
|
||||
if((attrs & VTERM_ATTR_REVERSE_MASK) && (a->pen.reverse != b->pen.reverse))
|
||||
return 1;
|
||||
if((attrs & VTERM_ATTR_STRIKE_MASK) && (a->pen.strike != b->pen.strike))
|
||||
return 1;
|
||||
if((attrs & VTERM_ATTR_FONT_MASK) && (a->pen.font != b->pen.font))
|
||||
return 1;
|
||||
if((attrs & VTERM_ATTR_FOREGROUND_MASK) && !vterm_color_equal(a->pen.fg, b->pen.fg))
|
||||
return 1;
|
||||
if((attrs & VTERM_ATTR_BACKGROUND_MASK) && !vterm_color_equal(a->pen.bg, b->pen.bg))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vterm_screen_get_attrs_extent(const VTermScreen *screen, VTermRect *extent, VTermPos pos, VTermAttrMask attrs)
|
||||
{
|
||||
int col;
|
||||
|
||||
ScreenCell *target = getcell(screen, pos.row, pos.col);
|
||||
|
||||
/* TODO: bounds check */
|
||||
extent->start_row = pos.row;
|
||||
extent->end_row = pos.row + 1;
|
||||
|
||||
if(extent->start_col < 0)
|
||||
extent->start_col = 0;
|
||||
if(extent->end_col < 0)
|
||||
extent->end_col = screen->cols;
|
||||
|
||||
for(col = pos.col - 1; col >= extent->start_col; col--)
|
||||
if(attrs_differ(attrs, target, getcell(screen, pos.row, col)))
|
||||
break;
|
||||
extent->start_col = col + 1;
|
||||
|
||||
for(col = pos.col + 1; col < extent->end_col; col++)
|
||||
if(attrs_differ(attrs, target, getcell(screen, pos.row, col)))
|
||||
break;
|
||||
extent->end_col = col - 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
1851
src/libvterm/src/state.c
Normal file
1851
src/libvterm/src/state.c
Normal file
File diff suppressed because it is too large
Load Diff
331
src/libvterm/src/unicode.c
Normal file
331
src/libvterm/src/unicode.c
Normal file
@@ -0,0 +1,331 @@
|
||||
#include "vterm_internal.h"
|
||||
|
||||
/* ### The following from http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
* With modifications:
|
||||
* made functions static
|
||||
* moved 'combining' table to file scope, so other functions can see it
|
||||
* ###################################################################
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is an implementation of wcwidth() and wcswidth() (defined in
|
||||
* IEEE Std 1002.1-2001) for Unicode.
|
||||
*
|
||||
* http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html
|
||||
* http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html
|
||||
*
|
||||
* In fixed-width output devices, Latin characters all occupy a single
|
||||
* "cell" position of equal width, whereas ideographic CJK characters
|
||||
* occupy two such cells. Interoperability between terminal-line
|
||||
* applications and (teletype-style) character terminals using the
|
||||
* UTF-8 encoding requires agreement on which character should advance
|
||||
* the cursor by how many cell positions. No established formal
|
||||
* standards exist at present on which Unicode character shall occupy
|
||||
* how many cell positions on character terminals. These routines are
|
||||
* a first attempt of defining such behavior based on simple rules
|
||||
* applied to data provided by the Unicode Consortium.
|
||||
*
|
||||
* For some graphical characters, the Unicode standard explicitly
|
||||
* defines a character-cell width via the definition of the East Asian
|
||||
* FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes.
|
||||
* In all these cases, there is no ambiguity about which width a
|
||||
* terminal shall use. For characters in the East Asian Ambiguous (A)
|
||||
* class, the width choice depends purely on a preference of backward
|
||||
* compatibility with either historic CJK or Western practice.
|
||||
* Choosing single-width for these characters is easy to justify as
|
||||
* the appropriate long-term solution, as the CJK practice of
|
||||
* displaying these characters as double-width comes from historic
|
||||
* implementation simplicity (8-bit encoded characters were displayed
|
||||
* single-width and 16-bit ones double-width, even for Greek,
|
||||
* Cyrillic, etc.) and not any typographic considerations.
|
||||
*
|
||||
* Much less clear is the choice of width for the Not East Asian
|
||||
* (Neutral) class. Existing practice does not dictate a width for any
|
||||
* of these characters. It would nevertheless make sense
|
||||
* typographically to allocate two character cells to characters such
|
||||
* as for instance EM SPACE or VOLUME INTEGRAL, which cannot be
|
||||
* represented adequately with a single-width glyph. The following
|
||||
* routines at present merely assign a single-cell width to all
|
||||
* neutral characters, in the interest of simplicity. This is not
|
||||
* entirely satisfactory and should be reconsidered before
|
||||
* establishing a formal standard in this area. At the moment, the
|
||||
* decision which Not East Asian (Neutral) characters should be
|
||||
* represented by double-width glyphs cannot yet be answered by
|
||||
* applying a simple rule from the Unicode database content. Setting
|
||||
* up a proper standard for the behavior of UTF-8 character terminals
|
||||
* will require a careful analysis not only of each Unicode character,
|
||||
* but also of each presentation form, something the author of these
|
||||
* routines has avoided to do so far.
|
||||
*
|
||||
* http://www.unicode.org/unicode/reports/tr11/
|
||||
*
|
||||
* Markus Kuhn -- 2007-05-26 (Unicode 5.0)
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software
|
||||
* for any purpose and without fee is hereby granted. The author
|
||||
* disclaims all warranties with regard to this software.
|
||||
*
|
||||
* Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
|
||||
*/
|
||||
|
||||
struct interval {
|
||||
int first;
|
||||
int last;
|
||||
};
|
||||
|
||||
/* sorted list of non-overlapping intervals of non-spacing characters */
|
||||
/* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */
|
||||
static const struct interval combining[] = {
|
||||
{ 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 },
|
||||
{ 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
|
||||
{ 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 },
|
||||
{ 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 },
|
||||
{ 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED },
|
||||
{ 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A },
|
||||
{ 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 },
|
||||
{ 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D },
|
||||
{ 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 },
|
||||
{ 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD },
|
||||
{ 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C },
|
||||
{ 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D },
|
||||
{ 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC },
|
||||
{ 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD },
|
||||
{ 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C },
|
||||
{ 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D },
|
||||
{ 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 },
|
||||
{ 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 },
|
||||
{ 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC },
|
||||
{ 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD },
|
||||
{ 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D },
|
||||
{ 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 },
|
||||
{ 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E },
|
||||
{ 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC },
|
||||
{ 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 },
|
||||
{ 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E },
|
||||
{ 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 },
|
||||
{ 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 },
|
||||
{ 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 },
|
||||
{ 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F },
|
||||
{ 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 },
|
||||
{ 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD },
|
||||
{ 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD },
|
||||
{ 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 },
|
||||
{ 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B },
|
||||
{ 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 },
|
||||
{ 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 },
|
||||
{ 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF },
|
||||
{ 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 },
|
||||
{ 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F },
|
||||
{ 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B },
|
||||
{ 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F },
|
||||
{ 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB },
|
||||
{ 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F },
|
||||
{ 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 },
|
||||
{ 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD },
|
||||
{ 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F },
|
||||
{ 0xE0100, 0xE01EF }
|
||||
};
|
||||
|
||||
|
||||
/* auxiliary function for binary search in interval table */
|
||||
static int bisearch(uint32_t ucs, const struct interval *table, int max) {
|
||||
int min = 0;
|
||||
int mid;
|
||||
|
||||
if ((int)ucs < table[0].first || (int)ucs > table[max].last)
|
||||
return 0;
|
||||
while (max >= min) {
|
||||
mid = (min + max) / 2;
|
||||
if ((int)ucs > table[mid].last)
|
||||
min = mid + 1;
|
||||
else if ((int)ucs < table[mid].first)
|
||||
max = mid - 1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The following two functions define the column width of an ISO 10646
|
||||
* character as follows:
|
||||
*
|
||||
* - The null character (U+0000) has a column width of 0.
|
||||
*
|
||||
* - Other C0/C1 control characters and DEL will lead to a return
|
||||
* value of -1.
|
||||
*
|
||||
* - Non-spacing and enclosing combining characters (general
|
||||
* category code Mn or Me in the Unicode database) have a
|
||||
* column width of 0.
|
||||
*
|
||||
* - SOFT HYPHEN (U+00AD) has a column width of 1.
|
||||
*
|
||||
* - Other format characters (general category code Cf in the Unicode
|
||||
* database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
|
||||
*
|
||||
* - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
|
||||
* have a column width of 0.
|
||||
*
|
||||
* - Spacing characters in the East Asian Wide (W) or East Asian
|
||||
* Full-width (F) category as defined in Unicode Technical
|
||||
* Report #11 have a column width of 2.
|
||||
*
|
||||
* - All remaining characters (including all printable
|
||||
* ISO 8859-1 and WGL4 characters, Unicode control characters,
|
||||
* etc.) have a column width of 1.
|
||||
*
|
||||
* This implementation assumes that uint32_t characters are encoded
|
||||
* in ISO 10646.
|
||||
*/
|
||||
|
||||
|
||||
static int mk_wcwidth(uint32_t ucs)
|
||||
{
|
||||
/* test for 8-bit control characters */
|
||||
if (ucs == 0)
|
||||
return 0;
|
||||
if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0))
|
||||
return -1;
|
||||
|
||||
/* binary search in table of non-spacing characters */
|
||||
if (bisearch(ucs, combining,
|
||||
sizeof(combining) / sizeof(struct interval) - 1))
|
||||
return 0;
|
||||
|
||||
/* if we arrive here, ucs is not a combining or C0/C1 control character */
|
||||
|
||||
return 1 +
|
||||
(ucs >= 0x1100 &&
|
||||
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
|
||||
ucs == 0x2329 || ucs == 0x232a ||
|
||||
(ucs >= 0x2e80 && ucs <= 0xa4cf &&
|
||||
ucs != 0x303f) || /* CJK ... Yi */
|
||||
(ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */
|
||||
(ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */
|
||||
(ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */
|
||||
(ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */
|
||||
(ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */
|
||||
(ucs >= 0xffe0 && ucs <= 0xffe6) ||
|
||||
(ucs >= 0x20000 && ucs <= 0x2fffd) ||
|
||||
(ucs >= 0x30000 && ucs <= 0x3fffd)));
|
||||
}
|
||||
|
||||
#if 0 /* unused */
|
||||
static int mk_wcswidth(const uint32_t *pwcs, size_t n)
|
||||
{
|
||||
int w, width = 0;
|
||||
|
||||
for (;*pwcs && n-- > 0; pwcs++)
|
||||
if ((w = mk_wcwidth(*pwcs)) < 0)
|
||||
return -1;
|
||||
else
|
||||
width += w;
|
||||
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The following functions are the same as mk_wcwidth() and
|
||||
* mk_wcswidth(), except that spacing characters in the East Asian
|
||||
* Ambiguous (A) category as defined in Unicode Technical Report #11
|
||||
* have a column width of 2. This variant might be useful for users of
|
||||
* CJK legacy encodings who want to migrate to UCS without changing
|
||||
* the traditional terminal character-width behaviour. It is not
|
||||
* otherwise recommended for general use.
|
||||
*/
|
||||
static int mk_wcwidth_cjk(uint32_t ucs)
|
||||
{
|
||||
/* sorted list of non-overlapping intervals of East Asian Ambiguous
|
||||
* characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */
|
||||
static const struct interval ambiguous[] = {
|
||||
{ 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 },
|
||||
{ 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 },
|
||||
{ 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 },
|
||||
{ 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 },
|
||||
{ 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED },
|
||||
{ 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA },
|
||||
{ 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 },
|
||||
{ 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B },
|
||||
{ 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 },
|
||||
{ 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 },
|
||||
{ 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 },
|
||||
{ 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE },
|
||||
{ 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 },
|
||||
{ 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA },
|
||||
{ 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 },
|
||||
{ 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB },
|
||||
{ 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB },
|
||||
{ 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 },
|
||||
{ 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 },
|
||||
{ 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 },
|
||||
{ 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 },
|
||||
{ 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 },
|
||||
{ 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 },
|
||||
{ 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 },
|
||||
{ 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC },
|
||||
{ 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 },
|
||||
{ 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 },
|
||||
{ 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 },
|
||||
{ 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 },
|
||||
{ 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 },
|
||||
{ 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 },
|
||||
{ 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B },
|
||||
{ 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 },
|
||||
{ 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 },
|
||||
{ 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E },
|
||||
{ 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 },
|
||||
{ 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 },
|
||||
{ 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F },
|
||||
{ 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 },
|
||||
{ 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF },
|
||||
{ 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B },
|
||||
{ 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 },
|
||||
{ 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 },
|
||||
{ 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 },
|
||||
{ 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 },
|
||||
{ 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 },
|
||||
{ 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 },
|
||||
{ 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 },
|
||||
{ 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 },
|
||||
{ 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F },
|
||||
{ 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF },
|
||||
{ 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD }
|
||||
};
|
||||
|
||||
/* binary search in table of non-spacing characters */
|
||||
if (bisearch(ucs, ambiguous,
|
||||
sizeof(ambiguous) / sizeof(struct interval) - 1))
|
||||
return 2;
|
||||
|
||||
return mk_wcwidth(ucs);
|
||||
}
|
||||
|
||||
static int mk_wcswidth_cjk(const uint32_t *pwcs, size_t n)
|
||||
{
|
||||
int w, width = 0;
|
||||
|
||||
for (;*pwcs && n-- > 0; pwcs++)
|
||||
if ((w = mk_wcwidth_cjk(*pwcs)) < 0)
|
||||
return -1;
|
||||
else
|
||||
width += w;
|
||||
|
||||
return width;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ################################
|
||||
* ### The rest added by Paul Evans */
|
||||
|
||||
INTERNAL int vterm_unicode_width(uint32_t codepoint)
|
||||
{
|
||||
return mk_wcwidth(codepoint);
|
||||
}
|
||||
|
||||
INTERNAL int vterm_unicode_is_combining(uint32_t codepoint)
|
||||
{
|
||||
return bisearch(codepoint, combining, sizeof(combining) / sizeof(struct interval) - 1);
|
||||
}
|
||||
47
src/libvterm/src/utf8.h
Normal file
47
src/libvterm/src/utf8.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* The following functions copied and adapted from libtermkey
|
||||
*
|
||||
* http://www.leonerd.org.uk/code/libtermkey/
|
||||
*/
|
||||
unsigned int utf8_seqlen(long codepoint);
|
||||
|
||||
#if defined(DEFINE_INLINES) || USE_INLINE
|
||||
INLINE unsigned int utf8_seqlen(long codepoint)
|
||||
{
|
||||
if(codepoint < 0x0000080) return 1;
|
||||
if(codepoint < 0x0000800) return 2;
|
||||
if(codepoint < 0x0010000) return 3;
|
||||
if(codepoint < 0x0200000) return 4;
|
||||
if(codepoint < 0x4000000) return 5;
|
||||
return 6;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Does NOT NUL-terminate the buffer */
|
||||
int fill_utf8(long codepoint, char *str);
|
||||
|
||||
#if defined(DEFINE_INLINES) || USE_INLINE
|
||||
INLINE int fill_utf8(long codepoint, char *str)
|
||||
{
|
||||
int nbytes = utf8_seqlen(codepoint);
|
||||
|
||||
/* This is easier done backwards */
|
||||
int b = nbytes;
|
||||
while(b > 1) {
|
||||
b--;
|
||||
str[b] = 0x80 | (codepoint & 0x3f);
|
||||
codepoint >>= 6;
|
||||
}
|
||||
|
||||
switch(nbytes) {
|
||||
case 1: str[0] = (codepoint & 0x7f); break;
|
||||
case 2: str[0] = 0xc0 | (codepoint & 0x1f); break;
|
||||
case 3: str[0] = 0xe0 | (codepoint & 0x0f); break;
|
||||
case 4: str[0] = 0xf0 | (codepoint & 0x07); break;
|
||||
case 5: str[0] = 0xf8 | (codepoint & 0x03); break;
|
||||
case 6: str[0] = 0xfc | (codepoint & 0x01); break;
|
||||
}
|
||||
|
||||
return nbytes;
|
||||
}
|
||||
#endif
|
||||
/* end copy */
|
||||
412
src/libvterm/src/vterm.c
Normal file
412
src/libvterm/src/vterm.c
Normal file
@@ -0,0 +1,412 @@
|
||||
#define DEFINE_INLINES
|
||||
|
||||
#include "vterm_internal.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "utf8.h"
|
||||
|
||||
/*****************
|
||||
* API functions *
|
||||
*****************/
|
||||
|
||||
static void *default_malloc(size_t size, void *allocdata UNUSED)
|
||||
{
|
||||
void *ptr = malloc(size);
|
||||
if(ptr)
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void default_free(void *ptr, void *allocdata UNUSED)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static VTermAllocatorFunctions default_allocator = {
|
||||
&default_malloc, /* malloc */
|
||||
&default_free /* free */
|
||||
};
|
||||
|
||||
VTerm *vterm_new(int rows, int cols)
|
||||
{
|
||||
return vterm_new_with_allocator(rows, cols, &default_allocator, NULL);
|
||||
}
|
||||
|
||||
VTerm *vterm_new_with_allocator(int rows, int cols, VTermAllocatorFunctions *funcs, void *allocdata)
|
||||
{
|
||||
/* Need to bootstrap using the allocator function directly */
|
||||
VTerm *vt = (*funcs->malloc)(sizeof(VTerm), allocdata);
|
||||
|
||||
vt->allocator = funcs;
|
||||
vt->allocdata = allocdata;
|
||||
|
||||
vt->rows = rows;
|
||||
vt->cols = cols;
|
||||
|
||||
vt->parser_state = NORMAL;
|
||||
|
||||
vt->parser_callbacks = NULL;
|
||||
vt->cbdata = NULL;
|
||||
|
||||
vt->strbuffer_len = 64;
|
||||
vt->strbuffer_cur = 0;
|
||||
vt->strbuffer = vterm_allocator_malloc(vt, vt->strbuffer_len);
|
||||
|
||||
vt->outbuffer_len = 64;
|
||||
vt->outbuffer_cur = 0;
|
||||
vt->outbuffer = vterm_allocator_malloc(vt, vt->outbuffer_len);
|
||||
|
||||
return vt;
|
||||
}
|
||||
|
||||
void vterm_free(VTerm *vt)
|
||||
{
|
||||
if(vt->screen)
|
||||
vterm_screen_free(vt->screen);
|
||||
|
||||
if(vt->state)
|
||||
vterm_state_free(vt->state);
|
||||
|
||||
vterm_allocator_free(vt, vt->strbuffer);
|
||||
vterm_allocator_free(vt, vt->outbuffer);
|
||||
|
||||
vterm_allocator_free(vt, vt);
|
||||
}
|
||||
|
||||
INTERNAL void *vterm_allocator_malloc(VTerm *vt, size_t size)
|
||||
{
|
||||
return (*vt->allocator->malloc)(size, vt->allocdata);
|
||||
}
|
||||
|
||||
INTERNAL void vterm_allocator_free(VTerm *vt, void *ptr)
|
||||
{
|
||||
(*vt->allocator->free)(ptr, vt->allocdata);
|
||||
}
|
||||
|
||||
void vterm_get_size(const VTerm *vt, int *rowsp, int *colsp)
|
||||
{
|
||||
if(rowsp)
|
||||
*rowsp = vt->rows;
|
||||
if(colsp)
|
||||
*colsp = vt->cols;
|
||||
}
|
||||
|
||||
void vterm_set_size(VTerm *vt, int rows, int cols)
|
||||
{
|
||||
vt->rows = rows;
|
||||
vt->cols = cols;
|
||||
|
||||
if(vt->parser_callbacks && vt->parser_callbacks->resize)
|
||||
(*vt->parser_callbacks->resize)(rows, cols, vt->cbdata);
|
||||
}
|
||||
|
||||
int vterm_get_utf8(const VTerm *vt)
|
||||
{
|
||||
return vt->mode.utf8;
|
||||
}
|
||||
|
||||
void vterm_set_utf8(VTerm *vt, int is_utf8)
|
||||
{
|
||||
vt->mode.utf8 = is_utf8;
|
||||
}
|
||||
|
||||
INTERNAL void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len)
|
||||
{
|
||||
if(len > vt->outbuffer_len - vt->outbuffer_cur) {
|
||||
DEBUG_LOG("vterm_push_output(): buffer overflow; truncating output\n");
|
||||
len = vt->outbuffer_len - vt->outbuffer_cur;
|
||||
}
|
||||
|
||||
memcpy(vt->outbuffer + vt->outbuffer_cur, bytes, len);
|
||||
vt->outbuffer_cur += len;
|
||||
}
|
||||
|
||||
static int outbuffer_is_full(VTerm *vt)
|
||||
{
|
||||
return vt->outbuffer_cur >= vt->outbuffer_len - 1;
|
||||
}
|
||||
|
||||
#if _XOPEN_SOURCE >= 500 || _ISOC99_SOURCE || _BSD_SOURCE
|
||||
# undef VSNPRINTF
|
||||
# define VSNPRINTF vsnprintf
|
||||
#else
|
||||
# ifdef VSNPRINTF
|
||||
/* Use a provided vsnprintf() function. */
|
||||
int VSNPRINTF(char *str, size_t str_m, const char *fmt, va_list ap);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
INTERNAL void vterm_push_output_vsprintf(VTerm *vt, const char *format, va_list args)
|
||||
{
|
||||
int written;
|
||||
#ifndef VSNPRINTF
|
||||
/* When vsnprintf() is not available (C90) fall back to vsprintf(). */
|
||||
char buffer[1024]; /* 1Kbyte is enough for everybody, right? */
|
||||
#endif
|
||||
|
||||
if(outbuffer_is_full(vt)) {
|
||||
DEBUG_LOG("vterm_push_output(): buffer overflow; truncating output\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef VSNPRINTF
|
||||
written = VSNPRINTF(vt->outbuffer + vt->outbuffer_cur,
|
||||
vt->outbuffer_len - vt->outbuffer_cur,
|
||||
format, args);
|
||||
|
||||
if(written == (int)(vt->outbuffer_len - vt->outbuffer_cur)) {
|
||||
/* output was truncated */
|
||||
vt->outbuffer_cur = vt->outbuffer_len - 1;
|
||||
}
|
||||
else
|
||||
vt->outbuffer_cur += written;
|
||||
#else
|
||||
written = vsprintf(buffer, format, args);
|
||||
|
||||
if(written >= (int)(vt->outbuffer_len - vt->outbuffer_cur)) {
|
||||
/* output was truncated */
|
||||
written = vt->outbuffer_len - vt->outbuffer_cur;
|
||||
}
|
||||
if (written > 0)
|
||||
{
|
||||
strncpy(vt->outbuffer + vt->outbuffer_cur, buffer, written + 1);
|
||||
vt->outbuffer_cur += written;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
INTERNAL void vterm_push_output_sprintf(VTerm *vt, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vterm_push_output_vsprintf(vt, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
INTERNAL void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, const char *fmt, ...)
|
||||
{
|
||||
size_t orig_cur = vt->outbuffer_cur;
|
||||
va_list args;
|
||||
|
||||
if(ctrl >= 0x80 && !vt->mode.ctrl8bit)
|
||||
vterm_push_output_sprintf(vt, ESC_S "%c", ctrl - 0x40);
|
||||
else
|
||||
vterm_push_output_sprintf(vt, "%c", ctrl);
|
||||
|
||||
va_start(args, fmt);
|
||||
vterm_push_output_vsprintf(vt, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if(outbuffer_is_full(vt))
|
||||
vt->outbuffer_cur = orig_cur;
|
||||
}
|
||||
|
||||
INTERNAL void vterm_push_output_sprintf_dcs(VTerm *vt, const char *fmt, ...)
|
||||
{
|
||||
size_t orig_cur = vt->outbuffer_cur;
|
||||
va_list args;
|
||||
|
||||
if(!vt->mode.ctrl8bit)
|
||||
vterm_push_output_sprintf(vt, ESC_S "%c", C1_DCS - 0x40);
|
||||
else
|
||||
vterm_push_output_sprintf(vt, "%c", C1_DCS);
|
||||
|
||||
va_start(args, fmt);
|
||||
vterm_push_output_vsprintf(vt, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
vterm_push_output_sprintf_ctrl(vt, C1_ST, "");
|
||||
|
||||
if(outbuffer_is_full(vt))
|
||||
vt->outbuffer_cur = orig_cur;
|
||||
}
|
||||
|
||||
size_t vterm_output_get_buffer_size(const VTerm *vt)
|
||||
{
|
||||
return vt->outbuffer_len;
|
||||
}
|
||||
|
||||
size_t vterm_output_get_buffer_current(const VTerm *vt)
|
||||
{
|
||||
return vt->outbuffer_cur;
|
||||
}
|
||||
|
||||
size_t vterm_output_get_buffer_remaining(const VTerm *vt)
|
||||
{
|
||||
return vt->outbuffer_len - vt->outbuffer_cur;
|
||||
}
|
||||
|
||||
size_t vterm_output_read(VTerm *vt, char *buffer, size_t len)
|
||||
{
|
||||
if(len > vt->outbuffer_cur)
|
||||
len = vt->outbuffer_cur;
|
||||
|
||||
memcpy(buffer, vt->outbuffer, len);
|
||||
|
||||
if(len < vt->outbuffer_cur)
|
||||
memmove(vt->outbuffer, vt->outbuffer + len, vt->outbuffer_cur - len);
|
||||
|
||||
vt->outbuffer_cur -= len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void vterm_parser_set_callbacks(VTerm *vt, const VTermParserCallbacks *callbacks, void *user)
|
||||
{
|
||||
vt->parser_callbacks = callbacks;
|
||||
vt->cbdata = user;
|
||||
}
|
||||
|
||||
void *vterm_parser_get_cbdata(VTerm *vt)
|
||||
{
|
||||
return vt->cbdata;
|
||||
}
|
||||
|
||||
VTermValueType vterm_get_attr_type(VTermAttr attr)
|
||||
{
|
||||
switch(attr) {
|
||||
case VTERM_ATTR_BOLD: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_ATTR_UNDERLINE: return VTERM_VALUETYPE_INT;
|
||||
case VTERM_ATTR_ITALIC: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_ATTR_BLINK: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_ATTR_REVERSE: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_ATTR_STRIKE: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_ATTR_FONT: return VTERM_VALUETYPE_INT;
|
||||
case VTERM_ATTR_FOREGROUND: return VTERM_VALUETYPE_COLOR;
|
||||
case VTERM_ATTR_BACKGROUND: return VTERM_VALUETYPE_COLOR;
|
||||
}
|
||||
return 0; /* UNREACHABLE */
|
||||
}
|
||||
|
||||
VTermValueType vterm_get_prop_type(VTermProp prop)
|
||||
{
|
||||
switch(prop) {
|
||||
case VTERM_PROP_CURSORVISIBLE: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_PROP_CURSORBLINK: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_PROP_ALTSCREEN: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_PROP_TITLE: return VTERM_VALUETYPE_STRING;
|
||||
case VTERM_PROP_ICONNAME: return VTERM_VALUETYPE_STRING;
|
||||
case VTERM_PROP_REVERSE: return VTERM_VALUETYPE_BOOL;
|
||||
case VTERM_PROP_CURSORSHAPE: return VTERM_VALUETYPE_INT;
|
||||
case VTERM_PROP_MOUSE: return VTERM_VALUETYPE_INT;
|
||||
}
|
||||
return 0; /* UNREACHABLE */
|
||||
}
|
||||
|
||||
void vterm_scroll_rect(VTermRect rect,
|
||||
int downward,
|
||||
int rightward,
|
||||
int (*moverect)(VTermRect src, VTermRect dest, void *user),
|
||||
int (*eraserect)(VTermRect rect, int selective, void *user),
|
||||
void *user)
|
||||
{
|
||||
VTermRect src;
|
||||
VTermRect dest;
|
||||
|
||||
if(abs(downward) >= rect.end_row - rect.start_row ||
|
||||
abs(rightward) >= rect.end_col - rect.start_col) {
|
||||
/* Scroll more than area; just erase the lot */
|
||||
(*eraserect)(rect, 0, user);
|
||||
return;
|
||||
}
|
||||
|
||||
if(rightward >= 0) {
|
||||
/* rect: [XXX................]
|
||||
* src: [----------------]
|
||||
* dest: [----------------]
|
||||
*/
|
||||
dest.start_col = rect.start_col;
|
||||
dest.end_col = rect.end_col - rightward;
|
||||
src.start_col = rect.start_col + rightward;
|
||||
src.end_col = rect.end_col;
|
||||
}
|
||||
else {
|
||||
/* rect: [................XXX]
|
||||
* src: [----------------]
|
||||
* dest: [----------------]
|
||||
*/
|
||||
int leftward = -rightward;
|
||||
dest.start_col = rect.start_col + leftward;
|
||||
dest.end_col = rect.end_col;
|
||||
src.start_col = rect.start_col;
|
||||
src.end_col = rect.end_col - leftward;
|
||||
}
|
||||
|
||||
if(downward >= 0) {
|
||||
dest.start_row = rect.start_row;
|
||||
dest.end_row = rect.end_row - downward;
|
||||
src.start_row = rect.start_row + downward;
|
||||
src.end_row = rect.end_row;
|
||||
}
|
||||
else {
|
||||
int upward = -downward;
|
||||
dest.start_row = rect.start_row + upward;
|
||||
dest.end_row = rect.end_row;
|
||||
src.start_row = rect.start_row;
|
||||
src.end_row = rect.end_row - upward;
|
||||
}
|
||||
|
||||
if(moverect)
|
||||
(*moverect)(dest, src, user);
|
||||
|
||||
if(downward > 0)
|
||||
rect.start_row = rect.end_row - downward;
|
||||
else if(downward < 0)
|
||||
rect.end_row = rect.start_row - downward;
|
||||
|
||||
if(rightward > 0)
|
||||
rect.start_col = rect.end_col - rightward;
|
||||
else if(rightward < 0)
|
||||
rect.end_col = rect.start_col - rightward;
|
||||
|
||||
(*eraserect)(rect, 0, user);
|
||||
}
|
||||
|
||||
void vterm_copy_cells(VTermRect dest,
|
||||
VTermRect src,
|
||||
void (*copycell)(VTermPos dest, VTermPos src, void *user),
|
||||
void *user)
|
||||
{
|
||||
int downward = src.start_row - dest.start_row;
|
||||
int rightward = src.start_col - dest.start_col;
|
||||
|
||||
int init_row, test_row, init_col, test_col;
|
||||
int inc_row, inc_col;
|
||||
|
||||
VTermPos pos;
|
||||
|
||||
if(downward < 0) {
|
||||
init_row = dest.end_row - 1;
|
||||
test_row = dest.start_row - 1;
|
||||
inc_row = -1;
|
||||
}
|
||||
else /* downward >= 0 */ {
|
||||
init_row = dest.start_row;
|
||||
test_row = dest.end_row;
|
||||
inc_row = +1;
|
||||
}
|
||||
|
||||
if(rightward < 0) {
|
||||
init_col = dest.end_col - 1;
|
||||
test_col = dest.start_col - 1;
|
||||
inc_col = -1;
|
||||
}
|
||||
else /* rightward >= 0 */ {
|
||||
init_col = dest.start_col;
|
||||
test_col = dest.end_col;
|
||||
inc_col = +1;
|
||||
}
|
||||
|
||||
for(pos.row = init_row; pos.row != test_row; pos.row += inc_row)
|
||||
for(pos.col = init_col; pos.col != test_col; pos.col += inc_col) {
|
||||
VTermPos srcpos;
|
||||
srcpos.row = pos.row + downward;
|
||||
srcpos.col = pos.col + rightward;
|
||||
(*copycell)(pos, srcpos, user);
|
||||
}
|
||||
}
|
||||
237
src/libvterm/src/vterm_internal.h
Normal file
237
src/libvterm/src/vterm_internal.h
Normal file
@@ -0,0 +1,237 @@
|
||||
#ifndef __VTERM_INTERNAL_H__
|
||||
#define __VTERM_INTERNAL_H__
|
||||
|
||||
#include "vterm.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define INTERNAL __attribute__((visibility("internal")))
|
||||
# define UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define INTERNAL
|
||||
# define UNUSED
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
# define DEBUG_LOG(s) fprintf(stderr, s)
|
||||
# define DEBUG_LOG1(s, a) fprintf(stderr, s, a)
|
||||
# define DEBUG_LOG2(s, a, b) fprintf(stderr, s, a, b)
|
||||
# define DEBUG_LOG3(s, a, b, c) fprintf(stderr, s, a, b, c)
|
||||
#else
|
||||
# define DEBUG_LOG(s)
|
||||
# define DEBUG_LOG1(s, a)
|
||||
# define DEBUG_LOG2(s, a, b)
|
||||
# define DEBUG_LOG3(s, a, b, c)
|
||||
#endif
|
||||
|
||||
#define ESC_S "\x1b"
|
||||
|
||||
typedef struct VTermEncoding VTermEncoding;
|
||||
|
||||
typedef struct {
|
||||
VTermEncoding *enc;
|
||||
|
||||
/* This size should be increased if required by other stateful encodings */
|
||||
char data[4*sizeof(uint32_t)];
|
||||
} VTermEncodingInstance;
|
||||
|
||||
struct VTermPen
|
||||
{
|
||||
VTermColor fg;
|
||||
VTermColor bg;
|
||||
unsigned int bold:1;
|
||||
unsigned int underline:2;
|
||||
unsigned int italic:1;
|
||||
unsigned int blink:1;
|
||||
unsigned int reverse:1;
|
||||
unsigned int strike:1;
|
||||
unsigned int font:4; /* To store 0-9 */
|
||||
};
|
||||
|
||||
int vterm_color_equal(VTermColor a, VTermColor b);
|
||||
|
||||
#if defined(DEFINE_INLINES) || USE_INLINE
|
||||
INLINE int vterm_color_equal(VTermColor a, VTermColor b)
|
||||
{
|
||||
return a.red == b.red && a.green == b.green && a.blue == b.blue;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct VTermState
|
||||
{
|
||||
VTerm *vt;
|
||||
|
||||
const VTermStateCallbacks *callbacks;
|
||||
void *cbdata;
|
||||
|
||||
const VTermParserCallbacks *fallbacks;
|
||||
void *fbdata;
|
||||
|
||||
int rows;
|
||||
int cols;
|
||||
|
||||
/* Current cursor position */
|
||||
VTermPos pos;
|
||||
|
||||
int at_phantom; /* True if we're on the "81st" phantom column to defer a wraparound */
|
||||
|
||||
int scrollregion_top;
|
||||
int scrollregion_bottom; /* -1 means unbounded */
|
||||
#define SCROLLREGION_BOTTOM(state) ((state)->scrollregion_bottom > -1 ? (state)->scrollregion_bottom : (state)->rows)
|
||||
int scrollregion_left;
|
||||
#define SCROLLREGION_LEFT(state) ((state)->mode.leftrightmargin ? (state)->scrollregion_left : 0)
|
||||
int scrollregion_right; /* -1 means unbounded */
|
||||
#define SCROLLREGION_RIGHT(state) ((state)->mode.leftrightmargin && (state)->scrollregion_right > -1 ? (state)->scrollregion_right : (state)->cols)
|
||||
|
||||
/* Bitvector of tab stops */
|
||||
unsigned char *tabstops;
|
||||
|
||||
VTermLineInfo *lineinfo;
|
||||
#define ROWWIDTH(state,row) ((state)->lineinfo[(row)].doublewidth ? ((state)->cols / 2) : (state)->cols)
|
||||
#define THISROWWIDTH(state) ROWWIDTH(state, (state)->pos.row)
|
||||
|
||||
/* Mouse state */
|
||||
int mouse_col, mouse_row;
|
||||
int mouse_buttons;
|
||||
int mouse_flags;
|
||||
#define MOUSE_WANT_CLICK 0x01
|
||||
#define MOUSE_WANT_DRAG 0x02
|
||||
#define MOUSE_WANT_MOVE 0x04
|
||||
|
||||
enum { MOUSE_X10, MOUSE_UTF8, MOUSE_SGR, MOUSE_RXVT } mouse_protocol;
|
||||
|
||||
/* Last glyph output, for Unicode recombining purposes */
|
||||
uint32_t *combine_chars;
|
||||
size_t combine_chars_size; /* Number of ELEMENTS in the above */
|
||||
int combine_width; /* The width of the glyph above */
|
||||
VTermPos combine_pos; /* Position before movement */
|
||||
|
||||
struct {
|
||||
unsigned int keypad:1;
|
||||
unsigned int cursor:1;
|
||||
unsigned int autowrap:1;
|
||||
unsigned int insert:1;
|
||||
unsigned int newline:1;
|
||||
unsigned int cursor_visible:1;
|
||||
unsigned int cursor_blink:1;
|
||||
unsigned int cursor_shape:2;
|
||||
unsigned int alt_screen:1;
|
||||
unsigned int origin:1;
|
||||
unsigned int screen:1;
|
||||
unsigned int leftrightmargin:1;
|
||||
unsigned int bracketpaste:1;
|
||||
} mode;
|
||||
|
||||
VTermEncodingInstance encoding[4], encoding_utf8;
|
||||
int gl_set, gr_set, gsingle_set;
|
||||
|
||||
struct VTermPen pen;
|
||||
|
||||
VTermColor default_fg;
|
||||
VTermColor default_bg;
|
||||
VTermColor colors[16]; /* Store the 8 ANSI and the 8 ANSI high-brights only */
|
||||
|
||||
int fg_index;
|
||||
int bg_index;
|
||||
int bold_is_highbright;
|
||||
|
||||
unsigned int protected_cell : 1;
|
||||
|
||||
/* Saved state under DEC mode 1048/1049 */
|
||||
struct {
|
||||
VTermPos pos;
|
||||
struct VTermPen pen;
|
||||
|
||||
struct {
|
||||
int cursor_visible:1;
|
||||
int cursor_blink:1;
|
||||
unsigned int cursor_shape:2;
|
||||
} mode;
|
||||
} saved;
|
||||
};
|
||||
|
||||
struct VTerm
|
||||
{
|
||||
VTermAllocatorFunctions *allocator;
|
||||
void *allocdata;
|
||||
|
||||
int rows;
|
||||
int cols;
|
||||
|
||||
struct {
|
||||
unsigned int utf8:1;
|
||||
unsigned int ctrl8bit:1;
|
||||
} mode;
|
||||
|
||||
enum VTermParserState {
|
||||
NORMAL,
|
||||
CSI,
|
||||
OSC,
|
||||
DCS,
|
||||
ESC,
|
||||
ESC_IN_OSC,
|
||||
ESC_IN_DCS
|
||||
} parser_state;
|
||||
const VTermParserCallbacks *parser_callbacks;
|
||||
void *cbdata;
|
||||
|
||||
/* len == malloc()ed size; cur == number of valid bytes */
|
||||
char *strbuffer;
|
||||
size_t strbuffer_len;
|
||||
size_t strbuffer_cur;
|
||||
|
||||
char *outbuffer;
|
||||
size_t outbuffer_len;
|
||||
size_t outbuffer_cur;
|
||||
|
||||
VTermState *state;
|
||||
VTermScreen *screen;
|
||||
};
|
||||
|
||||
struct VTermEncoding {
|
||||
void (*init) (VTermEncoding *enc, void *data);
|
||||
void (*decode)(VTermEncoding *enc, void *data,
|
||||
uint32_t cp[], int *cpi, int cplen,
|
||||
const char bytes[], size_t *pos, size_t len);
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ENC_UTF8,
|
||||
ENC_SINGLE_94
|
||||
} VTermEncodingType;
|
||||
|
||||
void *vterm_allocator_malloc(VTerm *vt, size_t size);
|
||||
void vterm_allocator_free(VTerm *vt, void *ptr);
|
||||
|
||||
void vterm_push_output_bytes(VTerm *vt, const char *bytes, size_t len);
|
||||
void vterm_push_output_vsprintf(VTerm *vt, const char *format, va_list args);
|
||||
void vterm_push_output_sprintf(VTerm *vt, const char *format, ...);
|
||||
void vterm_push_output_sprintf_ctrl(VTerm *vt, unsigned char ctrl, const char *fmt, ...);
|
||||
void vterm_push_output_sprintf_dcs(VTerm *vt, const char *fmt, ...);
|
||||
|
||||
void vterm_state_free(VTermState *state);
|
||||
|
||||
void vterm_state_newpen(VTermState *state);
|
||||
void vterm_state_resetpen(VTermState *state);
|
||||
void vterm_state_setpen(VTermState *state, const long args[], int argcount);
|
||||
int vterm_state_getpen(VTermState *state, long args[], int argcount);
|
||||
void vterm_state_savepen(VTermState *state, int save);
|
||||
|
||||
enum {
|
||||
C1_SS3 = 0x8f,
|
||||
C1_DCS = 0x90,
|
||||
C1_CSI = 0x9b,
|
||||
C1_ST = 0x9c
|
||||
};
|
||||
|
||||
void vterm_state_push_output_sprintf_CSI(VTermState *vts, const char *format, ...);
|
||||
|
||||
void vterm_screen_free(VTermScreen *screen);
|
||||
|
||||
VTermEncoding *vterm_lookup_encoding(VTermEncodingType type, char designation);
|
||||
|
||||
int vterm_unicode_width(uint32_t codepoint);
|
||||
int vterm_unicode_is_combining(uint32_t codepoint);
|
||||
|
||||
#endif
|
||||
200
src/libvterm/t/02parser.test
Normal file
200
src/libvterm/t/02parser.test
Normal file
@@ -0,0 +1,200 @@
|
||||
INIT
|
||||
UTF8 0
|
||||
WANTPARSER
|
||||
|
||||
!Basic text
|
||||
PUSH "hello"
|
||||
text 0x68, 0x65, 0x6c, 0x6c, 0x6f
|
||||
|
||||
!C0
|
||||
PUSH "\x03"
|
||||
control 3
|
||||
|
||||
PUSH "\x1f"
|
||||
control 0x1f
|
||||
|
||||
!C1 8bit
|
||||
PUSH "\x83"
|
||||
control 0x83
|
||||
|
||||
PUSH "\x9f"
|
||||
control 0x9f
|
||||
|
||||
!C1 7bit
|
||||
PUSH "\e\x43"
|
||||
control 0x83
|
||||
|
||||
PUSH "\e\x5f"
|
||||
control 0x9f
|
||||
|
||||
!High bytes
|
||||
PUSH "\xa0\xcc\xfe"
|
||||
text 0xa0, 0xcc, 0xfe
|
||||
|
||||
!Mixed
|
||||
PUSH "1\n2"
|
||||
text 0x31
|
||||
control 10
|
||||
text 0x32
|
||||
|
||||
!Escape
|
||||
PUSH "\e="
|
||||
escape "="
|
||||
|
||||
!Escape 2-byte
|
||||
PUSH "\e(X"
|
||||
escape "(X"
|
||||
|
||||
!Split write Escape
|
||||
PUSH "\e("
|
||||
PUSH "Y"
|
||||
escape "(Y"
|
||||
|
||||
!Escape cancels Escape, starts another
|
||||
PUSH "\e(\e)Z"
|
||||
escape ")Z"
|
||||
|
||||
!CAN cancels Escape, returns to normal mode
|
||||
PUSH "\e(\x{18}AB"
|
||||
text 0x41, 0x42
|
||||
|
||||
!C0 in Escape interrupts and continues
|
||||
PUSH "\e(\nX"
|
||||
control 10
|
||||
escape "(X"
|
||||
|
||||
!CSI 0 args
|
||||
PUSH "\e[a"
|
||||
csi 0x61 *
|
||||
|
||||
!CSI 1 arg
|
||||
PUSH "\e[9b"
|
||||
csi 0x62 9
|
||||
|
||||
!CSI 2 args
|
||||
PUSH "\e[3;4c"
|
||||
csi 0x63 3,4
|
||||
|
||||
!CSI 1 arg 1 sub
|
||||
PUSH "\e[1:2c"
|
||||
csi 0x63 1+,2
|
||||
|
||||
!CSI many digits
|
||||
PUSH "\e[678d"
|
||||
csi 0x64 678
|
||||
|
||||
!CSI leading zero
|
||||
PUSH "\e[007e"
|
||||
csi 0x65 7
|
||||
|
||||
!CSI qmark
|
||||
PUSH "\e[?2;7f"
|
||||
csi 0x66 L=3f 2,7
|
||||
|
||||
!CSI greater
|
||||
PUSH "\e[>c"
|
||||
csi 0x63 L=3e *
|
||||
|
||||
!CSI SP
|
||||
PUSH "\e[12 q"
|
||||
csi 0x71 12 I=20
|
||||
|
||||
!Mixed CSI
|
||||
PUSH "A\e[8mB"
|
||||
text 0x41
|
||||
csi 0x6d 8
|
||||
text 0x42
|
||||
|
||||
!Split write
|
||||
PUSH "\e"
|
||||
PUSH "[a"
|
||||
csi 0x61 *
|
||||
PUSH "foo\e["
|
||||
text 0x66, 0x6f, 0x6f
|
||||
PUSH "4b"
|
||||
csi 0x62 4
|
||||
PUSH "\e[12;"
|
||||
PUSH "3c"
|
||||
csi 0x63 12,3
|
||||
|
||||
!Escape cancels CSI, starts Escape
|
||||
PUSH "\e[123\e9"
|
||||
escape "9"
|
||||
|
||||
!CAN cancels CSI, returns to normal mode
|
||||
PUSH "\e[12\x{18}AB"
|
||||
text 0x41, 0x42
|
||||
|
||||
!C0 in Escape interrupts and continues
|
||||
PUSH "\e[12\n;3X"
|
||||
control 10
|
||||
csi 0x58 12,3
|
||||
|
||||
!OSC BEL
|
||||
PUSH "\e]1;Hello\x07"
|
||||
osc "1;Hello"
|
||||
|
||||
!OSC ST (7bit)
|
||||
PUSH "\e]1;Hello\e\\"
|
||||
osc "1;Hello"
|
||||
|
||||
!OSC ST (8bit)
|
||||
PUSH "\x{9d}1;Hello\x9c"
|
||||
osc "1;Hello"
|
||||
|
||||
!Escape cancels OSC, starts Escape
|
||||
PUSH "\e]Something\e9"
|
||||
escape "9"
|
||||
|
||||
!CAN cancels OSC, returns to normal mode
|
||||
PUSH "\e]12\x{18}AB"
|
||||
text 0x41, 0x42
|
||||
|
||||
!C0 in OSC interrupts and continues
|
||||
PUSH "\e]2;\nBye\x07"
|
||||
control 10
|
||||
osc "2;Bye"
|
||||
|
||||
!DCS BEL
|
||||
PUSH "\ePHello\x07"
|
||||
dcs "Hello"
|
||||
|
||||
!DCS ST (7bit)
|
||||
PUSH "\ePHello\e\\"
|
||||
dcs "Hello"
|
||||
|
||||
!DCS ST (8bit)
|
||||
PUSH "\x{90}Hello\x9c"
|
||||
dcs "Hello"
|
||||
|
||||
!Escape cancels DCS, starts Escape
|
||||
PUSH "\ePSomething\e9"
|
||||
escape "9"
|
||||
|
||||
!CAN cancels DCS, returns to normal mode
|
||||
PUSH "\eP12\x{18}AB"
|
||||
text 0x41, 0x42
|
||||
|
||||
!C0 in OSC interrupts and continues
|
||||
PUSH "\ePBy\ne\x07"
|
||||
control 10
|
||||
dcs "Bye"
|
||||
|
||||
!NUL ignored
|
||||
PUSH "\x{00}"
|
||||
|
||||
!NUL ignored within CSI
|
||||
PUSH "\e[12\x{00}3m"
|
||||
csi 0x6d 123
|
||||
|
||||
!DEL ignored
|
||||
PUSH "\x{7f}"
|
||||
|
||||
!DEL ignored within CSI
|
||||
PUSH "\e[12\x{7f}3m"
|
||||
csi 0x6d 123
|
||||
|
||||
!DEL inside text"
|
||||
PUSH "AB\x{7f}C"
|
||||
text 0x41,0x42
|
||||
text 0x43
|
||||
122
src/libvterm/t/03encoding_utf8.test
Normal file
122
src/libvterm/t/03encoding_utf8.test
Normal file
@@ -0,0 +1,122 @@
|
||||
INIT
|
||||
WANTENCODING
|
||||
|
||||
!Low
|
||||
ENCIN "123"
|
||||
encout 0x31,0x32,0x33
|
||||
|
||||
# We want to prove the UTF-8 parser correctly handles all the sequences.
|
||||
# Easy way to do this is to check it does low/high boundary cases, as that
|
||||
# leaves only two for each sequence length
|
||||
#
|
||||
# These ranges are therefore:
|
||||
#
|
||||
# Two bytes:
|
||||
# U+0080 = 000 10000000 => 00010 000000
|
||||
# => 11000010 10000000 = C2 80
|
||||
# U+07FF = 111 11111111 => 11111 111111
|
||||
# => 11011111 10111111 = DF BF
|
||||
#
|
||||
# Three bytes:
|
||||
# U+0800 = 00001000 00000000 => 0000 100000 000000
|
||||
# => 11100000 10100000 10000000 = E0 A0 80
|
||||
# U+FFFD = 11111111 11111101 => 1111 111111 111101
|
||||
# => 11101111 10111111 10111101 = EF BF BD
|
||||
# (We avoid U+FFFE and U+FFFF as they're invalid codepoints)
|
||||
#
|
||||
# Four bytes:
|
||||
# U+10000 = 00001 00000000 00000000 => 000 010000 000000 000000
|
||||
# => 11110000 10010000 10000000 10000000 = F0 90 80 80
|
||||
# U+1FFFFF = 11111 11111111 11111111 => 111 111111 111111 111111
|
||||
# => 11110111 10111111 10111111 10111111 = F7 BF BF BF
|
||||
|
||||
!2 byte
|
||||
ENCIN "\xC2\x80\xDF\xBF"
|
||||
encout 0x0080, 0x07FF
|
||||
|
||||
!3 byte
|
||||
ENCIN "\xE0\xA0\x80\xEF\xBF\xBD"
|
||||
encout 0x0800,0xFFFD
|
||||
|
||||
!4 byte
|
||||
ENCIN "\xF0\x90\x80\x80\xF7\xBF\xBF\xBF"
|
||||
encout 0x10000,0x1fffff
|
||||
|
||||
# Next up, we check some invalid sequences
|
||||
# + Early termination (back to low bytes too soon)
|
||||
# + Early restart (another sequence introduction before the previous one was finished)
|
||||
|
||||
!Early termination
|
||||
ENCIN "\xC2!"
|
||||
encout 0xfffd,0x21
|
||||
|
||||
ENCIN "\xE0!\xE0\xA0!"
|
||||
encout 0xfffd,0x21,0xfffd,0x21
|
||||
|
||||
ENCIN "\xF0!\xF0\x90!\xF0\x90\x80!"
|
||||
encout 0xfffd,0x21,0xfffd,0x21,0xfffd,0x21
|
||||
|
||||
!Early restart
|
||||
ENCIN "\xC2\xC2\x90"
|
||||
encout 0xfffd,0x0090
|
||||
|
||||
ENCIN "\xE0\xC2\x90\xE0\xA0\xC2\x90"
|
||||
encout 0xfffd,0x0090,0xfffd,0x0090
|
||||
|
||||
ENCIN "\xF0\xC2\x90\xF0\x90\xC2\x90\xF0\x90\x80\xC2\x90"
|
||||
encout 0xfffd,0x0090,0xfffd,0x0090,0xfffd,0x0090
|
||||
|
||||
# Test the overlong sequences by giving an overlong encoding of U+0000 and
|
||||
# an encoding of the highest codepoint still too short
|
||||
#
|
||||
# Two bytes:
|
||||
# U+0000 = C0 80
|
||||
# U+007F = 000 01111111 => 00001 111111 =>
|
||||
# => 11000001 10111111 => C1 BF
|
||||
#
|
||||
# Three bytes:
|
||||
# U+0000 = E0 80 80
|
||||
# U+07FF = 00000111 11111111 => 0000 011111 111111
|
||||
# => 11100000 10011111 10111111 = E0 9F BF
|
||||
#
|
||||
# Four bytes:
|
||||
# U+0000 = F0 80 80 80
|
||||
# U+FFFF = 11111111 11111111 => 000 001111 111111 111111
|
||||
# => 11110000 10001111 10111111 10111111 = F0 8F BF BF
|
||||
|
||||
!Overlong
|
||||
ENCIN "\xC0\x80\xC1\xBF"
|
||||
encout 0xfffd,0xfffd
|
||||
|
||||
ENCIN "\xE0\x80\x80\xE0\x9F\xBF"
|
||||
encout 0xfffd,0xfffd
|
||||
|
||||
ENCIN "\xF0\x80\x80\x80\xF0\x8F\xBF\xBF"
|
||||
encout 0xfffd,0xfffd
|
||||
|
||||
# UTF-16 surrogates U+D800 and U+DFFF
|
||||
!UTF-16 Surrogates
|
||||
ENCIN "\xED\xA0\x80\xED\xBF\xBF"
|
||||
encout 0xfffd,0xfffd
|
||||
|
||||
!Split write
|
||||
ENCIN "\xC2"
|
||||
ENCIN "\xA0"
|
||||
encout 0x000A0
|
||||
|
||||
ENCIN "\xE0"
|
||||
ENCIN "\xA0\x80"
|
||||
encout 0x00800
|
||||
ENCIN "\xE0\xA0"
|
||||
ENCIN "\x80"
|
||||
encout 0x00800
|
||||
|
||||
ENCIN "\xF0"
|
||||
ENCIN "\x90\x80\x80"
|
||||
encout 0x10000
|
||||
ENCIN "\xF0\x90"
|
||||
ENCIN "\x80\x80"
|
||||
encout 0x10000
|
||||
ENCIN "\xF0\x90\x80"
|
||||
ENCIN "\x80"
|
||||
encout 0x10000
|
||||
55
src/libvterm/t/10state_putglyph.test
Normal file
55
src/libvterm/t/10state_putglyph.test
Normal file
@@ -0,0 +1,55 @@
|
||||
INIT
|
||||
UTF8 1
|
||||
WANTSTATE g
|
||||
|
||||
!Low
|
||||
RESET
|
||||
PUSH "ABC"
|
||||
putglyph 0x41 1 0,0
|
||||
putglyph 0x42 1 0,1
|
||||
putglyph 0x43 1 0,2
|
||||
|
||||
!UTF-8 1 char
|
||||
# U+00C1 = 0xC3 0x81 name: LATIN CAPITAL LETTER A WITH ACUTE
|
||||
# U+00E9 = 0xC3 0xA9 name: LATIN SMALL LETTER E WITH ACUTE
|
||||
RESET
|
||||
PUSH "\xC3\x81\xC3\xA9"
|
||||
putglyph 0xc1 1 0,0
|
||||
putglyph 0xe9 1 0,1
|
||||
|
||||
!UTF-8 wide char
|
||||
# U+FF10 = 0xEF 0xBC 0x90 name: FULLWIDTH DIGIT ZERO
|
||||
RESET
|
||||
PUSH "\xEF\xBC\x90 "
|
||||
putglyph 0xff10 2 0,0
|
||||
putglyph 0x20 1 0,2
|
||||
|
||||
!UTF-8 combining chars
|
||||
# U+0301 = 0xCC 0x81 name: COMBINING ACUTE
|
||||
RESET
|
||||
PUSH "e\xCC\x81Z"
|
||||
putglyph 0x65,0x301 1 0,0
|
||||
putglyph 0x5a 1 0,1
|
||||
|
||||
!Combining across buffers
|
||||
RESET
|
||||
PUSH "e"
|
||||
putglyph 0x65 1 0,0
|
||||
PUSH "\xCC\x81Z"
|
||||
putglyph 0x65,0x301 1 0,0
|
||||
putglyph 0x5a 1 0,1
|
||||
|
||||
RESET
|
||||
PUSH "e"
|
||||
putglyph 0x65 1 0,0
|
||||
PUSH "\xCC\x81"
|
||||
putglyph 0x65,0x301 1 0,0
|
||||
PUSH "\xCC\x82"
|
||||
putglyph 0x65,0x301,0x302 1 0,0
|
||||
|
||||
!DECSCA protected
|
||||
RESET
|
||||
PUSH "A\e[1\"qB\e[2\"qC"
|
||||
putglyph 0x41 1 0,0
|
||||
putglyph 0x42 1 0,1 prot
|
||||
putglyph 0x43 1 0,2
|
||||
224
src/libvterm/t/11state_movecursor.test
Normal file
224
src/libvterm/t/11state_movecursor.test
Normal file
@@ -0,0 +1,224 @@
|
||||
INIT
|
||||
UTF8 1
|
||||
WANTSTATE
|
||||
|
||||
!Implicit
|
||||
PUSH "ABC"
|
||||
?cursor = 0,3
|
||||
!Backspace
|
||||
PUSH "\b"
|
||||
?cursor = 0,2
|
||||
!Horizontal Tab
|
||||
PUSH "\t"
|
||||
?cursor = 0,8
|
||||
!Carriage Return
|
||||
PUSH "\r"
|
||||
?cursor = 0,0
|
||||
!Linefeed
|
||||
PUSH "\n"
|
||||
?cursor = 1,0
|
||||
|
||||
!Backspace bounded by lefthand edge
|
||||
PUSH "\e[4;2H"
|
||||
?cursor = 3,1
|
||||
PUSH "\b"
|
||||
?cursor = 3,0
|
||||
PUSH "\b"
|
||||
?cursor = 3,0
|
||||
|
||||
!Backspace cancels phantom
|
||||
PUSH "\e[4;80H"
|
||||
?cursor = 3,79
|
||||
PUSH "X"
|
||||
?cursor = 3,79
|
||||
PUSH "\b"
|
||||
?cursor = 3,78
|
||||
|
||||
!HT bounded by righthand edge
|
||||
PUSH "\e[1;78H"
|
||||
?cursor = 0,77
|
||||
PUSH "\t"
|
||||
?cursor = 0,79
|
||||
PUSH "\t"
|
||||
?cursor = 0,79
|
||||
|
||||
RESET
|
||||
|
||||
!Index
|
||||
PUSH "ABC\eD"
|
||||
?cursor = 1,3
|
||||
!Reverse Index
|
||||
PUSH "\eM"
|
||||
?cursor = 0,3
|
||||
!Newline
|
||||
PUSH "\eE"
|
||||
?cursor = 1,0
|
||||
|
||||
RESET
|
||||
|
||||
!Cursor Forward
|
||||
PUSH "\e[B"
|
||||
?cursor = 1,0
|
||||
PUSH "\e[3B"
|
||||
?cursor = 4,0
|
||||
PUSH "\e[0B"
|
||||
?cursor = 5,0
|
||||
|
||||
!Cursor Down
|
||||
PUSH "\e[C"
|
||||
?cursor = 5,1
|
||||
PUSH "\e[3C"
|
||||
?cursor = 5,4
|
||||
PUSH "\e[0C"
|
||||
?cursor = 5,5
|
||||
|
||||
!Cursor Up
|
||||
PUSH "\e[A"
|
||||
?cursor = 4,5
|
||||
PUSH "\e[3A"
|
||||
?cursor = 1,5
|
||||
PUSH "\e[0A"
|
||||
?cursor = 0,5
|
||||
|
||||
!Cursor Backward
|
||||
PUSH "\e[D"
|
||||
?cursor = 0,4
|
||||
PUSH "\e[3D"
|
||||
?cursor = 0,1
|
||||
PUSH "\e[0D"
|
||||
?cursor = 0,0
|
||||
|
||||
!Cursor Next Line
|
||||
PUSH " "
|
||||
?cursor = 0,3
|
||||
PUSH "\e[E"
|
||||
?cursor = 1,0
|
||||
PUSH " "
|
||||
?cursor = 1,3
|
||||
PUSH "\e[2E"
|
||||
?cursor = 3,0
|
||||
PUSH "\e[0E"
|
||||
?cursor = 4,0
|
||||
|
||||
!Cursor Previous Line
|
||||
PUSH " "
|
||||
?cursor = 4,3
|
||||
PUSH "\e[F"
|
||||
?cursor = 3,0
|
||||
PUSH " "
|
||||
?cursor = 3,3
|
||||
PUSH "\e[2F"
|
||||
?cursor = 1,0
|
||||
PUSH "\e[0F"
|
||||
?cursor = 0,0
|
||||
|
||||
!Cursor Horizonal Absolute
|
||||
PUSH "\n"
|
||||
?cursor = 1,0
|
||||
PUSH "\e[20G"
|
||||
?cursor = 1,19
|
||||
PUSH "\e[G"
|
||||
?cursor = 1,0
|
||||
|
||||
!Cursor Position
|
||||
PUSH "\e[10;5H"
|
||||
?cursor = 9,4
|
||||
PUSH "\e[8H"
|
||||
?cursor = 7,0
|
||||
PUSH "\e[H"
|
||||
?cursor = 0,0
|
||||
|
||||
!Cursor Position cancels phantom
|
||||
PUSH "\e[10;78H"
|
||||
?cursor = 9,77
|
||||
PUSH "ABC"
|
||||
?cursor = 9,79
|
||||
PUSH "\e[10;80H"
|
||||
PUSH "C"
|
||||
?cursor = 9,79
|
||||
PUSH "X"
|
||||
?cursor = 10,1
|
||||
|
||||
RESET
|
||||
|
||||
!Bounds Checking
|
||||
PUSH "\e[A"
|
||||
?cursor = 0,0
|
||||
PUSH "\e[D"
|
||||
?cursor = 0,0
|
||||
PUSH "\e[25;80H"
|
||||
?cursor = 24,79
|
||||
PUSH "\e[B"
|
||||
?cursor = 24,79
|
||||
PUSH "\e[C"
|
||||
?cursor = 24,79
|
||||
PUSH "\e[E"
|
||||
?cursor = 24,0
|
||||
PUSH "\e[H"
|
||||
?cursor = 0,0
|
||||
PUSH "\e[F"
|
||||
?cursor = 0,0
|
||||
PUSH "\e[999G"
|
||||
?cursor = 0,79
|
||||
PUSH "\e[99;99H"
|
||||
?cursor = 24,79
|
||||
|
||||
RESET
|
||||
|
||||
!Horizontal Position Absolute
|
||||
PUSH "\e[5`"
|
||||
?cursor = 0,4
|
||||
|
||||
!Horizontal Position Relative
|
||||
PUSH "\e[3a"
|
||||
?cursor = 0,7
|
||||
|
||||
!Horizontal Position Backward
|
||||
PUSH "\e[3j"
|
||||
?cursor = 0,4
|
||||
|
||||
!Horizontal and Vertical Position
|
||||
PUSH "\e[3;3f"
|
||||
?cursor = 2,2
|
||||
|
||||
!Vertical Position Absolute
|
||||
PUSH "\e[5d"
|
||||
?cursor = 4,2
|
||||
|
||||
!Vertical Position Relative
|
||||
PUSH "\e[2e"
|
||||
?cursor = 6,2
|
||||
|
||||
!Vertical Position Backward
|
||||
PUSH "\e[2k"
|
||||
?cursor = 4,2
|
||||
|
||||
RESET
|
||||
|
||||
!Horizontal Tab
|
||||
PUSH "\t"
|
||||
?cursor = 0,8
|
||||
PUSH " "
|
||||
?cursor = 0,11
|
||||
PUSH "\t"
|
||||
?cursor = 0,16
|
||||
PUSH " "
|
||||
?cursor = 0,23
|
||||
PUSH "\t"
|
||||
?cursor = 0,24
|
||||
PUSH " "
|
||||
?cursor = 0,32
|
||||
PUSH "\t"
|
||||
?cursor = 0,40
|
||||
|
||||
!Cursor Horizontal Tab
|
||||
PUSH "\e[I"
|
||||
?cursor = 0,48
|
||||
PUSH "\e[2I"
|
||||
?cursor = 0,64
|
||||
|
||||
!Cursor Backward Tab
|
||||
PUSH "\e[Z"
|
||||
?cursor = 0,56
|
||||
PUSH "\e[2Z"
|
||||
?cursor = 0,40
|
||||
150
src/libvterm/t/12state_scroll.test
Normal file
150
src/libvterm/t/12state_scroll.test
Normal file
@@ -0,0 +1,150 @@
|
||||
INIT
|
||||
UTF8 1
|
||||
WANTSTATE s
|
||||
|
||||
!Linefeed
|
||||
PUSH "\n"x24
|
||||
?cursor = 24,0
|
||||
PUSH "\n"
|
||||
scrollrect 0..25,0..80 => +1,+0
|
||||
?cursor = 24,0
|
||||
|
||||
RESET
|
||||
|
||||
!Index
|
||||
PUSH "\e[25H"
|
||||
PUSH "\eD"
|
||||
scrollrect 0..25,0..80 => +1,+0
|
||||
|
||||
RESET
|
||||
|
||||
!Reverse Index
|
||||
PUSH "\eM"
|
||||
scrollrect 0..25,0..80 => -1,+0
|
||||
|
||||
RESET
|
||||
|
||||
!Linefeed in DECSTBM
|
||||
PUSH "\e[1;10r"
|
||||
?cursor = 0,0
|
||||
PUSH "\n"x9
|
||||
?cursor = 9,0
|
||||
PUSH "\n"
|
||||
scrollrect 0..10,0..80 => +1,+0
|
||||
?cursor = 9,0
|
||||
|
||||
!Linefeed outside DECSTBM
|
||||
PUSH "\e[20H"
|
||||
?cursor = 19,0
|
||||
PUSH "\n"
|
||||
?cursor = 20,0
|
||||
|
||||
!Index in DECSTBM
|
||||
PUSH "\e[10H"
|
||||
PUSH "\e[9;10r"
|
||||
PUSH "\eM"
|
||||
?cursor = 8,0
|
||||
PUSH "\eM"
|
||||
scrollrect 8..10,0..80 => -1,+0
|
||||
|
||||
!Reverse Index in DECSTBM
|
||||
PUSH "\e[25H"
|
||||
?cursor = 24,0
|
||||
PUSH "\n"
|
||||
# no scrollrect
|
||||
?cursor = 24,0
|
||||
|
||||
!Linefeed in DECSTBM+DECSLRM
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[3;10r\e[10;40s"
|
||||
PUSH "\e[10;10H\n"
|
||||
scrollrect 2..10,9..40 => +1,+0
|
||||
|
||||
!IND/RI in DECSTBM+DECSLRM
|
||||
PUSH "\eD"
|
||||
scrollrect 2..10,9..40 => +1,+0
|
||||
PUSH "\e[3;10H\eM"
|
||||
scrollrect 2..10,9..40 => -1,+0
|
||||
|
||||
!DECRQSS on DECSTBM
|
||||
PUSH "\eP\$qr\e\\"
|
||||
output "\eP1\$r3;10r\e\\"
|
||||
|
||||
!DECRQSS on DECSLRM
|
||||
PUSH "\eP\$qs\e\\"
|
||||
output "\eP1\$r10;40s\e\\"
|
||||
|
||||
!Setting invalid DECSLRM with !DECVSSM is still rejected
|
||||
PUSH "\e[?69l\e[;0s\e[?69h"
|
||||
|
||||
RESET
|
||||
|
||||
!Scroll Down
|
||||
PUSH "\e[S"
|
||||
scrollrect 0..25,0..80 => +1,+0
|
||||
?cursor = 0,0
|
||||
PUSH "\e[2S"
|
||||
scrollrect 0..25,0..80 => +2,+0
|
||||
?cursor = 0,0
|
||||
PUSH "\e[100S"
|
||||
scrollrect 0..25,0..80 => +25,+0
|
||||
|
||||
!Scroll Up
|
||||
PUSH "\e[T"
|
||||
scrollrect 0..25,0..80 => -1,+0
|
||||
?cursor = 0,0
|
||||
PUSH "\e[2T"
|
||||
scrollrect 0..25,0..80 => -2,+0
|
||||
?cursor = 0,0
|
||||
PUSH "\e[100T"
|
||||
scrollrect 0..25,0..80 => -25,+0
|
||||
|
||||
!SD/SU in DECSTBM
|
||||
PUSH "\e[5;20r"
|
||||
PUSH "\e[S"
|
||||
scrollrect 4..20,0..80 => +1,+0
|
||||
PUSH "\e[T"
|
||||
scrollrect 4..20,0..80 => -1,+0
|
||||
|
||||
RESET
|
||||
|
||||
!SD/SU in DECSTBM+DECSLRM
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[3;10r\e[10;40s"
|
||||
?cursor = 0,0
|
||||
PUSH "\e[3;10H"
|
||||
?cursor = 2,9
|
||||
PUSH "\e[S"
|
||||
scrollrect 2..10,9..40 => +1,+0
|
||||
PUSH "\e[?69l"
|
||||
PUSH "\e[S"
|
||||
scrollrect 2..10,0..80 => +1,+0
|
||||
|
||||
!Invalid boundaries
|
||||
RESET
|
||||
|
||||
PUSH "\e[100;105r\eD"
|
||||
PUSH "\e[5;2r\eD"
|
||||
|
||||
RESET
|
||||
WANTSTATE -s+me
|
||||
|
||||
!Scroll Down move+erase emulation
|
||||
PUSH "\e[S"
|
||||
moverect 1..25,0..80 -> 0..24,0..80
|
||||
erase 24..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "\e[2S"
|
||||
moverect 2..25,0..80 -> 0..23,0..80
|
||||
erase 23..25,0..80
|
||||
?cursor = 0,0
|
||||
|
||||
!Scroll Up move+erase emulation
|
||||
PUSH "\e[T"
|
||||
moverect 0..24,0..80 -> 1..25,0..80
|
||||
erase 0..1,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "\e[2T"
|
||||
moverect 0..23,0..80 -> 2..25,0..80
|
||||
erase 0..2,0..80
|
||||
?cursor = 0,0
|
||||
300
src/libvterm/t/13state_edit.test
Normal file
300
src/libvterm/t/13state_edit.test
Normal file
@@ -0,0 +1,300 @@
|
||||
INIT
|
||||
UTF8 1
|
||||
WANTSTATE se
|
||||
|
||||
!ICH
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "ACD"
|
||||
PUSH "\e[2D"
|
||||
?cursor = 0,1
|
||||
PUSH "\e[@"
|
||||
scrollrect 0..1,1..80 => +0,-1
|
||||
?cursor = 0,1
|
||||
PUSH "B"
|
||||
?cursor = 0,2
|
||||
PUSH "\e[3@"
|
||||
scrollrect 0..1,2..80 => +0,-3
|
||||
|
||||
!ICH with DECSLRM
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[;50s"
|
||||
PUSH "\e[20G\e[@"
|
||||
scrollrect 0..1,19..50 => +0,-1
|
||||
|
||||
!ICH outside DECSLRM
|
||||
PUSH "\e[70G\e[@"
|
||||
# nothing happens
|
||||
|
||||
!DCH
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "ABBC"
|
||||
PUSH "\e[3D"
|
||||
?cursor = 0,1
|
||||
PUSH "\e[P"
|
||||
scrollrect 0..1,1..80 => +0,+1
|
||||
?cursor = 0,1
|
||||
PUSH "\e[3P"
|
||||
scrollrect 0..1,1..80 => +0,+3
|
||||
?cursor = 0,1
|
||||
|
||||
!DCH with DECSLRM
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[;50s"
|
||||
PUSH "\e[20G\e[P"
|
||||
scrollrect 0..1,19..50 => +0,+1
|
||||
|
||||
!DCH outside DECSLRM
|
||||
PUSH "\e[70G\e[P"
|
||||
# nothing happens
|
||||
|
||||
!ECH
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "ABC"
|
||||
PUSH "\e[2D"
|
||||
?cursor = 0,1
|
||||
PUSH "\e[X"
|
||||
erase 0..1,1..2
|
||||
?cursor = 0,1
|
||||
PUSH "\e[3X"
|
||||
erase 0..1,1..4
|
||||
?cursor = 0,1
|
||||
# ECH more columns than there are should be bounded
|
||||
PUSH "\e[100X"
|
||||
erase 0..1,1..80
|
||||
|
||||
!IL
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "A\r\nC"
|
||||
?cursor = 1,1
|
||||
PUSH "\e[L"
|
||||
scrollrect 1..25,0..80 => -1,+0
|
||||
# TODO: ECMA-48 says we should move to line home, but neither xterm nor
|
||||
# xfce4-terminal do this
|
||||
?cursor = 1,1
|
||||
PUSH "\rB"
|
||||
?cursor = 1,1
|
||||
PUSH "\e[3L"
|
||||
scrollrect 1..25,0..80 => -3,+0
|
||||
|
||||
!IL with DECSTBM
|
||||
PUSH "\e[5;15r"
|
||||
PUSH "\e[5H\e[L"
|
||||
scrollrect 4..15,0..80 => -1,+0
|
||||
|
||||
!IL outside DECSTBM
|
||||
PUSH "\e[20H\e[L"
|
||||
# nothing happens
|
||||
|
||||
!IL with DECSTBM+DECSLRM
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[10;50s"
|
||||
PUSH "\e[5;10H\e[L"
|
||||
scrollrect 4..15,9..50 => -1,+0
|
||||
|
||||
!DL
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "A\r\nB\r\nB\r\nC"
|
||||
?cursor = 3,1
|
||||
PUSH "\e[2H"
|
||||
?cursor = 1,0
|
||||
PUSH "\e[M"
|
||||
scrollrect 1..25,0..80 => +1,+0
|
||||
?cursor = 1,0
|
||||
PUSH "\e[3M"
|
||||
scrollrect 1..25,0..80 => +3,+0
|
||||
?cursor = 1,0
|
||||
|
||||
!DL with DECSTBM
|
||||
PUSH "\e[5;15r"
|
||||
PUSH "\e[5H\e[M"
|
||||
scrollrect 4..15,0..80 => +1,+0
|
||||
|
||||
!DL outside DECSTBM
|
||||
PUSH "\e[20H\e[M"
|
||||
# nothing happens
|
||||
|
||||
!DL with DECSTBM+DECSLRM
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[10;50s"
|
||||
PUSH "\e[5;10H\e[M"
|
||||
scrollrect 4..15,9..50 => +1,+0
|
||||
|
||||
!DECIC
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
PUSH "\e[20G\e[5'}"
|
||||
scrollrect 0..25,19..80 => +0,-5
|
||||
|
||||
!DECIC with DECSTBM+DECSLRM
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[4;20r\e[20;60s"
|
||||
PUSH "\e[4;20H\e[3'}"
|
||||
scrollrect 3..20,19..60 => +0,-3
|
||||
|
||||
!DECIC outside DECSLRM
|
||||
PUSH "\e[70G\e['}"
|
||||
# nothing happens
|
||||
|
||||
!DECDC
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
PUSH "\e[20G\e[5'~"
|
||||
scrollrect 0..25,19..80 => +0,+5
|
||||
|
||||
!DECDC with DECSTBM+DECSLRM
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[4;20r\e[20;60s"
|
||||
PUSH "\e[4;20H\e[3'~"
|
||||
scrollrect 3..20,19..60 => +0,+3
|
||||
|
||||
!DECDC outside DECSLRM
|
||||
PUSH "\e[70G\e['~"
|
||||
# nothing happens
|
||||
|
||||
!EL 0
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "ABCDE"
|
||||
PUSH "\e[3D"
|
||||
?cursor = 0,2
|
||||
PUSH "\e[0K"
|
||||
erase 0..1,2..80
|
||||
?cursor = 0,2
|
||||
|
||||
!EL 1
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "ABCDE"
|
||||
PUSH "\e[3D"
|
||||
?cursor = 0,2
|
||||
PUSH "\e[1K"
|
||||
erase 0..1,0..3
|
||||
?cursor = 0,2
|
||||
|
||||
!EL 2
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "ABCDE"
|
||||
PUSH "\e[3D"
|
||||
?cursor = 0,2
|
||||
PUSH "\e[2K"
|
||||
erase 0..1,0..80
|
||||
?cursor = 0,2
|
||||
|
||||
!SEL
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "\e[11G"
|
||||
?cursor = 0,10
|
||||
PUSH "\e[?0K"
|
||||
erase 0..1,10..80 selective
|
||||
?cursor = 0,10
|
||||
PUSH "\e[?1K"
|
||||
erase 0..1,0..11 selective
|
||||
?cursor = 0,10
|
||||
PUSH "\e[?2K"
|
||||
erase 0..1,0..80 selective
|
||||
?cursor = 0,10
|
||||
|
||||
!ED 0
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "\e[2;2H"
|
||||
?cursor = 1,1
|
||||
PUSH "\e[0J"
|
||||
erase 1..2,1..80
|
||||
erase 2..25,0..80
|
||||
?cursor = 1,1
|
||||
|
||||
!ED 1
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "\e[2;2H"
|
||||
?cursor = 1,1
|
||||
PUSH "\e[1J"
|
||||
erase 0..1,0..80
|
||||
erase 1..2,0..2
|
||||
?cursor = 1,1
|
||||
|
||||
!ED 2
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "\e[2;2H"
|
||||
?cursor = 1,1
|
||||
PUSH "\e[2J"
|
||||
erase 0..25,0..80
|
||||
?cursor = 1,1
|
||||
|
||||
!SED
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
PUSH "\e[5;5H"
|
||||
?cursor = 4,4
|
||||
PUSH "\e[?0J"
|
||||
erase 4..5,4..80 selective
|
||||
erase 5..25,0..80 selective
|
||||
?cursor = 4,4
|
||||
PUSH "\e[?1J"
|
||||
erase 0..4,0..80 selective
|
||||
erase 4..5,0..5 selective
|
||||
?cursor = 4,4
|
||||
PUSH "\e[?2J"
|
||||
erase 0..25,0..80 selective
|
||||
?cursor = 4,4
|
||||
|
||||
!DECRQSS on DECSCA
|
||||
PUSH "\e[2\"q"
|
||||
PUSH "\eP\$q\"q\e\\"
|
||||
output "\eP1\$r2\"q\e\\"
|
||||
|
||||
WANTSTATE -s+m
|
||||
|
||||
!ICH move+erase emuation
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "ACD"
|
||||
PUSH "\e[2D"
|
||||
?cursor = 0,1
|
||||
PUSH "\e[@"
|
||||
moverect 0..1,1..79 -> 0..1,2..80
|
||||
erase 0..1,1..2
|
||||
?cursor = 0,1
|
||||
PUSH "B"
|
||||
?cursor = 0,2
|
||||
PUSH "\e[3@"
|
||||
moverect 0..1,2..77 -> 0..1,5..80
|
||||
erase 0..1,2..5
|
||||
|
||||
!DCH move+erase emulation
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "ABBC"
|
||||
PUSH "\e[3D"
|
||||
?cursor = 0,1
|
||||
PUSH "\e[P"
|
||||
moverect 0..1,2..80 -> 0..1,1..79
|
||||
erase 0..1,79..80
|
||||
?cursor = 0,1
|
||||
PUSH "\e[3P"
|
||||
moverect 0..1,4..80 -> 0..1,1..77
|
||||
erase 0..1,77..80
|
||||
?cursor = 0,1
|
||||
105
src/libvterm/t/14state_encoding.test
Normal file
105
src/libvterm/t/14state_encoding.test
Normal file
@@ -0,0 +1,105 @@
|
||||
INIT
|
||||
WANTSTATE g
|
||||
|
||||
!Default
|
||||
RESET
|
||||
PUSH "#"
|
||||
putglyph 0x23 1 0,0
|
||||
|
||||
!Designate G0=UK
|
||||
RESET
|
||||
PUSH "\e(A"
|
||||
PUSH "#"
|
||||
putglyph 0x00a3 1 0,0
|
||||
|
||||
!Designate G0=DEC drawing
|
||||
RESET
|
||||
PUSH "\e(0"
|
||||
PUSH "a"
|
||||
putglyph 0x2592 1 0,0
|
||||
|
||||
!Designate G1 + LS1
|
||||
RESET
|
||||
PUSH "\e)0"
|
||||
PUSH "a"
|
||||
putglyph 0x61 1 0,0
|
||||
PUSH "\x0e"
|
||||
PUSH "a"
|
||||
putglyph 0x2592 1 0,1
|
||||
!LS0
|
||||
PUSH "\x0f"
|
||||
PUSH "a"
|
||||
putglyph 0x61 1 0,2
|
||||
|
||||
!Designate G2 + LS2
|
||||
PUSH "\e*0"
|
||||
PUSH "a"
|
||||
putglyph 0x61 1 0,3
|
||||
PUSH "\en"
|
||||
PUSH "a"
|
||||
putglyph 0x2592 1 0,4
|
||||
PUSH "\x0f"
|
||||
PUSH "a"
|
||||
putglyph 0x61 1 0,5
|
||||
|
||||
!Designate G3 + LS3
|
||||
PUSH "\e+0"
|
||||
PUSH "a"
|
||||
putglyph 0x61 1 0,6
|
||||
PUSH "\eo"
|
||||
PUSH "a"
|
||||
putglyph 0x2592 1 0,7
|
||||
PUSH "\x0f"
|
||||
PUSH "a"
|
||||
putglyph 0x61 1 0,8
|
||||
|
||||
!SS2
|
||||
PUSH "a\x{8e}aa"
|
||||
putglyph 0x61 1 0,9
|
||||
putglyph 0x2592 1 0,10
|
||||
putglyph 0x61 1 0,11
|
||||
|
||||
!SS3
|
||||
PUSH "a\x{8f}aa"
|
||||
putglyph 0x61 1 0,12
|
||||
putglyph 0x2592 1 0,13
|
||||
putglyph 0x61 1 0,14
|
||||
|
||||
!LS1R
|
||||
RESET
|
||||
PUSH "\e~"
|
||||
PUSH "\xe1"
|
||||
putglyph 0x61 1 0,0
|
||||
PUSH "\e)0"
|
||||
PUSH "\xe1"
|
||||
putglyph 0x2592 1 0,1
|
||||
|
||||
!LS2R
|
||||
RESET
|
||||
PUSH "\e}"
|
||||
PUSH "\xe1"
|
||||
putglyph 0x61 1 0,0
|
||||
PUSH "\e*0"
|
||||
PUSH "\xe1"
|
||||
putglyph 0x2592 1 0,1
|
||||
|
||||
!LS3R
|
||||
RESET
|
||||
PUSH "\e|"
|
||||
PUSH "\xe1"
|
||||
putglyph 0x61 1 0,0
|
||||
PUSH "\e+0"
|
||||
PUSH "\xe1"
|
||||
putglyph 0x2592 1 0,1
|
||||
|
||||
UTF8 1
|
||||
|
||||
!Mixed US-ASCII and UTF-8
|
||||
# U+0108 == 0xc4 0x88
|
||||
RESET
|
||||
PUSH "\e(B"
|
||||
PUSH "AB\xc4\x88D"
|
||||
putglyph 0x0041 1 0,0
|
||||
putglyph 0x0042 1 0,1
|
||||
putglyph 0x0108 1 0,2
|
||||
putglyph 0x0044 1 0,3
|
||||
86
src/libvterm/t/15state_mode.test
Normal file
86
src/libvterm/t/15state_mode.test
Normal file
@@ -0,0 +1,86 @@
|
||||
INIT
|
||||
UTF8 1
|
||||
WANTSTATE gme
|
||||
|
||||
!Insert/Replace Mode
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "AC\e[DB"
|
||||
putglyph 0x41 1 0,0
|
||||
putglyph 0x43 1 0,1
|
||||
putglyph 0x42 1 0,1
|
||||
PUSH "\e[4h"
|
||||
PUSH "\e[G"
|
||||
PUSH "AC\e[DB"
|
||||
moverect 0..1,0..79 -> 0..1,1..80
|
||||
erase 0..1,0..1
|
||||
putglyph 0x41 1 0,0
|
||||
moverect 0..1,1..79 -> 0..1,2..80
|
||||
erase 0..1,1..2
|
||||
putglyph 0x43 1 0,1
|
||||
moverect 0..1,1..79 -> 0..1,2..80
|
||||
erase 0..1,1..2
|
||||
putglyph 0x42 1 0,1
|
||||
|
||||
!Insert mode only happens once for UTF-8 combining
|
||||
PUSH "e"
|
||||
moverect 0..1,2..79 -> 0..1,3..80
|
||||
erase 0..1,2..3
|
||||
putglyph 0x65 1 0,2
|
||||
PUSH "\xCC\x81"
|
||||
putglyph 0x65,0x301 1 0,2
|
||||
|
||||
!Newline/Linefeed mode
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "\e[5G\n"
|
||||
?cursor = 1,4
|
||||
PUSH "\e[20h"
|
||||
PUSH "\e[5G\n"
|
||||
?cursor = 2,0
|
||||
|
||||
!DEC origin mode
|
||||
RESET
|
||||
erase 0..25,0..80
|
||||
?cursor = 0,0
|
||||
PUSH "\e[5;15r"
|
||||
PUSH "\e[H"
|
||||
?cursor = 0,0
|
||||
PUSH "\e[3;3H"
|
||||
?cursor = 2,2
|
||||
PUSH "\e[?6h"
|
||||
PUSH "\e[H"
|
||||
?cursor = 4,0
|
||||
PUSH "\e[3;3H"
|
||||
?cursor = 6,2
|
||||
|
||||
!DECRQM on DECOM
|
||||
PUSH "\e[?6h"
|
||||
PUSH "\e[?6\$p"
|
||||
output "\e[?6;1\$y"
|
||||
PUSH "\e[?6l"
|
||||
PUSH "\e[?6\$p"
|
||||
output "\e[?6;2\$y"
|
||||
|
||||
!Origin mode with DECSLRM
|
||||
PUSH "\e[?6h"
|
||||
PUSH "\e[?69h"
|
||||
PUSH "\e[20;60s"
|
||||
PUSH "\e[H"
|
||||
?cursor = 4,19
|
||||
|
||||
PUSH "\e[?69l"
|
||||
|
||||
!Origin mode bounds cursor to scrolling region
|
||||
PUSH "\e[H"
|
||||
PUSH "\e[10A"
|
||||
?cursor = 4,0
|
||||
PUSH "\e[20B"
|
||||
?cursor = 14,0
|
||||
|
||||
!Origin mode without scroll region
|
||||
PUSH "\e[?6l"
|
||||
PUSH "\e[r\e[?6h"
|
||||
?cursor = 0,0
|
||||
48
src/libvterm/t/16state_resize.test
Normal file
48
src/libvterm/t/16state_resize.test
Normal file
@@ -0,0 +1,48 @@
|
||||
INIT
|
||||
WANTSTATE g
|
||||
|
||||
!Placement
|
||||
RESET
|
||||
PUSH "AB\e[79GCDE"
|
||||
putglyph 0x41 1 0,0
|
||||
putglyph 0x42 1 0,1
|
||||
putglyph 0x43 1 0,78
|
||||
putglyph 0x44 1 0,79
|
||||
putglyph 0x45 1 1,0
|
||||
|
||||
!Resize
|
||||
RESET
|
||||
RESIZE 27,85
|
||||
PUSH "AB\e[79GCDE"
|
||||
putglyph 0x41 1 0,0
|
||||
putglyph 0x42 1 0,1
|
||||
putglyph 0x43 1 0,78
|
||||
putglyph 0x44 1 0,79
|
||||
putglyph 0x45 1 0,80
|
||||
?cursor = 0,81
|
||||
|
||||
!Resize without reset
|
||||
RESIZE 28,90
|
||||
?cursor = 0,81
|
||||
PUSH "FGHI"
|
||||
putglyph 0x46 1 0,81
|
||||
putglyph 0x47 1 0,82
|
||||
putglyph 0x48 1 0,83
|
||||
putglyph 0x49 1 0,84
|
||||
?cursor = 0,85
|
||||
|
||||
!Resize shrink moves cursor
|
||||
RESIZE 25,80
|
||||
?cursor = 0,79
|
||||
|
||||
!Resize grow doesn't cancel phantom
|
||||
RESET
|
||||
PUSH "\e[79GAB"
|
||||
putglyph 0x41 1 0,78
|
||||
putglyph 0x42 1 0,79
|
||||
?cursor = 0,79
|
||||
RESIZE 30,100
|
||||
?cursor = 0,80
|
||||
PUSH "C"
|
||||
putglyph 0x43 1 0,80
|
||||
?cursor = 0,81
|
||||
172
src/libvterm/t/17state_mouse.test
Normal file
172
src/libvterm/t/17state_mouse.test
Normal file
@@ -0,0 +1,172 @@
|
||||
INIT
|
||||
WANTSTATE p
|
||||
|
||||
!DECRQM on with mouse off
|
||||
PUSH "\e[?1000\$p"
|
||||
output "\e[?1000;2\$y"
|
||||
PUSH "\e[?1002\$p"
|
||||
output "\e[?1002;2\$y"
|
||||
PUSH "\e[?1003\$p"
|
||||
output "\e[?1003;2\$y"
|
||||
|
||||
!Mouse in simple button report mode
|
||||
RESET
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
PUSH "\e[?1000h"
|
||||
settermprop 8 1
|
||||
|
||||
!Press 1
|
||||
MOUSEMOVE 0,0 0
|
||||
MOUSEBTN d 1 0
|
||||
output "\e[M\x20\x21\x21"
|
||||
|
||||
!Release 1
|
||||
MOUSEBTN u 1 0
|
||||
output "\e[M\x23\x21\x21"
|
||||
|
||||
!Ctrl-Press 1
|
||||
MOUSEBTN d 1 C
|
||||
output "\e[M\x30\x21\x21"
|
||||
MOUSEBTN u 1 C
|
||||
output "\e[M\x33\x21\x21"
|
||||
|
||||
!Button 2
|
||||
MOUSEBTN d 2 0
|
||||
output "\e[M\x21\x21\x21"
|
||||
MOUSEBTN u 2 0
|
||||
output "\e[M\x23\x21\x21"
|
||||
|
||||
!Position
|
||||
MOUSEMOVE 10,20 0
|
||||
MOUSEBTN d 1 0
|
||||
output "\e[M\x20\x35\x2b"
|
||||
|
||||
MOUSEBTN u 1 0
|
||||
output "\e[M\x23\x35\x2b"
|
||||
MOUSEMOVE 10,21 0
|
||||
# no output
|
||||
|
||||
!Wheel events
|
||||
MOUSEBTN d 4 0
|
||||
output "\e[M\x60\x36\x2b"
|
||||
MOUSEBTN d 4 0
|
||||
output "\e[M\x60\x36\x2b"
|
||||
MOUSEBTN d 5 0
|
||||
output "\e[M\x61\x36\x2b"
|
||||
|
||||
!DECRQM on mouse button mode
|
||||
PUSH "\e[?1000\$p"
|
||||
output "\e[?1000;1\$y"
|
||||
PUSH "\e[?1002\$p"
|
||||
output "\e[?1002;2\$y"
|
||||
PUSH "\e[?1003\$p"
|
||||
output "\e[?1003;2\$y"
|
||||
|
||||
!Drag events
|
||||
RESET
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
PUSH "\e[?1002h"
|
||||
settermprop 8 2
|
||||
|
||||
MOUSEMOVE 5,5 0
|
||||
MOUSEBTN d 1 0
|
||||
output "\e[M\x20\x26\x26"
|
||||
MOUSEMOVE 5,6 0
|
||||
output "\e[M\x40\x27\x26"
|
||||
MOUSEMOVE 6,6 0
|
||||
output "\e[M\x40\x27\x27"
|
||||
MOUSEMOVE 6,6 0
|
||||
# no output
|
||||
MOUSEBTN u 1 0
|
||||
output "\e[M\x23\x27\x27"
|
||||
MOUSEMOVE 6,7
|
||||
# no output
|
||||
|
||||
!DECRQM on mouse drag mode
|
||||
PUSH "\e[?1000\$p"
|
||||
output "\e[?1000;2\$y"
|
||||
PUSH "\e[?1002\$p"
|
||||
output "\e[?1002;1\$y"
|
||||
PUSH "\e[?1003\$p"
|
||||
output "\e[?1003;2\$y"
|
||||
|
||||
!Non-drag motion events
|
||||
PUSH "\e[?1003h"
|
||||
settermprop 8 3
|
||||
|
||||
MOUSEMOVE 6,8 0
|
||||
output "\e[M\x43\x29\x27"
|
||||
|
||||
!DECRQM on mouse motion mode
|
||||
PUSH "\e[?1000\$p"
|
||||
output "\e[?1000;2\$y"
|
||||
PUSH "\e[?1002\$p"
|
||||
output "\e[?1002;2\$y"
|
||||
PUSH "\e[?1003\$p"
|
||||
output "\e[?1003;1\$y"
|
||||
|
||||
!Bounds checking
|
||||
MOUSEMOVE 300,300 0
|
||||
output "\e[M\x43\xff\xff"
|
||||
MOUSEBTN d 1 0
|
||||
output "\e[M\x20\xff\xff"
|
||||
MOUSEBTN u 1 0
|
||||
output "\e[M\x23\xff\xff"
|
||||
|
||||
!DECRQM on standard encoding mode
|
||||
PUSH "\e[?1005\$p"
|
||||
output "\e[?1005;2\$y"
|
||||
PUSH "\e[?1006\$p"
|
||||
output "\e[?1006;2\$y"
|
||||
PUSH "\e[?1015\$p"
|
||||
output "\e[?1015;2\$y"
|
||||
|
||||
!UTF-8 extended encoding mode
|
||||
# 300 + 32 + 1 = 333 = U+014d = \xc5\x8d
|
||||
PUSH "\e[?1005h"
|
||||
MOUSEBTN d 1 0
|
||||
output "\e[M\x20\xc5\x8d\xc5\x8d"
|
||||
MOUSEBTN u 1 0
|
||||
output "\e[M\x23\xc5\x8d\xc5\x8d"
|
||||
|
||||
!DECRQM on UTF-8 extended encoding mode
|
||||
PUSH "\e[?1005\$p"
|
||||
output "\e[?1005;1\$y"
|
||||
PUSH "\e[?1006\$p"
|
||||
output "\e[?1006;2\$y"
|
||||
PUSH "\e[?1015\$p"
|
||||
output "\e[?1015;2\$y"
|
||||
|
||||
!SGR extended encoding mode
|
||||
PUSH "\e[?1006h"
|
||||
MOUSEBTN d 1 0
|
||||
output "\e[<0;301;301M"
|
||||
MOUSEBTN u 1 0
|
||||
output "\e[<0;301;301m"
|
||||
|
||||
!DECRQM on SGR extended encoding mode
|
||||
PUSH "\e[?1005\$p"
|
||||
output "\e[?1005;2\$y"
|
||||
PUSH "\e[?1006\$p"
|
||||
output "\e[?1006;1\$y"
|
||||
PUSH "\e[?1015\$p"
|
||||
output "\e[?1015;2\$y"
|
||||
|
||||
!rxvt extended encoding mode
|
||||
PUSH "\e[?1015h"
|
||||
MOUSEBTN d 1 0
|
||||
output "\e[0;301;301M"
|
||||
MOUSEBTN u 1 0
|
||||
output "\e[3;301;301M"
|
||||
|
||||
!DECRQM on rxvt extended encoding mode
|
||||
PUSH "\e[?1005\$p"
|
||||
output "\e[?1005;2\$y"
|
||||
PUSH "\e[?1006\$p"
|
||||
output "\e[?1006;2\$y"
|
||||
PUSH "\e[?1015\$p"
|
||||
output "\e[?1015;1\$y"
|
||||
36
src/libvterm/t/18state_termprops.test
Normal file
36
src/libvterm/t/18state_termprops.test
Normal file
@@ -0,0 +1,36 @@
|
||||
INIT
|
||||
WANTSTATE p
|
||||
|
||||
RESET
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
|
||||
!Cursor visibility
|
||||
PUSH "\e[?25h"
|
||||
settermprop 1 true
|
||||
PUSH "\e[?25\$p"
|
||||
output "\e[?25;1\$y"
|
||||
PUSH "\e[?25l"
|
||||
settermprop 1 false
|
||||
PUSH "\e[?25\$p"
|
||||
output "\e[?25;2\$y"
|
||||
|
||||
!Cursor blink
|
||||
PUSH "\e[?12h"
|
||||
settermprop 2 true
|
||||
PUSH "\e[?12\$p"
|
||||
output "\e[?12;1\$y"
|
||||
PUSH "\e[?12l"
|
||||
settermprop 2 false
|
||||
PUSH "\e[?12\$p"
|
||||
output "\e[?12;2\$y"
|
||||
|
||||
!Cursor shape
|
||||
PUSH "\e[3 q"
|
||||
settermprop 2 true
|
||||
settermprop 7 2
|
||||
|
||||
!Title
|
||||
PUSH "\e]2;Here is my title\a"
|
||||
settermprop 4 "Here is my title"
|
||||
69
src/libvterm/t/20state_wrapping.test
Normal file
69
src/libvterm/t/20state_wrapping.test
Normal file
@@ -0,0 +1,69 @@
|
||||
INIT
|
||||
UTF8 1
|
||||
WANTSTATE gm
|
||||
|
||||
!79th Column
|
||||
PUSH "\e[75G"
|
||||
PUSH "A"x5
|
||||
putglyph 0x41 1 0,74
|
||||
putglyph 0x41 1 0,75
|
||||
putglyph 0x41 1 0,76
|
||||
putglyph 0x41 1 0,77
|
||||
putglyph 0x41 1 0,78
|
||||
?cursor = 0,79
|
||||
|
||||
!80th Column Phantom
|
||||
PUSH "A"
|
||||
putglyph 0x41 1 0,79
|
||||
?cursor = 0,79
|
||||
|
||||
!Line Wraparound
|
||||
PUSH "B"
|
||||
putglyph 0x42 1 1,0
|
||||
?cursor = 1,1
|
||||
|
||||
!Line Wraparound during combined write
|
||||
PUSH "\e[78G"
|
||||
PUSH "BBBCC"
|
||||
putglyph 0x42 1 1,77
|
||||
putglyph 0x42 1 1,78
|
||||
putglyph 0x42 1 1,79
|
||||
putglyph 0x43 1 2,0
|
||||
putglyph 0x43 1 2,1
|
||||
?cursor = 2,2
|
||||
|
||||
!DEC Auto Wrap Mode
|
||||
RESET
|
||||
PUSH "\e[?7l"
|
||||
PUSH "\e[75G"
|
||||
PUSH "D"x6
|
||||
putglyph 0x44 1 0,74
|
||||
putglyph 0x44 1 0,75
|
||||
putglyph 0x44 1 0,76
|
||||
putglyph 0x44 1 0,77
|
||||
putglyph 0x44 1 0,78
|
||||
putglyph 0x44 1 0,79
|
||||
?cursor = 0,79
|
||||
PUSH "D"
|
||||
putglyph 0x44 1 0,79
|
||||
?cursor = 0,79
|
||||
PUSH "\e[?7h"
|
||||
|
||||
!80th column causes linefeed on wraparound
|
||||
PUSH "\e[25;78HABC"
|
||||
putglyph 0x41 1 24,77
|
||||
putglyph 0x42 1 24,78
|
||||
putglyph 0x43 1 24,79
|
||||
?cursor = 24,79
|
||||
PUSH "D"
|
||||
moverect 1..25,0..80 -> 0..24,0..80
|
||||
putglyph 0x44 1 24,0
|
||||
|
||||
!80th column phantom linefeed phantom cancelled by explicit cursor move
|
||||
PUSH "\e[25;78HABC"
|
||||
putglyph 0x41 1 24,77
|
||||
putglyph 0x42 1 24,78
|
||||
putglyph 0x43 1 24,79
|
||||
?cursor = 24,79
|
||||
PUSH "\e[25;1HD"
|
||||
putglyph 0x44 1 24,0
|
||||
60
src/libvterm/t/21state_tabstops.test
Normal file
60
src/libvterm/t/21state_tabstops.test
Normal file
@@ -0,0 +1,60 @@
|
||||
INIT
|
||||
WANTSTATE g
|
||||
|
||||
!Initial
|
||||
RESET
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,8
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,16
|
||||
?cursor = 0,17
|
||||
|
||||
!HTS
|
||||
PUSH "\e[5G\eH"
|
||||
PUSH "\e[G\tX"
|
||||
putglyph 0x58 1 0,4
|
||||
?cursor = 0,5
|
||||
|
||||
!TBC 0
|
||||
PUSH "\e[9G\e[g"
|
||||
PUSH "\e[G\tX\tX"
|
||||
putglyph 0x58 1 0,4
|
||||
putglyph 0x58 1 0,16
|
||||
?cursor = 0,17
|
||||
|
||||
!TBC 3
|
||||
PUSH "\e[3g\e[50G\eH\e[G"
|
||||
?cursor = 0,0
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,49
|
||||
?cursor = 0,50
|
||||
|
||||
!Tabstops after resize
|
||||
RESET
|
||||
RESIZE 30,100
|
||||
# Should be 100/8 = 12 tabstops
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,8
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,16
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,24
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,32
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,40
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,48
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,56
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,64
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,72
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,80
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,88
|
||||
PUSH "\tX"
|
||||
putglyph 0x58 1 0,96
|
||||
?cursor = 0,97
|
||||
64
src/libvterm/t/22state_save.test
Normal file
64
src/libvterm/t/22state_save.test
Normal file
@@ -0,0 +1,64 @@
|
||||
INIT
|
||||
WANTSTATE p
|
||||
|
||||
RESET
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
|
||||
!Set up state
|
||||
PUSH "\e[2;2H"
|
||||
?cursor = 1,1
|
||||
PUSH "\e[1m"
|
||||
?pen bold = on
|
||||
|
||||
!Save
|
||||
PUSH "\e[?1048h"
|
||||
|
||||
!Change state
|
||||
PUSH "\e[5;5H"
|
||||
?cursor = 4,4
|
||||
PUSH "\e[4 q"
|
||||
settermprop 2 false
|
||||
settermprop 7 2
|
||||
PUSH "\e[22;4m"
|
||||
?pen bold = off
|
||||
?pen underline = 1
|
||||
|
||||
!Restore
|
||||
PUSH "\e[?1048l"
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
?cursor = 1,1
|
||||
?pen bold = on
|
||||
?pen underline = 0
|
||||
|
||||
!Save/restore using DECSC/DECRC
|
||||
PUSH "\e[2;2H\e7"
|
||||
?cursor = 1,1
|
||||
|
||||
PUSH "\e[5;5H"
|
||||
?cursor = 4,4
|
||||
PUSH "\e8"
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
?cursor = 1,1
|
||||
|
||||
!Save twice, restore twice happens on both edge transitions
|
||||
PUSH "\e[2;10H\e[?1048h\e[6;10H\e[?1048h"
|
||||
PUSH "\e[H"
|
||||
?cursor = 0,0
|
||||
PUSH "\e[?1048l"
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
?cursor = 5,9
|
||||
PUSH "\e[H"
|
||||
?cursor = 0,0
|
||||
PUSH "\e[?1048l"
|
||||
settermprop 1 true
|
||||
settermprop 2 true
|
||||
settermprop 7 1
|
||||
?cursor = 5,9
|
||||
132
src/libvterm/t/25state_input.test
Normal file
132
src/libvterm/t/25state_input.test
Normal file
@@ -0,0 +1,132 @@
|
||||
INIT
|
||||
WANTSTATE
|
||||
|
||||
!Unmodified ASCII
|
||||
INCHAR 0 41
|
||||
output "A"
|
||||
INCHAR 0 61
|
||||
output "a"
|
||||
|
||||
!Ctrl modifier on ASCII letters
|
||||
INCHAR C 41
|
||||
output "\e[65;5u"
|
||||
INCHAR C 61
|
||||
output "\x01"
|
||||
|
||||
!Alt modifier on ASCII letters
|
||||
INCHAR A 41
|
||||
output "\eA"
|
||||
INCHAR A 61
|
||||
output "\ea"
|
||||
|
||||
!Ctrl-Alt modifier on ASCII letters
|
||||
INCHAR CA 41
|
||||
output "\e[65;7u"
|
||||
INCHAR CA 61
|
||||
output "\e\x01"
|
||||
|
||||
!Special handling of Ctrl-I
|
||||
INCHAR 0 49
|
||||
output "I"
|
||||
INCHAR 0 69
|
||||
output "i"
|
||||
INCHAR C 49
|
||||
output "\e[73;5u"
|
||||
INCHAR C 69
|
||||
output "\e[105;5u"
|
||||
INCHAR A 49
|
||||
output "\eI"
|
||||
INCHAR A 69
|
||||
output "\ei"
|
||||
INCHAR CA 49
|
||||
output "\e[73;7u"
|
||||
INCHAR CA 69
|
||||
output "\e[105;7u"
|
||||
|
||||
!Special handling of Space
|
||||
INCHAR 0 20
|
||||
output " "
|
||||
INCHAR S 20
|
||||
output "\e[32;2u"
|
||||
INCHAR C 20
|
||||
output "\0"
|
||||
INCHAR SC 20
|
||||
output "\e[32;6u"
|
||||
INCHAR A 20
|
||||
output "\e "
|
||||
INCHAR SA 20
|
||||
output "\e[32;4u"
|
||||
INCHAR CA 20
|
||||
output "\e\0"
|
||||
INCHAR SCA 20
|
||||
output "\e[32;8u"
|
||||
|
||||
!Cursor keys in reset (cursor) mode
|
||||
INKEY 0 Up
|
||||
output "\e[A"
|
||||
INKEY S Up
|
||||
output "\e[1;2A"
|
||||
INKEY C Up
|
||||
output "\e[1;5A"
|
||||
INKEY SC Up
|
||||
output "\e[1;6A"
|
||||
INKEY A Up
|
||||
output "\e[1;3A"
|
||||
INKEY SA Up
|
||||
output "\e[1;4A"
|
||||
INKEY CA Up
|
||||
output "\e[1;7A"
|
||||
INKEY SCA Up
|
||||
output "\e[1;8A"
|
||||
|
||||
!Cursor keys in application mode
|
||||
PUSH "\e[?1h"
|
||||
# Plain "Up" should be SS3 A now
|
||||
INKEY 0 Up
|
||||
output "\eOA"
|
||||
# Modified keys should still use CSI
|
||||
INKEY S Up
|
||||
output "\e[1;2A"
|
||||
INKEY C Up
|
||||
output "\e[1;5A"
|
||||
|
||||
!Shift-Tab should be different
|
||||
INKEY 0 Tab
|
||||
output "\x09"
|
||||
INKEY S Tab
|
||||
output "\e[Z"
|
||||
INKEY C Tab
|
||||
output "\e[9;5u"
|
||||
INKEY A Tab
|
||||
output "\e\x09"
|
||||
INKEY CA Tab
|
||||
output "\e[9;7u"
|
||||
|
||||
!Enter in linefeed mode
|
||||
INKEY 0 Enter
|
||||
output "\x0d"
|
||||
|
||||
!Enter in newline mode
|
||||
PUSH "\e[20h"
|
||||
INKEY 0 Enter
|
||||
output "\x0d\x0a"
|
||||
|
||||
!Keypad in DECKPNM
|
||||
INKEY 0 KP0
|
||||
output "0"
|
||||
|
||||
!Keypad in DECKPAM
|
||||
PUSH "\e="
|
||||
INKEY 0 KP0
|
||||
output "\eOp"
|
||||
|
||||
!Bracketed paste mode off
|
||||
PASTE START
|
||||
PASTE END
|
||||
|
||||
!Bracketed paste mode on
|
||||
PUSH "\e[?2004h"
|
||||
PASTE START
|
||||
output "\e[200~"
|
||||
PASTE END
|
||||
output "\e[201~"
|
||||
62
src/libvterm/t/26state_query.test
Normal file
62
src/libvterm/t/26state_query.test
Normal file
@@ -0,0 +1,62 @@
|
||||
INIT
|
||||
WANTSTATE
|
||||
|
||||
!DA
|
||||
RESET
|
||||
PUSH "\e[c"
|
||||
output "\e[?1;2c"
|
||||
|
||||
!DSR
|
||||
RESET
|
||||
PUSH "\e[5n"
|
||||
output "\e[0n"
|
||||
|
||||
!CPR
|
||||
PUSH "\e[6n"
|
||||
output "\e[1;1R"
|
||||
PUSH "\e[10;10H\e[6n"
|
||||
output "\e[10;10R"
|
||||
|
||||
!DECCPR
|
||||
PUSH "\e[?6n"
|
||||
output "\e[?10;10R"
|
||||
|
||||
!DECRQSS on DECSCUSR
|
||||
PUSH "\e[3 q"
|
||||
PUSH "\eP\$q q\e\\"
|
||||
output "\eP1\$r3 q\e\\"
|
||||
|
||||
!DECRQSS on SGR
|
||||
PUSH "\e[1;5;7m"
|
||||
PUSH "\eP\$qm\e\\"
|
||||
output "\eP1\$r1;5;7m\e\\"
|
||||
|
||||
!DECRQSS on SGR ANSI colours
|
||||
PUSH "\e[0;31;42m"
|
||||
PUSH "\eP\$qm\e\\"
|
||||
output "\eP1\$r31;42m\e\\"
|
||||
|
||||
!DECRQSS on SGR ANSI hi-bright colours
|
||||
PUSH "\e[0;93;104m"
|
||||
PUSH "\eP\$qm\e\\"
|
||||
output "\eP1\$r93;104m\e\\"
|
||||
|
||||
!DECRQSS on SGR 256-palette colours
|
||||
PUSH "\e[0;38:5:56;48:5:78m"
|
||||
PUSH "\eP\$qm\e\\"
|
||||
output "\eP1\$r38:5:56;48:5:78m\e\\"
|
||||
|
||||
!DECRQSS on SGR RGB8 colours
|
||||
PUSH "\e[0;38:2:24:68:112;48:2:13:57:101m"
|
||||
PUSH "\eP\$qm\e\\"
|
||||
output "\eP1\$r38:2:24:68:112;48:2:13:57:101m\e\\"
|
||||
|
||||
!S8C1T on DSR
|
||||
PUSH "\e G"
|
||||
PUSH "\e[5n"
|
||||
output "\x{9b}0n"
|
||||
PUSH "\e F"
|
||||
|
||||
!Truncation on attempted buffer overflow
|
||||
PUSH "\e[6n" x 20
|
||||
output "\e[10;10R" x 7
|
||||
32
src/libvterm/t/27state_reset.test
Normal file
32
src/libvterm/t/27state_reset.test
Normal file
@@ -0,0 +1,32 @@
|
||||
INIT
|
||||
WANTSTATE
|
||||
|
||||
RESET
|
||||
|
||||
!RIS homes cursor
|
||||
PUSH "\e[5;5H"
|
||||
?cursor = 4,4
|
||||
WANTSTATE +m
|
||||
PUSH "\ec"
|
||||
?cursor = 0,0
|
||||
WANTSTATE -m
|
||||
|
||||
!RIS cancels scrolling region
|
||||
PUSH "\e[5;10r"
|
||||
WANTSTATE +s
|
||||
PUSH "\ec\e[25H\n"
|
||||
scrollrect 0..25,0..80 => +1,+0
|
||||
WANTSTATE -s
|
||||
|
||||
!RIS erases screen
|
||||
PUSH "ABCDE"
|
||||
WANTSTATE +e
|
||||
PUSH "\ec"
|
||||
erase 0..25,0..80
|
||||
WANTSTATE -e
|
||||
|
||||
!RIS clears tabstops
|
||||
PUSH "\e[5G\eH\e[G\t"
|
||||
?cursor = 0,4
|
||||
PUSH "\ec\t"
|
||||
?cursor = 0,8
|
||||
61
src/libvterm/t/28state_dbl_wh.test
Normal file
61
src/libvterm/t/28state_dbl_wh.test
Normal file
@@ -0,0 +1,61 @@
|
||||
INIT
|
||||
WANTSTATE g
|
||||
|
||||
!Single Width, Single Height
|
||||
RESET
|
||||
PUSH "\e#5"
|
||||
PUSH "Hello"
|
||||
putglyph 0x48 1 0,0
|
||||
putglyph 0x65 1 0,1
|
||||
putglyph 0x6c 1 0,2
|
||||
putglyph 0x6c 1 0,3
|
||||
putglyph 0x6f 1 0,4
|
||||
|
||||
!Double Width, Single Height
|
||||
RESET
|
||||
PUSH "\e#6"
|
||||
PUSH "Hello"
|
||||
putglyph 0x48 1 0,0 dwl
|
||||
putglyph 0x65 1 0,1 dwl
|
||||
putglyph 0x6c 1 0,2 dwl
|
||||
putglyph 0x6c 1 0,3 dwl
|
||||
putglyph 0x6f 1 0,4 dwl
|
||||
?cursor = 0,5
|
||||
PUSH "\e[40GAB"
|
||||
putglyph 0x41 1 0,39 dwl
|
||||
putglyph 0x42 1 1,0
|
||||
?cursor = 1,1
|
||||
|
||||
!Double Height
|
||||
RESET
|
||||
PUSH "\e#3"
|
||||
PUSH "Hello"
|
||||
putglyph 0x48 1 0,0 dwl dhl-top
|
||||
putglyph 0x65 1 0,1 dwl dhl-top
|
||||
putglyph 0x6c 1 0,2 dwl dhl-top
|
||||
putglyph 0x6c 1 0,3 dwl dhl-top
|
||||
putglyph 0x6f 1 0,4 dwl dhl-top
|
||||
?cursor = 0,5
|
||||
PUSH "\r\n\e#4"
|
||||
PUSH "Hello"
|
||||
putglyph 0x48 1 1,0 dwl dhl-bottom
|
||||
putglyph 0x65 1 1,1 dwl dhl-bottom
|
||||
putglyph 0x6c 1 1,2 dwl dhl-bottom
|
||||
putglyph 0x6c 1 1,3 dwl dhl-bottom
|
||||
putglyph 0x6f 1 1,4 dwl dhl-bottom
|
||||
?cursor = 1,5
|
||||
|
||||
!Double Width scrolling
|
||||
RESET
|
||||
PUSH "\e[20H\e#6ABC"
|
||||
putglyph 0x41 1 19,0 dwl
|
||||
putglyph 0x42 1 19,1 dwl
|
||||
putglyph 0x43 1 19,2 dwl
|
||||
PUSH "\e[25H\n"
|
||||
PUSH "\e[19;4HDE"
|
||||
putglyph 0x44 1 18,3 dwl
|
||||
putglyph 0x45 1 18,4 dwl
|
||||
PUSH "\e[H\eM"
|
||||
PUSH "\e[20;6HFG"
|
||||
putglyph 0x46 1 19,5 dwl
|
||||
putglyph 0x47 1 19,6 dwl
|
||||
19
src/libvterm/t/29state_fallback.test
Normal file
19
src/libvterm/t/29state_fallback.test
Normal file
@@ -0,0 +1,19 @@
|
||||
INIT
|
||||
WANTSTATE f
|
||||
RESET
|
||||
|
||||
!Unrecognised control
|
||||
PUSH "\x03"
|
||||
control 03
|
||||
|
||||
!Unrecognised CSI
|
||||
PUSH "\e[?15;2z"
|
||||
csi 0x7a L=3f 15,2
|
||||
|
||||
!Unrecognised OSC
|
||||
PUSH "\e]27;Something\e\\"
|
||||
osc "27;Something"
|
||||
|
||||
!Unrecognised DCS
|
||||
PUSH "\ePz123\e\\"
|
||||
dcs "z123"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user