cache.c - ledit - Text editor (WIP)
HTML git clone git://lumidify.org/ledit.git (fast, but not encrypted)
HTML git clone https://lumidify.org/ledit.git (encrypted, but very slow)
HTML git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ledit.git (over tor)
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
cache.c (5114B)
---
1 #include <stdio.h>
2 #include <limits.h>
3 #include <stdlib.h>
4 #include <X11/Xlib.h>
5 #include <X11/Xutil.h>
6 #include <pango/pangoxft.h>
7 #include <X11/extensions/Xdbe.h>
8
9 #include "util.h"
10 #include "common.h"
11 #include "memory.h"
12 #include "cache.h"
13 #include "assert.h"
14
15 ledit_cache *
16 cache_create(Display *dpy) {
17 ledit_cache *cache = ledit_malloc(sizeof(ledit_cache));
18 cache->dpy = dpy;
19 cache->pixmaps = ledit_reallocarray(NULL, PIXMAP_CACHE_INITIAL_SIZE, sizeof(cache_pixmap));
20 cache->layouts = ledit_reallocarray(NULL, LAYOUT_CACHE_SIZE, sizeof(cache_layout));
21 for (size_t i = 0; i < PIXMAP_CACHE_INITIAL_SIZE; i++) {
22 cache->pixmaps[i].pixmap = None;
23 cache->pixmaps[i].draw = NULL;
24 cache->pixmaps[i].line = 0;
25 cache->pixmaps[i].valid = 0;
26 }
27 for (size_t i = 0; i < LAYOUT_CACHE_SIZE; i++) {
28 cache->layouts[i].layout = NULL;
29 cache->layouts[i].line = 0;
30 cache->layouts[i].valid = 0;
31 }
32 cache->num_pixmaps = PIXMAP_CACHE_INITIAL_SIZE;
33 cache->num_layouts = LAYOUT_CACHE_SIZE;
34 cache->cur_pixmap_index = cache->cur_layout_index = 0;
35 return cache;
36 }
37
38 void
39 cache_flush(
40 ledit_cache *cache, void *callback_data,
41 void (*invalidate_pixmap_line)(void *, size_t),
42 void (*invalidate_layout_line)(void *, size_t)) {
43 cache_invalidate_from_line(
44 cache, 0, callback_data, invalidate_pixmap_line, invalidate_layout_line
45 );
46 }
47
48 void
49 cache_invalidate_from_line(
50 ledit_cache *cache, size_t start, void *callback_data,
51 void (*invalidate_pixmap_line)(void *, size_t),
52 void (*invalidate_layout_line)(void *, size_t)) {
53 for (size_t i = 0; i < cache->num_pixmaps; i++) {
54 if (cache->pixmaps[i].line >= start) {
55 invalidate_pixmap_line(callback_data, cache->pixmaps[i].line);
56 cache->pixmaps[i].line = 0;
57 cache->pixmaps[i].valid = 0;
58 }
59 }
60 for (size_t i = 0; i < cache->num_layouts; i++) {
61 if (cache->layouts[i].line >= start) {
62 invalidate_layout_line(callback_data, cache->layouts[i].line);
63 cache->layouts[i].line = 0;
64 cache->layouts[i].valid = 0;
65 }
66 }
67 }
68
69 void
70 cache_destroy(ledit_cache *cache) {
71 for (size_t i = 0; i < cache->num_pixmaps; i++) {
72 if (cache->pixmaps[i].pixmap != None)
73 XFreePixmap(cache->dpy, cache->pixmaps[i].pixmap);
74 if (cache->pixmaps[i].draw != NULL)
75 XftDrawDestroy(cache->pixmaps[i].draw);
76 }
77 for (size_t i = 0; i < cache->num_layouts; i++) {
78 if (cache->layouts[i].layout != NULL)
79 g_object_unref(cache->layouts[i].layout);
80 }
81 free(cache->pixmaps);
82 free(cache->layouts);
83 free(cache);
84 }
85
86 cache_pixmap *
87 cache_get_pixmap(ledit_cache *cache, size_t index) {
88 ledit_assert(index < cache->num_pixmaps);
89 return &cache->pixmaps[index];
90 }
91
92 cache_layout *
93 cache_get_layout(ledit_cache *cache, size_t index) {
94 ledit_assert(index < cache->num_layouts);
95 return &cache->layouts[index];
96 }
97
98 /* FIXME: max pixmap cache size */
99 void
100 cache_assign_pixmap_index(
101 ledit_cache *cache, size_t line,
102 void *callback_data,
103 int (*line_needed)(void *, size_t),
104 void (*set_pixmap_line)(void *, size_t, size_t),
105 void (*invalidate_pixmap_line)(void *, size_t)) {
106 size_t line_index;
107 size_t entry_index;
108 for (size_t i = 0; i <= cache->num_pixmaps; i++) {
109 entry_index = (i + cache->cur_pixmap_index) % cache->num_pixmaps;
110 line_index = cache->pixmaps[entry_index].line;
111 int valid = cache->pixmaps[entry_index].valid;
112 /* replace line when entry isn't assigned or currently assigned line is not visible */
113 if (!valid ||
114 (valid && !line_needed(callback_data, line_index))) {
115 cache->cur_pixmap_index = (entry_index + 1) % cache->num_pixmaps;
116 cache_pixmap *pix = &cache->pixmaps[entry_index];
117 if (pix->valid)
118 invalidate_pixmap_line(callback_data, pix->line);
119 pix->line = line;
120 pix->valid = 1;
121 set_pixmap_line(callback_data, line, entry_index);
122 return;
123 }
124 }
125
126 /* no free entry found, increase cache size */
127 /* FIXME: maybe have maximum cache size */
128 size_t new_alloc = ideal_array_size(cache->num_pixmaps, add_sz(cache->num_pixmaps, 1));
129 cache->pixmaps = ledit_reallocarray(cache->pixmaps, new_alloc, sizeof(cache_pixmap));
130 entry_index = cache->num_pixmaps;
131 for (size_t i = cache->num_pixmaps; i < cache->num_pixmaps * 2; i++) {
132 cache->pixmaps[i].line = 0;
133 cache->pixmaps[i].valid = 0;
134 cache->pixmaps[i].pixmap = None;
135 cache->pixmaps[i].draw = NULL;
136 }
137 cache->num_pixmaps *= 2;
138 cache_pixmap *pix = &cache->pixmaps[entry_index];
139 pix->line = line;
140 pix->valid = 1;
141 set_pixmap_line(callback_data, line, entry_index);
142 }
143
144 /* FIXME: perhaps use "real" clock cache management, i.e. set a bit on a cache entry
145 when it is used so it isn't invalidated yet. */
146 void cache_assign_layout_index(
147 ledit_cache *cache, size_t line,
148 void *callback_data,
149 void (*set_layout_line)(void *, size_t, size_t),
150 void (*invalidate_layout_line)(void *, size_t)) {
151 size_t old = cache->cur_layout_index;
152 cache->cur_layout_index = (cache->cur_layout_index + 1) % cache->num_layouts;
153 cache_layout *layout = &cache->layouts[old];
154 if (layout->valid)
155 invalidate_layout_line(callback_data, layout->line);
156 layout->valid = 1;
157 layout->line = line;
158 set_layout_line(callback_data, line, old);
159 }