xF: make sure the caret is visible in X11 editor
This commit is contained in:
@@ -837,8 +837,8 @@ app_editor_position (void)
|
||||
size_t position = 0;
|
||||
for (int i = 0; i < g.editor.point; i++)
|
||||
{
|
||||
uint8_t encoded[6];
|
||||
int len = u8_uctomb (encoded, g.editor.line[i], sizeof encoded);
|
||||
uint8_t utf8[6];
|
||||
int len = u8_uctomb (utf8, g.editor.line[i], sizeof utf8);
|
||||
if (len > 0)
|
||||
position += len;
|
||||
}
|
||||
@@ -1954,44 +1954,67 @@ tui_make_editor (chtype attrs)
|
||||
#ifdef WITH_X11
|
||||
|
||||
static void
|
||||
x11_render_editor (struct widget *self)
|
||||
x11_process_editor (struct widget *self, int *x, int *caret, bool draw)
|
||||
{
|
||||
x11_render_padding (self);
|
||||
|
||||
struct x11_font *font = x11_widget_font (self);
|
||||
XftColor color = { .color = *x11_fg (self) };
|
||||
XftColor fg = { .color = *x11_fg (self) }, bg = { .color = *x11_bg (self) };
|
||||
|
||||
// A simplistic adaptation of tui_render_editor() follows.
|
||||
// TODO: Make this scroll around the caret, and fade like labels.
|
||||
int x = self->x;
|
||||
int caret = x;
|
||||
for (size_t i = 0; i < g.editor.len; i++)
|
||||
{
|
||||
if ((int) i == g.editor.point)
|
||||
caret = x;
|
||||
*caret = *x;
|
||||
|
||||
ucs4_t codepoint = g.editor.line[i];
|
||||
if (!iscntrl_ascii (codepoint))
|
||||
{
|
||||
uint8_t encoded[7] = {};
|
||||
if (u8_uctomb (encoded, codepoint, sizeof encoded - 1) > 0)
|
||||
x += x11_font_draw (font, &color, x, self->y, (char *) encoded);
|
||||
uint8_t utf8[7] = {};
|
||||
if (u8_uctomb (utf8, codepoint, sizeof utf8 - 1) > 0)
|
||||
*x += draw
|
||||
? x11_font_draw (font, &fg, *x, self->y, (char *) utf8)
|
||||
: x11_font_hadvance (font, (char *) utf8);
|
||||
continue;
|
||||
}
|
||||
|
||||
char escaped[] = { '^', codepoint == 127 ? '?' : codepoint + 64, 0 };
|
||||
int width = x11_font_hadvance (font, escaped);
|
||||
XRenderFillRectangle (g_xui.dpy, PictOpSrc, g_xui.x11_pixmap_picture,
|
||||
x11_fg (self), x, self->y, width, self->height);
|
||||
XftColor reverse = { .color = *x11_bg (self) };
|
||||
x += x11_font_draw (font, &reverse, x, self->y, escaped);
|
||||
if (draw)
|
||||
{
|
||||
XftDrawRect (g_xui.xft_draw, &fg, *x, self->y, width, self->height);
|
||||
*x += x11_font_draw (font, &bg, *x, self->y, escaped);
|
||||
}
|
||||
else
|
||||
*x += width;
|
||||
}
|
||||
if (g.editor.point == (int) g.editor.len)
|
||||
caret = x;
|
||||
*caret = *x;
|
||||
}
|
||||
|
||||
static void
|
||||
x11_render_editor (struct widget *self)
|
||||
{
|
||||
enum { CARET_WIDTH = 2 };
|
||||
|
||||
int caret = 0, width = 0;
|
||||
x11_process_editor (self, &width, &caret, false);
|
||||
|
||||
// Automatically scroll around the caret by changing where we start drawing:
|
||||
int x = self->x, width_limit = self->width - CARET_WIDTH;
|
||||
if (width > width_limit)
|
||||
{
|
||||
// Push it to the left until the caret is in the middle...
|
||||
int offset = MAX (0, caret - width_limit / 2);
|
||||
// ...but then push it to the right until text fills the whole width.
|
||||
offset = MIN (offset, width - width_limit);
|
||||
|
||||
x -= offset;
|
||||
}
|
||||
|
||||
x11_render_padding (self);
|
||||
x11_process_editor (self, &x, &caret, true);
|
||||
|
||||
XRenderColor white = { 0xffff, 0xffff, 0xffff, 0xffff };
|
||||
XRenderFillRectangle (g_xui.dpy, PictOpDifference, g_xui.x11_pixmap_picture,
|
||||
&white, caret, self->y, 2, self->height);
|
||||
&white, caret, self->y, CARET_WIDTH, self->height);
|
||||
}
|
||||
|
||||
static struct widget *
|
||||
@@ -2003,7 +2026,11 @@ x11_make_editor (chtype attrs)
|
||||
widget->width = -1;
|
||||
widget->height = g_xui.vunit;
|
||||
widget->text = "";
|
||||
return widget;
|
||||
|
||||
// Enforce clipping by putting this inside a container.
|
||||
struct widget *wrapper = xui_hbox (widget);
|
||||
wrapper->width = -1;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
static struct xui_scrollbar_part
|
||||
|
||||
Reference in New Issue
Block a user