ledit

Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/ledit.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/ledit.git (over tor)
Log | Files | Refs | README | 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 }