commit e6a8ecf9116eb9cec8ed1da33d69c91988f55e86
parent 1242d3b3fcdb252a60c422b8eb15396e641fd656
Author: lumidify <nobody@lumidify.org>
Date: Thu, 14 May 2020 11:37:48 +0200
Switch from gap buffers to arrays
Diffstat:
6 files changed, 143 insertions(+), 137 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,7 +1,7 @@
LIBS = -lm `pkg-config --libs x11 harfbuzz fontconfig fribidi`
STD = -std=c99
CFLAGS = -g -w -fcommon -Wall -Werror -Wextra `pkg-config --cflags x11 harfbuzz fontconfig fribidi` -pedantic
-OBJ = stb_truetype.o text-common.o text_buffer.o text-hb.o ltk.o ini.o grid.o button.o test1.o
+OBJ = stb_truetype.o text_edit.o text-common.o text_buffer.o text-hb.o ltk.o ini.o grid.o button.o test1.o
test1: $(OBJ)
gcc $(STD) -o $@ $(OBJ) $(LIBS)
diff --git a/array.h b/array.h
@@ -33,7 +33,13 @@ struct ltk_array_##name { \
size_t buf_size; \
size_t len; \
}; \
+ \
struct ltk_array_##name *ltk_array_create_##name(size_t initial_len); \
+type ltk_array_pop_##name(struct ltk_array_##name *ar); \
+void ltk_array_prepare_gap_##name( \
+ struct ltk_array_##name *ar, size_t index, size_t len); \
+void ltk_array_insert_##name(struct ltk_array_##name *ar, size_t index, \
+ type *elem, size_t len); \
void ltk_array_resize_##name(struct ltk_array_##name *ar, size_t size); \
void ltk_array_destroy_##name(struct ltk_array_##name *ar); \
void ltk_array_clear_##name(struct ltk_array_##name *ar); \
@@ -57,6 +63,39 @@ error: \
exit(1); \
} \
\
+type \
+ltk_array_pop_##name(struct ltk_array_##name *ar) { \
+ if (ar->len == 0) { \
+ (void)fprintf(stderr, "Array empty; cannot pop.\n"); \
+ exit(1); \
+ } \
+ ar->len--; \
+ return ar->buf[ar->len]; \
+} \
+ \
+void \
+ltk_array_prepare_gap_##name(struct ltk_array_##name *ar, size_t index, size_t len) { \
+ if (index > ar->len) { \
+ (void)fprintf(stderr, "Array index out of bounds\n"); \
+ exit(1); \
+ } \
+ ltk_array_resize_##name(ar, ar->len + len); \
+ ar->len += len; \
+ if (ar->len == index) \
+ return; \
+ memmove(ar->buf + index + len, ar->buf + index, ar->len - index); \
+} \
+ \
+void \
+ltk_array_insert_##name(struct ltk_array_##name *ar, size_t index, \
+ type *elem, size_t len) { \
+ ltk_array_prepare_gap_##name(ar, index, len); \
+ ltk_array_resize_##name(ar, ar->len + len); \
+ for (int i = 0; i < len; i++) { \
+ ar->buf[index + i] = elem[i]; \
+ } \
+} \
+ \
void \
ltk_array_append_##name(struct ltk_array_##name *ar, type elem) { \
if (ar->len == ar->buf_size) \
diff --git a/text_buffer.c b/text_buffer.c
@@ -34,25 +34,21 @@
#include <harfbuzz/hb.h>
#include <harfbuzz/hb-ot.h>
#include "text-common.h"
-#include "gap_buffer.h"
#include "array.h"
-#include "stack.h"
#include "text_buffer.h"
#include "ltk.h"
extern Ltk *ltk_global;
-LTK_GAP_BUFFER_INIT_IMPL(uint32, uint32_t)
-LTK_GAP_BUFFER_INIT_IMPL(script, hb_script_t)
-LTK_GAP_BUFFER_INIT_IMPL(int, int)
+LTK_ARRAY_INIT_IMPL(uint32, uint32_t)
+LTK_ARRAY_INIT_IMPL(script, hb_script_t)
LTK_ARRAY_INIT_IMPL(level, FriBidiLevel)
LTK_ARRAY_INIT_IMPL(int, int)
-LTK_STACK_INIT_IMPL(script, int, hb_script_t, pair_index, script)
/* based on http://codemadness.org/git/dwm-font/file/drw.c.html#l315 */
/* FIXME: rename this once everything is cleaned up (currently conflicts with the
old render function */
-void
+XImage *
ltk_render_text_line_new(
struct ltk_text_line *tl,
int max_width,
@@ -63,6 +59,7 @@ ltk_render_text_line_new(
XColor fg,
XColor bg)
{
+ XImage *img;
int cur_x = 0, cur_y = 0;
int par_is_rtl = FRIBIDI_IS_RTL(tl->dir);
ltk_array_clear_int(tl->wrap_indeces);
@@ -91,21 +88,20 @@ ltk_render_text_line_new(
}
} while (cur = cur->next);
- if (tl->img) XDestroyImage(tl->img);
XWindowAttributes attrs;
XGetWindowAttributes(dpy, window, &attrs);
int depth = attrs.depth;
- tl->img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, max_width, tl->h * tl->wrap_indeces->len, 32, 0);
- tl->img->data = calloc(tl->img->bytes_per_line, tl->img->height);
- XInitImage(tl->img);
+ img = XCreateImage(dpy, CopyFromParent, depth, ZPixmap, 0, NULL, max_width, tl->h * tl->wrap_indeces->len, 32, 0);
+ img->data = calloc(img->bytes_per_line, img->height);
+ XInitImage(img);
int b;
for (int i = 0; i < tl->h * tl->wrap_indeces->len; i++) {
- b = tl->img->bytes_per_line * i;
+ b = img->bytes_per_line * i;
for (int j = 0; j < max_width; j++) {
- tl->img->data[b++] = bg.blue / 257;
- tl->img->data[b++] = bg.green / 257;
- tl->img->data[b++] = bg.red / 257;
+ img->data[b++] = bg.blue / 257;
+ img->data[b++] = bg.green / 257;
+ img->data[b++] = bg.red / 257;
b++;
}
}
@@ -132,11 +128,11 @@ ltk_render_text_line_new(
y = glyph->y_abs + tl->h * cur_line;
for (int i = 0; i < glyph->info->h; i++) {
for (int j = 0; j < glyph->info->w; j++) {
- b = (y + i) * tl->img->bytes_per_line + (x + j) * 4;
+ b = (y + i) * img->bytes_per_line + (x + j) * 4;
a = glyph->info->alphamap[i * glyph->info->w + j] / 255.0;
- tl->img->data[b] = (fg.blue * a + (1 - a) * (uint16_t)tl->img->data[b] * 257) / 257;
- tl->img->data[b + 1] = (fg.green * a + (1 - a) * (uint16_t)tl->img->data[b + 1] * 257) / 257;
- tl->img->data[b + 2] = (fg.red * a + (1 - a) * (uint16_t)tl->img->data[b + 2] * 257) / 257;
+ img->data[b] = (fg.blue * a + (1 - a) * (uint16_t)img->data[b] * 257) / 257;
+ img->data[b + 1] = (fg.green * a + (1 - a) * (uint16_t)img->data[b + 1] * 257) / 257;
+ img->data[b + 2] = (fg.red * a + (1 - a) * (uint16_t)img->data[b + 2] * 257) / 257;
}
}
}
@@ -144,31 +140,6 @@ ltk_render_text_line_new(
}
}
-/*
-NOTE: The following notes are outdated.
-Notes: When inserting a character, check what the direction of the surrounding
-script is - if it is the same (or a weak direction), then just insert the char
-without re-doing the bidi algorithm. Only redo the whole line/paragraph is the
-dir of the inserted character is different. Assume the text is LTR until a strong
-character is inserted, i.e. the line should keep a flag if it already has a strong
-dir set.
-When reordering, the cursor needs to be kept in the right place:
-a) The logical to visual mapping from FriBidi needs to be used to find the position
-of the cursor in the text that gets passed to Harfbuzz.
-b) The cluster values from Harfbuzz need to be used to figure out where the cursor
-is on the screen.
-Harfbuzz also should be given some context - maybe even completely reshape the
-text until the last and next space? That would only be a problem with weird very
-long words (mainly nonsense). At least maybe take up to five or so chars on each
-side and pass even more with the optional context-passing feature for hb_shape.
-Question: Does both the logical and visual text need to be stored? The logical text
-is technically the master copy, but the visual text is what gets passed to harfbuzz.
--> Actually, since the visual text has to be split into script runs anyways, maybe
-just append text to that (and also add it to the master buffer simultaneously). As
-soon as a different script is inserted, everything has to be redone anyways. Also,
-when reshaping with context, only the text in the current run has to be passed at all.
-*/
-
/* Begin stuff stolen from raqm */
/* Special paired characters for script detection */
@@ -211,7 +182,7 @@ get_pair_index (const FriBidiChar ch) {
return -1;
}
-#define STACK_IS_EMPTY(stack) ((stack)->size <= 0)
+#define STACK_IS_EMPTY(stack) ((stack)->len <= 0)
#define IS_OPEN(pair_index) (((pair_index) & 1) == 0)
/* Resolve the script for each character in the input string, if the character
@@ -225,50 +196,52 @@ ltk_resolve_scripts(struct ltk_text_line *tl) {
int last_set_index = -1;
hb_script_t last_script = HB_SCRIPT_INVALID;
hb_script_t cur_script;
- struct ltk_stack_script *stack = NULL;
+ struct ltk_array_script *script_stack = NULL;
+ struct ltk_array_int *pair_indeces = NULL;
hb_unicode_funcs_t* unicode_funcs = hb_unicode_funcs_get_default();
- stack = ltk_stack_create_script(tl->len);
+ script_stack = ltk_array_create_script(4);
+ pair_indeces = ltk_array_create_int(4);
for (int i = 0; i < (int) tl->len; i++) {
- cur_script = ltk_gap_buffer_get_script(tl->scripts, i);
+ cur_script = tl->scripts->buf[i];
if (cur_script == HB_SCRIPT_COMMON && last_script_index != -1) {
- int pair_index = get_pair_index(ltk_gap_buffer_get_uint32(tl->log_buf, i));
+ int pair_index = get_pair_index(tl->log_buf->buf[i]);
if (pair_index >= 0) {
if (IS_OPEN (pair_index)) {
/* is a paired character */
- ltk_gap_buffer_set_script(tl->scripts, i, last_script);
+ tl->scripts->buf[i] = last_script;
last_set_index = i;
- ltk_stack_push_script(stack, cur_script, pair_index);
+ ltk_array_append_script(script_stack, cur_script);
+ ltk_array_append_int(pair_indeces, pair_index);
} else {
/* is a close paired character */
/* find matching opening (by getting the last
* even index for current odd index) */
- while (!STACK_IS_EMPTY(stack) &&
- stack->pair_index[stack->size] != (pair_index & ~1)) {
- ltk_stack_pop_script(stack);
+ while (!STACK_IS_EMPTY(pair_indeces) &&
+ pair_indeces->buf[pair_indeces->len-1] != (pair_index & ~1)) {
+ ltk_array_pop_script(script_stack);
+ ltk_array_pop_int(pair_indeces);
}
- if (!STACK_IS_EMPTY(stack)) {
- ltk_gap_buffer_set_script(
- tl->scripts, i,
- ltk_stack_top2_script(stack, HB_SCRIPT_INVALID));
+ if (!STACK_IS_EMPTY(script_stack)) {
+ tl->scripts->buf[i] = script_stack->buf[script_stack->len-1];
last_script = cur_script;
last_set_index = i;
} else {
- ltk_gap_buffer_set_script(tl->scripts, i, last_script);
+ tl->scripts->buf[i] = last_script;
last_set_index = i;
}
}
} else {
- ltk_gap_buffer_set_script(tl->scripts, i, last_script);
+ tl->scripts->buf[i] = last_script;
last_set_index = i;
}
} else if (cur_script == HB_SCRIPT_INHERITED && last_script_index != -1) {
- ltk_gap_buffer_set_script(tl->scripts, i, last_script);
+ tl->scripts->buf[i] = last_script;
last_set_index = i;
} else {
for (int j = last_set_index + 1; j < i; ++j)
- ltk_gap_buffer_set_script(tl->scripts, j, cur_script);
+ tl->scripts->buf[j] = cur_script;
last_script = cur_script;
last_script_index = i;
last_set_index = i;
@@ -281,14 +254,14 @@ ltk_resolve_scripts(struct ltk_text_line *tl) {
*/
hb_script_t scr;
for (int i = tl->len - 2; i >= 0; --i) {
- scr = ltk_gap_buffer_get_script(tl->scripts, i);
+ scr = tl->scripts->buf[i];
if (scr == HB_SCRIPT_INHERITED || scr == HB_SCRIPT_COMMON) {
- ltk_gap_buffer_set_script(tl->scripts, i,
- ltk_gap_buffer_get_script(tl->scripts, i + 1));
+ tl->scripts->buf[i] = tl->scripts->buf[i + 1];
}
}
- ltk_stack_destroy_script(stack);
+ ltk_array_destroy_script(script_stack);
+ ltk_array_destroy_int(pair_indeces);
return 1;
}
@@ -327,12 +300,12 @@ ltk_text_line_itemize(struct ltk_text_line *tl) {
while (start_index < tl->len) {
end_index = start_index;
cur_level = last_level = tl->bidi_levels->buf[start_index];
- cur_script = last_script = ltk_gap_buffer_get_script(tl->scripts, start_index);
+ cur_script = last_script = tl->scripts->buf[start_index];
while (end_index < tl->len &&
cur_level == last_level && cur_script == last_script) {
end_index++;
cur_level = tl->bidi_levels->buf[end_index];
- cur_script = ltk_gap_buffer_get_script(tl->scripts, end_index);
+ cur_script = tl->scripts->buf[end_index];
}
dir = HB_DIRECTION_LTR;
if (FRIBIDI_LEVEL_IS_RTL(last_level))
@@ -466,7 +439,7 @@ ltk_text_line_shape(LtkTextManager *tm, struct ltk_text_line *tl) {
FcDefaultSubstitute(pat);
FcCharSet *cs = FcCharSetCreate();
for (int i = run->start_index; i < run->start_index + run->len; i++) {
- FcCharSetAddChar(cs, ltk_gap_buffer_get_uint32(tl->vis_buf, i));
+ FcCharSetAddChar(cs, tl->vis_buf->buf[i]);
}
FcPatternAddCharSet(pat, FC_CHARSET, cs);
match = FcFontMatch(NULL, pat, &result);
@@ -546,21 +519,10 @@ ltk_text_line_destroy_runs(struct ltk_text_run *runs) {
static void
ltk_text_line_recalculate(LtkTextManager *tm, struct ltk_text_line *tl) {
- ltk_gap_buffer_clear_uint32(tl->vis_buf);
- ltk_gap_buffer_clear_int(tl->log2vis);
- ltk_gap_buffer_clear_int(tl->vis2log);
- /* yeah, this is hacky */
- tl->vis_buf->len = tl->vis_buf->buf_size;
- tl->log2vis->len = tl->log2vis->buf_size;
- tl->vis2log->len = tl->vis2log->buf_size;
- size_t gap_pos = tl->log_buf->gap_left;
- size_t gap_end = tl->log_buf->buf_size - tl->log_buf->gap_size;
- ltk_gap_buffer_move_gap_uint32(tl->log_buf, gap_end);
fribidi_log2vis(
- tl->log_buf, tl->log_buf->buf_size - tl->log_buf->gap_size,
+ tl->log_buf, tl->log_buf->len,
&tl->dir, tl->vis_buf, tl->log2vis, tl->vis2log, tl->bidi_levels
);
- ltk_gap_buffer_move_gap_uint32(tl->log_buf, gap_pos);
struct ltk_text_run *old_runs = tl->first_run;
ltk_text_line_itemize(tl);
ltk_text_line_shape(tm, tl);
@@ -573,38 +535,17 @@ ltk_text_line_recalculate(LtkTextManager *tm, struct ltk_text_line *tl) {
void
ltk_text_line_insert_text(struct ltk_text_line *tl, uint32_t *text, size_t len) {
- /* check if any characters have a different script, only recalc then */
- /*
- hb_unicode_funcs_t *uf= hb_unicode_funcs_get_default();
- struct ltk_text_run *run = tl->cur_run;
- int recalc = 0;
- hb_script_t script;
- for (int i = 0; i < len; i++) {
- scr = hb_unicode_script(uf, text[i]);
- if (script != run->script &&
- script != HB_SCRIPT_INHERITED &&
- script != HB_SCRIPT_COMMON) {
- recalc = 1;
- }
- }
- */
- ltk_gap_buffer_insert_uint32(tl->log_buf, text, 0, len);
- if (len > tl->scripts->gap_size)
- ltk_gap_buffer_resize_gap_script(tl->scripts, len + 8);
+ ltk_array_insert_uint32(tl->log_buf, tl->cursor_pos, text, len);
+ ltk_array_prepare_gap_script(tl->scripts, tl->cursor_pos, len);
hb_unicode_funcs_t *ufuncs = hb_unicode_funcs_get_default();
- for (int i = 0; i < len; i++) {
- ltk_gap_buffer_insert_single_script(
- tl->scripts, hb_unicode_script(ufuncs, text[i]));
- }
- if (len > tl->vis_buf->gap_size)
- ltk_gap_buffer_resize_gap_uint32(tl->vis_buf, len + 8);
- if (len > tl->log2vis->gap_size)
- ltk_gap_buffer_resize_gap_int(tl->log2vis, len + 8);
- if (len > tl->vis2log->gap_size)
- ltk_gap_buffer_resize_gap_int(tl->vis2log, len + 8);
- if (len + tl->bidi_levels->len > tl->bidi_levels->buf_size)
- ltk_array_resize_level(tl->bidi_levels, tl->bidi_levels->len + len + 8);
+ for (int i = 0; i < len; i++)
+ tl->scripts->buf[tl->cursor_pos + i] = hb_unicode_script(ufuncs, text[i]);
+ ltk_array_resize_uint32(tl->vis_buf, tl->vis_buf->len + len);
+ ltk_array_resize_int(tl->log2vis, tl->log2vis->len + len);
+ ltk_array_resize_int(tl->vis2log, tl->vis2log->len + len);
+ ltk_array_resize_level(tl->bidi_levels, tl->bidi_levels->len + len);
tl->len += len;
+ tl->cursor_pos += len;
/* FIXME: Why am I passing tm? It's global anyways */
ltk_text_line_recalculate(tl, ltk_global->tm);
}
@@ -629,12 +570,12 @@ struct ltk_text_line *
ltk_text_line_create(void) {
struct ltk_text_line *line = malloc(sizeof(struct ltk_text_line));
if (!line) goto error;
- line->log_buf = ltk_gap_buffer_create_uint32();
- line->scripts = ltk_gap_buffer_create_script();
- line->vis_buf = ltk_gap_buffer_create_uint32();
- line->log2vis = ltk_gap_buffer_create_int();
- line->vis2log = ltk_gap_buffer_create_int();
- line->bidi_levels = ltk_array_create_level(8);
+ line->log_buf = ltk_array_create_uint32(4);
+ line->vis_buf = ltk_array_create_uint32(4);
+ line->log2vis = ltk_array_create_int(4);
+ line->vis2log = ltk_array_create_int(4);
+ line->scripts = ltk_array_create_script(4);
+ line->bidi_levels = ltk_array_create_level(4);
line->wrap_indeces = ltk_array_create_int(1);
line->first_run = NULL;
line->cur_run = NULL;
@@ -642,6 +583,7 @@ ltk_text_line_create(void) {
line->height = 0;
line->dir = FRIBIDI_TYPE_ON;
line->len = 0;
+ line->cursor_pos = 0;
error:
(void)fprintf(stderr, "No memory left while creating text line\n");
exit(1);
@@ -661,14 +603,13 @@ ltk_text_buffer_create(void) {
void
ltk_text_line_destroy(struct ltk_text_line *tl) {
- ltk_gap_buffer_destroy_uint32(tl->log_buf);
- ltk_gap_buffer_destroy_uint32(tl->vis_buf);
- ltk_gap_buffer_destroy_script(tl->scripts);
- ltk_gap_buffer_destroy_int(tl->log2vis);
- ltk_gap_buffer_destroy_int(tl->vis2log);
+ ltk_array_destroy_uint32(tl->log_buf);
+ ltk_array_destroy_uint32(tl->vis_buf);
+ ltk_array_destroy_script(tl->scripts);
+ ltk_array_destroy_int(tl->log2vis);
+ ltk_array_destroy_int(tl->vis2log);
ltk_array_destroy_level(tl->bidi_levels);
ltk_array_destroy_int(tl->wrap_indeces);
ltk_text_line_destroy_runs(tl->first_run);
- if (tl->img) XDestroyImage(tl->img);
free(tl);
}
diff --git a/text_buffer.h b/text_buffer.h
@@ -33,12 +33,10 @@ Requires the following includes:
/* Note: hb_script_t and FriBidiLevel are really just uint32_t's, but
I'm not sure if I should rely on that, so they're separate here */
-LTK_GAP_BUFFER_INIT_DECL(uint32, uint32_t)
-LTK_GAP_BUFFER_INIT_DECL(script, hb_script_t)
-LTK_GAP_BUFFER_INIT_DECL(int, int)
+LTK_ARRAY_INIT_DECL(uint32, uint32_t)
+LTK_ARRAY_INIT_DECL(script, hb_script_t)
LTK_ARRAY_INIT_DECL(level, FriBidiLevel)
LTK_ARRAY_INIT_DECL(int, int)
-LTK_STACK_INIT_DECL(script, int, hb_script_t, pair_index, script)
struct ltk_text_run {
LtkGlyph *glyphs;
@@ -58,26 +56,26 @@ struct ltk_text_run {
};
struct ltk_text_line {
- struct ltk_gap_buffer_uint32 *log_buf; /* buffer of the logical text */
- struct ltk_gap_buffer_script *scripts;
- struct ltk_gap_buffer_uint32 *vis_buf; /* buffer of visual text */
- struct ltk_gap_buffer_int *log2vis;
- struct ltk_gap_buffer_int *vis2log;
+ struct ltk_array_uint32 *log_buf; /* buffer of the logical text */
+ struct ltk_array_script *scripts;
+ struct ltk_array_uint32 *vis_buf; /* buffer of visual text */
+ struct ltk_array_int *log2vis;
+ struct ltk_array_int *vis2log;
struct ltk_array_level *bidi_levels;
+ struct ltk_array_int *wrap_indeces;
struct ltk_text_run *first_run; /* first node in the linked list of runs */
struct ltk_text_run *last_run; /* last node in the linked list of runs */
struct ltk_text_run *cur_run; /* current node in the linked list of runs */
struct ltk_text_line *next; /* next text line in the buffer */
unsigned int height; /* height of the line (including wrapping) */
FriBidiCharType dir; /* overall paragraph direction */
- struct ltk_array_int *wrap_indeces;
size_t len;
uint16_t font_size;
int y_max;
int y_min;
int w;
int h;
- XImage *img;
+ size_t cursor_pos;
};
struct ltk_text_buffer {
@@ -86,4 +84,10 @@ struct ltk_text_buffer {
unsigned int line_gap;
};
+XImage *ltk_render_text_line_new(struct ltk_text_line *tl, int max_width,
+ Display *dpy, Window window, GC gc, Colormap colormap, XColor fg, XColor bg);
+void ltk_text_line_insert_text(struct ltk_text_line *tl, uint32_t *text, size_t len);
+struct ltk_text_line *ltk_text_line_create(void);
+void ltk_text_line_destroy(struct ltk_text_line *tl);
+
#endif /* _TEXT_BUFFER_H_ */
diff --git a/text_edit.c b/text_edit.c
@@ -21,6 +21,20 @@
* SOFTWARE.
*/
+#include <stdint.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "khash.h"
+#include "ltk.h"
+#include "stb_truetype.h"
+#include <fribidi.h>
+#include <harfbuzz/hb.h>
+#include <fontconfig/fontconfig.h>
+#include "text-common.h"
+#include "array.h"
+#include "text_buffer.h"
+#include "text_edit.h"
+
extern Ltk *ltk_global;
void
@@ -29,9 +43,9 @@ ltk_draw_text_edit(LtkTextEdit *te) {
XColor bg = ltk_global->theme->window->bg;
LtkRect rect = te->widget.rect;
LtkWindow *window = te->widget.window;
- if (!te->tl->img)
+ if (!te->img)
ltk_render_text_line_new(te->tl, rect.w, ltk_global->display, window->xwindow, window->gc, ltk_global->colormap, fg, bg);
- XPutImage(ltk_global->display, window->xwindow, window->gc, te->tl->img, 0, 0, rect.x, rect.y, te->tl->w, te->tl->h);
+ XPutImage(ltk_global->display, window->xwindow, window->gc, te->img, 0, 0, rect.x, rect.y, te->tl->w, te->tl->h);
}
LtkTextEdit *ltk_create_text_edit(LtkWindow *window, const char *text) {
@@ -41,8 +55,10 @@ LtkTextEdit *ltk_create_text_edit(LtkWindow *window, const char *text) {
ltk_fill_widget_defaults(&te->widget, window, <k_draw_text_edit, <k_destroy_text_edit, 1);
te->tl = ltk_text_line_create();
ltk_text_line_insert_utf8(te->tl, text);
+ te->img = NULL;
}
void ltk_destroy_text_edit(LtkTextEdit *te) {
ltk_text_line_destroy(te->tl);
+ if (te->img) XDestroyImage(te->img);
free(te);
}
diff --git a/text_edit.h b/text_edit.h
@@ -21,8 +21,12 @@
* SOFTWARE.
*/
+#ifndef _LTK_TEXT_EDIT_H_
+#define _LTK_TEXT_EDIT_H_
+
typedef struct {
LtkWidget widget;
+ XImage *img;
struct ltk_text_line *tl;
} LtkTextEdit;
@@ -30,3 +34,5 @@ typedef struct {
void ltk_draw_text_edit(LtkTextEdit *te);
LtkTextEdit *ltk_create_text_edit(LtkWindow *window, const char *text);
void ltk_destroy_text_edit(LtkTextEdit *te);
+
+#endif /* _LTK_TEXT_EDIT_H_ */