Update xrdp font handling to use new UTF-8 calls

This commit is contained in:
matt335672 2023-09-26 10:08:44 +01:00
parent 3a5b8936d1
commit a50afc6500
8 changed files with 178 additions and 188 deletions

View File

@ -166,80 +166,6 @@ check_bounds(struct xrdp_bitmap *b, int *x, int *y, int *cx, int *cy)
return 1;
}
/*****************************************************************************/
/* add a ch at index position in text, index starts at 0 */
/* if index = -1 add it to the end */
int
add_char_at(char *text, int text_size, twchar ch, int index)
{
int len;
int i;
twchar *wstr;
len = g_mbstowcs(0, text, 0);
wstr = (twchar *)g_malloc((len + 16) * sizeof(twchar), 0);
g_mbstowcs(wstr, text, len + 1);
if ((index >= len) || (index < 0))
{
wstr[len] = ch;
wstr[len + 1] = 0;
g_wcstombs(text, wstr, text_size);
g_free(wstr);
return 0;
}
for (i = (len - 1); i >= index; i--)
{
wstr[i + 1] = wstr[i];
}
wstr[i + 1] = ch;
wstr[len + 1] = 0;
g_wcstombs(text, wstr, text_size);
g_free(wstr);
return 0;
}
/*****************************************************************************/
/* remove a ch at index position in text, index starts at 0 */
/* if index = -1 remove it from the end */
int
remove_char_at(char *text, int text_size, int index)
{
int len;
int i;
twchar *wstr;
len = g_mbstowcs(0, text, 0);
if (len <= 0)
{
return 0;
}
wstr = (twchar *)g_malloc((len + 16) * sizeof(twchar), 0);
g_mbstowcs(wstr, text, len + 1);
if ((index >= (len - 1)) || (index < 0))
{
wstr[len - 1] = 0;
g_wcstombs(text, wstr, text_size);
g_free(wstr);
return 0;
}
for (i = index; i < (len - 1); i++)
{
wstr[i] = wstr[i + 1];
}
wstr[len - 1] = 0;
g_wcstombs(text, wstr, text_size);
g_free(wstr);
return 0;
}
/*****************************************************************************/
int
set_string(char **in_str, const char *in)
@ -253,22 +179,3 @@ set_string(char **in_str, const char *in)
*in_str = g_strdup(in);
return 0;
}
/*****************************************************************************/
int
wchar_repeat(twchar *dest, int dest_size_in_wchars, twchar ch, int repeat)
{
int index;
for (index = 0; index < repeat; index++)
{
if (index >= dest_size_in_wchars)
{
break;
}
dest[index] = ch;
}
return 0;
}

View File

@ -153,7 +153,7 @@ get_keysym_from_scan_code(int device_flags, int scan_code, int *keys,
}
/*****************************************************************************/
twchar
char32_t
get_char_from_scan_code(int device_flags, int scan_code, int *keys,
int caps_lock, int num_lock, int scroll_lock,
struct xrdp_keymap *keymap)
@ -169,7 +169,7 @@ get_char_from_scan_code(int device_flags, int scan_code, int *keys,
return 0;
}
return (twchar)(ki->chr);
return ki->chr;
}
/*****************************************************************************/

View File

