aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--codecov.yml2
-rw-r--r--runtime/doc/eval.txt42
-rw-r--r--src/nvim/api/ui.c3
-rw-r--r--src/nvim/digraph.c37
-rw-r--r--src/nvim/eval.c9
-rw-r--r--src/nvim/event/defs.h2
-rw-r--r--src/nvim/quickfix.c189
-rw-r--r--src/nvim/screen.c57
-rw-r--r--src/nvim/testdir/test_fold.vim14
-rw-r--r--src/nvim/testdir/test_quickfix.vim123
-rw-r--r--src/nvim/tui/tui.c18
-rw-r--r--src/nvim/ui.c39
-rw-r--r--src/nvim/ui.h2
-rw-r--r--src/nvim/ui_bridge.c12
-rw-r--r--test/functional/ex_cmds/digraphs_spec.lua14
15 files changed, 371 insertions, 192 deletions
diff --git a/codecov.yml b/codecov.yml
index dbcb0c16ca..481eea89ee 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -14,7 +14,7 @@ coverage:
status:
project: yes
patch: yes
- changes: yes
+ changes: no
parsers:
gcov:
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 1ebc1bc652..064c08c190 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -4335,23 +4335,39 @@ 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()|
+ efm errorformat to use when parsing "lines". If
+ not present, then the 'erroformat' option
+ value is used.
+ id get information for the quickfix list with
+ |quickfix-ID|; zero means the id for the
+ current list or the list specifed by "nr"
items quickfix list entries
+ lines use 'errorformat' to extract items from a list
+ of lines and return the resulting entries.
+ Only a |List| type is accepted. The current
+ quickfix list is not modified.
nr get information for this quickfix list; zero
- means the current quickfix list and '$' means
+ means the current quickfix list and "$" means
the last quickfix list
title get the list title
winid get the |window-ID| (if opened)
all all of the above quickfix properties
Non-string items in {what} are ignored.
If "nr" is not present then the current quickfix list is used.
+ If both "nr" and a non-zero "id" are specified, then the list
+ specified by "id" is used.
To get the number of lists in the quickfix stack, set 'nr' to
'$' in {what}. The 'nr' value in the returned dictionary
contains the quickfix stack size.
+ When 'text' is specified, all the other items are ignored. The
+ returned dictionary contains the entry 'items' with the list
+ of entries.
In case of error processing {what}, an empty dictionary is
returned.
The returned dictionary contains the following entries:
context context information stored with |setqflist()|
+ id quickfix list ID |quickfix-ID|
items quickfix list entries
nr quickfix list number
title quickfix list title text
@@ -4360,6 +4376,7 @@ getqflist([{what}]) *getqflist()*
Examples: >
:echo getqflist({'all': 1})
:echo getqflist({'nr': 2, 'title': 1})
+ :echo getqflist({'lines' : ["F1:10:L10"]})
<
getreg([{regname} [, 1 [, {list}]]]) *getreg()*
@@ -6904,7 +6921,7 @@ setqflist({list} [, {action}[, {what}]]) *setqflist()*
is created. The new quickfix list is added after the current
quickfix list in the stack and all the following lists are
freed. To add a new quickfix list at the end of the stack,
- set "nr" in {what} to '$'.
+ set "nr" in {what} to "$".
If {title} is given, it will be used to set |w:quickfix_title|
after opening the quickfix window.
@@ -6914,24 +6931,31 @@ 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
- text use 'errorformat' to extract items from the
- text and add the resulting entries to the
- quickfix list {nr}. The value can be a string
- with one line or a list with multiple lines.
+ efm errorformat to use when parsing text from
+ "lines". If this is not present, then the
+ 'errorformat' option value is used.
+ id quickfix list identifier |quickfix-ID|
items list of quickfix entries. Same as the {list}
argument.
+ lines use 'errorformat' to parse a list of lines and
+ add the resulting entries to the quickfix list
+ {nr} or {id}. Only a |List| value is supported.
nr list number in the quickfix stack; zero
- means the current quickfix list and '$' means
+ 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. When creating a new quickfix list, "nr" can be
set to a value one greater than the quickfix stack size.
+ When modifying a quickfix list, to guarantee that the correct
+ list is modified, "id" should be used instead of "nr" to
+ specify the list.
Examples: >
- :call setqflist([], 'r', {'title': 'My search'})
- :call setqflist([], 'r', {'nr': 2, 'title': 'Errors'})
+ :call setqflist([], 'r', {'title': 'My search'})
+ :call setqflist([], 'r', {'nr': 2, 'title': 'Errors'})
+ :call setqflist([], 'a', {'id':myid, 'lines':["F1:10:L10"]})
<
Returns zero for success, -1 for failure.
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 76e3927820..509032892b 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -424,7 +424,8 @@ static void remote_ui_put(UI *ui, const char *cell)
static void remote_ui_raw_line(UI *ui, Integer grid, Integer row,
Integer startcol, Integer endcol,
Integer clearcol, Integer clearattr,
- const schar_T *chunk, const sattr_T *attrs)
+ Boolean wrap, const schar_T *chunk,
+ const sattr_T *attrs)
{
UIData *data = ui->data;
if (ui->ui_ext[kUINewgrid]) {
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index c0915224e5..8f7487262e 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -1359,6 +1359,12 @@ static digr_T digraphdefault[] =
{ 'f', 't', 0xfb05 },
{ 's', 't', 0xfb06 },
+ // extra alternatives, easier to remember
+ { 'W', '`', 0x1e80 },
+ { 'w', '`', 0x1e81 },
+ { 'Y', '`', 0x1ef2 },
+ { 'y', '`', 0x1ef3 },
+
// Vim 5.x compatible digraphs that don't conflict with the above
{ '~', '!', 161 }, //
{ 'c', '|', 162 }, //
@@ -1520,34 +1526,6 @@ static int getexactdigraph(int char1, int char2, int meta_char)
}
}
- if ((retval != 0) && !enc_utf8) {
- char_u buf[6], *to;
- vimconv_T vc;
-
- // Convert the Unicode digraph to 'encoding'.
- int i = utf_char2bytes(retval, buf);
- retval = 0;
- vc.vc_type = CONV_NONE;
-
- if (convert_setup(&vc, (char_u *)"utf-8", p_enc) == OK) {
- vc.vc_fail = true;
- assert(i >= 0);
- size_t len = (size_t)i;
- to = string_convert(&vc, buf, &len);
-
- if (to != NULL) {
- retval = utf_ptr2char(to);
- xfree(to);
- }
- (void)convert_setup(&vc, NULL, NULL);
- }
- }
-
- // Ignore multi-byte characters when not in multi-byte mode.
- if (!has_mbyte && (retval > 0xff)) {
- retval = 0;
- }
-
if (retval == 0) {
// digraph deleted or not found
if ((char1 == ' ') && meta_char) {
@@ -1654,8 +1632,7 @@ void listdigraphs(void)
tmp.result = getexactdigraph(tmp.char1, tmp.char2, FALSE);
if ((tmp.result != 0)
- && (tmp.result != tmp.char2)
- && (has_mbyte || (tmp.result <= 255))) {
+ && (tmp.result != tmp.char2)) {
printdigraph(&tmp);
}
dp++;
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index d750a47588..541a255dcc 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -8872,9 +8872,14 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
char_u buf[FOLD_TEXT_LEN];
foldinfo_T foldinfo;
int fold_count;
+ static bool entered = false;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
+ if (entered) {
+ return; // reject recursive use
+ }
+ entered = true;
linenr_T lnum = tv_get_lnum(argvars);
// Treat illegal types and illegal string values for {lnum} the same.
if (lnum < 0) {
@@ -8888,6 +8893,8 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
rettv->vval.v_string = text;
}
+
+ entered = false;
}
/*
@@ -9943,7 +9950,7 @@ static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg,
if (what_arg->v_type == VAR_UNKNOWN) {
tv_list_alloc_ret(rettv, kListLenMayKnow);
if (is_qf || wp != NULL) {
- (void)get_errorlist(wp, -1, rettv->vval.v_list);
+ (void)get_errorlist(NULL, wp, -1, rettv->vval.v_list);
}
} else {
tv_dict_alloc_ret(rettv);
diff --git a/src/nvim/event/defs.h b/src/nvim/event/defs.h
index 55b2d277bb..fdd4f17d5c 100644
--- a/src/nvim/event/defs.h
+++ b/src/nvim/event/defs.h
@@ -4,7 +4,7 @@
#include <assert.h>
#include <stdarg.h>
-#define EVENT_HANDLER_MAX_ARGC 9
+#define EVENT_HANDLER_MAX_ARGC 10
typedef void (*argv_callback)(void **argv);
typedef struct message {
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 263b8b3a77..ba2f2ba969 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -82,6 +82,7 @@ struct qfline_S {
/// created using setqflist()/setloclist() with a title and/or user context
/// information and entries can be added later using setqflist()/setloclist().
typedef struct qf_list_S {
+ unsigned qf_id; ///< Unique identifier for this list
qfline_T *qf_start; ///< pointer to the first error
qfline_T *qf_last; ///< pointer to the last error
qfline_T *qf_ptr; ///< pointer to the current error
@@ -116,7 +117,8 @@ struct qf_info_S {
qf_list_T qf_lists[LISTCOUNT];
};
-static qf_info_T ql_info; /* global quickfix list */
+static qf_info_T ql_info; // global quickfix list
+static unsigned last_qf_id = 0; // Last Used quickfix list id
#define FMT_PATTERNS 10 /* maximum number of % recognized */
@@ -1224,6 +1226,7 @@ static void qf_new_list(qf_info_T *qi, char_u *qf_title)
qi->qf_curlist = qi->qf_listcount++;
memset(&qi->qf_lists[qi->qf_curlist], 0, (size_t)(sizeof(qf_list_T)));
qf_store_title(qi, qi->qf_curlist, qf_title);
+ qi->qf_lists[qi->qf_curlist].qf_id = ++last_qf_id;
}
/*
@@ -1467,6 +1470,9 @@ void copy_loclist(win_T *from, win_T *to)
to_qfl->qf_index = from_qfl->qf_index; /* current index in the list */
+ // Assign a new ID for the location list
+ to_qfl->qf_id = ++last_qf_id;
+
/* When no valid entries are present in the list, qf_ptr points to
* the first item in the list */
if (to_qfl->qf_nonevalid) {
@@ -2414,7 +2420,7 @@ static void qf_free_items(qf_info_T *qi, int idx)
while (qfl->qf_count && qfl->qf_start != NULL) {
qfp = qfl->qf_start;
qfpnext = qfp->qf_next;
- if (qfl->qf_title != NULL && !stop) {
+ if (!stop) {
xfree(qfp->qf_text);
stop = (qfp == qfpnext);
xfree(qfp->qf_pattern);
@@ -2458,6 +2464,7 @@ static void qf_free(qf_info_T *qi, int idx)
qfl->qf_title = NULL;
tv_free(qfl->qf_ctx);
qfl->qf_ctx = NULL;
+ qfl->qf_id = 0;
}
/*
@@ -4031,18 +4038,22 @@ static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start)
/// Add each quickfix error to list "list" as a dictionary.
/// If qf_idx is -1, use the current list. Otherwise, use the specified list.
-int get_errorlist(win_T *wp, int qf_idx, list_T *list)
+int get_errorlist(const qf_info_T *qi_arg, win_T *wp, int qf_idx, list_T *list)
{
- qf_info_T *qi = &ql_info;
+ const qf_info_T *qi = qi_arg;
char_u buf[2];
qfline_T *qfp;
int i;
int bufnum;
- if (wp != NULL) {
- qi = GET_LOC_LIST(wp);
- if (qi == NULL)
- return FAIL;
+ if (qi == NULL) {
+ qi = &ql_info;
+ if (wp != NULL) {
+ qi = GET_LOC_LIST(wp);
+ if (qi == NULL) {
+ return FAIL;
+ }
+ }
}
if (qf_idx == -1) {
@@ -4106,9 +4117,48 @@ enum {
QF_GETLIST_NR = 0x4,
QF_GETLIST_WINID = 0x8,
QF_GETLIST_CONTEXT = 0x10,
+ QF_GETLIST_ID = 0x20,
QF_GETLIST_ALL = 0xFF
};
+// Parse text from 'di' and return the quickfix list items
+static int qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
+{
+ int status = FAIL;
+ char_u *errorformat = p_efm;
+ dictitem_T *efm_di;
+
+ // Only a List value is supported
+ if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL) {
+ // If errorformat is supplied then use it, otherwise use the 'efm'
+ // option setting
+ if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) {
+ if (efm_di->di_tv.v_type != VAR_STRING
+ || efm_di->di_tv.vval.v_string == NULL) {
+ return FAIL;
+ }
+ errorformat = efm_di->di_tv.vval.v_string;
+ }
+
+ list_T *l = tv_list_alloc(kListLenMayKnow);
+ qf_info_T *qi = xmalloc(sizeof(*qi));
+ memset(qi, 0, sizeof(*qi));
+ qi->qf_refcount++;
+
+ if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
+ true, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) {
+ (void)get_errorlist(qi, NULL, 0, l);
+ qf_free(qi, 0);
+ }
+ xfree(qi);
+
+ tv_dict_add_list(retdict, S_LEN("items"), l);
+ status = OK;
+ }
+
+ return status;
+}
+
/// Return quickfix/location list details (title) as a
/// dictionary. 'what' contains the details to return. If 'list_idx' is -1,
/// then current list is used. Otherwise the specified list is used.
@@ -4117,17 +4167,22 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
qf_info_T *qi = &ql_info;
dictitem_T *di;
+ if ((di = tv_dict_find(what, S_LEN("lines"))) != NULL) {
+ return qf_get_list_from_lines(what, di, retdict);
+ }
+
if (wp != NULL) {
qi = GET_LOC_LIST(wp);
- if (qi == NULL) {
- // If querying for the size of the location list, return 0
- if (((di = tv_dict_find(what, S_LEN("nr"))) != NULL)
- && (di->di_tv.v_type == VAR_STRING)
- && strequal((const char *)di->di_tv.vval.v_string, "$")) {
- return tv_dict_add_nr(retdict, S_LEN("nr"), 0);
- }
- return FAIL;
+ }
+ // List is not present or is empty
+ if (qi == NULL || qi->qf_listcount == 0) {
+ // If querying for the size of the list, return 0
+ if (((di = tv_dict_find(what, S_LEN("nr"))) != NULL)
+ && (di->di_tv.v_type == VAR_STRING)
+ && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) {
+ return tv_dict_add_nr(retdict, S_LEN("nr"), 0);
}
+ return FAIL;
}
int status = OK;
@@ -4143,44 +4198,51 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
if (qf_idx < 0 || qf_idx >= qi->qf_listcount) {
return FAIL;
}
- } else if (qi->qf_listcount == 0) { // stack is empty
- return FAIL;
}
- flags |= QF_GETLIST_NR;
} else if (di->di_tv.v_type == VAR_STRING
&& strequal((const char *)di->di_tv.vval.v_string, "$")) {
// Get the last quickfix list number
- if (qi->qf_listcount > 0) {
- qf_idx = qi->qf_listcount - 1;
- } else {
- qf_idx = -1; // Quickfix stack is empty
- }
- flags |= QF_GETLIST_NR;
+ qf_idx = qi->qf_listcount - 1;
} else {
return FAIL;
}
+ flags |= QF_GETLIST_NR;
}
- if (qf_idx != -1) {
- if (tv_dict_find(what, S_LEN("all")) != NULL) {
- flags |= QF_GETLIST_ALL;
- }
-
- if (tv_dict_find(what, S_LEN("title")) != NULL) {
- flags |= QF_GETLIST_TITLE;
- }
-
- if (tv_dict_find(what, S_LEN("winid")) != NULL) {
- flags |= QF_GETLIST_WINID;
- }
-
- if (tv_dict_find(what, S_LEN("context")) != NULL) {
- flags |= QF_GETLIST_CONTEXT;
+ if ((di = tv_dict_find(what, S_LEN("id"))) != NULL) {
+ // Look for a list with the specified id
+ if (di->di_tv.v_type == VAR_NUMBER) {
+ // For zero, use the current list or the list specifed by 'nr'
+ if (di->di_tv.vval.v_number != 0) {
+ for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++) {
+ if (qi->qf_lists[qf_idx].qf_id == di->di_tv.vval.v_number) {
+ break;
+ }
+ }
+ if (qf_idx == qi->qf_listcount) {
+ return FAIL; // List not found
+ }
+ }
+ flags |= QF_GETLIST_ID;
+ } else {
+ return FAIL;
}
+ }
- if (tv_dict_find(what, S_LEN("items")) != NULL) {
- flags |= QF_GETLIST_ITEMS;
- }
+ if (tv_dict_find(what, S_LEN("all")) != NULL) {
+ flags |= QF_GETLIST_ALL;
+ }
+ if (tv_dict_find(what, S_LEN("title")) != NULL) {
+ flags |= QF_GETLIST_TITLE;
+ }
+ if (tv_dict_find(what, S_LEN("winid")) != NULL) {
+ flags |= QF_GETLIST_WINID;
+ }
+ if (tv_dict_find(what, S_LEN("context")) != NULL) {
+ flags |= QF_GETLIST_CONTEXT;
+ }
+ if (tv_dict_find(what, S_LEN("items")) != NULL) {
+ flags |= QF_GETLIST_ITEMS;
}
if (flags & QF_GETLIST_TITLE) {
@@ -4201,7 +4263,7 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
}
if ((status == OK) && (flags & QF_GETLIST_ITEMS)) {
list_T *l = tv_list_alloc(kListLenMayKnow);
- (void)get_errorlist(wp, qf_idx, l);
+ (void)get_errorlist(qi, NULL, qf_idx, l);
tv_dict_add_list(retdict, S_LEN("items"), l);
}
@@ -4218,6 +4280,10 @@ int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict)
}
}
+ if ((status == OK) && (flags & QF_GETLIST_ID)) {
+ status = tv_dict_add_nr(retdict, S_LEN("id"), qi->qf_lists[qf_idx].qf_id);
+ }
+
return status;
}
@@ -4336,6 +4402,7 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action,
dictitem_T *di;
int retval = FAIL;
int newlist = false;
+ char_u *errorformat = p_efm;
if (action == ' ' || qi->qf_curlist == qi->qf_listcount) {
newlist = true;
@@ -4374,6 +4441,22 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action,
}
}
+ if (!newlist && (di = tv_dict_find(what, S_LEN("id"))) != NULL) {
+ // Use the quickfix/location list with the specified id
+ if (di->di_tv.v_type == VAR_NUMBER) {
+ for (qf_idx = 0; qf_idx < qi->qf_listcount; qf_idx++) {
+ if (qi->qf_lists[qf_idx].qf_id == di->di_tv.vval.v_number) {
+ break;
+ }
+ }
+ if (qf_idx == qi->qf_listcount) {
+ return FAIL; // List not found
+ }
+ } else {
+ return FAIL;
+ }
+ }
+
if (newlist) {
qi->qf_curlist = qf_idx;
qf_new_list(qi, title);
@@ -4401,16 +4484,20 @@ static int qf_set_properties(qf_info_T *qi, dict_T *what, int action,
}
}
- if ((di = tv_dict_find(what, S_LEN("text"))) != NULL) {
- // Only string and list values are supported
- if ((di->di_tv.v_type == VAR_STRING
- && di->di_tv.vval.v_string != NULL)
- || (di->di_tv.v_type == VAR_LIST
- && di->di_tv.vval.v_list != NULL)) {
+ if ((di = tv_dict_find(what, S_LEN("efm"))) != NULL) {
+ if (di->di_tv.v_type != VAR_STRING || di->di_tv.vval.v_string == NULL) {
+ return FAIL;
+ }
+ errorformat = di->di_tv.vval.v_string;
+ }
+
+ if ((di = tv_dict_find(what, S_LEN("lines"))) != NULL) {
+ // Only a List value is supported
+ if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL) {
if (action == 'r') {
qf_free_items(qi, qf_idx);
}
- if (qf_init_ext(qi, qf_idx, NULL, NULL, &di->di_tv, p_efm,
+ if (qf_init_ext(qi, qf_idx, NULL, NULL, &di->di_tv, errorformat,
false, (linenr_T)0, (linenr_T)0, NULL, NULL) > 0) {
retval = OK;
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 884fef69d1..ca57148431 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -2012,7 +2012,7 @@ static void fold_line(win_T *wp, long fold_count, foldinfo_T *foldinfo, linenr_T
}
screen_line(row + wp->w_winrow, wp->w_wincol, wp->w_width,
- wp->w_width, false, wp, wp->w_hl_attr_normal);
+ wp->w_width, false, wp, wp->w_hl_attr_normal, false);
/*
* Update w_cline_height and w_cline_folded if the cursor line was
@@ -2900,7 +2900,7 @@ win_line (
&& filler_todo <= 0
) {
screen_line(screen_row, wp->w_wincol, col, -wp->w_width, wp->w_p_rl, wp,
- wp->w_hl_attr_normal);
+ wp->w_hl_attr_normal, false);
// Pretend we have finished updating the window. Except when
// 'cursorcolumn' is set.
if (wp->w_p_cuc) {
@@ -3989,7 +3989,7 @@ win_line (
}
}
screen_line(screen_row, wp->w_wincol, col, wp->w_width, wp->w_p_rl, wp,
- wp->w_hl_attr_normal);
+ wp->w_hl_attr_normal, false);
row++;
/*
@@ -4197,8 +4197,22 @@ win_line (
|| (wp->w_p_list && lcs_eol != NUL && p_extra != at_end_str)
|| (n_extra != 0 && (c_extra != NUL || *p_extra != NUL)))
) {
+ bool wrap = wp->w_p_wrap // Wrapping enabled.
+ && filler_todo <= 0 // Not drawing diff filler lines.
+ && lcs_eol_one != -1 // Haven't printed the lcs_eol character.
+ && row != endrow - 1 // Not the last line being displayed.
+ && wp->w_width == Columns // Window spans the width of the screen.
+ && !wp->w_p_rl; // Not right-to-left.
screen_line(screen_row, wp->w_wincol, col - boguscols,
- wp->w_width, wp->w_p_rl, wp, wp->w_hl_attr_normal);
+ wp->w_width, wp->w_p_rl, wp, wp->w_hl_attr_normal, wrap);
+ if (wrap) {
+ // Force a redraw of the first column of the next line.
+ ScreenAttrs[LineOffset[screen_row + 1]] = -1;
+
+ // Remember that the line wraps, used for modeless copy.
+ LineWraps[screen_row] = true;
+ }
+
boguscols = 0;
++row;
++screen_row;
@@ -4225,28 +4239,6 @@ win_line (
break;
}
- if (ui_current_row() == screen_row - 1
- && filler_todo <= 0
- && wp->w_width == Columns) {
- /* Remember that the line wraps, used for modeless copy. */
- LineWraps[screen_row - 1] = TRUE;
-
- // Special trick to make copy/paste of wrapped lines work with
- // xterm/screen: write an extra character beyond the end of
- // the line. This will work with all terminal types
- // (regardless of the xn,am settings).
- // Only do this if the cursor is on the current line
- // (something has been written in it).
- // Don't do this for double-width characters.
- // Don't do this for a window not at the right screen border.
- if (utf_off2cells(LineOffset[screen_row],
- LineOffset[screen_row] + screen_Columns) != 2
- && utf_off2cells(LineOffset[screen_row - 1] + (int)Columns - 2,
- LineOffset[screen_row] + screen_Columns) != 2) {
- ui_add_linewrap(screen_row - 1);
- }
- }
-
col = 0;
off = (unsigned)(current_ScreenLine - ScreenLines);
if (wp->w_p_rl) {
@@ -4312,9 +4304,11 @@ static int char_needs_redraw(int off_from, int off_to, int cols)
* "rlflag" is TRUE in a rightleft window:
* When TRUE and "clear_width" > 0, clear columns 0 to "endcol"
* When FALSE and "clear_width" > 0, clear columns "endcol" to "clear_width"
+ * If "wrap" is true, then hint to the UI that "row" contains a line
+ * which has wrapped into the next row.
*/
-static void screen_line(int row, int coloff, int endcol,
- int clear_width, int rlflag, win_T *wp, int bg_attr)
+static void screen_line(int row, int coloff, int endcol, int clear_width,
+ int rlflag, win_T *wp, int bg_attr, bool wrap)
{
unsigned off_from;
unsigned off_to;
@@ -4475,7 +4469,7 @@ static void screen_line(int row, int coloff, int endcol,
}
if (clear_end > start_dirty) {
ui_line(row, coloff+start_dirty, coloff+end_dirty, coloff+clear_end,
- bg_attr);
+ bg_attr, wrap);
}
}
@@ -5435,7 +5429,8 @@ void screen_puts_line_flush(bool set_cursor)
if (set_cursor) {
ui_cursor_goto(put_dirty_row, put_dirty_last);
}
- ui_line(put_dirty_row, put_dirty_first, put_dirty_last, put_dirty_last, 0);
+ ui_line(put_dirty_row, put_dirty_first, put_dirty_last, put_dirty_last, 0,
+ false);
put_dirty_first = -1;
put_dirty_last = 0;
}
@@ -5794,7 +5789,7 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1,
put_dirty_last = MAX(put_dirty_last, dirty_last);
} else {
int last = c2 != ' ' ? dirty_last : dirty_first + (c1 != ' ');
- ui_line(row, dirty_first, last, dirty_last, attr);
+ ui_line(row, dirty_first, last, dirty_last, attr, false);
}
}
diff --git a/src/nvim/testdir/test_fold.vim b/src/nvim/testdir/test_fold.vim
index 6917378890..e7d5a2ae2c 100644
--- a/src/nvim/testdir/test_fold.vim
+++ b/src/nvim/testdir/test_fold.vim
@@ -278,6 +278,7 @@ func Test_move_folds_around_manual()
call assert_equal(0, foldlevel(6))
call assert_equal(9, foldclosedend(7))
call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
+
%d
" Ensure moving around the edges still works.
call setline(1, PrepIndent("a") + repeat(["a"], 3) + ["\ta"])
@@ -634,3 +635,16 @@ func Test_fold_move()
set fdm& sw& fdl&
enew!
endfunc
+
+func Test_foldtext_recursive()
+ new
+ call setline(1, ['{{{', 'some text', '}}}'])
+ setlocal foldenable foldmethod=marker foldtext=foldtextresult(v\:foldstart)
+ " This was crashing because of endless recursion.
+ 2foldclose
+ redraw
+ call assert_equal(1, foldlevel(2))
+ call assert_equal(1, foldclosed(2))
+ call assert_equal(3, foldclosedend(2))
+ bwipe!
+endfunc
diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim
index f603f46d63..7a53db7605 100644
--- a/src/nvim/testdir/test_quickfix.vim
+++ b/src/nvim/testdir/test_quickfix.vim
@@ -1879,8 +1879,9 @@ func Xproperty_tests(cchar)
call g:Xsetlist([], 'r', {'nr':2,'title':'Fruits','context':['Fruits']})
let l1=g:Xgetlist({'nr':1,'all':1})
let l2=g:Xgetlist({'nr':2,'all':1})
- let l1.nr=2
- let l2.nr=1
+ let save_id = l1.id
+ let l1.id=l2.id
+ let l2.id=save_id
call g:Xsetlist([], 'r', l1)
call g:Xsetlist([], 'r', l2)
let newl1=g:Xgetlist({'nr':1,'all':1})
@@ -2280,27 +2281,39 @@ func Xsetexpr_tests(cchar)
call s:setup_commands(a:cchar)
let t = ["File1:10:Line10", "File1:20:Line20"]
- call g:Xsetlist([], ' ', {'text' : t})
- call g:Xsetlist([], 'a', {'text' : "File1:30:Line30"})
+ call g:Xsetlist([], ' ', {'lines' : t})
+ call g:Xsetlist([], 'a', {'lines' : ["File1:30:Line30"]})
let l = g:Xgetlist()
call assert_equal(3, len(l))
call assert_equal(20, l[1].lnum)
call assert_equal('Line30', l[2].text)
- call g:Xsetlist([], 'r', {'text' : "File2:5:Line5"})
+ call g:Xsetlist([], 'r', {'lines' : ["File2:5:Line5"]})
let l = g:Xgetlist()
call assert_equal(1, len(l))
call assert_equal('Line5', l[0].text)
- call assert_equal(-1, g:Xsetlist([], 'a', {'text' : 10}))
+ call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : 10}))
+ call assert_equal(-1, g:Xsetlist([], 'a', {'lines' : "F1:10:L10"}))
call g:Xsetlist([], 'f')
" Add entries to multiple lists
- call g:Xsetlist([], 'a', {'nr' : 1, 'text' : ["File1:10:Line10"]})
- call g:Xsetlist([], 'a', {'nr' : 2, 'text' : ["File2:20:Line20"]})
- call g:Xsetlist([], 'a', {'nr' : 1, 'text' : ["File1:15:Line15"]})
- call g:Xsetlist([], 'a', {'nr' : 2, 'text' : ["File2:25:Line25"]})
+ call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:10:Line10"]})
+ call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:20:Line20"]})
+ call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["File1:15:Line15"]})
+ call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["File2:25:Line25"]})
call assert_equal('Line15', g:Xgetlist({'nr':1, 'items':1}).items[1].text)
call assert_equal('Line25', g:Xgetlist({'nr':2, 'items':1}).items[1].text)
+
+ " Adding entries using a custom efm
+ set efm&
+ call g:Xsetlist([], ' ', {'efm' : '%f#%l#%m',
+ \ 'lines' : ["F1#10#L10", "F2#20#L20"]})
+ call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
+ call g:Xsetlist([], 'a', {'efm' : '%f#%l#%m', 'lines' : ["F3:30:L30"]})
+ call assert_equal('F3:30:L30', g:Xgetlist({'items':1}).items[2].text)
+ call assert_equal(20, g:Xgetlist({'items':1}).items[1].lnum)
+ call assert_equal(-1, g:Xsetlist([], 'a', {'efm' : [],
+ \ 'lines' : ['F1:10:L10']}))
endfunc
func Test_setexpr()
@@ -2315,16 +2328,16 @@ func Xmultidirstack_tests(cchar)
call g:Xsetlist([], 'f')
Xexpr "" | Xexpr ""
- call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "Entering dir 'Xone/a'"})
- call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "Entering dir 'Xtwo/a'"})
- call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "one.txt:3:one one one"})
- call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "two.txt:5:two two two"})
+ call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["Entering dir 'Xone/a'"]})
+ call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["Entering dir 'Xtwo/a'"]})
+ call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["one.txt:3:one one one"]})
+ call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["two.txt:5:two two two"]})
let l1 = g:Xgetlist({'nr':1, 'items':1})
let l2 = g:Xgetlist({'nr':2, 'items':1})
- call assert_equal('Xone/a/one.txt', bufname(l1.items[1].bufnr))
+ call assert_equal(expand('Xone/a/one.txt'), bufname(l1.items[1].bufnr))
call assert_equal(3, l1.items[1].lnum)
- call assert_equal('Xtwo/a/two.txt', bufname(l2.items[1].bufnr))
+ call assert_equal(expand('Xtwo/a/two.txt'), bufname(l2.items[1].bufnr))
call assert_equal(5, l2.items[1].lnum)
endfunc
@@ -2352,10 +2365,10 @@ func Xmultifilestack_tests(cchar)
call g:Xsetlist([], 'f')
Xexpr "" | Xexpr ""
- call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "[one.txt]"})
- call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "[two.txt]"})
- call g:Xsetlist([], 'a', {'nr' : 1, 'text' : "(3,5) one one one"})
- call g:Xsetlist([], 'a', {'nr' : 2, 'text' : "(5,9) two two two"})
+ call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["[one.txt]"]})
+ call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["[two.txt]"]})
+ call g:Xsetlist([], 'a', {'nr' : 1, 'lines' : ["(3,5) one one one"]})
+ call g:Xsetlist([], 'a', {'nr' : 2, 'lines' : ["(5,9) two two two"]})
let l1 = g:Xgetlist({'nr':1, 'items':1})
let l2 = g:Xgetlist({'nr':2, 'items':1})
@@ -2501,3 +2514,73 @@ func Test_add_qf()
call XaddQf_tests('c')
call XaddQf_tests('l')
endfunc
+
+" Test for getting the quickfix list items from some text without modifying
+" the quickfix stack
+func XgetListFromLines(cchar)
+ call s:setup_commands(a:cchar)
+ call g:Xsetlist([], 'f')
+
+ let l = g:Xgetlist({'lines' : ["File2:20:Line20", "File2:30:Line30"]}).items
+ call assert_equal(2, len(l))
+ call assert_equal(30, l[1].lnum)
+
+ call assert_equal({}, g:Xgetlist({'lines' : 10}))
+ call assert_equal({}, g:Xgetlist({'lines' : 'File1:10:Line10'}))
+ call assert_equal([], g:Xgetlist({'lines' : []}).items)
+ call assert_equal([], g:Xgetlist({'lines' : [10, 20]}).items)
+
+ " Parse text using a custom efm
+ set efm&
+ let l = g:Xgetlist({'lines':['File3#30#Line30'], 'efm' : '%f#%l#%m'}).items
+ call assert_equal('Line30', l[0].text)
+ let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : '%f-%l-%m'}).items
+ call assert_equal('File3:30:Line30', l[0].text)
+ let l = g:Xgetlist({'lines':['File3:30:Line30'], 'efm' : [1,2]})
+ call assert_equal({}, l)
+ call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':'%2'})", 'E376:')
+ call assert_fails("call g:Xgetlist({'lines':['abc'], 'efm':''})", 'E378:')
+
+ " Make sure that the quickfix stack is not modified
+ call assert_equal(0, g:Xgetlist({'nr' : '$'}).nr)
+endfunc
+
+func Test_get_list_from_lines()
+ call XgetListFromLines('c')
+ call XgetListFromLines('l')
+endfunc
+
+" Tests for the quickfix list id
+func Xqfid_tests(cchar)
+ call s:setup_commands(a:cchar)
+
+ call g:Xsetlist([], 'f')
+ call assert_equal({}, g:Xgetlist({'id':0}))
+ Xexpr ''
+ let start_id = g:Xgetlist({'id' : 0}).id
+ Xexpr '' | Xexpr ''
+ Xolder
+ call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id)
+ call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id)
+ call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id)
+ call assert_equal({}, g:Xgetlist({'id':0, 'nr':99}))
+ call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr)
+ call assert_equal({}, g:Xgetlist({'id':99, 'nr':0}))
+ call assert_equal({}, g:Xgetlist({'id':"abc", 'nr':0}))
+
+ call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]})
+ call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context)
+ call g:Xsetlist([], 'a', {'id':start_id+1, 'lines':['F1:10:L10']})
+ call assert_equal('L10', g:Xgetlist({'nr':2, 'items':1}).items[0].text)
+ call assert_equal(-1, g:Xsetlist([], 'a', {'id':999, 'title':'Vim'}))
+ call assert_equal(-1, g:Xsetlist([], 'a', {'id':'abc', 'title':'Vim'}))
+
+ let qfid = g:Xgetlist({'id':0, 'nr':0})
+ call g:Xsetlist([], 'f')
+ call assert_equal({}, g:Xgetlist({'id':qfid, 'nr':0}))
+endfunc
+
+func Test_qf_id()
+ call Xqfid_tests('c')
+ call Xqfid_tests('l')
+endfunc
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 0781b03965..841294aaad 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -1191,7 +1191,8 @@ static void tui_option_set(UI *ui, String name, Object value)
static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol,
Integer endcol, Integer clearcol, Integer clearattr,
- const schar_T *chunk, const sattr_T *attrs)
+ Boolean wrap, const schar_T *chunk,
+ const sattr_T *attrs)
{
TUIData *data = ui->data;
UGrid *grid = &data->grid;
@@ -1212,6 +1213,21 @@ static void tui_raw_line(UI *ui, Integer g, Integer linerow, Integer startcol,
clear_region(ui, (int)linerow, (int)linerow, (int)endcol, (int)clearcol-1,
cl_attrs);
}
+
+ if (wrap && ui->width == grid->width && linerow + 1 < grid->height) {
+ // Only do line wrapping if the grid width is equal to the terminal
+ // width and the line continuation is within the grid.
+
+ if (endcol != grid->width) {
+ // Print the last cell of the row, if we haven't already done so.
+ cursor_goto(ui, (int)linerow, grid->width - 1);
+ print_cell(ui, &grid->cells[linerow][grid->width - 1]);
+ }
+
+ // Wrap the cursor over to the next line. The next line will be
+ // printed immediately without an intervening newline.
+ final_column_wrap(ui);
+ }
}
static void invalidate(UI *ui, int top, int bot, int left, int right)
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 07aa032a50..e291111f82 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -80,7 +80,7 @@ static char uilog_last_event[1024] = { 0 };
#endif
// UI_CALL invokes a function on all registered UI instances. The functions can
-// have 0-5 arguments (configurable by SELECT_NTH).
+// have 0-10 arguments (configurable by SELECT_NTH).
//
// See http://stackoverflow.com/a/11172679 for how it works.
#ifdef _MSC_VER
@@ -102,9 +102,9 @@ static char uilog_last_event[1024] = { 0 };
} \
} while (0)
#endif
-#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, \
- MORE, MORE, MORE, MORE, MORE, ZERO, ignore)
-#define SELECT_NTH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, ...) a10
+#define CNT(...) SELECT_NTH(__VA_ARGS__, MORE, MORE, MORE, MORE, MORE, \
+ MORE, MORE, MORE, MORE, ZERO, ignore)
+#define SELECT_NTH(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11
#define UI_CALL_HELPER(c, ...) UI_CALL_HELPER2(c, __VA_ARGS__)
// Resolves to UI_CALL_MORE or UI_CALL_ZERO.
#define UI_CALL_HELPER2(c, ...) UI_CALL_##c(__VA_ARGS__)
@@ -315,10 +315,11 @@ void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
}
}
-void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr)
+void ui_line(int row, int startcol, int endcol, int clearcol, int clearattr,
+ bool wrap)
{
size_t off = LineOffset[row]+(size_t)startcol;
- UI_CALL(raw_line, 1, row, startcol, endcol, clearcol, clearattr,
+ UI_CALL(raw_line, 1, row, startcol, endcol, clearcol, clearattr, wrap,
(const schar_T *)ScreenLines+off, (const sattr_T *)ScreenAttrs+off);
if (p_wd) { // 'writedelay': flush & delay each time.
int old_row = row, old_col = col;
@@ -341,32 +342,6 @@ void ui_cursor_goto(int new_row, int new_col)
pending_cursor_update = true;
}
-void ui_add_linewrap(int row)
-{
- // TODO(bfredl): check that this actually still works
- // and move to TUI module in that case.
-#if 0
- // First make sure we are at the end of the screen line,
- // then output the same character again to let the
- // terminal know about the wrap. If the terminal doesn't
- // auto-wrap, we overwrite the character.
- if (ui_current_col() != Columns) {
- screen_char(LineOffset[row] + (unsigned)Columns - 1, row,
- (int)(Columns - 1));
- }
-
- // When there is a multi-byte character, just output a
- // space to keep it simple. */
- if (ScreenLines[LineOffset[row] + (Columns - 1)][1] != 0) {
- ui_putc(' ');
- } else {
- ui_puts(ScreenLines[LineOffset[row] + (Columns - 1)]);
- }
- // force a redraw of the first char on the next line
- ScreenAttrs[LineOffset[row+1]] = (sattr_T)-1;
-#endif
-}
-
void ui_mode_info_set(void)
{
pending_mode_info_update = true;
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index 584d8a77c6..df489f569f 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -47,7 +47,7 @@ struct ui_t {
// in to the public grid_line format.
void (*raw_line)(UI *ui, Integer grid, Integer row, Integer startcol,
Integer endcol, Integer clearcol, Integer clearattr,
- const schar_T *chunk, const sattr_T *attrs);
+ Boolean wrap, const schar_T *chunk, const sattr_T *attrs);
void (*event)(UI *ui, char *name, Array args, bool *args_consumed);
void (*stop)(UI *ui);
void (*inspect)(UI *ui, Dictionary *info);
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index a96a24bde7..ebd4651f4d 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -152,24 +152,24 @@ static void ui_bridge_raw_line_event(void **argv)
UI *ui = UI(argv[0]);
ui->raw_line(ui, PTR2INT(argv[1]), PTR2INT(argv[2]), PTR2INT(argv[3]),
PTR2INT(argv[4]), PTR2INT(argv[5]), PTR2INT(argv[6]),
- argv[7], argv[8]);
- xfree(argv[7]);
+ PTR2INT(argv[7]), argv[8], argv[9]);
xfree(argv[8]);
+ xfree(argv[9]);
}
static void ui_bridge_raw_line(UI *ui, Integer grid, Integer row,
Integer startcol, Integer endcol,
Integer clearcol, Integer clearattr,
- const schar_T *chunk, const sattr_T *attrs)
+ Boolean wrap, const schar_T *chunk,
+ const sattr_T *attrs)
{
size_t ncol = (size_t)(endcol-startcol);
schar_T *c = xmemdup(chunk, ncol * sizeof(schar_T));
sattr_T *hl = xmemdup(attrs, ncol * sizeof(sattr_T));
- UI_BRIDGE_CALL(ui, raw_line, 9, ui, INT2PTR(grid), INT2PTR(row),
+ UI_BRIDGE_CALL(ui, raw_line, 10, ui, INT2PTR(grid), INT2PTR(row),
INT2PTR(startcol), INT2PTR(endcol), INT2PTR(clearcol),
- INT2PTR(clearattr), c, hl);
+ INT2PTR(clearattr), INT2PTR(wrap), c, hl);
}
-
static void ui_bridge_suspend(UI *b)
{
UIBridgeData *data = (UIBridgeData *)b;
diff --git a/test/functional/ex_cmds/digraphs_spec.lua b/test/functional/ex_cmds/digraphs_spec.lua
index f2d0b76739..37d3814136 100644
--- a/test/functional/ex_cmds/digraphs_spec.lua
+++ b/test/functional/ex_cmds/digraphs_spec.lua
@@ -23,13 +23,13 @@ describe(':digraphs', function()
it('displays digraphs', function()
feed(':digraphs<CR>')
screen:expect([[
- A@ {6:Å} 197 E` {6:È} 200 E^ {6:Ê} 202 E" {6:Ë} 203 I` {6:Ì} 204 |
- I^ {6:Î} 206 I" {6:Ï} 207 N~ {6:Ñ} 209 O` {6:Ò} 210 O^ {6:Ô} 212 |
- O~ {6:Õ} 213 /\ {6:×} 215 U` {6:Ù} 217 U^ {6:Û} 219 Ip {6:Þ} 222 |
- a` {6:à} 224 a^ {6:â} 226 a~ {6:ã} 227 a" {6:ä} 228 a@ {6:å} 229 |
- e` {6:è} 232 e^ {6:ê} 234 e" {6:ë} 235 i` {6:ì} 236 i^ {6:î} 238 |
- n~ {6:ñ} 241 o` {6:ò} 242 o^ {6:ô} 244 o~ {6:õ} 245 u` {6:ù} 249 |
- u^ {6:û} 251 y" {6:ÿ} 255 |
+ E` {6:È} 200 E^ {6:Ê} 202 E" {6:Ë} 203 I` {6:Ì} 204 I^ {6:Î} 206 |
+ I" {6:Ï} 207 N~ {6:Ñ} 209 O` {6:Ò} 210 O^ {6:Ô} 212 O~ {6:Õ} 213 |
+ /\ {6:×} 215 U` {6:Ù} 217 U^ {6:Û} 219 Ip {6:Þ} 222 a` {6:à} 224 |
+ a^ {6:â} 226 a~ {6:ã} 227 a" {6:ä} 228 a@ {6:å} 229 e` {6:è} 232 |
+ e^ {6:ê} 234 e" {6:ë} 235 i` {6:ì} 236 i^ {6:î} 238 n~ {6:ñ} 241 |
+ o` {6:ò} 242 o^ {6:ô} 244 o~ {6:õ} 245 u` {6:ù} 249 u^ {6:û} 251 |
+ y" {6:ÿ} 255 |
{3:Press ENTER or type command to continue}^ |
]])
end)