Introduction
Introduction Statistics Contact Development Disclaimer Help
tModify cache to cache individual lines - ledit - Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/git/ledit.git (encrypted, but very slow)
Log
Files
Refs
README
LICENSE
---
commit 88b7f6c08a1e2a47f33aa5b4d33f18df60b5011f
parent e9c86a9b95b0a349d3f34f2a15dd3afffafc3b52
Author: lumidify <[email protected]>
Date: Sat, 10 Apr 2021 21:18:46 +0200
Modify cache to cache individual lines
Diffstat:
M ledit.c | 291 +++++++++++------------------…
1 file changed, 106 insertions(+), 185 deletions(-)
---
diff --git a/ledit.c b/ledit.c
t@@ -32,8 +32,6 @@ struct key {
void (*func)(void); /* callback function */
};
-#define MAX_CACHE_PIXELS 100
-
static struct {
Display *dpy;
GC gc;
t@@ -56,17 +54,31 @@ static struct {
Atom wm_delete_msg;
} state;
+struct cache_pixmap {
+ Pixmap pixmap;
+ XftDraw *draw;
+ int w, h;
+ int line;
+};
+
/* FIXME: possibly use at least 32 bits int? */
static struct {
- Pixmap pix;
- XftDraw *draw;
- int pix_w, pix_h;
- long start_offset;
- int valid_height;
- int begin_line, begin_softline;
- int dirty;
+ struct cache_pixmap *entries;
+ int entries_num;
+ int cur_replace_index;
} cache;
+static size_t lines_num = 0;
+static size_t lines_cap = 0;
+
+static int cur_line = 0;
+static int cur_subline = 0;
+static int cur_index = 0;
+static int trailing = 0;
+static long total_height = 0;
+static double cur_display_offset = 0;
+
+
static void mainloop(void);
static void setup(int argc, char *argv[]);
static void cleanup(void);
t@@ -94,24 +106,57 @@ static struct line {
int w;
int h;
long y_offset;
- /*
- XftDraw *draw;
- Pixmap pix;
- unsigned int pix_w;
- unsigned int pix_h;
- */
+ int cache_index;
char dirty;
} *lines = NULL;
-static size_t lines_num = 0;
-static size_t lines_cap = 0;
+static void
+init_cache(void) {
+ /* FIXME: prevent overflow */
+ cache.entries = malloc(20 * sizeof(struct cache_pixmap));
+ if (!cache.entries) exit(1);
+ for (int i = 0; i < 20; i++) {
+ cache.entries[i].pixmap = None;
+ cache.entries[i].line = -1;
+ }
+ cache.entries_num = 20;
+ cache.cur_replace_index = -1;
+}
-static int cur_line = 0;
-static int cur_subline = 0;
-static int cur_index = 0;
-static int trailing = 0;
-static long total_height = 0;
-static double cur_display_offset = 0;
+static void
+assign_free_cache_index(int line) {
+ int found = 0;
+ int real_index;
+ int tmp_line;
+ /* start at 1 because the cache->cur_replace_index is actually the las…
+ for (int i = 1; i <= cache.entries_num; i++) {
+ real_index = (i + cache.cur_replace_index) % cache.entries_num;
+ tmp_line = cache.entries[real_index].line;
+ /* replace line when entry isn't assigned or currently assigne…
+ if (tmp_line == -1 ||
+ (tmp_line >= 0 &&
+ (lines[tmp_line].y_offset >= cur_display_offset + state.h…
+ lines[tmp_line].y_offset + lines[tmp_line].h <= cur_disp…
+ if (tmp_line >= 0)
+ lines[tmp_line].cache_index = -1;
+ cache.entries[real_index].line = line;
+ cache.cur_replace_index = real_index;
+ lines[line].cache_index = real_index;
+ return;
+ }
+ }
+
+ /* no free entry found, increase cache size */
+ cache.entries = realloc(cache.entries, cache.entries_num * 2 * sizeof(…
+ if (!cache.entries) exit(1);
+ real_index = cache.entries_num;
+ for (size_t i = cache.entries_num + 1; i < cache.entries_num * 2; i++)…
+ cache.entries[i].line = -1;
+ }
+ cache.entries_num *= 2;
+ cache.entries[real_index].line = line;
+ lines[line].cache_index = real_index;
+}
static void
init_line(struct line *l) {
t@@ -122,97 +167,16 @@ init_line(struct line *l) {
pango_layout_set_wrap(l->layout, PANGO_WRAP_WORD_CHAR);
l->text = NULL;
l->cap = l->len = 0;
- /*l->pix = None;*/
+ l->cache_index = -1;
+ l->dirty = 1;
/* FIXME: does this set line height reasonably when no text yet? */
pango_layout_get_pixel_size(l->layout, &l->w, &l->h);
l->y_offset = 0;
- //l->dirty = 1;
}
static void recalc_cur_line_size(void);
static void recalc_line_size_absolute(void);
-enum CachePosition {
- CACHE_NONE,
- CACHE_BOTH,
- CACHE_TOP,
- CACHE_BOTTOM
-};
-
-static void redraw_cache_complete(enum CachePosition pos);
-static void redraw_cache_after_cur_line(void);
-static void redraw_cache_only_cur_line(void);
-
-#define MAX_INT(a, b) ((a) > (b) ? (a) : (b))
-#define MIN_INT(a, b) ((a) < (b) ? (a) : (b))
-
-/* FIXME: Implement pos */
-static void
-redraw_cache_complete(enum CachePosition pos) {
- long start = cur_display_offset > MAX_CACHE_PIXELS ? (long)(cur_displa…
- long end = (long)(cur_display_offset) + state.h + MAX_CACHE_PIXELS;
- int start_line = 0;
- int end_line = 0;
-
- /* FIXME: make this more efficient - we can't start at cur_line
- * because that may be off screen */
- /*
- for (start_line = cur_line;
- lines[start_line].y_offset > cur_display_offset;
- start_line--) {
- }
-
- for (end_line = cur_line;
- end_line < lines_num &&
- lines[end_line].y_offset + lines[end_line].h < cur_display_offset…
- end_line++) {
- }
- */
-
- for (start_line = 0;
- start_line < lines_num - 1 &&
- lines[start_line].y_offset + lines[start_line].h <= cur_display_o…
- start_line++) {
- /* NOP */
- }
- for (end_line = start_line;
- end_line < lines_num - 1 &&
- lines[end_line].y_offset + lines[end_line].h < cur_display_offset…
- end_line++) {
- /* NOP */
- }
-
- if (lines[start_line].y_offset < start) {
- printf("FIX THIS CODE 1!\n");
- }
- if (lines[end_line].y_offset + lines[end_line].h > end) {
- printf("FIX THIS CODE 2!\n");
- }
-
- /* FIXME: only wipe what is necessary */
- XftDrawRect(cache.draw, &state.bg, 0, 0, cache.pix_w, cache.pix_h);
- int cur_y = 0;
- for (int i = start_line; i <= end_line; i++) {
- if (lines[i].w > cache.pix_w || cur_y + lines[i].h > cache.pix…
- break; /* should never happen */
- }
- pango_xft_render_layout(cache.draw, &state.fg, lines[i].layout…
- cur_y += lines[i].h;
- }
- cache.valid_height = cur_y;
- cache.start_offset = lines[start_line].y_offset;
- cache.begin_line = start_line;
- cache.dirty = 0;
-}
-
-static void
-redraw_cache_after_cur_line(void) {
-}
-
-static void
-redraw_cache_only_cur_line(void) {
-}
-
static void
insert_text(struct line *l, int index, char *text, int len) {
if (len == -1)
t@@ -229,33 +193,35 @@ insert_text(struct line *l, int index, char *text, int l…
l->len += len;
pango_layout_set_text(l->layout, l->text, l->len);
recalc_cur_line_size();
- cache.dirty = 1;
+ l->dirty = 1;
}
static void insert_line_entry(int index);
static void
-render_line(struct line *l) {
+render_line(int line) {
/* FIXME: check for <= 0 on size */
- /*
- if (l->pix == None) {
- l->pix = XCreatePixmap(state.dpy, state.back_buf, l->w + 10, l…
- l->pix_w = l->w + 10;
- l->pix_h = l->h + 10;
- l->draw = XftDrawCreate(state.dpy, l->pix, state.vis, state.cm…
- } else if (l->pix_w < l->w || l->pix_h < l->h) {
- int new_w = l->w > l->pix_w ? l->w + 10 : l->pix_w + 10;
- int new_h = l->h > l->pix_h ? l->h + 10 : l->pix_h + 10;
- XFreePixmap(state.dpy, l->pix);
- l->pix = XCreatePixmap(state.dpy, state.back_buf, new_w, new_h…
- l->pix_w = new_w;
- l->pix_h = new_h;
- XftDrawChange(l->draw, l->pix);
- }
- XftDrawRect(l->draw, &state.bg, 0, 0, l->w, l->h);
- pango_xft_render_layout(l->draw, &state.fg, l->layout, 0, 0);
+ struct line *l = &lines[line];
+ if (l->cache_index == -1)
+ assign_free_cache_index(line);
+ struct cache_pixmap *pix = &cache.entries[l->cache_index];
+ if (pix->pixmap == None) {
+ pix->pixmap = XCreatePixmap(state.dpy, state.back_buf, l->w + …
+ pix->w = l->w + 10;
+ pix->h = l->h + 10;
+ pix->draw = XftDrawCreate(state.dpy, pix->pixmap, state.vis, s…
+ } else if (pix->w < l->w || pix->h < l->h) {
+ int new_w = l->w > pix->w ? l->w + 10 : pix->w + 10;
+ int new_h = l->h > pix->h ? l->h + 10 : pix->h + 10;
+ XFreePixmap(state.dpy, pix->pixmap);
+ pix->pixmap = XCreatePixmap(state.dpy, state.back_buf, new_w, …
+ pix->w = new_w;
+ pix->h = new_h;
+ XftDrawChange(pix->draw, pix->pixmap);
+ }
+ XftDrawRect(pix->draw, &state.bg, 0, 0, l->w, l->h);
+ pango_xft_render_layout(pix->draw, &state.fg, l->layout, 0, 0);
l->dirty = 0;
- */
}
static void
t@@ -274,7 +240,6 @@ append_line(int text_index, int line_index) {
if (text_index != -1) {
struct line *l = &lines[line_index];
int len = l->len - text_index;
- //new_l->pix = None;
new_l->len = len;
new_l->cap = len + 10;
new_l->text = malloc(new_l->cap);
t@@ -328,11 +293,13 @@ set_line_cursor_attrs(int line, int index) {
} else {
pango_layout_set_attributes(lines[line].layout, basic_attrs);
}
+ lines[line].dirty = 1;
}
static void
wipe_line_cursor_attrs(int line) {
pango_layout_set_attributes(lines[line].layout, basic_attrs);
+ lines[line].dirty = 1;
}
static void
t@@ -477,34 +444,16 @@ mainloop(void) {
XSetForeground(state.dpy, state.gc, state.bg.pixel);
XFillRectangle(state.dpy, state.back_buf, state.gc, 0,…
int h = 0;
- if (cache.dirty)
- redraw_cache_complete(CACHE_BOTH);
+
/*int cur_line_height = 0;*/
- /*
int tmp_w, tmp_h;
int cur_line_y = 0;
int cursor_displayed = 0;
for (int i = 0; i < lines_num; i++) {
- if (lines[i].dirty) {
- if (i == cur_line && cur_mode == NORMA…
- PangoAttribute *attr0 = pango_…
- PangoAttribute *attr1 = pango_…
- attr0->start_index = cur_index;
- attr0->end_index = cur_index +…
- attr1->start_index = cur_index;
- attr1->end_index = cur_index +…
- PangoAttribute *attr2 = pango_…
- PangoAttrList *list = pango_at…
- pango_attr_list_insert(list, a…
- pango_attr_list_insert(list, a…
- pango_attr_list_insert(list, a…
- pango_layout_set_attributes(li…
- } else {
- pango_layout_set_attributes(li…
- }
- render_line(&lines[i]);
- }
if (h + lines[i].h > cur_display_offset) {
+ if (lines[i].dirty || lines[i].cache_i…
+ render_line(i);
+ }
int final_y = 0;
int dest_y = h - cur_display_offset;
int final_h = lines[i].h;
t@@ -516,7 +465,7 @@ mainloop(void) {
if (dest_y + final_h > state.h) {
final_h -= final_y + final_h -…
}
- XCopyArea(state.dpy, lines[i].pix, sta…
+ XCopyArea(state.dpy, cache.entries[lin…
if (i == cur_line) {
cur_line_y = h - cur_display_o…
cursor_displayed = 1;
t@@ -526,32 +475,25 @@ mainloop(void) {
break;
h += lines[i].h;
}
- */
- double offset = cur_display_offset - cache.start_offse…
- if (offset < 0) {
- printf("FIX THIS CODE 3!\n");
- offset = 0;
- }
- XCopyArea(state.dpy, cache.pix, state.back_buf, state.…
need_redraw = 0;
XSetForeground(state.dpy, state.gc, state.fg.pixel);
PangoRectangle strong, weak;
pango_layout_get_cursor_pos(lines[cur_line].layout, cu…
/* FIXME: long, int, etc. */
- long cursor_y = strong.y / PANGO_SCALE + lines[cur_lin…
- if (cursor_y >= cur_display_offset && cursor_y < cur_d…
+ int cursor_y = strong.y / PANGO_SCALE + cur_line_y;
+ if (cursor_displayed && cursor_y >= 0) {
if (cur_mode == NORMAL && cur_index == lines[c…
XFillRectangle(
state.dpy, state.back_buf, state.g…
- strong.x / PANGO_SCALE, cursor_y -…
+ strong.x / PANGO_SCALE, cursor_y,
10, strong.height / PANGO_SCALE
);
} else if (cur_mode == INSERT) {
XDrawLine(
state.dpy, state.back_buf, state.g…
- strong.x / PANGO_SCALE, cursor_y -…
- strong.x / PANGO_SCALE, (strong.y …
+ strong.x / PANGO_SCALE, cursor_y,
+ strong.x / PANGO_SCALE, (strong.y …
);
}
}
t@@ -630,10 +572,7 @@ setup(int argc, char *argv[]) {
InputOutput, state.vis, CWBackPixel | CWColormap | CWBitGravity, &…
state.back_buf = XdbeAllocateBackBufferName(state.dpy, state.win, Xdbe…
- cache.pix = XCreatePixmap(state.dpy, state.back_buf, 500, 500, state.d…
- cache.pix_w = cache.pix_h = 500;
- cache.draw = XftDrawCreate(state.dpy, cache.pix, state.vis, state.cm);
- cache.dirty = 1;
+ init_cache();
memset(&gcv, 0, sizeof(gcv));
gcv.line_width = 1;
t@@ -695,10 +634,8 @@ ensure_cursor_shown(void) {
long cursor_y = strong.y / PANGO_SCALE + lines[cur_line].y_offset;
if (cursor_y < cur_display_offset) {
cur_display_offset = cursor_y;
- cache.dirty = 1;
} else if (cursor_y + strong.height / PANGO_SCALE > cur_display_offset…
cur_display_offset = cursor_y - state.h + strong.height / PANG…
- cache.dirty = 1;
}
}
t@@ -755,16 +692,9 @@ resize_window(int w, int h) {
lines[i].h = tmp_h;
lines[i].w = tmp_w;
lines[i].y_offset = total_height;
+ lines[i].dirty = 1;
total_height += tmp_h;
}
- if (cache.pix_w < state.w - 10 || cache.pix_h < state.h + 2 * MAX_CACH…
- XFreePixmap(state.dpy, cache.pix);
- cache.pix = XCreatePixmap(state.dpy, state.back_buf, state.w, …
- cache.pix_w = state.w;
- cache.pix_h = state.h + 2 * MAX_CACHE_PIXELS + 50;
- XftDrawChange(cache.draw, cache.pix);
- }
- cache.dirty = 1;
}
static void
t@@ -804,7 +734,6 @@ backspace(void) {
pango_layout_set_text(l->layout, l->text, l->len);
}
set_line_cursor_attrs(cur_line, cur_index);
- cache.dirty = 1;
recalc_cur_line_size();
}
t@@ -831,7 +760,6 @@ delete_key(void) {
pango_layout_set_text(l->layout, l->text, l->len);
}
set_line_cursor_attrs(cur_line, cur_index);
- cache.dirty = 1;
recalc_cur_line_size();
}
t@@ -858,7 +786,6 @@ move_cursor(int dir) {
cur_index = lines[cur_line].len;
}
set_line_cursor_attrs(cur_line, cur_index);
- cache.dirty = 1;
}
static void
t@@ -879,7 +806,6 @@ return_key(void) {
wipe_line_cursor_attrs(cur_line);
cur_line++;
set_line_cursor_attrs(cur_line, cur_index);
- cache.dirty = 1;
cur_index = 0;
recalc_line_size_absolute();
}
t@@ -899,7 +825,6 @@ escape_key(void) {
cursor_left();
}
set_line_cursor_attrs(cur_line, cur_index);
- cache.dirty = 1;
/*
if (cur_index > 0)
cursor_left();
t@@ -915,7 +840,6 @@ i_key(void) {
}
*/
wipe_line_cursor_attrs(cur_line);
- cache.dirty = 1;
}
static void
t@@ -946,7 +870,6 @@ line_down(void) {
if (cur_index > 0 && cur_mode == NORMAL && cur_index >= lines[cur_line…
cursor_left();
set_line_cursor_attrs(cur_line, cur_index);
- cache.dirty = 1;
}
static void
t@@ -977,14 +900,12 @@ line_up(void) {
if (cur_index > 0 && cur_mode == NORMAL && cur_index >= lines[cur_line…
cursor_left();
set_line_cursor_attrs(cur_line, cur_index);
- cache.dirty = 1;
}
static void
zero_key(void) {
cur_index = 0;
set_line_cursor_attrs(cur_line, cur_index);
- cache.dirty = 1;
}
static struct key keys_en[] = {
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.