sorta kinda working on strings for cmenu. being lazy
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
tag:
|
||||
ctags --langmap=c:.c.h --languages=c -R .
|
||||
+28
-8
@@ -4,6 +4,8 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utf.h"
|
||||
|
||||
typedef struct Color {
|
||||
uint8_t r, g, b;
|
||||
} Color;
|
||||
@@ -22,23 +24,41 @@ typedef enum Key {
|
||||
Count_Key
|
||||
} Key;
|
||||
|
||||
typedef uint32_t CodePoint;
|
||||
|
||||
bool KeyPressed(Key key);
|
||||
bool InputGetNextPrintable(CodePoint const *out_key);
|
||||
|
||||
typedef struct Cell {
|
||||
CodePoint character;
|
||||
Color foreground;
|
||||
Color background;
|
||||
} Cell;
|
||||
|
||||
typedef struct Window {
|
||||
int const width;
|
||||
int const height;
|
||||
CodePoint *characters;
|
||||
Color *foreground;
|
||||
Color *background;
|
||||
int width;
|
||||
int height;
|
||||
Cell *cells;
|
||||
} Window;
|
||||
|
||||
Window *WindowCreate();
|
||||
typedef struct PlatformState {
|
||||
Window *prev;
|
||||
Window *curr;
|
||||
} PlatformState;
|
||||
|
||||
// Options for the backend. These options don't necessarily apply for all platforms.
|
||||
typedef struct PlatformOpts {
|
||||
float window_width_fraction; // decide the width of the window as a fraction of the total resolution. for gui backends
|
||||
float window_height_fraction; // decide the height of the window as a fraction of the total resolution. for gui backends
|
||||
} PlatformOpts;
|
||||
|
||||
PlatformOpts WindowCreateOptsDefault();
|
||||
Window *WindowCreate(PlatformOpts opts);
|
||||
void WindowClear(Window *window, Color color);
|
||||
void WindowFlip(Window *window);
|
||||
|
||||
void PlatformInit(PlatformOpts opts);
|
||||
int PlatformGetWidth();
|
||||
int PlatformGetHeight();
|
||||
|
||||
// TODO: the platform layer would really update the keys being pressed, and
|
||||
// receive a diff in the form of actions. print this line from here and change
|
||||
// colors at these points.
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "str.h"
|
||||
|
||||
static bool intToIndex(String string, int i, size_t *out_index) {
|
||||
int val = 0;
|
||||
bool is_ok = true;
|
||||
if (i >= 0) {
|
||||
val = i;
|
||||
} else {
|
||||
val = string.size + 1 + i;
|
||||
}
|
||||
|
||||
if (val < 0) {
|
||||
val = 0;
|
||||
is_ok = false;
|
||||
} else if (val > string.size) {
|
||||
val = string.size;
|
||||
is_ok = false;
|
||||
}
|
||||
|
||||
*out_index = val;
|
||||
return is_ok;
|
||||
}
|
||||
|
||||
bool StringSub(String string, int start, int end, String *out_substr) {
|
||||
|
||||
size_t start_index = 0;
|
||||
bool start_ok = intToIndex(string, start, &start_index);
|
||||
size_t end_index = 0;
|
||||
bool end_ok = intToIndex(string, end, &end_index);
|
||||
|
||||
if (string.size == 0 || start_index >= end_index) {
|
||||
out_substr->size=0;
|
||||
out_substr->buffer=NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
out_substr->buffer = &string.buffer[start_index];
|
||||
out_substr->size = end_index - start_index;
|
||||
|
||||
return start_ok && end_ok;
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct String {
|
||||
unsigned char const *buffer;
|
||||
size_t size;
|
||||
} String;
|
||||
|
||||
#define STRING(content) ((String){.buffer=#content, .size=sizeof(#content)-1})
|
||||
|
||||
bool StringSub(String string, int start, int end, String *out_substr);
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "utf.h"
|
||||
#include "str.h"
|
||||
|
||||
typedef struct Utf8Parser {
|
||||
String str;
|
||||
} Utf8Parser;
|
||||
|
||||
bool Utf8ParserNextCodePoint(Utf8Parser *this, CodePoint *out_codepoint) {
|
||||
uitn8_t const flag_1_bytes = 0;
|
||||
uint8_t const mask_1_bytes = 1 << 7;
|
||||
|
||||
uint8_t const flag_continuation = mask_1_bytes;
|
||||
uint8_t const mask_continuation = (1 << 7) | (1 << 6);
|
||||
|
||||
uint8_t const flag_2_bytes = mask_continuation;
|
||||
uint8_t const mask_2_bytes = (1 << 7) | (1 << 6) | (1 << 5);
|
||||
|
||||
uint8_t const flag_3_bytes = mask_2_bytes;
|
||||
uint8_t const mask_3_bytes = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4);
|
||||
|
||||
uint8_t const flag_4_bytes = mask_3_bytes;
|
||||
uint8_t const mask_4_bytes = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3);
|
||||
|
||||
if (this->str.size == 0) {
|
||||
*out_codepoint = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((this->str.buffer[0] & mask_1_bytes) == flag_1_bytes) {
|
||||
*out_codepoint = (CodePoint) str[0];
|
||||
bool ok = StringSub(this->str, 1, -1, &this->str);
|
||||
assert(ok && "has to be ok since the size is not 0");
|
||||
return ok;
|
||||
} else
|
||||
}
|
||||
|
||||
// max must be less than or equal to the capacity of target.
|
||||
bool CodePointsFromUtf8String(
|
||||
uint8_t const *str,
|
||||
CodePoint *target,
|
||||
int max
|
||||
) {
|
||||
|
||||
for (size_t i = 0; str[i] != '\0' && max > 0;) {
|
||||
if ((str[i] & mask_1_bytes) == flag_1_bytes) {
|
||||
*target = (CodePoint) str[i];
|
||||
|
||||
target += 1;
|
||||
max -= 1;
|
||||
i += 1;
|
||||
} else
|
||||
if ((str[i] & mask_2_bytes) == flag_2_bytes) {
|
||||
} else
|
||||
if ((str[i] & mask_3_bytes) == flag_3_bytes) {
|
||||
} else
|
||||
if ((str[i] & mask_4_bytes) == flag_4_bytes) {
|
||||
} else {
|
||||
false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef UTF
|
||||
#define UTF
|
||||
|
||||
typedef uint32_t CodePoint;
|
||||
|
||||
int CodePointsFromUtf8String(char const *str, CodePoint *target, unsigned int max);
|
||||
|
||||
#endif // UTF
|
||||
|
||||
Reference in New Issue
Block a user