1
0
mirror of https://github.com/rkd77/elinks.git synced 2025-01-03 14:57:44 -05:00

[combining] Drop CONFIG_COMBINE and meson option 'combining'

It was broken by design. It seems that without this option,
texts with combining characters are also displayed.
There are issues with dialogs, but with -Dcombining=true
dialogs also were "mis-displayed".
This commit is contained in:
Witold Filipczyk 2024-10-07 15:37:56 +02:00
parent 81e505663a
commit aa7cafdad7
16 changed files with 4 additions and 382 deletions

View File

@ -34,9 +34,6 @@
/* Define if you want: codepoint lookup */
#mesondefine CONFIG_CODEPOINT
/* Define if you want: Combining characters support */
#mesondefine CONFIG_COMBINE
/* Define if you want: Cookies support */
#mesondefine CONFIG_COOKIES

View File

@ -1790,9 +1790,6 @@ EL_ARG_ENABLE(CONFIG_SMALL, small, [Small binary],
EL_ARG_ENABLE(CONFIG_UTF8, utf-8, [UTF-8],
[ --disable-utf-8 disable UTF-8 support])
EL_ARG_DEPEND(CONFIG_COMBINE, combining, [CONFIG_UTF8:yes HAVE_WCWIDTH:yes], [Combining characters],
[ --enable-combining support Unicode combining characters (experimental)])
EL_ARG_ENABLE(CONFIG_REPRODUCIBLE, reproducible, [Reproducible builds],
[ --enable-reproducible enable reproducible build])

View File

@ -680,7 +680,7 @@ CONFIG_SMALL=no
# support for double-width characters (like Japanese, etc.).
#
# Some features of Unicode are not handled at all. Combining characters is
# most visible absence; but see CONFIG_COMBINE below.
# most visible absence.
# Some features are partially supported. Like line breaking between
# double-width characters. There is no other detection for determining when to
# break or not.
@ -691,42 +691,6 @@ CONFIG_SMALL=no
CONFIG_UTF8=yes
### Unicode combining characters support
#
# Extends CONFIG_UTF8 with spotty support for combining characters
# such as U+0303 COMBINING TILDE.
#
# This feature is experimental and has been filed as enhancement 824.
# Known bugs and weaknesses:
#
# - It assumes wcwidth(wc)==0 means wc is a combining character.
# However, wcwidth also returns 0 for various control characters
# (e.g. U+200E LEFT-TO-RIGHT MARK), and apparently returns -1 if
# LC_CTYPE does not support the wide character. Besides, wchar_t
# might not be Unicode at all. ELinks should instead use Unicode
# character properties, perhaps via ICU.
#
# - It assumes all combining characters are nonspacing.
#
# - It works only if the terminal is using the UTF-8 charset.
#
# - It allocates an internal code for each different combining
# character sequence. A malicious web page could easily use up all
# the available codes, and the ELinks process would thenceforth be
# unable to display any new sequences.
#
# - It does not understand canonical equivalences.
#
# - Combining characters work only in HTML text. They do not work in
# HTML forms, HTML links, HTML document titles, plain text, menus,
# dialog boxes, or keymaps.
#
# Default: disabled
CONFIG_COMBINE=no
### Back-trace Printing
#
# Once upon a time, a disaster happens and ELinks crashes. That is a very sad

View File

@ -66,7 +66,6 @@ conf_data.set('CONFIG_FASTMEM', get_option('fastmem'))
conf_data.set('CONFIG_OWN_LIBC', get_option('own-libc'))
conf_data.set('CONFIG_SMALL', get_option('small'))
conf_data.set('CONFIG_UTF8', get_option('utf-8'))
conf_data.set('CONFIG_COMBINE', get_option('combining'))
conf_data.set('CONFIG_XTERM', get_option('xterm'))
conf_data.set('CONFIG_GPM', get_option('gpm'))

View File

@ -37,7 +37,6 @@ option('fastmem', type: 'boolean', value: false, description: 'direct use of sys
option('own-libc', type: 'boolean', value: false, description: 'force use of internal functions instead of those of system libc')
option('small', type: 'boolean', value: false, description: 'reduce binary size as far as possible (but see the bottom of doc/small.txt!)')
option('utf-8', type: 'boolean', value: true, description: 'UTF-8 support')
option('combining', type: 'boolean', value: false, description: 'support Unicode combining characters (experimental)')
option('xterm', type: 'boolean', value: false, description: 'how to invoke the X terminal emulator')
option('gpm', type: 'boolean', value: true, description: 'gpm (mouse) support')

View File

@ -1077,12 +1077,10 @@ static union option_info config_options_info[] = {
"terminal codepage is used. ELinks ignores this option "
"if the terminal codepage is UTF-8.")),
#ifdef CONFIG_COMBINE
INIT_OPT_BOOL("terminal._template_", N_("Combining characters"),
"combine", OPT_ZERO, 0,
N_("Enable combining characters. It works only with "
"the xterm in UTF-8 mode.")),
#endif
INIT_OPT_BOOL("terminal._template_", N_("Restrict frames in cp850/852"),
"restrict_852", OPT_ZERO, 0,

View File

@ -97,9 +97,7 @@ enum termopt {
TERM_OPT_UNDERLINE,
TERM_OPT_ITALIC,
TERM_OPT_STRIKE,
#ifdef CONFIG_COMBINE
TERM_OPT_COMBINE,
#endif
#ifdef CONFIG_LIBSIXEL
TERM_OPT_SIXEL,
#endif
@ -117,9 +115,7 @@ static struct option_resolver resolvers[] = {
{ TERM_OPT_UNDERLINE, "underline" },
{ TERM_OPT_ITALIC, "italic" },
{ TERM_OPT_STRIKE, "strike" },
#ifdef CONFIG_COMBINE
{ TERM_OPT_COMBINE, "combine" },
#endif
#ifdef CONFIG_LIBSIXEL
{ TERM_OPT_SIXEL, "sixel" },
#endif
@ -246,9 +242,7 @@ terminal_options(struct terminal *term, void *xxx, struct session *ses)
add_dlg_checkbox(dlg, _("Underline", term), &values[TERM_OPT_UNDERLINE].number);
add_dlg_checkbox(dlg, _("Strikethrough", term), &values[TERM_OPT_STRIKE].number);
add_dlg_checkbox(dlg, _("UTF-8 I/O", term), &values[TERM_OPT_UTF_8_IO].number);
#ifdef CONFIG_COMBINE
add_dlg_checkbox(dlg, _("Combining characters", term), &values[TERM_OPT_COMBINE].number);
#endif
#ifdef CONFIG_LIBSIXEL
add_dlg_checkbox(dlg, _("Sixel", term), &values[TERM_OPT_SIXEL].number);
#endif

View File

@ -219,10 +219,6 @@ init_document(struct cache_entry *cached, struct document_options *options)
init_list(document->images);
#endif
#ifdef CONFIG_COMBINE
document->comb_x = -1;
document->comb_y = -1;
#endif
object_nolock(document, "document");
object_lock(document);
@ -365,10 +361,6 @@ reset_document(struct document *document)
mem_free_set(&document->slines1, NULL);
mem_free_set(&document->slines2, NULL);
mem_free_set(&document->search_points, NULL);
#ifdef CONFIG_COMBINE
discard_comb_x_y(document);
#endif
}
void

View File

@ -285,14 +285,6 @@ struct document {
#ifdef CONFIG_UTF8
char buf[7];
unsigned char buf_length;
#endif
#ifdef CONFIG_COMBINE
/* base char + 5 combining chars = 6 */
unicode_val_T combi[UCS_MAX_LENGTH_COMBINED];
/* the number of combining characters. The base char is not counted. */
unsigned int combi_length;
/* Positions of the last base character.*/
int comb_x, comb_y;
#endif
unsigned int cache_id; /**< Used to check cache entries. */

View File

@ -8,15 +8,6 @@
#include <stdint.h>
#endif
/* Our current implementation of combining characters requires
* wcwidth(). Therefore the configure script should have disabled
* CONFIG_COMBINE if wcwidth() doesn't exist. */
#ifdef CONFIG_COMBINE
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 500 /* for wcwidth */
#endif
#endif
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
@ -378,108 +369,6 @@ expand_lines(struct html_context *html_context, struct part *part,
}
}
/* document.comb_x and document.comb_y exist only when CONFIG_COMBINE
* is defined. assert() does nothing if CONFIG_FASTMEM is defined. */
#if defined(CONFIG_COMBINE) && !defined(CONFIG_FASTMEM)
/** Assert that path->document->comb_x and part->document->comb_y
* refer to an allocated struct screen_char, or comb_x is -1.
*
* The CONFIG_COMBINE variant of set_hline() can update the
* screen_char.data at these coordinates. Sometimes, the coordinates
* have not been valid, and the update has corrupted memory. These
* assertions should catch that bug if it happens again.
*
* @post This function can leave ::assert_failed set, so the caller
* should use ::if_assert_failed, perhaps with discard_comb_x_y(). */
static void
assert_comb_x_y_ok(const struct document *document)
{
assert(document);
if (document->comb_x != -1) {
assert(document->comb_y >= 0);
assert(document->comb_y < document->height);
assert(document->comb_x >= 0);
assert(document->comb_x < document->data[document->comb_y].length);
}
}
#else
# define assert_comb_x_y_ok(document) ((void) 0)
#endif
#ifdef CONFIG_COMBINE
/** Discard any combining characters that have not yet been combined
* with to the previous base character. */
void
discard_comb_x_y(struct document *document)
{
document->comb_x = -1;
document->comb_y = -1;
document->combi_length = 0;
}
#endif
#ifdef CONFIG_COMBINE
static void
move_comb_x_y(struct part *part, int xf, int yf, int xt, int yt)
{
if (part->document->comb_x != -1
&& part->document->comb_y == Y(yf)
&& part->document->comb_x >= X(xf)) {
if (yt >= 0) {
part->document->comb_x += xt - xf;
part->document->comb_y += yt - yf;
} else
discard_comb_x_y(part->document);
}
}
#else
# define move_comb_x_y(part, xf, yf, xt, yt) ((void) 0)
#endif
#ifdef CONFIG_COMBINE
static void
set_comb_x_y(struct part *part, int x, int y)
{
struct document *document = part->document;
document->comb_x = X(x);
document->comb_y = Y(y);
assert_comb_x_y_ok(document);
if_assert_failed discard_comb_x_y(document);
}
#else
# define set_comb_x_y(part, x, y) ((void) 0)
#endif
#ifdef CONFIG_COMBINE
static void
put_combined(struct part *part, int x)
{
struct document *document = part->document;
if (document->combi_length) {
if (document->comb_x != -1) {
unicode_val_T prev = get_combined(document->combi, document->combi_length + 1);
assert_comb_x_y_ok(document);
if_assert_failed prev = UCS_NO_CHAR;
/* Make sure the combined character is not considered as
* a space. */
if (x)
part->spaces[x - 1] = 0;
if (prev != UCS_NO_CHAR)
document->data[document->comb_y]
.ch.chars[document->comb_x].data = prev;
}
document->combi_length = 0;
}
}
#else
# define put_combined(part, x) ((void) 0)
#endif
#ifdef CONFIG_UTF8
/* First possibly do the format change and then find out what coordinates
* to use since sub- or superscript might change them */
@ -523,9 +412,6 @@ set_hline(struct html_context *html_context, const char *chars, int charslen,
if (part->document) {
struct document *const document = part->document;
assert_comb_x_y_ok(document);
if_assert_failed discard_comb_x_y(document);
/* Reallocate LINE(y).chars[] to large enough. The
* last parameter of realloc_line is the index of the
* last element to which we may want to write,
@ -583,10 +469,7 @@ set_hline(struct html_context *html_context, const char *chars, int charslen,
goto good_char;
} else {
/* Still not full char */
assert_comb_x_y_ok(document);
LINE(y).length = orig_length;
assert_comb_x_y_ok(document);
if_assert_failed discard_comb_x_y(document);
return 0;
}
}
@ -627,38 +510,6 @@ good_char:
&& html_context->options->wrap_nbsp)
data = UCS_SPACE;
#ifdef CONFIG_COMBINE
if (wcwidth((wchar_t)data)) {
put_combined(part, x);
document->combi[0] = data;
} else {
if (part->cx == x) {
if (X(x)) {
/* Isolated combining
* character not on the
* first column: combine
* it with whatever is
* printed at its left. */
document->combi[0] = POS(x - 1, y).data;
set_comb_x_y(part, x - 1, y);
} else {
/* Isolated combining
* character on the
* first column: use
* UCS_NO_BREAK_SPACE as
* the base character.
* */
document->combi[0] = UCS_NO_BREAK_SPACE;
set_comb_x_y(part, x, y);
schar->data = UCS_SPACE;
copy_screen_chars(&POS(x++, y), schar, 1);
}
}
if (document->combi_length < (UCS_MAX_LENGTH_COMBINED - 1))
document->combi[++document->combi_length] = data;
continue;
}
#endif /* CONFIG_COMBINE */
part->spaces[x] = (data == UCS_SPACE);
#ifdef CONFIG_CODEPOINT
@ -674,10 +525,6 @@ good_char:
} else
#endif
#ifdef CONFIG_COMBINE
if (unicode_to_cell(data) == 0)
continue;
#endif
if (unicode_to_cell(data) == 2) {
schar->data = (unicode_val_T)data;
part->char_width[x] = 2;
@ -689,14 +536,8 @@ good_char:
part->char_width[x] = unicode_to_cell(data);
schar->data = (unicode_val_T)data;
}
set_comb_x_y(part, x, y);
copy_screen_chars(&POS(x++, y), schar, 1);
} /* while chars < end */
/* Display any trailing combining characters. */
put_combined(part, x);
} else { /* not UTF-8 */
for (; charslen > 0; charslen--, x++, chars++) {
part->char_width[x] = 1;
@ -724,10 +565,7 @@ good_char:
* which is the number of bytes, not the number of cells.
* Change the length to the correct size, but don't let it
* get smaller than it was on entry to this function. */
assert_comb_x_y_ok(document);
LINE(y).length = int_max(orig_length, X(x));
assert_comb_x_y_ok(document);
if_assert_failed discard_comb_x_y(document);
len = x - x2;
} else { /* part->document == NULL */
if (utf8) {
@ -737,13 +575,10 @@ good_char:
unicode_val_T data;
data = utf8_to_unicode((char **)&chars, end);
#ifdef CONFIG_COMBINE
if (data == UCS_SOFT_HYPHEN
|| (data != UCS_NO_CHAR && wcwidth((wchar_t)data) == 0))
#else
if (data == UCS_SOFT_HYPHEN)
#endif
if (data == UCS_SOFT_HYPHEN) {
continue;
}
if (data == UCS_NO_BREAK_SPACE
&& html_context->options->wrap_nbsp)
@ -983,11 +818,7 @@ move_chars(struct html_context *html_context, int x, int y, int nx, int ny)
copy_chars(html_context, nx, ny, LEN(y) - x, &POS(x, y));
assert_comb_x_y_ok(part->document);
move_comb_x_y(part, x, y, nx, ny);
LINE(y).length = X(x);
assert_comb_x_y_ok(part->document);
if_assert_failed discard_comb_x_y(part->document);
move_links(html_context, x, y, nx, ny);
if (par_elformat.blockquote_level && !html_context->table_level) {
@ -1019,18 +850,11 @@ shift_chars(struct html_context *html_context, int y, int shift)
copy_screen_chars(a, &POS(0, y), len);
assert_comb_x_y_ok(part->document);
if_assert_failed discard_comb_x_y(part->document);
clear_hchars(html_context, 0, y, shift, a);
copy_chars(html_context, shift, y, len, a);
fmem_free(a);
move_links(html_context, 0, y, shift, y);
move_comb_x_y(part, 0, y, shift, y);
assert_comb_x_y_ok(part->document);
if_assert_failed discard_comb_x_y(part->document);
}
static inline void
@ -1046,15 +870,8 @@ del_chars(struct html_context *html_context, int x, int y)
assert(part && part->document && part->document->data);
if_assert_failed return;
assert_comb_x_y_ok(part->document);
if_assert_failed discard_comb_x_y(part->document);
LINE(y).length = X(x);
move_comb_x_y(part, x, y, -1, -1);
move_links(html_context, x, y, -1, -1);
assert_comb_x_y_ok(part->document);
if_assert_failed discard_comb_x_y(part->document);
}
#if TABLE_LINE_PADDING < 0
@ -1379,7 +1196,6 @@ justify_line(struct html_context *html_context, int y)
* link. */
new_spaces = new_start - prev_end - 1;
if (word && new_spaces) {
move_comb_x_y(part, prev_end + 1, y, new_start, y);
move_links(html_context, prev_end + 1, y, new_start, y);
insert_spaces_in_link(part,
new_start, y, new_spaces);

View File

@ -123,14 +123,6 @@ void line_break(struct html_context *html_context);
void *html_special(struct html_context *html_context, html_special_type_T c, ...);
#ifdef CONFIG_COMBINE
/** Discard any combining characters that have not yet been combined
* with to the previous base character. */
void discard_comb_x_y(struct document *document);
#else
# define discard_comb_x_y(document) ((void) 0)
#endif
#ifdef __cplusplus
}

View File

@ -869,69 +869,6 @@ cp_to_unicode(int codepage, char **string, const char *end)
return ret;
}
#ifdef CONFIG_COMBINE
unicode_val_T last_combined = UCS_BEGIN_COMBINED - 1;
unicode_val_T **combined;
struct hash *combined_hash;
unicode_val_T
get_combined(unicode_val_T *data, int length)
{
struct hash_item *item;
unicode_val_T *key;
int i, indeks;
assert(length >= 1 && length <= UCS_MAX_LENGTH_COMBINED);
if_assert_failed return UCS_NO_CHAR;
if (!combined_hash) combined_hash = init_hash8();
if (!combined_hash) return UCS_NO_CHAR;
item = get_hash_item(combined_hash, (char *)data, length * sizeof(*data));
if (item) return (unicode_val_T)(intptr_t)item->value;
if (last_combined >= UCS_END_COMBINED) return UCS_NO_CHAR;
key = (unicode_val_T *)mem_alloc((length + 1) * sizeof(*key));
if (!key) return UCS_NO_CHAR;
for (i = 0; i < length; i++)
key[i] = data[i];
key[i] = UCS_END_COMBINED;
last_combined++;
indeks = last_combined - UCS_BEGIN_COMBINED;
combined = (unicode_val_T **)mem_realloc(combined, sizeof(*combined) * (indeks + 1));
if (!combined) {
mem_free(key);
last_combined--;
return UCS_NO_CHAR;
}
combined[indeks] = key;
item = add_hash_item(combined_hash, (char *)key,
length * sizeof(*data), (void *)(intptr_t)(last_combined));
if (!item) {
last_combined--;
mem_free(key);
return UCS_NO_CHAR;
}
return last_combined;
}
void
free_combined()
{
int i, end = last_combined - UCS_BEGIN_COMBINED + 1;
if (combined_hash)
free_hash(&combined_hash);
for (i = 0; i < end; i++)
mem_free(combined[i]);
mem_free_if(combined);
}
#endif /* CONFIG_COMBINE */
static void
add_utf8(struct conv_table *ct, unicode_val_T u, const char *str)
{

View File

@ -33,15 +33,6 @@ typedef uint32_t unicode_val_T;
* for the second cell of a double-cell character. */
#define UCS_NO_CHAR ((unicode_val_T) 0xFFFFFFFD)
#ifdef CONFIG_COMBINE
#define UCS_END_COMBINED ((unicode_val_T) 0xFFFFFFFC)
#define UCS_BEGIN_COMBINED ((unicode_val_T) (UCS_END_COMBINED - (unicode_val_T) 10000))
/* Base character and up to 5 combining characters. */
#define UCS_MAX_LENGTH_COMBINED 6
#endif /* CONFIG_COMBINE */
/* If ELinks should display a double-cell character but there is only
* one cell available, it displays this character instead. This must
* be a single-cell character but need not be unique. Possible values
@ -168,14 +159,6 @@ int strlen_utf8(char **);
unicode_val_T utf8_to_unicode(char **, const char *);
unicode_val_T cp_to_unicode(int, char **, const char *);
#ifdef CONFIG_COMBINE
extern unicode_val_T last_combined;
extern unicode_val_T **combined;
extern struct hash *combined_hash;
unicode_val_T get_combined(unicode_val_T *, int);
void free_combined();
#endif /* CONFIG_COMBINE */
unicode_val_T cp2u(int, unsigned char);
const char *cp2utf8(int, int);

View File

@ -332,9 +332,6 @@ terminate_all_subsystems(void)
done_event();
terminate_select();
terminate_osdep();
#ifdef CONFIG_COMBINE
free_combined();
#endif
#ifdef CONFIG_LIBDOM
free_libdom();
#endif

View File

@ -185,9 +185,6 @@ get_dyn_full_version(struct terminal *term, int more)
#ifdef CONFIG_UTF8
comma, "UTF-8",
#endif
#ifdef CONFIG_COMBINE
comma, _("Combining characters", term),
#endif
#ifdef CONFIG_LIBEV
comma, (event_enabled ? _("libev", term) : _("libev (disabled)", term)), "(", get_libevent_version(), ")",
#endif

View File

@ -271,10 +271,8 @@ struct screen_driver_opt {
unsigned int utf8_cp:1;
#endif /* CONFIG_UTF8 */
#ifdef CONFIG_COMBINE
/* Whether the terminal supports combining characters. */
unsigned int combine:1;
#endif /* CONFIG_COMBINE */
#ifdef CONFIG_TERMINFO
/* Whether use terminfo. */
@ -321,9 +319,7 @@ static const struct screen_driver_opt dumb_screen_driver_opt = {
#ifdef CONFIG_UTF8
/* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */
#ifdef CONFIG_COMBINE
/* combine */ 0,
#endif /* CONFIG_COMBINE */
#ifdef CONFIG_TERMINFO
/* terminfo */ 0,
#endif
@ -348,9 +344,7 @@ static const struct screen_driver_opt vt100_screen_driver_opt = {
#ifdef CONFIG_UTF8
/* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */
#ifdef CONFIG_COMBINE
/* combine */ 0,
#endif /* CONFIG_COMBINE */
#ifdef CONFIG_TERMINFO
/* terminfo */ 0,
#endif
@ -375,9 +369,7 @@ static const struct screen_driver_opt linux_screen_driver_opt = {
#ifdef CONFIG_UTF8
/* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */
#ifdef CONFIG_COMBINE
/* combine */ 0,
#endif /* CONFIG_COMBINE */
#ifdef CONFIG_TERMINFO
/* terminfo */ 0,
#endif
@ -402,9 +394,7 @@ static const struct screen_driver_opt koi8_screen_driver_opt = {
#ifdef CONFIG_UTF8
/* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */
#ifdef CONFIG_COMBINE
/* combine */ 0,
#endif /* CONFIG_COMBINE */
#ifdef CONFIG_TERMINFO
/* terminfo */ 0,
#endif
@ -429,9 +419,7 @@ static const struct screen_driver_opt freebsd_screen_driver_opt = {
#ifdef CONFIG_UTF8
/* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */
#ifdef CONFIG_COMBINE
/* combine */ 0,
#endif /* CONFIG_COMBINE */
#ifdef CONFIG_TERMINFO
/* terminfo */ 0,
#endif
@ -456,9 +444,7 @@ static const struct screen_driver_opt fbterm_screen_driver_opt = {
#ifdef CONFIG_UTF8
/* utf8_cp: */ 0,
#endif /* CONFIG_UTF8 */
#ifdef CONFIG_COMBINE
/* combine */ 0,
#endif /* CONFIG_COMBINE */
#ifdef CONFIG_TERMINFO
/* terminfo */ 0,
#endif
@ -510,9 +496,7 @@ set_screen_driver_opt(struct screen_driver *driver, struct option *term_spec)
* function need not carefully restore options one by one. */
copy_struct(&driver->opt, screen_driver_opts[driver->type]);
#ifdef CONFIG_COMBINE
driver->opt.combine = get_opt_bool_tree(term_spec, "combine", NULL);
#endif /* CONFIG_COMBINE */
#ifdef CONFIG_LIBSIXEL
driver->opt.sixel = get_opt_bool_tree(term_spec, "sixel", NULL);
@ -858,23 +842,7 @@ add_char_data(struct string *screen, struct screen_driver *driver,
}
if (data == UCS_NO_CHAR)
return;
#ifdef CONFIG_COMBINE
if (data >= UCS_BEGIN_COMBINED && data <= last_combined) {
unicode_val_T *text = combined[data - UCS_BEGIN_COMBINED];
if (driver->opt.combine) {
/* XTerm */
while (*text != UCS_END_COMBINED) {
add_to_string(screen, encode_utf8(*text));
text++;
}
return;
} else {
/* Others */
data = *text;
}
}
#endif /* CONFIG_COMBINE */
if (!isscreensafe_ucs(data))
data = UCS_SPACE;
add_to_string(screen, encode_utf8(data));