vtgl

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

vtgl.h (12003B)


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