Browse Source

SIN: Reformat the whole codebase using tweaked .clang-format

yes, sorry, was actually quite well formatted (clang-format default) ... but its probably just me working on the code ever. So, i will just use my preferences here.
I find it important. visual guy and all other excuses...
master
heck 2 years ago
parent
commit
53575550f0
  1. 37
      .clang-format
  2. 2
      Makefile.conf
  3. 12
      src/base.h
  4. 12
      src/cli_main.c
  5. 69
      src/field.c
  6. 3
      src/field.h
  7. 36
      src/gbuffer.c
  8. 85
      src/gbuffer.h
  9. 74
      src/osc_out.c
  10. 25
      src/osc_out.h
  11. 80
      src/oso.c
  12. 15
      src/oso.h
  13. 145
      src/sim.c
  14. 9
      src/sim.h
  15. 35
      src/sokol_time.h
  16. 110
      src/sysmisc.c
  17. 53
      src/sysmisc.h
  18. 203
      src/term_util.c
  19. 34
      src/term_util.h
  20. 1245
      src/tui_main.c
  21. 19
      src/vmio.c
  22. 13
      src/vmio.h

37
.clang-format

@ -3,3 +3,40 @@ ReflowComments: false
MacroBlockBegin: "^BEGIN_OPERATOR"
MacroBlockEnd: "^END_OPERATOR"
Language: Cpp
DerivePointerAlignment: true
SortIncludes: Never
PointerAlignment: Left
AlignAfterOpenBracket: AlwaysBreak
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
BinPackArguments: false
BinPackParameters: false
ExperimentalAutoDetectBinPacking: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterFunction: true
ColumnLimit: 100
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyReturnTypeOnItsOwnLine: 1000000
PenaltyBreakAssignment: 1000000
PenaltyExcessCharacter: 10
IndentCaseLabels: true
IndentWidth: 4
MaxEmptyLinesToKeep: 2
NamespaceIndentation: All
SpaceAfterTemplateKeyword: false
AccessModifierOffset: -4
AllowShortBlocksOnASingleLine: Always
IndentPPDirectives: BeforeHash
IndentExternBlock: Indent
Cpp11BracedListStyle: false

2
Makefile.conf

@ -1,4 +1,4 @@
TARGET=tui_main
TARGET=orca_tui
LANG_VERSION=c99

12
src/base.h