@ -333,6 +333,17 @@ xrdp_painter_draw_bitmap(struct xrdp_painter *self,
int x, int y, int cx, int cy);
int
xrdp_painter_text_width(struct xrdp_painter *self, const char *text);
/* As above, but have a maximum Unicode character count for the string */
int
xrdp_painter_text_width_count(struct xrdp_painter *self,
const char *text, unsigned int c32_count);
/* Size of a string composed of a repeated number of Unicode characters */
int
xrdp_painter_repeated_char_width(struct xrdp_painter *self,
char32_t c32, unsigned int repeat_count);
unsigned int
xrdp_painter_font_body_height(const struct xrdp_painter *self);
int
@ -349,6 +360,11 @@ xrdp_painter_draw_text2(struct xrdp_painter *self,
int box_right, int box_bottom,
int x, int y, char *data, int data_len);
int
xrdp_painter_draw_char(struct xrdp_painter *self,
struct xrdp_bitmap *bitmap,
int x, int y, char32_t chr,
unsigned int repeat_count);
int
xrdp_painter_copy(struct xrdp_painter *self,
struct xrdp_bitmap *src,
struct xrdp_bitmap *dst,
@ -403,13 +419,7 @@ rect_contained_by(struct xrdp_rect *in1, int left, int top,
int
check_bounds(struct xrdp_bitmap *b, int *x, int *y, int *cx, int *cy);
int
add_char_at(char *text, int text_size, twchar ch, int index);
int
remove_char_at(char *text, int text_size, int index);
int
set_string(char **in_str, const char *in);
int
wchar_repeat(twchar *dest, int dest_size_in_wchars, twchar ch, int repeat);
/* in lang.c */
struct xrdp_key_info *
@ -420,7 +430,7 @@ int
get_keysym_from_scan_code(int device_flags, int scan_code, int *keys,
int caps_lock, int num_lock, int scroll_lock,
struct xrdp_keymap *keymap);
twchar
char32_t
get_char_from_scan_code(int device_flags, int scan_code, int *keys,
int caps_lock, int num_lock, int scroll_lock,
struct xrdp_keymap *keymap);

View File

@ -621,8 +621,6 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
struct xrdp_rect r2;
struct xrdp_painter *painter;
unsigned int font_height;
twchar wtext[256];
char text[256];
char *p;
if (self == 0) /* if no bitmap */
@ -821,10 +819,9 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
if (self->password_char != 0)
{
i = g_mbstowcs(0, self->caption1, 0);
g_memset(text, self->password_char, i);
text[i] = 0;
xrdp_painter_draw_text(painter, self, 4, 2, text);
unsigned int repeat_count = utf8_char_count(self->caption1);
xrdp_painter_draw_char(painter, self, 4, 2, self->password_char,
repeat_count);
}
else
{
@ -838,18 +835,16 @@ xrdp_bitmap_invalidate(struct xrdp_bitmap *self, struct xrdp_rect *rect)
{
if (self->password_char != 0)
{
wchar_repeat(wtext, 255, self->password_char, self->edit_pos);
wtext[self->edit_pos] = 0;
g_wcstombs(text, wtext, 255);
w = xrdp_painter_repeated_char_width(painter,
self->password_char,
self->edit_pos);
}
else
{
g_mbstowcs(wtext, self->caption1, 255);
wtext[self->edit_pos] = 0;
g_wcstombs(text, wtext, 255);
w = xrdp_painter_text_width_count(painter, self->caption1,
self->edit_pos);
}
w = xrdp_painter_text_width(painter, text);
painter->fg_color = self->wm->white;
painter->rop = 0x5a;
xrdp_painter_fill_rect(painter, self, 4 + w, 3, 2, self->height - 6);
@ -1027,14 +1022,11 @@ int
xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg,
int param1, int param2)
{
twchar c;
int n;
int i;
int shift;
int ext;
int scan_code;
int num_bytes;
int num_chars;
struct xrdp_bitmap *b;
struct xrdp_bitmap *focus_out_control;
@ -1174,7 +1166,7 @@ xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg,
else if ((scan_code == 77 || scan_code == 80) &&
(ext || self->wm->num_lock == 0))
{
if (self->edit_pos < g_mbstowcs(0, self->caption1, 0))
if (self->edit_pos < (int)utf8_char_count(self->caption1))
{
self->edit_pos++;
xrdp_bitmap_invalidate(self, 0);
@ -1183,14 +1175,14 @@ xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg,
/* backspace */
else if (scan_code == 14)
{
n = g_mbstowcs(0, self->caption1, 0);
n = utf8_char_count(self->caption1);
if (n > 0)
{
if (self->edit_pos > 0)
{
self->edit_pos--;
remove_char_at(self->caption1, 255, self->edit_pos);
utf8_remove_char_at(self->caption1, self->edit_pos);
xrdp_bitmap_invalidate(self, 0);
}
}
@ -1199,13 +1191,13 @@ xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg,
else if (scan_code == 83 &&
(ext || self->wm->num_lock == 0))
{
n = g_mbstowcs(0, self->caption1, 0);
n = utf8_char_count(self->caption1);
if (n > 0)
{
if (self->edit_pos < n)
{
remove_char_at(self->caption1, 255, self->edit_pos);
utf8_remove_char_at(self->caption1, self->edit_pos);
xrdp_bitmap_invalidate(self, 0);
}
}
@ -1214,7 +1206,7 @@ xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg,
else if (scan_code == 79 &&
(ext || self->wm->num_lock == 0))
{
n = g_mbstowcs(0, self->caption1, 0);
n = utf8_char_count(self->caption1);
if (self->edit_pos < n)
{
@ -1234,16 +1226,15 @@ xrdp_bitmap_def_proc(struct xrdp_bitmap *self, int msg,
}
else
{
c = get_char_from_scan_code
(param2, scan_code, self->wm->keys, self->wm->caps_lock,
self->wm->num_lock, self->wm->scroll_lock,
&(self->wm->keymap));
num_chars = g_mbstowcs(0, self->caption1, 0);
num_bytes = g_strlen(self->caption1);
if ((c >= 32) && (num_chars < 127) && (num_bytes < 250))
char32_t c = get_char_from_scan_code
(param2, scan_code, self->wm->keys, self->wm->caps_lock,
self->wm->num_lock, self->wm->scroll_lock,
&(self->wm->keymap));
// Add a printing character to the string. If successful,
// bump the edit position and re-display the string
if (c >= ' ' &&
utf8_add_char_at(self->caption1, 256, c, self->edit_pos))
{
add_char_at(self->caption1, 255, c, self->edit_pos);
self->edit_pos++;
xrdp_bitmap_invalidate(self, 0);
}

View File

@ -467,7 +467,7 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
{
g_strncpy(b->caption1, value + ASK_LEN, 255);
}
b->edit_pos = g_mbstowcs(0, b->caption1, 0);
b->edit_pos = utf8_char_count(b->caption1);
if (self->login_window->focused_control == 0)
{
@ -486,7 +486,7 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
self->session->client_info->domain,
combo->data_list->count, 0, resultIP);
g_strncpy(b->caption1, resultIP, 255);
b->edit_pos = g_mbstowcs(0, b->caption1, 0);
b->edit_pos = utf8_char_count(b->caption1);
}
}
@ -495,7 +495,7 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
self->session->client_info->username[0])
{
g_strncpy(b->caption1, self->session->client_info->username, 255);
b->edit_pos = g_mbstowcs(0, b->caption1, 0);
b->edit_pos = utf8_char_count(b->caption1);
if (b->edit_pos > 0)
{

View File

@ -22,6 +22,8 @@
#include <config_ac.h>
#endif
#include <limits.h>
#include "xrdp.h"
#include "string_calls.h"
@ -428,37 +430,54 @@ xrdp_painter_rop(int rop, int src, int dst)
int
xrdp_painter_text_width(struct xrdp_painter *self, const char *text)
{
int index;
int rv;
int len;
struct xrdp_font_char *font_item;
twchar *wstr;
return xrdp_painter_text_width_count(self, text, UINT_MAX);
}
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_text_width:");
/*****************************************************************************/
int
xrdp_painter_text_width_count(struct xrdp_painter *self, const char *text,
unsigned int c32_count)
{
int rv = 0;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_text_width_count:");
xrdp_painter_font_needed(self);
if (self->font == 0)
if (self->font != NULL && text != NULL)
{
return 0;
unsigned int index;
for (index = 0 ; index < c32_count; ++index)
{
struct xrdp_font_char *font_item;
char32_t c32 = utf8_get_next_char(&text, NULL);
if (c32 == 0)
{
break; // Terminator
}
font_item = XRDP_FONT_GET_CHAR(self->font, c32);
rv += font_item->incby;
}
}
if (text == 0)
return rv;
}
/*****************************************************************************/
int
xrdp_painter_repeated_char_width(struct xrdp_painter *self,
char32_t chr, unsigned int repeat_count)
{
int rv = 0;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_repeated_char_width:");
xrdp_painter_font_needed(self);
if (self->font != NULL)
{
return 0;
struct xrdp_font_char *font_item = XRDP_FONT_GET_CHAR(self->font, chr);
rv = font_item->incby * repeat_count;
}
rv = 0;
len = g_mbstowcs(0, text, 0);
wstr = (twchar *)g_malloc((len + 2) * sizeof(twchar), 0);
g_mbstowcs(wstr, text, len + 1);
for (index = 0; index < len; index++)
{
font_item = XRDP_FONT_GET_CHAR(self->font, wstr[index]);
rv = rv + font_item->incby;
}
g_free(wstr);
return rv;
}
@ -764,10 +783,11 @@ xrdp_painter_fill_rect(struct xrdp_painter *self,
}
/*****************************************************************************/
int
xrdp_painter_draw_text(struct xrdp_painter *self,
struct xrdp_bitmap *dst,
int x, int y, const char *text)
static int
xrdp_painter_draw_utf32(struct xrdp_painter *self,
struct xrdp_bitmap *dst,
int x, int y,
char32_t utf32[], unsigned int utf32len)
{
int i;
int f;
@ -776,8 +796,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
int x1;
int y1;
int flags;
int len;
int index;
unsigned int index;
int total_width;
int total_height;
int dx;
@ -789,7 +808,6 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
struct xrdp_rect draw_rect;
struct xrdp_font *font;
struct xrdp_font_char *font_item;
twchar *wstr;
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_painter_draw_text:");
@ -798,9 +816,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
return 0;
}
len = g_mbstowcs(0, text, 0);
if (len < 1)
if (utf32len < 1)
{
return 0;
}
@ -829,15 +845,15 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
if (dst->type != WND_TYPE_OFFSCREEN)
{
ldst = self->wm->screen;
/* convert to wide char */
wstr = (twchar *)g_malloc((len + 2) * sizeof(twchar), 0);
g_mbstowcs(wstr, text, len + 1);
font = self->font;
// Calculate total width and height fields
total_width = 0;
total_height = 0;
for (index = 0; index < len; index++)
for (index = 0 ; index < utf32len; ++index)
{
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
font_item = XRDP_FONT_GET_CHAR(font, utf32[index]);
k = font_item->incby;
total_width += k;
/* Use the nominal height of the font to work out the
@ -846,6 +862,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
font->body_height + font_item->baseline + font_item->height;
total_height = MAX(total_height, glyph_height);
}
xrdp_bitmap_get_screen_clip(dst, self, &clip_rect, &dx, &dy);
region = xrdp_region_create(self->wm);
xrdp_wm_get_vis_region(self->wm, dst, x, y,
@ -873,9 +890,9 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
draw_rect.left, draw_rect.top,
draw_rect.right - draw_rect.left,
draw_rect.bottom - draw_rect.top);
for (index = 0; index < len; index++)
for (index = 0 ; index < utf32len; ++index)
{
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
font_item = XRDP_FONT_GET_CHAR(font, utf32[index]);
g_memset(&pat, 0, sizeof(pat));
pat.format = PT_FORMAT_c1;
pat.width = font_item->width;
@ -899,25 +916,22 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
}
painter_clear_clip(self->painter);
xrdp_region_delete(region);
g_free(wstr);
}
return 0;
#endif
}
/* convert to wide char */
wstr = (twchar *)g_malloc((len + 2) * sizeof(twchar), 0);
g_mbstowcs(wstr, text, len + 1);
font = self->font;
f = 0;
k = 0;
total_width = 0;
total_height = 0;
data = (char *)g_malloc(len * 4, 1);
index = 0;
data = (char *)g_malloc(utf32len * 2, 1);
for (index = 0; index < len; index++)
for (index = 0 ; index < utf32len; ++index)
{
font_item = XRDP_FONT_GET_CHAR(font, wstr[index]);
font_item = XRDP_FONT_GET_CHAR(font, utf32[index]);
i = xrdp_cache_add_char(self->wm->cache, font_item);
f = HIWORD(i);
c = LOWORD(i);
@ -960,7 +974,7 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
self->fg_color, 0,
x - 1, y - 1, x + total_width, y + total_height,
0, 0, 0, 0,
x1, y1, data, len * 2, &draw_rect);
x1, y1, data, utf32len * 2, &draw_rect);
}
k++;
@ -968,10 +982,44 @@ xrdp_painter_draw_text(struct xrdp_painter *self,
xrdp_region_delete(region);
g_free(data);
g_free(wstr);
return 0;
}
/*****************************************************************************/
int
xrdp_painter_draw_text(struct xrdp_painter *self,
struct xrdp_bitmap *dst,
int x, int y, const char *text)
{
int rv = 0;
unsigned int c32_count = utf8_char_count(text);
if (c32_count > 0)
{
char32_t *utf32 = (char32_t *)malloc(c32_count * sizeof(char32_t));
if (utf32 == NULL)
{
rv = 1;
}
else
{
unsigned int i = 0;
char32_t c32;
while ((c32 = utf8_get_next_char(&text, NULL)) != 0)
{
utf32[i++] = c32;
}
rv = xrdp_painter_draw_utf32(self, dst, x, y, utf32, c32_count);
free (utf32);
}
}
return rv;
}
/*****************************************************************************/
int
xrdp_painter_draw_text2(struct xrdp_painter *self,
@ -1063,6 +1111,40 @@ xrdp_painter_draw_text2(struct xrdp_painter *self,
return 0;
}
/*****************************************************************************/
int
xrdp_painter_draw_char(struct xrdp_painter *self,
struct xrdp_bitmap *dst,
int x, int y, char32_t chr,
unsigned int repeat_count)
{
int rv = 0;
if (repeat_count > 0)
{
char32_t *utf32 =
(char32_t *)malloc(repeat_count * sizeof(char32_t));
if (utf32 == NULL)
{
rv = 1;
}
else
{
unsigned int i = 0;
for (i = 0; i < repeat_count; ++i)
{
utf32[i] = chr;
}
rv = xrdp_painter_draw_utf32(self, dst, x, y, utf32, repeat_count);
free (utf32);
}
}
return rv;
}
/*****************************************************************************/
int
xrdp_painter_copy(struct xrdp_painter *self,

View File

@ -419,7 +419,7 @@ struct xrdp_mm
struct xrdp_key_info
{
int sym;
int chr;
char32_t chr;
};
struct xrdp_keymap
@ -632,7 +632,7 @@ struct xrdp_bitmap
struct list *child_list;
/* for edit */
int edit_pos;
twchar password_char;
char32_t password_char;
/* for button or combo */
int state; /* for button 0 = normal 1 = down */
/* for combo */

View File

@ -1645,8 +1645,8 @@ xrdp_wm_key_sync(struct xrdp_wm *self, int device_flags, int key_flags)
}
/*****************************************************************************/
int
xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, int unicode)
static int
xrdp_wm_key_unicode(struct xrdp_wm *self, int device_flags, char32_t unicode)
{
int index;