vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

util.c (3811B)


      1 /* See LICENSE for copyright details */
      2 static b32
      3 equal_iv2(iv2 a, iv2 b)
      4 {
      5 	b32 result = a.x == b.x && a.y == b.y;
      6 	return result;
      7 }
      8 
      9 static b32
     10 equal_uv2(uv2 a, uv2 b)
     11 {
     12 	b32 result = a.x == b.x && a.y == b.y;
     13 	return result;
     14 }
     15 
     16 static b32
     17 is_valid_range(Range r)
     18 {
     19 	b32 result = !equal_iv2(r.end, INVALID_RANGE_END);
     20 	return result;
     21 }
     22 
     23 static Range
     24 normalize_range(Range r)
     25 {
     26 	Range result;
     27 	if (r.start.y < r.end.y) {
     28 		result = r;
     29 	} else if (r.end.y < r.start.y) {
     30 		result = (Range){.start = r.end, .end = r.start};
     31 	} else {
     32 		result.start.y = result.end.y = r.start.y;
     33 		result.start.x = MIN(r.start.x, r.end.x);
     34 		result.end.x   = MAX(r.start.x, r.end.x);
     35 	}
     36 	return result;
     37 }
     38 
     39 static void
     40 mem_copy(s8 src, s8 dest)
     41 {
     42 	ASSERT(src.len > 0 && dest.len > 0);
     43 	ASSERT(dest.len >= src.len);
     44 	for (size i = 0; i < src.len; i++)
     45 		dest.data[i] = src.data[i];
     46 }
     47 
     48 static void *
     49 mem_clear(void *p_, u8 c, size len)
     50 {
     51 	u8 *p = p_;
     52 	while (len) p[--len] = c;
     53 	return p;
     54 }
     55 
     56 #define alloc(a, t, n)  (t *)alloc_(a, sizeof(t), _Alignof(t), n)
     57 __attribute((malloc, alloc_size(4, 2), alloc_align(3)))
     58 static void *
     59 alloc_(Arena *a, size len, size align, size count)
     60 {
     61 	size padding   = -(uintptr_t)a->beg & (align - 1);
     62 	size available = a->end - a->beg - padding;
     63 	if (available <= 0 || available / len <= count) {
     64 		ASSERT(0);
     65 	}
     66 
     67 	void *p  = a->beg + padding;
     68 	a->beg  += padding + count * len;
     69 	return mem_clear(p, 0, count * len);
     70 }
     71 
     72 /* NOTE: This performs wrapping of the ring buffer as needed; since a line could be in
     73  * progress this must also adjust the start and end of the current line */
     74 static void
     75 commit_to_rb(TermView *tv, size len)
     76 {
     77 	ASSERT(len <= tv->log.cap);
     78 
     79 	tv->log.widx   += len;
     80 	tv->log.filled += len;
     81 
     82 	CLAMP(tv->log.filled, 0, tv->log.cap);
     83 	if (tv->log.widx >= tv->log.cap) {
     84 		tv->log.widx -= tv->log.cap;
     85 
     86 		size line = tv->lines.widx;
     87 		tv->lines.buf[line].start -= tv->log.cap;
     88 		tv->lines.buf[line].end   -= tv->log.cap;
     89 	}
     90 
     91 	ASSERT(tv->log.filled >= 0);
     92 	ASSERT(tv->log.widx >= 0 && tv->log.widx < tv->log.cap);
     93 }
     94 
     95 static void
     96 line_buf_alloc(LineBuf *lb, Arena *a, u8 *start_position, CellStyle state, size capacity)
     97 {
     98 	lb->cap          = capacity;
     99 	lb->filled       = 0;
    100 	lb->widx         = 0;
    101 	lb->buf          = alloc(a, Line, capacity);
    102 	lb->buf[0].start = start_position;
    103 	lb->buf[0].end   = start_position;
    104 	lb->buf[0].cursor_state = state;
    105 }
    106 
    107 static s8
    108 s8alloc(Arena *a, size len)
    109 {
    110 	return (s8){.len = len, .data = alloc(a, u8, len)};
    111 }
    112 
    113 static char *
    114 s8_to_cstr(Arena *a, s8 s)
    115 {
    116 	char *cstr = alloc(a, char, s.len + 1);
    117 	for (size i = 0; i < s.len; i++)
    118 		cstr[i] = s.data[i];
    119 	cstr[s.len] = 0;
    120 	return cstr;
    121 }
    122 
    123 static struct conversion_result
    124 i32_from_cstr(char *s, char delim)
    125 {
    126 	struct conversion_result ret = {.status = CR_FAILURE};
    127 	i32 scale = 1;
    128 
    129 	if (!s || !s[0])
    130 		return ret;
    131 
    132 	if (s[0] == '-') {
    133 		s++;
    134 		scale = -1;
    135 	}
    136 
    137 	for (; *s && *s != delim; s++) {
    138 		if (!BETWEEN(s[0], '0', '9'))
    139 			return ret;
    140 		ret.i *= 10;
    141 		ret.i += s[0] - '0';
    142 	}
    143 
    144 	ret.i        *= scale;
    145 	ret.status    = CR_SUCCESS;
    146 	ret.unparsed  = (*s == delim) ? s + 1 : s;
    147 
    148 	return ret;
    149 }
    150 
    151 static s8
    152 utf8_encode(u32 cp)
    153 {
    154 	static u8 buf[4];
    155 	s8 ret = { .data = buf, .len = -1 };
    156 	if (cp < 0x80) {
    157 		ret.len = 1;
    158 		buf[0] = cp & 0x7F;
    159 	} else if (cp < 0x800) {
    160 		ret.len = 2;
    161 		buf[0] = ((cp >>  6) & 0x1F) | 0xC0;
    162 		buf[1] = ((cp >>  0) & 0x3F) | 0x80;
    163 	} else if (cp < 0x10000) {
    164 		ret.len = 3;
    165 		buf[0] = ((cp >> 12) & 0x0F) | 0xE0;
    166 		buf[1] = ((cp >>  6) & 0x3F) | 0x80;
    167 		buf[2] = ((cp >>  0) & 0x3F) | 0x80;
    168 	} else if (cp < 0x200000) {
    169 		ret.len = 4;
    170 		buf[0] = ((cp >> 18) & 0x07) | 0xF0;
    171 		buf[1] = ((cp >> 12) & 0x3F) | 0x80;
    172 		buf[2] = ((cp >>  6) & 0x3F) | 0x80;
    173 		buf[3] = ((cp >>  0) & 0x3F) | 0x80;
    174 	}
    175 	return ret;
    176 }
    177 
    178 #include "extern/utf8_decode.c"
    179 #include "extern/wcwidth.c"