@ -30,8 +30,7 @@
// (gcc / clang) or other
#if defined(__GNUC__) || defined(__clang__)
#define ORCA_ASSUME_ALIGNED(_ptr, _alignment) \
__builtin_assume_aligned(_ptr, _alignment)
#define ORCA_ASSUME_ALIGNED(_ptr, _alignment) __builtin_assume_aligned(_ptr, _alignment)
#define ORCA_PURE __attribute__((pure))
#define ORCA_LIKELY(_x) __builtin_expect(_x, 1)
#define ORCA_UNLIKELY(_x) __builtin_expect(_x, 0)
@ -49,8 +48,7 @@
// array count, safer on gcc/clang
#if defined(__GNUC__) || defined(__clang__)
#define ORCA_ASSERT_IS_ARRAY(_array) \
(sizeof(char[1 - 2 * __builtin_types_compatible_p( \
__typeof(_array), __typeof(&(_array)[0]))]) - \
(sizeof(char[1 - 2 * __builtin_types_compatible_p(__typeof(_array), __typeof(&(_array)[0]))]) - \
1)
#define ORCA_ARRAY_COUNTOF(_array) \
(sizeof(_array) / sizeof((_array)[0]) + ORCA_ASSERT_IS_ARRAY(_array))
@ -76,7 +74,8 @@ typedef ssize_t Isz;
typedef char Glyph;
typedef U8 Mark;
ORCA_FORCEINLINE static Usz orca_round_up_power2(Usz x) {
ORCA_FORCEINLINE static Usz orca_round_up_power2(Usz x)
{
assert(x <= SIZE_MAX / 2 + 1);
x -= 1;
x |= x >> 1;
@ -91,7 +90,8 @@ ORCA_FORCEINLINE static Usz orca_round_up_power2(Usz x) {
}
ORCA_OK_IF_UNUSED
static bool orca_is_valid_glyph(Glyph c) {
static bool orca_is_valid_glyph(Glyph c)
{
if (c >= '0' && c <= '9')
return true;
if (c >= 'A' && c <= 'Z')

12
src/cli_main.c

@ -5,7 +5,8 @@
#include "vmio.h"
#include <getopt.h>
static ORCA_NOINLINE void usage(void) { // clang-format off
static ORCA_NOINLINE void usage(void)
{ // clang-format off
fprintf(stderr,
"Usage: cli [options] infile\n\n"
"Options:\n"
@ -16,7 +17,8 @@ fprintf(stderr,
" -h or --help Print this message and exit.\n"
);} // clang-format on
int main(int argc, char **argv) {
int main(int argc, char **argv)
{
static struct option cli_options[] = { { "help", no_argument, 0, 'h' },
{ "quiet", no_argument, 0, 'q' },
{ NULL, 0, NULL, 0 } };
@ -33,7 +35,8 @@ int main(int argc, char **argv) {
case 't':
ticks = atoi(optarg);
if (ticks == 0 && strcmp(optarg, "0")) {
fprintf(stderr,
fprintf(
stderr,
"Bad timestep argument %s.\n"
"Must be 0 or a positive integer.\n",
optarg);
@ -88,8 +91,7 @@ int main(int argc, char **argv) {
for (Usz i = 0; i < max_ticks; ++i) {
mbuffer_clear(mbuf_r.buffer, field.height, field.width);
oevent_list_clear(&oevent_list);
orca_run(field.buffer, mbuf_r.buffer, field.height, field.width, i,
&oevent_list, 0);
orca_run(field.buffer, mbuf_r.buffer, field.height, field.width, i, &oevent_list, 0);
}
mbuf_reusable_deinit(&mbuf_r);
oevent_list_deinit(&oevent_list);

69
src/field.c

@ -2,13 +2,15 @@
#include "gbuffer.h"
#include <ctype.h>
void field_init(Field *f) {
void field_init(Field *f)
{
f->buffer = NULL;
f->height = 0;
f->width = 0;
}
void field_init_fill(Field *f, Usz height, Usz width, Glyph fill_char) {
void field_init_fill(Field *f, Usz height, Usz width, Glyph fill_char)
{
assert(height <= ORCA_Y_MAX && width <= ORCA_X_MAX);
Usz num_cells = height * width;
f->buffer = malloc(num_cells * sizeof(Glyph));
@ -17,9 +19,13 @@ void field_init_fill(Field *f, Usz height, Usz width, Glyph fill_char) {
f->width = (U16)width;
}
void field_deinit(Field *f) { free(f->buffer); }
void field_deinit(Field *f)
{
free(f->buffer);
}
void field_resize_raw(Field *f, Usz height, Usz width) {
void field_resize_raw(Field *f, Usz height, Usz width)
{
assert(height <= ORCA_Y_MAX && width <= ORCA_X_MAX);
Usz cells = height * width;
f->buffer = realloc(f->buffer, cells * sizeof(Glyph));
@ -27,23 +33,42 @@ void field_resize_raw(Field *f, Usz height, Usz width) {
f->width = (U16)width;
}
void field_resize_raw_if_necessary(Field *field, Usz height, Usz width) {
void field_resize_raw_if_necessary(Field *field, Usz height, Usz width)
{
if (field->height != height || field->width != width) {
field_resize_raw(field, height, width);
}
}
void field_copy(Field *src, Field *dest) {
void field_copy(Field *src, Field *dest)
{
field_resize_raw_if_necessary(dest, src->height, src->width);
gbuffer_copy_subrect(src->buffer, dest->buffer, src->height, src->width,
dest->height, dest->width, 0, 0, 0, 0, src->height,
gbuffer_copy_subrect(
src->buffer,
dest->buffer,
src->height,
src->width,
dest->height,
dest->width,
0,
0,
0,
0,
src->height,
src->width);
}
static inline bool glyph_char_is_valid(char c) { return c >= '!' && c <= '~'; }
static inline bool glyph_char_is_valid(char c)
{
return c >= '!' && c <= '~';
}
void field_fput(Field *f, FILE *stream) {
enum { Column_buffer_count = 4096 };
void field_fput(Field *f, FILE *stream)
{
enum
{
Column_buffer_count = 4096
};
char out_buffer[Column_buffer_count];
Usz f_height = f->height;
Usz f_width = f->width;
@ -62,12 +87,16 @@ void field_fput(Field *f, FILE *stream) {
}
}
Field_load_error field_load_file(char const *filepath, Field *field) {
Field_load_error field_load_file(char const *filepath, Field *field)
{
FILE *file = fopen(filepath, "r");
if (file == NULL) {
return Field_load_error_cant_open_file;
}
enum { Bufsize = 4096 };
enum
{
Bufsize = 4096
};
char buf[Bufsize];
Usz first_row_columns = 0;
Usz rows = 0;
@ -116,7 +145,8 @@ Field_load_error field_load_file(char const *filepath, Field *field) {
return Field_load_error_ok;
}
char const *field_load_error_string(Field_load_error fle) {
char const *field_load_error_string(Field_load_error fle)
{
char const *errstr = "Unknown";
switch (fle) {
case Field_load_error_ok:
@ -141,12 +171,14 @@ char const *field_load_error_string(Field_load_error fle) {
return errstr;
}
void mbuf_reusable_init(Mbuf_reusable *mbr) {
void mbuf_reusable_init(Mbuf_reusable *mbr)
{
mbr->buffer = NULL;
mbr->capacity = 0;
}
void mbuf_reusable_ensure_size(Mbuf_reusable *mbr, Usz height, Usz width) {
void mbuf_reusable_ensure_size(Mbuf_reusable *mbr, Usz height, Usz width)
{
Usz capacity = height * width;
if (mbr->capacity < capacity) {
mbr->buffer = realloc(mbr->buffer, capacity);
@ -154,4 +186,7 @@ void mbuf_reusable_ensure_size(Mbuf_reusable *mbr, Usz height, Usz width) {
}
}
void mbuf_reusable_deinit(Mbuf_reusable *mbr) { free(mbr->buffer); }
void mbuf_reusable_deinit(Mbuf_reusable *mbr)
{
free(mbr->buffer);
}

3
src/field.h

@ -19,7 +19,8 @@ void field_resize_raw_if_necessary(Field *field, Usz height, Usz width);
void field_copy(Field *src, Field *dest);
void field_fput(Field *field, FILE *stream);
typedef enum {
typedef enum
{
Field_load_error_ok = 0,
Field_load_error_cant_open_file = 1,
Field_load_error_too_many_columns = 2,

36
src/gbuffer.c

@ -1,11 +1,20 @@
#include "gbuffer.h"
void gbuffer_copy_subrect(Glyph *src, Glyph *dest, Usz src_height,
Usz src_width, Usz dest_height, Usz dest_width,
Usz src_y, Usz src_x, Usz dest_y, Usz dest_x,
Usz height, Usz width) {
if (src_height <= src_y || src_width <= src_x || dest_height <= dest_y ||
dest_width <= dest_x)
void gbuffer_copy_subrect(
Glyph *src,
Glyph *dest,
Usz src_height,
Usz src_width,
Usz dest_height,
Usz dest_width,
Usz src_y,
Usz src_x,
Usz dest_y,
Usz dest_x,
Usz height,
Usz width)
{
if (src_height <= src_y || src_width <= src_x || dest_height <= dest_y || dest_width <= dest_x)
return;
Usz ny_0 = src_height - src_y;
Usz ny_1 = dest_height - dest_y;
@ -48,8 +57,16 @@ void gbuffer_copy_subrect(Glyph *src, Glyph *dest, Usz src_height,
}
}
void gbuffer_fill_subrect(Glyph *gbuffer, Usz f_height, Usz f_width, Usz y,
Usz x, Usz height, Usz width, Glyph fill_char) {
void gbuffer_fill_subrect(
Glyph *gbuffer,
Usz f_height,
Usz f_width,
Usz y,
Usz x,
Usz height,
Usz width,
Glyph fill_char)
{
if (y >= f_height || x >= f_width)
return;
Usz rows_0 = f_height - y;
@ -74,7 +91,8 @@ void gbuffer_fill_subrect(Glyph *gbuffer, Usz f_height, Usz f_width, Usz y,
}
}
void mbuffer_clear(Mark *mbuf, Usz height, Usz width) {
void mbuffer_clear(Mark *mbuf, Usz height, Usz width)
{
Usz cleared_size = height * width;
memset(mbuf, 0, cleared_size);
}

85
src/gbuffer.h

@ -1,9 +1,15 @@
#pragma once
#include "base.h"
ORCA_PURE static inline Glyph gbuffer_peek_relative(Glyph *gbuf, Usz height,
Usz width, Usz y, Usz x,
Isz delta_y, Isz delta_x) {
ORCA_PURE static inline Glyph gbuffer_peek_relative(
Glyph *gbuf,
Usz height,
Usz width,
Usz y,
Usz x,
Isz delta_y,
Isz delta_x)
{
Isz y0 = (Isz)y + delta_y;
Isz x0 = (Isz)x + delta_x;
if (y0 < 0 || x0 < 0 || (Usz)y0 >= height || (Usz)x0 >= width)
@ -11,16 +17,23 @@ ORCA_PURE static inline Glyph gbuffer_peek_relative(Glyph *gbuf, Usz height,
return gbuf[(Usz)y0 * width + (Usz)x0];
}
static inline void gbuffer_poke(Glyph *gbuf, Usz height, Usz width, Usz y,
Usz x, Glyph g) {
static inline void gbuffer_poke(Glyph *gbuf, Usz height, Usz width, Usz y, Usz x, Glyph g)
{
assert(y < height && x < width);
(void)height;
gbuf[y * width + x] = g;
}
static inline void gbuffer_poke_relative(Glyph *gbuf, Usz height, Usz width,
Usz y, Usz x, Isz delta_y, Isz delta_x,
Glyph g) {
static inline void gbuffer_poke_relative(
Glyph *gbuf,
Usz height,
Usz width,
Usz y,
Usz x,
Isz delta_y,
Isz delta_x,
Glyph g)
{
Isz y0 = (Isz)y + delta_y;
Isz x0 = (Isz)x + delta_x;
if (y0 < 0 || x0 < 0 || (Usz)y0 >= height || (Usz)x0 >= width)
@ -29,16 +42,33 @@ static inline void gbuffer_poke_relative(Glyph *gbuf, Usz height, Usz width,
}
ORCA_NOINLINE
void gbuffer_copy_subrect(Glyph *src, Glyph *dest, Usz src_grid_h,
Usz src_grid_w, Usz dest_grid_h, Usz dest_grid_w,
Usz src_y, Usz src_x, Usz dest_y, Usz dest_x,
Usz height, Usz width);
void gbuffer_copy_subrect(
Glyph *src,
Glyph *dest,
Usz src_grid_h,
Usz src_grid_w,
Usz dest_grid_h,
Usz dest_grid_w,
Usz src_y,
Usz src_x,
Usz dest_y,
Usz dest_x,
Usz height,
Usz width);
ORCA_NOINLINE
void gbuffer_fill_subrect(Glyph *gbuf, Usz grid_h, Usz grid_w, Usz y, Usz x,
Usz height, Usz width, Glyph fill_char);
void gbuffer_fill_subrect(
Glyph *gbuf,
Usz grid_h,
Usz grid_w,
Usz y,
Usz x,
Usz height,
Usz width,
Glyph fill_char);
typedef enum {
typedef enum
{
Mark_flag_none = 0,
Mark_flag_input = 1 << 0,
Mark_flag_output = 1 << 1,
@ -48,15 +78,15 @@ typedef enum {
} Mark_flags;
ORCA_OK_IF_UNUSED
static Mark_flags mbuffer_peek(Mark *mbuf, Usz height, Usz width, Usz y,
Usz x) {
static Mark_flags mbuffer_peek(Mark *mbuf, Usz height, Usz width, Usz y, Usz x)
{
(void)height;
return mbuf[y * width + x];
}
ORCA_OK_IF_UNUSED
static Mark_flags mbuffer_peek_relative(Mark *mbuf, Usz height, Usz width,
Usz y, Usz x, Isz offs_y, Isz offs_x) {
static Mark_flags mbuffer_peek_relative(Mark *mbuf, Usz height, Usz width, Usz y, Usz x, Isz offs_y, Isz offs_x)
{
Isz y0 = (Isz)y + offs_y;
Isz x0 = (Isz)x + offs_x;
if (y0 >= (Isz)height || x0 >= (Isz)width || y0 < 0 || x0 < 0)
@ -65,16 +95,23 @@ static Mark_flags mbuffer_peek_relative(Mark *mbuf, Usz height, Usz width,
}
ORCA_OK_IF_UNUSED
static void mbuffer_poke_flags_or(Mark *mbuf, Usz height, Usz width, Usz y,
Usz x, Mark_flags flags) {
static void mbuffer_poke_flags_or(Mark *mbuf, Usz height, Usz width, Usz y, Usz x, Mark_flags flags)
{
(void)height;
mbuf[y * width + x] |= (Mark)flags;
}
ORCA_OK_IF_UNUSED
static void mbuffer_poke_relative_flags_or(Mark *mbuf, Usz height, Usz width,
Usz y, Usz x, Isz offs_y, Isz offs_x,
Mark_flags flags) {
static void mbuffer_poke_relative_flags_or(
Mark *mbuf,
Usz height,
Usz width,
Usz y,
Usz x,
Isz offs_y,
Isz offs_x,
Mark_flags flags)
{
Isz y0 = (Isz)y + offs_y;
Isz x0 = (Isz)x + offs_x;
if (y0 >= (Isz)height || x0 >= (Isz)width || y0 < 0 || x0 < 0)

74
src/osc_out.c

@ -15,9 +15,8 @@ struct Oosc_dev {
struct addrinfo *head;
};
Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev **out_ptr,
char const *dest_addr,
char const *dest_port) {
Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev **out_ptr, char const *dest_addr, char const *dest_port)
{
struct addrinfo hints = { 0 };
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
@ -71,8 +70,7 @@ Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev **out_ptr,
}
}
#endif
int udpfd =
socket(chosen->ai_family, chosen->ai_socktype, chosen->ai_protocol);
int udpfd = socket(chosen->ai_family, chosen->ai_socktype, chosen->ai_protocol);
if (udpfd < 0) {
#if 0
fprintf(stderr, "Failed to open UDP socket, error number: %d\n", errno);
@ -88,15 +86,16 @@ Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev **out_ptr,
return Oosc_udp_create_error_ok;
}
void oosc_dev_destroy(Oosc_dev *dev) {
void oosc_dev_destroy(Oosc_dev *dev)
{
close(dev->fd);
freeaddrinfo(dev->head);
free(dev);
}
void oosc_send_datagram(Oosc_dev *dev, char const *data, Usz size) {
ssize_t res = sendto(dev->fd, data, size, 0, dev->chosen->ai_addr,
dev->chosen->ai_addrlen);
void oosc_send_datagram(Oosc_dev *dev, char const *data, Usz size)
{
ssize_t res = sendto(dev->fd, data, size, 0, dev->chosen->ai_addr, dev->chosen->ai_addrlen);
(void)res;
// TODO handle this in UI somehow
#if 0
@ -107,9 +106,13 @@ void oosc_send_datagram(Oosc_dev *dev, char const *data, Usz size) {
#endif
}
static bool oosc_write_strn(char *restrict buffer, Usz buffer_size,
Usz *buffer_pos, char const *restrict in_str,
Usz in_str_len) {
static bool oosc_write_strn(
char *restrict buffer,
Usz buffer_size,
Usz *buffer_pos,
char const *restrict in_str,
Usz in_str_len)
{
// no overflow check, should be fine
Usz in_plus_null = in_str_len + 1;
Usz null_pad = (4 - in_plus_null % 4) % 4;
@ -129,12 +132,11 @@ static bool oosc_write_strn(char *restrict buffer, Usz buffer_size,
return true;
}
void oosc_send_int32s(Oosc_dev *dev, char const *osc_address, I32 const *vals,
Usz count) {
void oosc_send_int32s(Oosc_dev *dev, char const *osc_address, I32 const *vals, Usz count)
{
char buffer[2048];
Usz buf_pos = 0;
if (!oosc_write_strn(buffer, sizeof(buffer), &buf_pos, osc_address,
strlen(osc_address)))
if (!oosc_write_strn(buffer, sizeof(buffer), &buf_pos, osc_address, strlen(osc_address)))
return;
Usz typetag_str_size = 1 + count + 1; // comma, 'i'... , null
Usz typetag_str_null_pad = (4 - typetag_str_size % 4) % 4;
@ -167,19 +169,30 @@ void oosc_send_int32s(Oosc_dev *dev, char const *osc_address, I32 const *vals,
oosc_send_datagram(dev, buffer, buf_pos);
}
void susnote_list_init(Susnote_list *sl) {
void susnote_list_init(Susnote_list *sl)
{
sl->buffer = NULL;
sl->count = 0;
sl->capacity = 0;
}
void susnote_list_deinit(Susnote_list *sl) { free(sl->buffer); }
void susnote_list_deinit(Susnote_list *sl)
{
free(sl->buffer);
}
void susnote_list_clear(Susnote_list *sl) { sl->count = 0; }
void susnote_list_clear(Susnote_list *sl)
{
sl->count = 0;
}
void susnote_list_add_notes(Susnote_list *sl, Susnote const *restrict notes,
Usz added_count, Usz *restrict start_removed,
Usz *restrict end_removed) {
void susnote_list_add_notes(
Susnote_list *sl,
Susnote const *restrict notes,
Usz added_count,
Usz *restrict start_removed,
Usz *restrict end_removed)
{
Susnote *buffer = sl->buffer;
Usz count = sl->count;
Usz cap = sl->capacity;
@ -212,10 +225,13 @@ void susnote_list_add_notes(Susnote_list *sl, Susnote const *restrict notes,
*end_removed = rem;
}
void susnote_list_advance_time(Susnote_list *sl, double delta_time,
void susnote_list_advance_time(
Susnote_list *sl,
double delta_time,
Usz *restrict start_removed,
Usz *restrict end_removed,
double *soonest_deadline) {
double *soonest_deadline)
{
Susnote *restrict buffer = sl->buffer;
Usz count = sl->count;
*end_removed = count;
@ -240,9 +256,12 @@ void susnote_list_advance_time(Susnote_list *sl, double delta_time,
sl->count = count;
}
void susnote_list_remove_by_chan_mask(Susnote_list *sl, Usz chan_mask,
void susnote_list_remove_by_chan_mask(
Susnote_list *sl,
Usz chan_mask,
Usz *restrict start_removed,
Usz *restrict end_removed) {
Usz *restrict end_removed)
{
Susnote *restrict buffer = sl->buffer;
Usz count = sl->count;
*end_removed = count;
@ -261,7 +280,8 @@ void susnote_list_remove_by_chan_mask(Susnote_list *sl, Usz chan_mask,
sl->count = count;
}
double susnote_list_soonest_deadline(Susnote_list const *sl) {
double susnote_list_soonest_deadline(Susnote_list const *sl)
{
float soonest = 1.0f;
Susnote const *buffer = sl->buffer;
for (Usz i = 0, n = sl->count; i < n; ++i) {

25
src/osc_out.h

@ -3,15 +3,14 @@
typedef struct Oosc_dev Oosc_dev;
typedef enum {
typedef enum
{
Oosc_udp_create_error_ok = 0,
Oosc_udp_create_error_getaddrinfo_failed = 1,
Oosc_udp_create_error_couldnt_open_socket = 2,
} Oosc_udp_create_error;
Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev **out_ptr,
char const *dest_addr,
char const *dest_port);
Oosc_udp_create_error oosc_dev_create_udp(Oosc_dev **out_ptr, char const *dest_addr, char const *dest_port);
void oosc_dev_destroy(Oosc_dev *dev);
// Send a raw UDP datagram.
@ -19,8 +18,7 @@ void oosc_send_datagram(Oosc_dev *dev, char const *data, Usz size);
// Send a list/array of 32-bit integers in OSC format to the specified "osc
// address" (a path like /foo) as a UDP datagram.
void oosc_send_int32s(Oosc_dev *dev, char const *osc_address, I32 const *vals,
Usz count);
void oosc_send_int32s(Oosc_dev *dev, char const *osc_address, I32 const *vals, Usz count);
// Susnote is for handling MIDI note sustains -- each MIDI on event should be
// matched with a MIDI note-off event. The duration/sustain length of a MIDI
@ -40,15 +38,22 @@ typedef struct {
void susnote_list_init(Susnote_list *sl);
void susnote_list_deinit(Susnote_list *sl);
void susnote_list_clear(Susnote_list *sl);
void susnote_list_add_notes(Susnote_list *sl, Susnote const *restrict notes,
Usz count, Usz *restrict start_removed,
void susnote_list_add_notes(
Susnote_list *sl,
Susnote const *restrict notes,
Usz count,
Usz *restrict start_removed,
Usz *restrict end_removed);
void susnote_list_advance_time(
Susnote_list *sl, double delta_time, Usz *restrict start_removed,
Susnote_list *sl,
double delta_time,
Usz *restrict start_removed,
Usz *restrict end_removed,
// 1.0 if no notes remain or none are shorter than 1.0
double *soonest_deadline);
void susnote_list_remove_by_chan_mask(Susnote_list *sl, Usz chan_mask,
void susnote_list_remove_by_chan_mask(
Susnote_list *sl,
Usz chan_mask,
Usz *restrict start_removed,
Usz *restrict end_removed);

80
src/oso.c

@ -25,7 +25,8 @@ typedef struct oso {
size_t len, cap;
} oso_header;
OSO_INTERNAL oso *oso_impl_reallochdr(oso_header *hdr, size_t new_cap) {
OSO_INTERNAL oso *oso_impl_reallochdr(oso_header *hdr, size_t new_cap)
{
if (hdr) {
oso_header *new_hdr = realloc(hdr, sizeof(oso_header) + new_cap + 1);
if (!new_hdr) {
@ -43,7 +44,8 @@ OSO_INTERNAL oso *oso_impl_reallochdr(oso_header *hdr, size_t new_cap) {
((char *)(hdr + 1))[0] = '\0';
return hdr + 1;
}
OSO_INTERNAL oso *oso_impl_catvprintf(oso *s, char const *fmt, va_list ap) {
OSO_INTERNAL oso *oso_impl_catvprintf(oso *s, char const *fmt, va_list ap)
{
size_t old_len;
int required;
va_list cpy;
@ -60,7 +62,8 @@ OSO_INTERNAL oso *oso_impl_catvprintf(oso *s, char const *fmt, va_list ap) {
}
OSO_NOINLINE
void osoensurecap(oso **p, size_t new_cap) {
void osoensurecap(oso **p, size_t new_cap)
{
oso *s = *p;
if (new_cap > OSO_CAP_MAX) {
if (s) {
@ -79,7 +82,8 @@ void osoensurecap(oso **p, size_t new_cap) {
}
OSO_NOINLINE
void osomakeroomfor(oso **p, size_t add_len) {
void osomakeroomfor(oso **p, size_t add_len)
{
oso *s = *p;
oso_header *hdr = NULL;
size_t new_cap;
@ -102,12 +106,14 @@ void osomakeroomfor(oso **p, size_t add_len) {
*p = oso_impl_reallochdr(hdr, new_cap);
}
void osoput(oso **p, char const *restrict cstr) {
void osoput(oso **p, char const *restrict cstr)
{
osoputlen(p, cstr, strlen(cstr));
}
OSO_NOINLINE
void osoputlen(oso **p, char const *restrict cstr, size_t len) {
void osoputlen(oso **p, char const *restrict cstr, size_t len)
{
oso *s = *p;
osoensurecap(&s, len);
if (s) {
@ -117,12 +123,14 @@ void osoputlen(oso **p, char const *restrict cstr, size_t len) {
}
*p = s;
}
void osoputoso(oso **p, oso const *other) {
void osoputoso(oso **p, oso const *other)
{
if (!other)
return;
osoputlen(p, (char const *)other, OSO_HDR(other)->len);
}
void osoputvprintf(oso **p, char const *fmt, va_list ap) {
void osoputvprintf(oso **p, char const *fmt, va_list ap)
{
oso *s = *p;
if (s) {
OSO_HDR(s)->len = 0;
@ -130,7 +138,8 @@ void osoputvprintf(oso **p, char const *fmt, va_list ap) {
}
*p = oso_impl_catvprintf(s, fmt, ap);
}
void osoputprintf(oso **p, char const *fmt, ...) {
void osoputprintf(oso **p, char const *fmt, ...)
{
oso *s = *p;
if (s) {
OSO_HDR(s)->len = 0;
@ -141,9 +150,13 @@ void osoputprintf(oso **p, char const *fmt, ...) {
*p = oso_impl_catvprintf(s, fmt, ap);
va_end(ap);
}
void osocat(oso **p, char const *cstr) { osocatlen(p, cstr, strlen(cstr)); }
void osocat(oso **p, char const *cstr)
{
osocatlen(p, cstr, strlen(cstr));
}
OSO_NOINLINE
void osocatlen(oso **p, char const *cstr, size_t len) {
void osocatlen(oso **p, char const *cstr, size_t len)
{
oso *s = *p;
osomakeroomfor(&s, len);
if (s) {
@ -155,44 +168,61 @@ void osocatlen(oso **p, char const *cstr, size_t len) {
}
*p = s;
}
void osocatoso(oso **p, oso const *other) {
void osocatoso(oso **p, oso const *other)
{
if (!other)
return;
osocatlen(p, (char const *)other, OSO_HDR(other)->len);
}
void osocatvprintf(oso **p, char const *fmt, va_list ap) {
void osocatvprintf(oso **p, char const *fmt, va_list ap)
{
*p = oso_impl_catvprintf(*p, fmt, ap);
}
void osocatprintf(oso **p, char const *fmt, ...) {
void osocatprintf(oso **p, char const *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
*p = oso_impl_catvprintf(*p, fmt, ap);
va_end(ap);
}
void osoclear(oso **p) {
void osoclear(oso **p)
{
oso *s = *p;
if (!s)
return;
OSO_HDR(s)->len = 0;
((char *)s)[0] = '\0';
}
void osofree(oso *s) {
void osofree(oso *s)
{
if (s)
free(OSO_HDR(s));
}
void osowipe(oso **p) {
void osowipe(oso **p)
{
osofree(*p);
*p = NULL;
}
void ososwap(oso **a, oso **b) {
void ososwap(oso **a, oso **b)
{
oso *tmp = *a;
*a = *b;
*b = tmp;
}
void osopokelen(oso *s, size_t len) { OSO_HDR(s)->len = len; }
size_t osolen(oso const *s) { return s ? OSO_HDR(s)->len : 0; }
size_t osocap(oso const *s) { return s ? OSO_HDR(s)->cap : 0; }
void osolencap(oso const *s, size_t *out_len, size_t *out_cap) {
void osopokelen(oso *s, size_t len)
{
OSO_HDR(s)->len = len;
}
size_t osolen(oso const *s)
{
return s ? OSO_HDR(s)->len : 0;
}
size_t osocap(oso const *s)
{
return s ? OSO_HDR(s)->cap : 0;
}
void osolencap(oso const *s, size_t *out_len, size_t *out_cap)
{
if (!s) {
*out_len = 0;
*out_cap = 0;
@ -202,14 +232,16 @@ void osolencap(oso const *s, size_t *out_len, size_t *out_cap) {
*out_len = hdr->len;
*out_cap = hdr->cap;
}
size_t osoavail(oso const *s) {
size_t osoavail(oso const *s)
{
if (!s)
return 0;
oso_header *h = OSO_HDR(s);
return h->cap - h->len;
}
void osotrim(oso *restrict s, char const *restrict cut_set) {
void osotrim(oso *restrict s, char const *restrict cut_set)
{
if (!s)
return;
char *str, *end, *start_pos, *end_pos;

15
src/oso.h

@ -122,19 +122,15 @@ void osoputlen(oso **p, char const *cstr, size_t len) OSO_NONNULL();
void osoputoso(oso **p, oso const *other) OSO_NONNULL(1);
// ^- Same as above, but using another `oso`. `*p` and `other` must not point
// to overlapping memory.
void osoputvprintf(oso **p, char const *fmt, va_list ap) OSO_NONNULL(1, 2)
OSO_PRINTF(2, 0);
void osoputprintf(oso **p, char const *fmt, ...) OSO_NONNULL(1, 2)
OSO_PRINTF(2, 3);
void osoputvprintf(oso **p, char const *fmt, va_list ap) OSO_NONNULL(1, 2) OSO_PRINTF(2, 0);
void osoputprintf(oso **p, char const *fmt, ...) OSO_NONNULL(1, 2) OSO_PRINTF(2, 3);
// ^- Same as above, but do it by using printf.
void osocat(oso **p, char const *cstr) OSO_NONNULL();
void osocatlen(oso **p, char const *cstr, size_t len) OSO_NONNULL();
void osocatoso(oso **p, oso const *other) OSO_NONNULL(1);
void osocatvprintf(oso **p, char const *fmt, va_list ap) OSO_NONNULL(1, 2)
OSO_PRINTF(2, 0);
void osocatprintf(oso **p, char const *fmt, ...) OSO_NONNULL(1, 2)
OSO_PRINTF(2, 3);
void osocatvprintf(oso **p, char const *fmt, va_list ap) OSO_NONNULL(1, 2) OSO_PRINTF(2, 0);
void osocatprintf(oso **p, char const *fmt, ...) OSO_NONNULL(1, 2) OSO_PRINTF(2, 3);
// ^- Append string to oso string. Same rules as `osoput` family.
void osoensurecap(oso **p, size_t cap) OSO_NONNULL();
@ -169,8 +165,7 @@ size_t osolen(oso const *s);
// ^- Bytes in use by the string (not including the '\0' character.)
size_t osocap(oso const *s);
// ^- Bytes allocated on heap (not including the '\0' terminator.)
void osolencap(oso const *s, size_t *out_len, size_t *out_cap)
OSO_NONNULL(2, 3);
void osolencap(oso const *s, size_t *out_len, size_t *out_cap) OSO_NONNULL(2, 3);
// ^- Get both the len and the cap in one call.
size_t osoavail(oso const *s);
// ^- osocap(s) - osolen(s)

145
src/sim.c

@ -8,8 +8,12 @@ static Glyph const glyph_table[36] = {
'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 12-23
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', // 24-35
};
enum { Glyphs_index_count = sizeof glyph_table };
static inline Glyph glyph_of(Usz index) {
enum
{
Glyphs_index_count = sizeof glyph_table
};
static inline Glyph glyph_of(Usz index)
{
assert(index < Glyphs_index_count);
return glyph_table[index];
}
@ -22,8 +26,12 @@ static U8 const index_table[128] = {
0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 64-79
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0, // 80-95
0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 96-111
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0}; // 112-127
static ORCA_FORCEINLINE Usz index_of(Glyph c) { return index_table[c & 0x7f]; }
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 0, 0, 0, 0
}; // 112-127
static ORCA_FORCEINLINE Usz index_of(Glyph c)
{
return index_table[c & 0x7f];
}
// Reference implementation:
// static Usz index_of(Glyph c) {
@ -33,18 +41,26 @@ static ORCA_FORCEINLINE Usz index_of(Glyph c) { return index_table[c & 0x7f]; }
// return 0;
// }
static ORCA_FORCEINLINE bool glyph_is_lowercase(Glyph g) { return g & 1 << 5; }
static ORCA_FORCEINLINE Glyph glyph_lowered_unsafe(Glyph g) {
static ORCA_FORCEINLINE bool glyph_is_lowercase(Glyph g)
{
return g & 1 << 5;
}
static ORCA_FORCEINLINE Glyph glyph_lowered_unsafe(Glyph g)
{
return (Glyph)(g | 1 << 5);
}
static inline Glyph glyph_with_case(Glyph g, Glyph caser) {
enum { Case_bit = 1 << 5, Alpha_bit = 1 << 6 };
return (Glyph)((g & ~Case_bit) | ((~g & Alpha_bit) >> 1) |
(caser & Case_bit));
static inline Glyph glyph_with_case(Glyph g, Glyph caser)
{
enum
{
Case_bit = 1 << 5,
Alpha_bit = 1 << 6
};
return (Glyph)((g & ~Case_bit) | ((~g & Alpha_bit) >> 1) | (caser & Case_bit));
}
static ORCA_PURE bool oper_has_neighboring_bang(Glyph const *gbuf, Usz h, Usz w,
Usz y, Usz x) {
static ORCA_PURE bool oper_has_neighboring_bang(Glyph const *gbuf, Usz h, Usz w, Usz y, Usz x)
{
Glyph const *gp = gbuf + w * y + x;
if (x < w - 1 && gp[1] == '*')
return true;
@ -60,7 +76,8 @@ static ORCA_PURE bool oper_has_neighboring_bang(Glyph const *gbuf, Usz h, Usz w,
}
// Returns UINT8_MAX if not a valid note.
static U8 midi_note_number_of(Glyph g) {
static U8 midi_note_number_of(Glyph g)
{
int sharp = (g & 1 << 5) >> 5; // sharp=1 if lowercase
g &= (Glyph) ~(1 << 5); // make uppercase
if (g < 'A' || g > 'Z') // A through Z only
@ -76,9 +93,17 @@ typedef struct {
Usz random_seed;
} Oper_extra_params;
static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer,
Usz height, Usz width, Usz y, Usz x, Isz delta_y,
Isz delta_x, Glyph g) {
static void oper_poke_and_stun(
Glyph *restrict gbuffer,
Mark *restrict mbuffer,
Usz height,
Usz width,
Usz y,
Usz x,
Isz delta_y,
Isz delta_x,
Glyph g)
{
Isz y0 = (Isz)y + delta_y;
Isz x0 = (Isz)x + delta_x;
if (y0 < 0 || x0 < 0 || (Usz)y0 >= height || (Usz)x0 >= width)
@ -96,10 +121,17 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer,
#define BEGIN_OPERATOR(_oper_name) \
OPER_FUNCTION_ATTRIBS oper_behavior_##_oper_name( \
Glyph *const restrict gbuffer, Mark *const restrict mbuffer, \
Usz const height, Usz const width, Usz const y, Usz const x, \
Usz Tick_number, Oper_extra_params *const extra_params, \
Mark const cell_flags, Glyph const This_oper_char) { \
Glyph *const restrict gbuffer, \
Mark *const restrict mbuffer, \
Usz const height, \
Usz const width, \
Usz const y, \
Usz const x, \
Usz Tick_number, \
Oper_extra_params *const extra_params, \
Mark const cell_flags, \
Glyph const This_oper_char) \
{ \
(void)gbuffer; \
(void)mbuffer; \
(void)height; \
@ -116,17 +148,13 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer,
#define PEEK(_delta_y, _delta_x) \
gbuffer_peek_relative(gbuffer, height, width, y, x, _delta_y, _delta_x)
#define POKE(_delta_y, _delta_x, _glyph) \
gbuffer_poke_relative(gbuffer, height, width, y, x, _delta_y, _delta_x, \
_glyph)
gbuffer_poke_relative(gbuffer, height, width, y, x, _delta_y, _delta_x, _glyph)
#define STUN(_delta_y, _delta_x) \
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \
_delta_x, Mark_flag_sleep)
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, _delta_x, Mark_flag_sleep)
#define POKE_STUNNED(_delta_y, _delta_x, _glyph) \
oper_poke_and_stun(gbuffer, mbuffer, height, width, y, x, _delta_y, \
_delta_x, _glyph)
oper_poke_and_stun(gbuffer, mbuffer, height, width, y, x, _delta_y, _delta_x, _glyph)
#define LOCK(_delta_y, _delta_x) \
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \
_delta_x, Mark_flag_lock)
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, _delta_x, Mark_flag_lock)
#define IN Mark_flag_input
#define OUT Mark_flag_output
@ -143,8 +171,7 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer,
return
#define PORT(_delta_y, _delta_x, _flags) \
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, \
_delta_x, (_flags) ^ Mark_flag_lock)
mbuffer_poke_relative_flags_or(mbuffer, height, width, y, x, _delta_y, _delta_x, (_flags) ^ Mark_flag_lock)
//////// Operators
#define UNIQUE_OPERATORS(_) \
@ -186,8 +213,7 @@ static void oper_poke_and_stun(Glyph *restrict gbuffer, Mark *restrict mbuffer,
_('Z', lerp)
BEGIN_OPERATOR(movement)
if (glyph_is_lowercase(This_oper_char) &&
!oper_has_neighboring_bang(gbuffer, height, width, y, x))
if (glyph_is_lowercase(This_oper_char) && !oper_has_neighboring_bang(gbuffer, height, width, y, x))
return;
Isz delta_y, delta_x;
switch (glyph_lowered_unsafe(This_oper_char)) {
@ -243,8 +269,7 @@ BEGIN_OPERATOR(midicc)
if (channel > 15)
return;
PORT(0, 0, OUT);
Oevent_midi_cc *oe =
(Oevent_midi_cc *)oevent_list_alloc_item(extra_params->oevent_list);
Oevent_midi_cc *oe = (Oevent_midi_cc *)oevent_list_alloc_item(extra_params->oevent_list);
oe->oevent_type = Oevent_type_midi_cc;
oe->channel = (U8)channel;
oe->control = (U8)index_of(control_g);
@ -307,8 +332,7 @@ BEGIN_OPERATOR(midi)
vel_num = 127;
}
PORT(0, 0, OUT);
Oevent_midi_note *oe =
(Oevent_midi_note *)oevent_list_alloc_item(extra_params->oevent_list);
Oevent_midi_note *oe = (Oevent_midi_note *)oevent_list_alloc_item(extra_params->oevent_list);
oe->oevent_type = (U8)Oevent_type_midi_note;
oe->channel = (U8)channel_num;
oe->octave = octave_num;
@ -338,8 +362,7 @@ BEGIN_OPERATOR(udp)
n = i;
STOP_IF_NOT_BANGED;
PORT(0, 0, OUT);
Oevent_udp_string *oe =
(Oevent_udp_string *)oevent_list_alloc_item(extra_params->oevent_list);
Oevent_udp_string *oe = (Oevent_udp_string *)oevent_list_alloc_item(extra_params->oevent_list);
oe->oevent_type = (U8)Oevent_type_udp_string;
oe->count = (U8)n;
for (i = 0; i < n; ++i) {
@ -364,8 +387,7 @@ BEGIN_OPERATOR(osc)
for (Usz i = 0; i < len; ++i) {
buff[i] = (U8)index_of(PEEK(0, (Isz)i + 3));
}
Oevent_osc_ints *oe =
&oevent_list_alloc_item(extra_params->oevent_list)->osc_ints;
Oevent_osc_ints *oe = &oevent_list_alloc_item(extra_params->oevent_list)->osc_ints;
oe->oevent_type = (U8)Oevent_type_osc_ints;
oe->glyph = g;
oe->count = (U8)len;
@ -389,8 +411,7 @@ BEGIN_OPERATOR(midipb)
if (channel > 15)
return;
PORT(0, 0, OUT);
Oevent_midi_pb *oe =
(Oevent_midi_pb *)oevent_list_alloc_item(extra_params->oevent_list);
Oevent_midi_pb *oe = (Oevent_midi_pb *)oevent_list_alloc_item(extra_params->oevent_list);
oe->oevent_type = Oevent_type_midi_pb;
oe->channel = (U8)channel;
oe->msb = (U8)(index_of(msb_g) * 127 / 35); // 0~35 -> 0~127
@ -634,8 +655,7 @@ BEGIN_OPERATOR(random)
max = a;
}
// Initial input params for the hash
Usz key = (extra_params->random_seed + y * width + x) ^
(Tick_number << UINT32_C(16));
Usz key = (extra_params->random_seed + y * width + x) ^ (Tick_number << UINT32_C(16));
// 32-bit shift_mult hash to evenly distribute bits
key = (key ^ UINT32_C(61)) ^ (key >> UINT32_C(16));
key = key + (key << UINT32_C(3));
@ -745,8 +765,15 @@ END_OPERATOR
//////// Run simulation
void orca_run(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, Usz width,
Usz tick_number, Oevent_list *oevent_list, Usz random_seed) {
void orca_run(
Glyph *restrict gbuf,
Mark *restrict mbuf,
Usz height,
Usz width,
Usz tick_number,
Oevent_list *oevent_list,
Usz random_seed)
{
Glyph vars_slots[Glyphs_index_count];
memset(vars_slots, '.', sizeof(vars_slots));
Oper_extra_params extras;
@ -767,15 +794,33 @@ void orca_run(Glyph *restrict gbuf, Mark *restrict mbuf, Usz height, Usz width,
switch (glyph_char) {
#define UNIQUE_CASE(_oper_char, _oper_name) \
case _oper_char: \
oper_behavior_##_oper_name(gbuf, mbuf, height, width, iy, ix, tick_number, \
&extras, cell_flags, glyph_char); \
oper_behavior_##_oper_name( \
gbuf, \
mbuf, \
height, \
width, \
iy, \
ix, \
tick_number, \
&extras, \
cell_flags, \
glyph_char); \
break;
#define ALPHA_CASE(_upper_oper_char, _oper_name) \
case _upper_oper_char: \
case (char)(_upper_oper_char | 1 << 5): \
oper_behavior_##_oper_name(gbuf, mbuf, height, width, iy, ix, tick_number, \
&extras, cell_flags, glyph_char); \
oper_behavior_##_oper_name( \
gbuf, \
mbuf, \
height, \
width, \
iy, \
ix, \
tick_number, \
&extras, \
cell_flags, \
glyph_char); \
break;
UNIQUE_OPERATORS(UNIQUE_CASE)
ALPHA_OPERATORS(ALPHA_CASE)

9
src/sim.h

@ -2,6 +2,11 @@
#include "base.h"
#include "vmio.h"
void orca_run(Glyph *restrict gbuffer, Mark *restrict mbuffer, Usz height,
Usz width, Usz tick_number, Oevent_list *oevent_list,
void orca_run(
Glyph *restrict gbuffer,
Mark *restrict mbuffer,
Usz height,
Usz width,
Usz tick_number,
Oevent_list *oevent_list,
Usz random_seed);

35
src/sokol_time.h

@ -142,15 +142,16 @@ static uint64_t _stm_posix_start;
see https://gist.github.com/jspohr/3dc4f00033d79ec5bdaf67bc46c813e3
*/
#if defined(_WIN32) || (defined(__APPLE__) && defined(__MACH__))
_SOKOL_PRIVATE int64_t int64_muldiv(int64_t value, int64_t numer, int64_t denom) {
_SOKOL_PRIVATE int64_t int64_muldiv(int64_t value, int64_t numer, int64_t denom)
{
int64_t q = value / denom;
int64_t r = value % denom;
return q * numer + r * numer / denom;
}
#endif
SOKOL_API_IMPL void stm_setup(void) {
SOKOL_API_IMPL void stm_setup(void)
{
SOKOL_ASSERT(0 == _stm_initialized);
_stm_initialized = 1;
#if defined(_WIN32)
@ -166,7 +167,8 @@ SOKOL_API_IMPL void stm_setup(void) {
#endif
}
SOKOL_API_IMPL uint64_t stm_now(void) {
SOKOL_API_IMPL uint64_t stm_now(void)
{
SOKOL_ASSERT(_stm_initialized);
uint64_t now;
#if defined(_WIN32)
@ -184,21 +186,23 @@ SOKOL_API_IMPL uint64_t stm_now(void) {
return now;
}
SOKOL_API_IMPL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks) {
SOKOL_API_IMPL uint64_t stm_diff(uint64_t new_ticks, uint64_t old_ticks)
{
if (new_ticks > old_ticks) {
return new_ticks - old_ticks;
}
else {
} else {
/* FIXME: this should be a value that converts to a non-null double */
return 1;
}
}
SOKOL_API_IMPL uint64_t stm_since(uint64_t start_ticks) {
SOKOL_API_IMPL uint64_t stm_since(uint64_t start_ticks)
{
return stm_diff(stm_now(), start_ticks);
}
SOKOL_API_IMPL uint64_t stm_laptime(uint64_t* last_time) {
SOKOL_API_IMPL uint64_t stm_laptime(uint64_t *last_time)
{
SOKOL_ASSERT(last_time);
uint64_t dt = 0;
uint64_t now = stm_now();
@ -209,20 +213,23 @@ SOKOL_API_IMPL uint64_t stm_laptime(uint64_t* last_time) {
return dt;
}
SOKOL_API_IMPL double stm_sec(uint64_t ticks) {
SOKOL_API_IMPL double stm_sec(uint64_t ticks)
{
return (double)ticks / 1000000000.0;
}
SOKOL_API_IMPL double stm_ms(uint64_t ticks) {
SOKOL_API_IMPL double stm_ms(uint64_t ticks)
{
return (double)ticks / 1000000.0;
}
SOKOL_API_IMPL double stm_us(uint64_t ticks) {
SOKOL_API_IMPL double stm_us(uint64_t ticks)
{
return (double)ticks / 1000.0;
}
SOKOL_API_IMPL double stm_ns(uint64_t ticks) {
SOKOL_API_IMPL double stm_ns(uint64_t ticks)
{
return (double)ticks;
}
#endif /* SOKOL_IMPL */

110
src/sysmisc.c

@ -8,7 +8,8 @@
static char const *const xdg_config_home_env = "XDG_CONFIG_HOME";
static char const *const home_env = "HOME";
void expand_home_tilde(oso **path) {
void expand_home_tilde(oso **path)
{
oso *s = *path;
size_t n = osolen(s);
if (n < 2)
@ -30,9 +31,15 @@ done:
}
ORCA_NOINLINE
Cboard_error cboard_copy(Glyph const *gbuffer, Usz field_height,
Usz field_width, Usz rect_y, Usz rect_x, Usz rect_h,
Usz rect_w) {
Cboard_error cboard_copy(
Glyph const *gbuffer,
Usz field_height,
Usz field_width,
Usz rect_y,
Usz rect_x,
Usz rect_h,
Usz rect_w)
{
(void)field_height;
FILE *fp =
#ifdef ORCA_OS_MAC
@ -53,8 +60,8 @@ Cboard_error cboard_copy(Glyph const *gbuffer, Usz field_height,
}
ORCA_NOINLINE
Cboard_error cboard_paste(Glyph *gbuffer, Usz height, Usz width, Usz y, Usz x,
Usz *out_h, Usz *out_w) {
Cboard_error cboard_paste(Glyph *gbuffer, Usz height, Usz width, Usz y, Usz x, Usz *out_h, Usz *out_w)
{
FILE *fp =
#ifdef ORCA_OS_MAC
popen("pbpaste -pboard general -Prefer txt 2>/dev/null", "r");
@ -94,9 +101,15 @@ Cboard_error cboard_paste(Glyph *gbuffer, Usz height, Usz width, Usz y, Usz x,
}
ORCA_NOINLINE
Conf_read_result conf_read_line(FILE *file, char *buf, Usz bufsize,
char **out_left, Usz *out_leftsize,
char **out_right, Usz *out_rightsize) {
Conf_read_result conf_read_line(
FILE *file,
char *buf,
Usz bufsize,
char **out_left,
Usz *out_leftsize,
char **out_right,
Usz *out_rightsize)
{
// a0 and a1 are the start and end positions of the left side of an "foo=bar"
// pair. b0 and b1 are the positions right side. Leading and trailing spaces
// will be removed.
@ -208,16 +221,22 @@ ok:
return Conf_read_left_and_right;
}
bool conf_read_match(FILE **pfile, char const *const *names, Usz nameslen,
char *buf, Usz bufsize, Usz *out_index, char **out_value) {
bool conf_read_match(
FILE **pfile,
char const *const *names,
Usz nameslen,
char *buf,
Usz bufsize,
Usz *out_index,
char **out_value)
{
FILE *file = *pfile;
if (!file)
return false;
char *left;
Usz leftsz, rightsz;
next_line:;
Conf_read_result res =
conf_read_line(file, buf, bufsize, &left, &leftsz, out_value, &rightsz);
Conf_read_result res = conf_read_line(file, buf, bufsize, &left, &leftsz, out_value, &rightsz);
switch (res) {
case Conf_read_left_and_right:
for (Usz i = 0; i < nameslen; i++) {
@ -239,12 +258,14 @@ next_line:;
return false;
}
typedef enum {
typedef enum
{
Conf_dir_ok = 0,
Conf_dir_no_home,
} Conf_dir_error;
static Conf_dir_error try_get_conf_dir(oso **out) {
static Conf_dir_error try_get_conf_dir(oso **out)
{
char const *xdgcfgdir = getenv(xdg_config_home_env);
if (xdgcfgdir) {
Usz xdgcfgdirlen = strlen(xdgcfgdir);
@ -264,8 +285,8 @@ static Conf_dir_error try_get_conf_dir(oso **out) {
return Conf_dir_no_home;
}
static void conf_impl_catconfpath(oso **p, char const *conf_file_name,
size_t conflen) {
static void conf_impl_catconfpath(oso **p, char const *conf_file_name, size_t conflen)
{
oso *path = *p;
size_t n = osolen(path);
osoensurecap(&path, n + 1 + conflen);
@ -279,7 +300,8 @@ done:
*p = path;
}
FILE *conf_file_open_for_reading(char const *conf_file_name) {
FILE *conf_file_open_for_reading(char const *conf_file_name)
{
if (!conf_file_name)
return NULL;
oso *path = NULL;
@ -296,8 +318,8 @@ FILE *conf_file_open_for_reading(char const *conf_file_name) {
return file;
}
Conf_save_start_error conf_save_start(Conf_save *p,
char const *conf_file_name) {
Conf_save_start_error conf_save_start(Conf_save *p, char const *conf_file_name)
{
*p = (Conf_save){ 0 };
oso *dir = NULL;
Conf_save_start_error err;
@ -369,7 +391,8 @@ cleanup:
return err;
}
void conf_save_cancel(Conf_save *p) {
void conf_save_cancel(Conf_save *p)
{
osofree(p->canonpath);
osofree(p->temppath);
if (p->origfile)
@ -379,7 +402,8 @@ void conf_save_cancel(Conf_save *p) {
*p = (Conf_save){ 0 };
}
Conf_save_commit_error conf_save_commit(Conf_save *p) {
Conf_save_commit_error conf_save_commit(Conf_save *p)
{
Conf_save_commit_error err;
fclose(p->tempfile);
p->tempfile = NULL;
@ -401,7 +425,8 @@ cleanup:
return err;
}
char const *ezconf_w_errorstring(Ezconf_w_error error) {
char const *ezconf_w_errorstring(Ezconf_w_error error)
{
switch (error) {
case Ezconf_w_ok:
return "No error";
@ -438,24 +463,33 @@ char const *ezconf_w_errorstring(Ezconf_w_error error) {
return "Unknown";
}
void ezconf_r_start(Ezconf_r *ezcr, char const *conf_file_name) {
void ezconf_r_start(Ezconf_r *ezcr, char const *conf_file_name)
{
ezcr->file = conf_file_open_for_reading(conf_file_name);
ezcr->index = 0;
ezcr->value = NULL;
}
bool ezconf_r_step(Ezconf_r *ezcr, char const *const *names, size_t nameslen) {
return conf_read_match(&ezcr->file, names, nameslen, ezcr->buffer,
sizeof ezcr->buffer, &ezcr->index, &ezcr->value);
bool ezconf_r_step(Ezconf_r *ezcr, char const *const *names, size_t nameslen)
{
return conf_read_match(
&ezcr->file,
names,
nameslen,
ezcr->buffer,
sizeof ezcr->buffer,
&ezcr->index,
&ezcr->value);
}
enum {
enum
{
Confwflag_add_newline = 1 << 0,
Ezconf_opt_written = 1 << 0,
};
void ezconf_w_start(Ezconf_w *ezcw, Ezconf_opt *optsbuffer, size_t buffercap,
char const *conf_file_name) {
void ezconf_w_start(Ezconf_w *ezcw, Ezconf_opt *optsbuffer, size_t buffercap, char const *conf_file_name)
{
*ezcw = (Ezconf_w){ .save = { 0 } }; // Weird to silence clang warning
ezcw->opts = optsbuffer;
ezcw->optscap = buffercap;
@ -492,14 +526,16 @@ void ezconf_w_start(Ezconf_w *ezcw, Ezconf_opt *optsbuffer, size_t buffercap,
}
ezcw->error = error;
}
void ezconf_w_addopt(Ezconf_w *ezcw, char const *key, intptr_t id) {
void ezconf_w_addopt(Ezconf_w *ezcw, char const *key, intptr_t id)
{
size_t count = ezcw->optscount, cap = ezcw->optscap;
if (count == cap)
return;
ezcw->opts[count] = (Ezconf_opt){ .name = key, .id = id, .flags = 0 };
ezcw->optscount = count + 1;
}
bool ezconf_w_step(Ezconf_w *ezcw) {
bool ezconf_w_step(Ezconf_w *ezcw)
{
uint32_t stateflags = ezcw->stateflags;
FILE *origfile = ezcw->save.origfile, *tempfile = ezcw->save.tempfile;
Ezconf_opt *opts = ezcw->opts, *chosen = NULL;
@ -520,8 +556,14 @@ bool ezconf_w_step(Ezconf_w *ezcw) {
char linebuff[1024];
char *left, *right;
size_t leftsz, rightsz;
Conf_read_result res = conf_read_line(origfile, linebuff, sizeof linebuff,
&left, &leftsz, &right, &rightsz);
Conf_read_result res = conf_read_line(
origfile,
linebuff,
sizeof linebuff,
&left,
&leftsz,
&right,
&rightsz);
switch (res) {
case Conf_read_left_and_right: {
for (size_t i = 0; i < optscount; i++) {

53
src/sysmisc.h

@ -5,21 +5,27 @@ struct oso;
void expand_home_tilde(struct oso **path);
typedef enum {
typedef enum
{
Cboard_error_none = 0,
Cboard_error_unavailable,
Cboard_error_popen_failed,
Cboard_error_process_exit_error,
} Cboard_error;
Cboard_error cboard_copy(Glyph const *gbuffer, Usz field_height,
Usz field_width, Usz rect_y, Usz rect_x, Usz rect_h,
Cboard_error cboard_copy(
Glyph const *gbuffer,
Usz field_height,
Usz field_width,
Usz rect_y,
Usz rect_x,
Usz rect_h,
Usz rect_w);
Cboard_error cboard_paste(Glyph *gbuffer, Usz height, Usz width, Usz y, Usz x,
Usz *out_h, Usz *out_w);
Cboard_error cboard_paste(Glyph *gbuffer, Usz height, Usz width, Usz y, Usz x, Usz *out_h, Usz *out_w);
typedef enum {
typedef enum
{
Conf_read_left_and_right = 0, // left and right will be set
Conf_read_irrelevant, // only left will be set
Conf_read_buffer_too_small, // neither will be set
@ -27,12 +33,23 @@ typedef enum {
Conf_read_io_error, // "
} Conf_read_result;
Conf_read_result conf_read_line(FILE *file, char *buf, Usz bufsize,
char **out_left, Usz *out_leftlen,
char **out_right, Usz *out_rightlen);
bool conf_read_match(FILE **pfile, char const *const *names, Usz nameslen,
char *buf, Usz bufsize, Usz *out_index, char **out_value);
Conf_read_result conf_read_line(
FILE *file,
char *buf,
Usz bufsize,
char **out_left,
Usz *out_leftlen,
char **out_right,
Usz *out_rightlen);
bool conf_read_match(
FILE **pfile,
char const *const *names,
Usz nameslen,
char *buf,
Usz bufsize,
Usz *out_index,
char **out_value);
FILE *conf_file_open_for_reading(char const *conf_file_name);
@ -41,7 +58,8 @@ typedef struct {
struct oso *canonpath, *temppath;
} Conf_save;
typedef enum {
typedef enum
{
Conf_save_start_ok = 0,
Conf_save_start_bad_conf_name,
Conf_save_start_alloc_failed,
@ -53,7 +71,8 @@ typedef enum {
Conf_save_start_temp_file_open_failed,
} Conf_save_start_error;
typedef enum {
typedef enum
{
Conf_save_commit_ok = 0,
Conf_save_commit_temp_fsync_failed,
Conf_save_commit_temp_close_failed,
@ -94,7 +113,8 @@ typedef struct {
void ezconf_r_start(Ezconf_r *ezcr, char const *conf_file_name);
bool ezconf_r_step(Ezconf_r *ezcr, char const *const *names, Usz nameslen);
typedef enum {
typedef enum
{
Ezconf_w_ok = 0,
Ezconf_w_bad_conf_name,
Ezconf_w_oom,
@ -130,7 +150,6 @@ typedef struct {
uint32_t stateflags;
} Ezconf_w;
void ezconf_w_start(Ezconf_w *ezcw, Ezconf_opt *optsbuffer, size_t buffercap,
char const *conf_file_name);
void ezconf_w_start(Ezconf_w *ezcw, Ezconf_opt *optsbuffer, size_t buffercap, char const *conf_file_name);
void ezconf_w_addopt(Ezconf_w *ezcw, char const *key, intptr_t id);
bool ezconf_w_step(Ezconf_w *ezcw);

203
src/term_util.c

@ -3,15 +3,18 @@
#include <ctype.h>
#include <form.h>
void term_util_init_colors() {
void term_util_init_colors()
{
if (has_colors()) {
// Enable color
start_color();
use_default_colors();
for (int ifg = 0; ifg < Colors_count; ++ifg) {
for (int ibg = 0; ibg < Colors_count; ++ibg) {
int res = init_pair((short int)(1 + ifg * Colors_count + ibg),
(short int)(ifg - 1), (short int)(ibg - 1));
int res = init_pair(
(short int)(1 + ifg * Colors_count + ibg),
(short int)(ifg - 1),
(short int)(ibg - 1));
(void)res;
// Might fail on Linux virtual console/terminal for a couple of colors.
// Just ignore.
@ -29,8 +32,7 @@ void term_util_init_colors() {
}
#define ORCA_CONTAINER_OF(ptr, type, member) \
((type *)((char *)(1 ? (ptr) : &((type *)0)->member) - \
offsetof(type, member)))
((type *)((char *)(1 ? (ptr) : &((type *)0)->member) - offsetof(type, member)))
struct Qmsg {
Qblock qblock;
@ -65,8 +67,12 @@ ORCA_NOINLINE static void qmenu_reprint(Qmenu *qm);
Qnav_stack qnav_stack;
void qnav_init() { qnav_stack = (Qnav_stack){0}; }
void qnav_deinit() {
void qnav_init()
{
qnav_stack = (Qnav_stack){ 0 };
}
void qnav_deinit()
{
while (qnav_stack.top)
qnav_stack_pop();
}
@ -77,7 +83,8 @@ void qnav_deinit() {
// you've finished doing the rest of the setup on the Qblock. The y and x
// fields can be junk, though, since this function writes to them without
// reading them.
static ORCA_NOINLINE void qnav_reposition_block(Qblock *qb) {
static ORCA_NOINLINE void qnav_reposition_block(Qblock *qb)
{
int top = 0, left = 0;
Qblock *prev = qb->down;
if (!prev)
@ -114,7 +121,8 @@ done:
qb->y = top;
qb->x = left;
}
static ORCA_NOINLINE void qnav_stack_push(Qblock *qb, int height, int width) {
static ORCA_NOINLINE void qnav_stack_push(Qblock *qb, int height, int width)
{
#ifndef NDEBUG
for (Qblock *i = qnav_stack.top; i; i = i->down) {
assert(i != qb);
@ -133,14 +141,19 @@ static ORCA_NOINLINE void qnav_stack_push(Qblock *qb, int height, int width) {
qnav_stack.occlusion_dirty = true;
}
Qblock *qnav_top_block() { return qnav_stack.top; }
Qblock *qnav_top_block()
{
return qnav_stack.top;
}
void qblock_init(Qblock *qb, Qblock_type_tag tag) {
void qblock_init(Qblock *qb, Qblock_type_tag tag)
{
*qb = (Qblock){ 0 };
qb->tag = tag;
}
void qnav_free_block(Qblock *qb) {
void qnav_free_block(Qblock *qb)
{
switch (qb->tag) {
case Qblock_type_qmsg: {
Qmsg *qm = qmsg_of(qb);
@ -156,7 +169,8 @@ void qnav_free_block(Qblock *qb) {
}
}
void qnav_stack_pop(void) {
void qnav_stack_pop(void)
{
assert(qnav_stack.top);
if (!qnav_stack.top)
return;
@ -178,7 +192,8 @@ void qnav_stack_pop(void) {
delwin(outer_window);
}
bool qnav_draw(void) {
bool qnav_draw(void)
{
bool drew_any = false;
if (!qnav_stack.bottom)
goto done;
@ -227,7 +242,8 @@ done:
return drew_any;
}
void qnav_adjust_term_size(void) {
void qnav_adjust_term_size(void)
{
if (!qnav_stack.bottom)
return;
for (Qblock *qb = qnav_stack.bottom; qb; qb = qb->up)
@ -235,13 +251,22 @@ void qnav_adjust_term_size(void) {
qnav_stack.occlusion_dirty = true;
}
void qblock_print_border(Qblock *qb, unsigned int attr) {
wborder(qb->outer_window, ACS_VLINE | attr, ACS_VLINE | attr,
ACS_HLINE | attr, ACS_HLINE | attr, ACS_ULCORNER | attr,
ACS_URCORNER | attr, ACS_LLCORNER | attr, ACS_LRCORNER | attr);
void qblock_print_border(Qblock *qb, unsigned int attr)
{
wborder(
qb->outer_window,
ACS_VLINE | attr,
ACS_VLINE | attr,
ACS_HLINE | attr,
ACS_HLINE | attr,
ACS_ULCORNER | attr,
ACS_URCORNER | attr,
ACS_LLCORNER | attr,
ACS_LRCORNER | attr);
}
void qblock_print_title(Qblock *qb, char const *title, int attr) {
void qblock_print_title(Qblock *qb, char const *title, int attr)
{
wmove(qb->outer_window, 0, 1);
attr_t attrs = A_NORMAL;
short pair = 0;
@ -253,9 +278,13 @@ void qblock_print_title(Qblock *qb, char const *title, int attr) {
wattr_set(qb->outer_window, attrs, pair, NULL);
}
void qblock_set_title(Qblock *qb, char const *title) { qb->title = title; }
void qblock_set_title(Qblock *qb, char const *title)
{
qb->title = title;
}
void qblock_print_frame(Qblock *qb, bool active) {
void qblock_print_frame(Qblock *qb, bool active)
{
qblock_print_border(qb, active ? A_NORMAL : A_DIM);
if (qb->title) {
qblock_print_title(qb, qb->title, active ? A_NORMAL : A_DIM);
@ -268,19 +297,25 @@ void qblock_print_frame(Qblock *qb, bool active) {
}
}
WINDOW *qmsg_window(Qmsg *qm) { return qm->qblock.content_window; }
WINDOW *qmsg_window(Qmsg *qm)
{
return qm->qblock.content_window;
}
void qmsg_set_title(Qmsg *qm, char const *title) {
void qmsg_set_title(Qmsg *qm, char const *title)
{
qblock_set_title(&qm->qblock, title);
}
void qmsg_set_dismiss_mode(Qmsg *qm, Qmsg_dismiss_mode mode) {
void qmsg_set_dismiss_mode(Qmsg *qm, Qmsg_dismiss_mode mode)
{
if (qm->dismiss_mode == mode)
return;
qm->dismiss_mode = mode;
}
Qmsg *qmsg_push(int height, int width) {
Qmsg *qmsg_push(int height, int width)
{
Qmsg *qm = malloc(sizeof(Qmsg));
qblock_init(&qm->qblock, Qblock_type_qmsg);
qm->dismiss_mode = Qmsg_dismiss_mode_explicitly;
@ -288,7 +323,8 @@ Qmsg *qmsg_push(int height, int width) {
return qm;
}
Qmsg *qmsg_printf_push(char const *title, char const *fmt, ...) {
Qmsg *qmsg_printf_push(char const *title, char const *fmt, ...)
{
int titlewidth = title ? (int)strlen(title) : 0;
va_list ap;
va_start(ap, fmt);
@ -339,7 +375,8 @@ Qmsg *qmsg_printf_push(char const *title, char const *fmt, ...) {
return msg;
}
bool qmsg_drive(Qmsg *qm, int key, Qmsg_action *out_action) {
bool qmsg_drive(Qmsg *qm, int key, Qmsg_action *out_action)
{
*out_action = (Qmsg_action){ 0 };
Qmsg_dismiss_mode dm = qm->dismiss_mode;
switch (dm) {
@ -364,9 +401,13 @@ bool qmsg_drive(Qmsg *qm, int key, Qmsg_action *out_action) {
return false;
}
Qmsg *qmsg_of(Qblock *qb) { return ORCA_CONTAINER_OF(qb, Qmsg, qblock); }
Qmsg *qmsg_of(Qblock *qb)
{
return ORCA_CONTAINER_OF(qb, Qmsg, qblock);
}
Qmenu *qmenu_create(int id) {
Qmenu *qmenu_create(int id)
{
Qmenu *qm = (Qmenu *)malloc(sizeof(Qmenu));
qblock_init(&qm->qblock, Qblock_type_qmenu);
qm->items = NULL;
@ -378,9 +419,16 @@ Qmenu *qmenu_create(int id) {
qm->is_frontmost = 0;
return qm;
}
void qmenu_destroy(Qmenu *qm) { qmenu_free(qm); }
int qmenu_id(Qmenu const *qm) { return qm->id; }
static ORCA_NOINLINE Qmenu_item *qmenu_allocitems(Qmenu *qm, Usz count) {
void qmenu_destroy(Qmenu *qm)
{
qmenu_free(qm);
}
int qmenu_id(Qmenu const *qm)
{
return qm->id;
}
static ORCA_NOINLINE Qmenu_item *qmenu_allocitems(Qmenu *qm, Usz count)
{
Usz old_count = qm->items_count;
if (old_count > SIZE_MAX - count) // overflow
exit(1);
@ -402,7 +450,8 @@ static ORCA_NOINLINE Qmenu_item *qmenu_allocitems(Qmenu *qm, Usz count) {
qm->items_count = new_count;
return items + old_count;
}
ORCA_NOINLINE static void qmenu_reprint(Qmenu *qm) {
ORCA_NOINLINE static void qmenu_reprint(Qmenu *qm)
{
WINDOW *win = qm->qblock.content_window;
Qmenu_item *items = qm->items;
bool isfront = qm->is_frontmost;
@ -416,10 +465,12 @@ ORCA_NOINLINE static void qmenu_reprint(Qmenu *qm) {
waddstr(win, items[i].text);
}
}
void qmenu_set_title(Qmenu *qm, char const *title) {
void qmenu_set_title(Qmenu *qm, char const *title)
{
qblock_set_title(&qm->qblock, title);
}
void qmenu_add_choice(Qmenu *qm, int id, char const *text) {
void qmenu_add_choice(Qmenu *qm, int id, char const *text)
{
assert(id != 0);
Qmenu_item *item = qmenu_allocitems(qm, 1);
item->text = text;
@ -429,7 +480,8 @@ void qmenu_add_choice(Qmenu *qm, int id, char const *text) {
if (!qm->current_item)
qm->current_item = id;
}
void qmenu_add_printf(Qmenu *qm, int id, char const *fmt, ...) {
void qmenu_add_printf(Qmenu *qm, int id, char const *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int textsize = vsnprintf(NULL, 0, fmt, ap);
@ -450,21 +502,27 @@ void qmenu_add_printf(Qmenu *qm, int id, char const *fmt, ...) {
if (!qm->current_item)
qm->current_item = id;
}
void qmenu_add_spacer(Qmenu *qm) {
void qmenu_add_spacer(Qmenu *qm)
{
Qmenu_item *item = qmenu_allocitems(qm, 1);
item->text = " ";
item->id = 0;
item->owns_string = false;
item->is_spacer = true;
}
void qmenu_set_current_item(Qmenu *qm, int id) {
void qmenu_set_current_item(Qmenu *qm, int id)
{
if (qm->current_item == id)
return;
qm->current_item = id;
qm->needs_reprint = 1;
}
int qmenu_current_item(Qmenu *qm) { return qm->current_item; }
void qmenu_push_to_nav(Qmenu *qm) {
int qmenu_current_item(Qmenu *qm)
{
return qm->current_item;
}
void qmenu_push_to_nav(Qmenu *qm)
{
// Probably a programming error if there are no items. Make the menu visible
// so the programmer knows something went wrong.
if (qm->items_count == 0)
@ -489,7 +547,8 @@ void qmenu_push_to_nav(Qmenu *qm) {
qnav_stack_push(&qm->qblock, menu_min_h, menu_min_w);
}
static void qmenu_free(Qmenu *qm) {
static void qmenu_free(Qmenu *qm)
{
Qmenu_item *items = qm->items;
for (Usz i = 0, n = qm->items_count; i < n; ++i) {
if (items[i].owns_string)
@ -499,7 +558,8 @@ static void qmenu_free(Qmenu *qm) {
free(qm);
}
ORCA_NOINLINE static void qmenu_drive_upordown(Qmenu *qm, bool downwards) {
ORCA_NOINLINE static void qmenu_drive_upordown(Qmenu *qm, bool downwards)
{
Qmenu_item *items = qm->items;
Usz n = qm->items_count;
if (n <= 1)
@ -529,7 +589,8 @@ found:;
}
}
bool qmenu_drive(Qmenu *qm, int key, Qmenu_action *out_action) {
bool qmenu_drive(Qmenu *qm, int key, Qmenu_action *out_action)
{
switch (key) {
case 27: {
out_action->any.type = Qmenu_action_type_canceled;
@ -551,9 +612,13 @@ bool qmenu_drive(Qmenu *qm, int key, Qmenu_action *out_action) {
return false;
}
Qmenu *qmenu_of(Qblock *qb) { return ORCA_CONTAINER_OF(qb, Qmenu, qblock); }
Qmenu *qmenu_of(Qblock *qb)
{
return ORCA_CONTAINER_OF(qb, Qmenu, qblock);
}
bool qmenu_top_is_menu(int id) {
bool qmenu_top_is_menu(int id)
{
Qblock *qb = qnav_top_block();
if (!qb)
return false;
@ -563,7 +628,8 @@ bool qmenu_top_is_menu(int id) {
return qm->id == id;
}
Qform *qform_create(int id) {
Qform *qform_create(int id)
{
Qform *qf = (Qform *)malloc(sizeof(Qform));
qblock_init(&qf->qblock, Qblock_type_qform);
qf->ncurses_form = NULL;
@ -572,7 +638,8 @@ Qform *qform_create(int id) {
qf->id = id;
return qf;
}
static void qform_free(Qform *qf) {
static void qform_free(Qform *qf)
{
curs_set(0);
unpost_form(qf->ncurses_form);
free_form(qf->ncurses_form);
@ -581,12 +648,20 @@ static void qform_free(Qform *qf) {
}
free(qf);
}
int qform_id(Qform const *qf) { return qf->id; }
Qform *qform_of(Qblock *qb) { return ORCA_CONTAINER_OF(qb, Qform, qblock); }
void qform_set_title(Qform *qf, char const *title) {
int qform_id(Qform const *qf)
{
return qf->id;
}
Qform *qform_of(Qblock *qb)
{
return ORCA_CONTAINER_OF(qb, Qform, qblock);
}
void qform_set_title(Qform *qf, char const *title)
{
qblock_set_title(&qf->qblock, title);
}
void qform_add_line_input(Qform *qf, int id, char const *initial) {
void qform_add_line_input(Qform *qf, int id, char const *initial)
{
FIELD *f = new_field(1, 30, 0, 0, 0, 0);
if (initial)
set_field_buffer(f, 0, initial);
@ -596,7 +671,8 @@ void qform_add_line_input(Qform *qf, int id, char const *initial) {
++qf->fields_count;
qf->ncurses_fields[qf->fields_count] = NULL;
}
void qform_push_to_nav(Qform *qf) {
void qform_push_to_nav(Qform *qf)
{
qf->ncurses_form = new_form(qf->ncurses_fields);
int form_min_h, form_min_w;
scale_form(qf->ncurses_form, &form_min_h, &form_min_w);
@ -608,13 +684,15 @@ void qform_push_to_nav(Qform *qf) {
curs_set(1);
form_driver(qf->ncurses_form, REQ_END_LINE);
}
void qform_single_line_input(int id, char const *title, char const *initial) {
void qform_single_line_input(int id, char const *title, char const *initial)
{
Qform *qf = qform_create(id);
qform_set_title(qf, title);
qform_add_line_input(qf, 1, initial);
qform_push_to_nav(qf);
}
bool qform_drive(Qform *qf, int key, Qform_action *out_action) {
bool qform_drive(Qform *qf, int key, Qform_action *out_action)
{
switch (key) {
case 27:
out_action->any.type = Qform_action_type_canceled;
@ -653,7 +731,8 @@ bool qform_drive(Qform *qf, int key, Qform_action *out_action) {
form_driver(qf->ncurses_form, key);
return false;
}
static Usz size_without_trailing_spaces(char const *str) {
static Usz size_without_trailing_spaces(char const *str)
{
Usz size = strlen(str);
for (;;) {
if (size == 0)
@ -664,7 +743,8 @@ static Usz size_without_trailing_spaces(char const *str) {
}
return size;
}
static FIELD *qform_find_field(Qform const *qf, int id) {
static FIELD *qform_find_field(Qform const *qf, int id)
{
Usz count = qf->fields_count;
for (Usz i = 0; i < count; ++i) {
FIELD *f = qf->ncurses_fields[i];
@ -673,7 +753,8 @@ static FIELD *qform_find_field(Qform const *qf, int id) {
}
return NULL;
}
bool qform_get_text_line(Qform const *qf, int id, oso **out) {
bool qform_get_text_line(Qform const *qf, int id, oso **out)
{
FIELD *f = qform_find_field(qf, id);
if (!f)
return false;
@ -685,10 +766,12 @@ bool qform_get_text_line(Qform const *qf, int id, oso **out) {
osoputlen(out, buf, trimmed);
return true;
}
bool qform_get_single_text_line(Qform const *qf, struct oso **out) {
bool qform_get_single_text_line(Qform const *qf, struct oso **out)
{
return qform_get_text_line(qf, 1, out);
}
oso *qform_get_nonempty_single_line_input(Qform *qf) {
oso *qform_get_nonempty_single_line_input(Qform *qf)
{
oso *s = NULL;
if (qform_get_text_line(qf, 1, &s) && osolen(s) > 0)
return s;

34
src/term_util.h

@ -15,7 +15,8 @@
struct oso;
typedef enum {
typedef enum
{
C_natural,
C_black,
C_red,
@ -27,15 +28,18 @@ typedef enum {
C_white,
} Color_name;
enum {
enum
{
Colors_count = C_white + 1,
};
enum {
enum
{
Cdef_normal = COLOR_PAIR(1),
};
typedef enum {
typedef enum
{
A_normal = A_NORMAL,
A_bold = A_BOLD,
A_dim = A_DIM,
@ -43,14 +47,15 @@ typedef enum {
A_reverse = A_REVERSE,
} Term_attr;
static ORCA_FORCEINLINE ORCA_OK_IF_UNUSED attr_t fg_bg(Color_name fg,
Color_name bg) {
static ORCA_FORCEINLINE ORCA_OK_IF_UNUSED attr_t fg_bg(Color_name fg, Color_name bg)
{
return COLOR_PAIR(1 + fg * Colors_count + bg);
}
void term_util_init_colors(void);
typedef enum {
typedef enum
{
Qblock_type_qmsg,
Qblock_type_qmenu,
Qblock_type_qform,
@ -73,7 +78,8 @@ typedef struct Qmsg Qmsg;
typedef struct Qmenu Qmenu;
typedef enum {
typedef enum
{
Qmenu_action_type_canceled,
Qmenu_action_type_picked,
} Qmenu_action_type;
@ -94,7 +100,8 @@ typedef union {
typedef struct Qform Qform;
typedef enum {
typedef enum
{
Qform_action_type_canceled,
Qform_action_type_submitted,
} Qform_action_type;
@ -105,7 +112,8 @@ typedef union {
Qform_action_any any;
} Qform_action;
typedef enum {
typedef enum
{
Qmsg_dismiss_mode_explicitly, // Space, return, escape dismisses. Default.
Qmsg_dismiss_mode_easily, // Any key dismisses.
Qmsg_dismiss_mode_passthrough, // Easily, and pass through key event.
@ -126,8 +134,7 @@ void qblock_print_frame(Qblock *qb, bool active);
void qblock_set_title(Qblock *qb, char const *title);
Qmsg *qmsg_push(int height, int width);
Qmsg *qmsg_printf_push(char const *title, char const *fmt, ...)
ORCA_TERM_UTIL_PRINTF(2, 3);
Qmsg *qmsg_printf_push(char const *title, char const *fmt, ...) ORCA_TERM_UTIL_PRINTF(2, 3);
WINDOW *qmsg_window(Qmsg *qm);
void qmsg_set_title(Qmsg *qm, char const *title);
void qmsg_set_dismiss_mode(Qmsg *qm, Qmsg_dismiss_mode mode);
@ -142,8 +149,7 @@ void qmenu_destroy(Qmenu *qm);
int qmenu_id(Qmenu const *qm);
void qmenu_set_title(Qmenu *qm, char const *title);
void qmenu_add_choice(Qmenu *qm, int id, char const *text);
void qmenu_add_printf(Qmenu *qm, int id, char const *fmt, ...)
ORCA_TERM_UTIL_PRINTF(3, 4);
void qmenu_add_printf(Qmenu *qm, int id, char const *fmt, ...) ORCA_TERM_UTIL_PRINTF(3, 4);
void qmenu_add_spacer(Qmenu *qm);
void qmenu_set_current_item(Qmenu *qm, int id);
void qmenu_push_to_nav(Qmenu *qm);

1245
src/tui_main.c

File diff suppressed because it is too large

19
src/vmio.c

@ -1,13 +1,21 @@
#include "vmio.h"
void oevent_list_init(Oevent_list *olist) {
void oevent_list_init(Oevent_list *olist)
{
olist->buffer = NULL;
olist->count = 0;
olist->capacity = 0;
}
void oevent_list_deinit(Oevent_list *olist) { free(olist->buffer); }
void oevent_list_clear(Oevent_list *olist) { olist->count = 0; }
void oevent_list_copy(Oevent_list const *src, Oevent_list *dest) {
void oevent_list_deinit(Oevent_list *olist)
{
free(olist->buffer);
}
void oevent_list_clear(Oevent_list *olist)
{
olist->count = 0;
}
void oevent_list_copy(Oevent_list const *src, Oevent_list *dest)
{
Usz src_count = src->count;
if (dest->capacity < src_count) {
Usz new_cap = orca_round_up_power2(src_count);
@ -17,7 +25,8 @@ void oevent_list_copy(Oevent_list const *src, Oevent_list *dest) {
memcpy(dest->buffer, src->buffer, src_count * sizeof(Oevent));
dest->count = src_count;
}
Oevent *oevent_list_alloc_item(Oevent_list *olist) {
Oevent *oevent_list_alloc_item(Oevent_list *olist)
{
Usz count = olist->count;
if (olist->capacity == count) {
// Note: no overflow check, but you're probably out of memory if this

13
src/vmio.h

@ -1,7 +1,8 @@
#pragma once
#include "base.h"
typedef enum {
typedef enum
{
Oevent_type_midi_note,
Oevent_type_midi_cc,
Oevent_type_midi_pb,
@ -28,7 +29,10 @@ typedef struct {
U8 channel, lsb, msb;
} Oevent_midi_pb;
enum { Oevent_osc_int_count = 35 };
enum
{
Oevent_osc_int_count = 35
};
typedef struct {
U8 oevent_type;
@ -37,7 +41,10 @@ typedef struct {
U8 numbers[Oevent_osc_int_count];
} Oevent_osc_ints;
enum { Oevent_udp_string_count = 16 };
enum
{
Oevent_udp_string_count = 16
};
typedef struct {
U8 oevent_type;

Loading…
Cancel
Save