vtgl

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

vtgl.h (12086B)


      1 /* See LICENSE for copyright details */
      2 #ifndef _VTGL_H_
      3 #define _VTGL_H_
      4 
      5 #include <stddef.h>
      6 #include <stdint.h>
      7 
      8 #ifndef asm
      9 #define asm __asm__
     10 #endif
     11 
     12 #ifndef typeof
     13 #define typeof __typeof__
     14 #endif
     15 
     16 #ifndef static_assert
     17 #define static_assert _Static_assert
     18 #endif
     19 
     20 #define atomic_and(ptr, n)          __atomic_and_fetch(ptr, n, __ATOMIC_RELEASE);
     21 #define atomic_fetch_add(ptr, n)    __atomic_fetch_add(ptr, n, __ATOMIC_RELEASE);
     22 #define atomic_load(ptr)            __atomic_load_n(ptr, __ATOMIC_ACQUIRE)
     23 #define atomic_exchange_n(ptr, val) __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST)
     24 
     25 #define PI       3.1415926535897932384f
     26 
     27 #define KB(a)    ((a) << 10ULL)
     28 #define MB(a)    ((a) << 20ULL)
     29 
     30 #define ARRAY_COUNT(a)   (size)(sizeof(a) / sizeof(*a))
     31 #define ABS(a)           ((a) < 0 ? (-a) : (a))
     32 #define BETWEEN(x, a, b) ((x) >= (a) && (x) <= (b))
     33 #define CLAMP(x, a, b)   ((x) = (x) < (a) ? (a) : (x) > (b) ? (b) : (x))
     34 #define MAX(a, b)        ((a) >= (b) ? (a) : (b))
     35 #define MIN(a, b)        ((a) <= (b) ? (a) : (b))
     36 #define SGN(a)           ((a) < 0 ? (-1) : (1))
     37 
     38 #define SAFE_RATIO_1(a, b) ((b) ? (a) / (b) : (a))
     39 
     40 #define ISCONTROLC0(c)   ((c) <= 0x1F || (c) == 0x7F)
     41 #define ISCONTROLC1(c)   (BETWEEN((c), 0x80, 0x9F))
     42 #define ISCONTROL(c)     (ISCONTROLC0(c) || ISCONTROLC1(c))
     43 #define ISSPACE(c)       ((c) == ' ' || (c) == '\n' || (c) == '\t')
     44 #define ISPRINT(c)       BETWEEN((c), ' ', '~')
     45 
     46 #define ISPOWEROFTWO(a) (((a) & ((a) - 1)) == 0)
     47 
     48 /* NOTE: GLFW does not sequentially number keys so switch statement will never be optimized */
     49 #define ENCODE_KEY(action, mod, key) (((action) << 24) | ((mod) << 16) | ((key) & 0xFFFF))
     50 
     51 #define BACKLOG_SIZE  (MB(16))
     52 #define BACKLOG_LINES (8192UL)
     53 
     54 #define ALT_BACKLOG_SIZE  (MB(2))
     55 #define ALT_BACKLOG_LINES (1024UL)
     56 
     57 #define I32_MAX INT32_MAX
     58 #define I64_MIN INT64_MIN
     59 
     60 typedef float     f32;
     61 typedef double    f64;
     62 typedef char      c8;
     63 typedef int8_t    i8;
     64 typedef uint8_t   u8;
     65 typedef int16_t   i16;
     66 typedef uint16_t  u16;
     67 typedef int32_t   i32;
     68 typedef uint32_t  u32;
     69 typedef uint32_t  b32;
     70 typedef int64_t   i64;
     71 typedef uint64_t  u64;
     72 typedef ptrdiff_t iptr;
     73 typedef ptrdiff_t size;
     74 typedef size_t    usize;
     75 
     76 #include "intrinsics.c"
     77 
     78 #ifdef _DEBUG
     79 #define ASSERT(c) do { if (!(c)) debugbreak(); } while(0)
     80 #define DEBUG_EXPORT
     81 #else
     82 #define ASSERT(c) do { (void)(c); } while(0)
     83 #define DEBUG_EXPORT static
     84 #endif
     85 
     86 typedef struct { void *memory; size size; } MemoryBlock;
     87 
     88 typedef struct { u8 *beg, *end; } Arena;
     89 typedef struct { Arena *arena; u8 *old_beg; } TempArena;
     90 
     91 typedef struct { size len; u8 *data; } s8;
     92 #define s8(s) (s8){.len = ARRAY_COUNT(s) - 1, .data = (u8 *)s}
     93 
     94 typedef s8 os_mapped_file;
     95 
     96 typedef struct {
     97 	u8   *buf;
     98 	u32  cap;
     99 	u32  widx;
    100 	b32  errors;
    101 } Stream;
    102 
    103 /* NOTE: virtual memory ring buffer */
    104 typedef struct {
    105 	size  cap;
    106 	size  filled;
    107 	size  widx;
    108 	u8   *buf;
    109 } RingBuf;
    110 
    111 typedef union {
    112 	struct { i32 x, y; };
    113 	struct { i32 w, h; };
    114 	i32 E[2];
    115 } iv2;
    116 
    117 typedef union {
    118 	struct { f32 x, y; };
    119 	struct { f32 w, h; };
    120 	f32 E[2];
    121 } v2;
    122 
    123 typedef struct { iv2 start, end; } Range;
    124 #define INVALID_RANGE_END (iv2){.x = -1, .y = -1}
    125 
    126 #define INVALID_FILE (-1)
    127 enum file_attribute {
    128 	FA_READ   = 1 << 0,
    129 	FA_WRITE  = 1 << 1,
    130 	FA_APPEND = 1 << 2,
    131 };
    132 
    133 /* NOTE: for now we will do the callback route but this will change if we do multithreading */
    134 #define PLATFORM_FILE_WATCH_CALLBACK_FN(name) void name(u8 *path, void *user_ctx)
    135 typedef PLATFORM_FILE_WATCH_CALLBACK_FN(platform_file_watch_callback_fn);
    136 
    137 #define PLATFORM_ADD_FILE_WATCH_FN(name) void name(u8 *path, platform_file_watch_callback_fn *fn, \
    138                                                    void *user_ctx)
    139 typedef PLATFORM_ADD_FILE_WATCH_FN(platform_add_file_watch_fn);
    140 
    141 #define PLATFORM_ALLOCATE_RING_BUFFER_FN(name) void name(RingBuf *rb, size capacity)
    142 typedef PLATFORM_ALLOCATE_RING_BUFFER_FN(platform_allocate_ring_buffer_fn);
    143 
    144 #define PLATFORM_CLIPBOARD_FN(name) b32 name(Stream *buffer, u32 clipboard)
    145 typedef PLATFORM_CLIPBOARD_FN(platform_clipboard_fn);
    146 
    147 #define PLATFORM_READ_FILE_FN(name) s8 name(u8 *path, Arena *a)
    148 typedef PLATFORM_READ_FILE_FN(platform_read_file_fn);
    149 
    150 /* TODO: this should possibly just take a stream buffer */
    151 #define PLATFORM_READ_FN(name) size name(iptr file, s8 buffer)
    152 typedef PLATFORM_READ_FN(platform_read_fn);
    153 
    154 #define PLATFORM_SET_TERMINAL_SIZE_FN(name) void name(iptr child, i32 rows, i32 columns, \
    155                                                       i32 window_width, i32 window_height)
    156 typedef PLATFORM_SET_TERMINAL_SIZE_FN(platform_set_terminal_size_fn);
    157 
    158 #define PLATFORM_WINDOW_TITLE_FN(name) void name(Stream *buffer)
    159 typedef PLATFORM_WINDOW_TITLE_FN(platform_window_title_fn);
    160 
    161 #define PLATFORM_WRITE_FN(name) b32 name(iptr file, s8 raw)
    162 typedef PLATFORM_WRITE_FN(platform_write_fn);
    163 
    164 typedef struct {
    165 	platform_add_file_watch_fn       *add_file_watch;
    166 	platform_allocate_ring_buffer_fn *allocate_ring_buffer;
    167 	platform_clipboard_fn            *get_clipboard;
    168 	platform_clipboard_fn            *set_clipboard;
    169 	platform_read_file_fn            *read_file;
    170 	platform_read_fn                 *read;
    171 	platform_set_terminal_size_fn    *set_terminal_size;
    172 	platform_window_title_fn         *get_window_title;
    173 	platform_window_title_fn         *set_window_title;
    174 	platform_write_fn                *write;
    175 
    176 	u8 path_separator;
    177 } PlatformAPI;
    178 
    179 /* NOTE: CLIPBOARD_1 need not be supported on all platforms */
    180 enum {
    181 	CLIPBOARD_0,
    182 	CLIPBOARD_1,
    183 };
    184 
    185 /* TODO: for now these are just based on the GLFW keycodes directly. It might
    186  * be better for the platform to define these values themselves */
    187 #define ACT_RELEASE 0
    188 #define ACT_PRESS   1
    189 #define ACT_REPEAT  2
    190 
    191 #define KEY_SPACE              32
    192 #define KEY_APOSTROPHE         39  /* ' */
    193 #define KEY_COMMA              44  /* , */
    194 #define KEY_MINUS              45  /* - */
    195 #define KEY_PERIOD             46  /* . */
    196 #define KEY_SLASH              47  /* / */
    197 #define KEY_0                  48
    198 #define KEY_1                  49
    199 #define KEY_2                  50
    200 #define KEY_3                  51
    201 #define KEY_4                  52
    202 #define KEY_5                  53
    203 #define KEY_6                  54
    204 #define KEY_7                  55
    205 #define KEY_8                  56
    206 #define KEY_9                  57
    207 #define KEY_SEMICOLON          59  /* ; */
    208 #define KEY_EQUAL              61  /* = */
    209 #define KEY_A                  65
    210 #define KEY_B                  66
    211 #define KEY_C                  67
    212 #define KEY_D                  68
    213 #define KEY_E                  69
    214 #define KEY_F                  70
    215 #define KEY_G                  71
    216 #define KEY_H                  72
    217 #define KEY_I                  73
    218 #define KEY_J                  74
    219 #define KEY_K                  75
    220 #define KEY_L                  76
    221 #define KEY_M                  77
    222 #define KEY_N                  78
    223 #define KEY_O                  79
    224 #define KEY_P                  80
    225 #define KEY_Q                  81
    226 #define KEY_R                  82
    227 #define KEY_S                  83
    228 #define KEY_T                  84
    229 #define KEY_U                  85
    230 #define KEY_V                  86
    231 #define KEY_W                  87
    232 #define KEY_X                  88
    233 #define KEY_Y                  89
    234 #define KEY_Z                  90
    235 #define KEY_LEFT_BRACKET       91  /* [ */
    236 #define KEY_BACKSLASH          92  /* \ */
    237 #define KEY_RIGHT_BRACKET      93  /* ] */
    238 #define KEY_GRAVE_ACCENT       96  /* ` */
    239 #define KEY_WORLD_1            161 /* non-US #1 */
    240 #define KEY_WORLD_2            162 /* non-US #2 */
    241 
    242 /* Function keys */
    243 #define KEY_ESCAPE             256
    244 #define KEY_ENTER              257
    245 #define KEY_TAB                258
    246 #define KEY_BACKSPACE          259
    247 #define KEY_INSERT             260
    248 #define KEY_DELETE             261
    249 #define KEY_RIGHT              262
    250 #define KEY_LEFT               263
    251 #define KEY_DOWN               264
    252 #define KEY_UP                 265
    253 #define KEY_PAGE_UP            266
    254 #define KEY_PAGE_DOWN          267
    255 #define KEY_HOME               268
    256 #define KEY_END                269
    257 #define KEY_CAPS_LOCK          280
    258 #define KEY_SCROLL_LOCK        281
    259 #define KEY_NUM_LOCK           282
    260 #define KEY_PRINT_SCREEN       283
    261 #define KEY_PAUSE              284
    262 #define KEY_F1                 290
    263 #define KEY_F2                 291
    264 #define KEY_F3                 292
    265 #define KEY_F4                 293
    266 #define KEY_F5                 294
    267 #define KEY_F6                 295
    268 #define KEY_F7                 296
    269 #define KEY_F8                 297
    270 #define KEY_F9                 298
    271 #define KEY_F10                299
    272 #define KEY_F11                300
    273 #define KEY_F12                301
    274 #define KEY_F13                302
    275 #define KEY_F14                303
    276 #define KEY_F15                304
    277 #define KEY_F16                305
    278 #define KEY_F17                306
    279 #define KEY_F18                307
    280 #define KEY_F19                308
    281 #define KEY_F20                309
    282 #define KEY_F21                310
    283 #define KEY_F22                311
    284 #define KEY_F23                312
    285 #define KEY_F24                313
    286 #define KEY_F25                314
    287 #define KEY_KP_0               320
    288 #define KEY_KP_1               321
    289 #define KEY_KP_2               322
    290 #define KEY_KP_3               323
    291 #define KEY_KP_4               324
    292 #define KEY_KP_5               325
    293 #define KEY_KP_6               326
    294 #define KEY_KP_7               327
    295 #define KEY_KP_8               328
    296 #define KEY_KP_9               329
    297 #define KEY_KP_DECIMAL         330
    298 #define KEY_KP_DIVIDE          331
    299 #define KEY_KP_MULTIPLY        332
    300 #define KEY_KP_SUBTRACT        333
    301 #define KEY_KP_ADD             334
    302 #define KEY_KP_ENTER           335
    303 #define KEY_KP_EQUAL           336
    304 
    305 enum input_keys {
    306 	MOUSE_LEFT,
    307 	MOUSE_RIGHT,
    308 	MOUSE_MIDDLE,
    309 	MOUSE_EXTENDED_0,
    310 	MOUSE_EXTENDED_1,
    311 
    312 	KEY_LEFT_SHIFT,
    313 	KEY_LEFT_CONTROL,
    314 	KEY_LEFT_ALT,
    315 	KEY_LEFT_SUPER,
    316 	KEY_RIGHT_SHIFT,
    317 	KEY_RIGHT_CONTROL,
    318 	KEY_RIGHT_ALT,
    319 	KEY_RIGHT_SUPER,
    320 	KEY_MENU,
    321 
    322 	INPUT_KEY_COUNT,
    323 };
    324 
    325 enum modifiers {
    326 	MOD_SHIFT   = (1 << 0),
    327 	MOD_CONTROL = (1 << 1),
    328 	MOD_ALT     = (1 << 2),
    329 	MOD_SUPER   = (1 << 3),
    330 
    331 	MOD_MASK    = (MOD_SHIFT|MOD_CONTROL|MOD_ALT|MOD_SUPER),
    332 };
    333 
    334 typedef struct {
    335 	/* TODO: is this even supported or does GLFW only call you once per poll? */
    336 	u16 transitions;
    337 	u16 ended_down;
    338 } ButtonState;
    339 
    340 typedef struct TerminalInput {
    341 	ButtonState keys[INPUT_KEY_COUNT];
    342 
    343 	iv2 window_size;
    344 
    345 	b32 data_available;
    346 	b32 executable_reloaded;
    347 	b32 window_refreshed;
    348 	b32 window_focused;
    349 	b32 pending_updates;
    350 
    351 	u32 modifiers;
    352 
    353 	v2 mouse;
    354 	v2 last_mouse;
    355 	v2 mouse_scroll;
    356 
    357 	/* TODO: do we want the 32bit codepoints instead? */
    358 	s8 character_input;
    359 
    360 	f32 dt;
    361 } TerminalInput;
    362 
    363 typedef struct TerminalMemory {
    364 	u64   memory_size;
    365 	void *memory;
    366 
    367 	u64   debug_memory_size;
    368 	void *debug_memory;
    369 
    370 	PlatformAPI platform_api;
    371 } TerminalMemory;
    372 
    373 /************************************************************/
    374 /* NOTE: functions provided by the terminal to the platform */
    375 /************************************************************/
    376 #define VTGL_INITIALIZE_FN(name) iv2 name(TerminalMemory *memory, iptr child, iv2 requested_cells, iv2 monitor_size)
    377 typedef VTGL_INITIALIZE_FN(vtgl_initialize_fn);
    378 
    379 #define VTGL_FRAME_STEP_FN(name) b32 name(TerminalMemory *memory, TerminalInput *input)
    380 typedef VTGL_FRAME_STEP_FN(vtgl_frame_step_fn);
    381 
    382 #define VTGL_RENDER_FRAME_FN(name) void name(TerminalMemory *memory, TerminalInput *input, Arena arena)
    383 typedef VTGL_RENDER_FRAME_FN(vtgl_render_frame_fn);
    384 
    385 #define VTGL_ACTIVE_SELECTION_FN(name) Range name(TerminalMemory *memory, Stream *out)
    386 typedef VTGL_ACTIVE_SELECTION_FN(vtgl_active_selection_fn);
    387 
    388 #define VTGL_HANDLE_KEYS_FN(name) void name(TerminalMemory *memory, TerminalInput *input, \
    389                                             i32 key, i32 action, u32 modifiers)
    390 typedef VTGL_HANDLE_KEYS_FN(vtgl_handle_keys_fn);
    391 
    392 #include "util.h"
    393 #include "util.c"
    394 
    395 #include "debug.h"
    396 
    397 #ifdef __ARM_ARCH_ISA_A64
    398 #include "platform_linux_aarch64.c"
    399 #elif defined(__linux__) && (defined(__x86_64__) || defined(_M_X64))
    400 #include "platform_linux_amd64.c"
    401 #else
    402 #error Unsupported Platform!
    403 #endif
    404 
    405 #endif /*_VTGL_H_ */