got fonts working on Linux
commit
aeb43dcfb9
|
@ -745,14 +745,7 @@ process_config_file(Application_Links *app){
|
|||
char str_space[512];
|
||||
String str = make_fixed_width_string(str_space);
|
||||
if (config_string_var(item, "treat_as_code", 0, &str)){
|
||||
if (str.size < sizeof(treat_as_code_exts.extension_space)){
|
||||
set_extensions(&treat_as_code_exts, str);
|
||||
print_message(app, str.str, str.size);
|
||||
print_message(app, "\n", 1);
|
||||
}
|
||||
else{
|
||||
print_message(app, literal("STRING TOO LONG!\n"));
|
||||
}
|
||||
set_extensions(&treat_as_code_exts, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -40,6 +40,15 @@ typedef int32_t b32_4tech;
|
|||
#endif
|
||||
// standard preamble end
|
||||
|
||||
static b32_4tech
|
||||
codepoint_is_whitespace(u32_4tech codepoint){
|
||||
b32_4tech result = false;
|
||||
if (codepoint == ' ' || codepoint == '\r' || codepoint == '\n' || codepoint == '\t'){
|
||||
result = true;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
static u32_4tech
|
||||
utf8_to_u32_length_unchecked(u8_4tech *buffer, u32_4tech *length_out){
|
||||
u32_4tech result = 0;
|
||||
|
@ -146,28 +155,28 @@ utf8_to_u32(u8_4tech **buffer_ptr, u8_4tech *end){
|
|||
}
|
||||
|
||||
static void
|
||||
u32_to_utf8_unchecked(u32_4tech code_point, u8_4tech *buffer, u32_4tech *length_out){
|
||||
if (code_point <= 0x7F){
|
||||
buffer[0] = (u8_4tech)code_point;
|
||||
u32_to_utf8_unchecked(u32_4tech codepoint, u8_4tech *buffer, u32_4tech *length_out){
|
||||
if (codepoint <= 0x7F){
|
||||
buffer[0] = (u8_4tech)codepoint;
|
||||
*length_out = 1;
|
||||
}
|
||||
else if (code_point <= 0x7FF){
|
||||
buffer[0] = (u8_4tech)(0xC0 | (code_point >> 6));
|
||||
buffer[1] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
else if (codepoint <= 0x7FF){
|
||||
buffer[0] = (u8_4tech)(0xC0 | (codepoint >> 6));
|
||||
buffer[1] = (u8_4tech)(0x80 | (codepoint & 0x3F));
|
||||
*length_out = 2;
|
||||
}
|
||||
else if (code_point <= 0xFFFF){
|
||||
buffer[0] = (u8_4tech)(0xE0 | (code_point >> 12));
|
||||
buffer[1] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
|
||||
buffer[2] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
else if (codepoint <= 0xFFFF){
|
||||
buffer[0] = (u8_4tech)(0xE0 | (codepoint >> 12));
|
||||
buffer[1] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F));
|
||||
buffer[2] = (u8_4tech)(0x80 | (codepoint & 0x3F));
|
||||
*length_out = 3;
|
||||
}
|
||||
else{
|
||||
code_point &= 0x001FFFFF;
|
||||
buffer[0] = (u8_4tech)(0xF0 | (code_point >> 18));
|
||||
buffer[1] = (u8_4tech)(0x80 | ((code_point >> 12) & 0x3F));
|
||||
buffer[2] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
|
||||
buffer[3] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
codepoint &= 0x001FFFFF;
|
||||
buffer[0] = (u8_4tech)(0xF0 | (codepoint >> 18));
|
||||
buffer[1] = (u8_4tech)(0x80 | ((codepoint >> 12) & 0x3F));
|
||||
buffer[2] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F));
|
||||
buffer[3] = (u8_4tech)(0x80 | (codepoint & 0x3F));
|
||||
*length_out = 4;
|
||||
}
|
||||
}
|
||||
|
@ -186,11 +195,11 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *
|
|||
|
||||
*error = false;
|
||||
for(; s < s_end;){
|
||||
u32_4tech code_point = 0;
|
||||
u32_4tech codepoint = 0;
|
||||
u32_4tech utf8_size = 0;
|
||||
|
||||
if (s[0] <= 0x7F){
|
||||
code_point = (u32_4tech)s[0];
|
||||
codepoint = (u32_4tech)s[0];
|
||||
utf8_size = 1;
|
||||
}
|
||||
else if (s[0] <= 0xE0){
|
||||
|
@ -199,8 +208,8 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *
|
|||
break;
|
||||
}
|
||||
|
||||
code_point = ((u32_4tech)((s[0])&0x1F)) << 6;
|
||||
code_point |= ((u32_4tech)((s[1])&0x3F));
|
||||
codepoint = ((u32_4tech)((s[0])&0x1F)) << 6;
|
||||
codepoint |= ((u32_4tech)((s[1])&0x3F));
|
||||
utf8_size = 2;
|
||||
}
|
||||
else if (s[0] <= 0xF0){
|
||||
|
@ -209,9 +218,9 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *
|
|||
break;
|
||||
}
|
||||
|
||||
code_point = ((u32_4tech)((s[0])&0x0F)) << 12;
|
||||
code_point |= ((u32_4tech)((s[1])&0x3F)) << 6;
|
||||
code_point |= ((u32_4tech)((s[2])&0x3F));
|
||||
codepoint = ((u32_4tech)((s[0])&0x0F)) << 12;
|
||||
codepoint |= ((u32_4tech)((s[1])&0x3F)) << 6;
|
||||
codepoint |= ((u32_4tech)((s[2])&0x3F));
|
||||
utf8_size = 3;
|
||||
}
|
||||
else{
|
||||
|
@ -220,26 +229,26 @@ utf8_to_utf16_minimal_checking(u16_4tech *dst, umem_4tech max_wchars, u8_4tech *
|
|||
break;
|
||||
}
|
||||
|
||||
code_point = ((u32_4tech)((s[0])&0x07)) << 18;
|
||||
code_point |= ((u32_4tech)((s[1])&0x3F)) << 12;
|
||||
code_point |= ((u32_4tech)((s[2])&0x3F)) << 6;
|
||||
code_point |= ((u32_4tech)((s[3])&0x3F));
|
||||
codepoint = ((u32_4tech)((s[0])&0x07)) << 18;
|
||||
codepoint |= ((u32_4tech)((s[1])&0x3F)) << 12;
|
||||
codepoint |= ((u32_4tech)((s[2])&0x3F)) << 6;
|
||||
codepoint |= ((u32_4tech)((s[3])&0x3F));
|
||||
utf8_size = 4;
|
||||
}
|
||||
|
||||
s += utf8_size;
|
||||
limit -= utf8_size;
|
||||
|
||||
if (code_point <= 0xD7FF || (code_point >= 0xE000 && code_point <= 0xFFFF)){
|
||||
*d = (u16_4tech)(code_point);
|
||||
if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)){
|
||||
*d = (u16_4tech)(codepoint);
|
||||
d += advance;
|
||||
needed_max += 1;
|
||||
}
|
||||
else if (code_point >= 0x10000 && code_point <= 0x10FFFF){
|
||||
code_point -= 0x10000;
|
||||
else if (codepoint >= 0x10000 && codepoint <= 0x10FFFF){
|
||||
codepoint -= 0x10000;
|
||||
|
||||
u32_4tech high = (code_point >> 10) & 0x03FF;
|
||||
u32_4tech low = (code_point) & 0x03FF;
|
||||
u32_4tech high = (codepoint >> 10) & 0x03FF;
|
||||
u32_4tech low = (codepoint) & 0x03FF;
|
||||
|
||||
high += 0xD800;
|
||||
low += 0xDC00;
|
||||
|
@ -283,11 +292,11 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s
|
|||
*error = false;
|
||||
|
||||
for (; s < s_end;){
|
||||
u32_4tech code_point = 0;
|
||||
u32_4tech codepoint = 0;
|
||||
u32_4tech utf16_size = 0;
|
||||
|
||||
if (s[0] <= 0xD7FF || (s[0] >= 0xE000 && s[0] <= 0xFFFF)){
|
||||
code_point = s[0];
|
||||
codepoint = s[0];
|
||||
utf16_size = 1;
|
||||
}
|
||||
else{
|
||||
|
@ -299,7 +308,7 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s
|
|||
|
||||
u32_4tech high = s[0] - 0xD800;
|
||||
u32_4tech low = s[1] - 0xDC00;
|
||||
code_point = ((high << 10) | (low)) + 0x10000;
|
||||
codepoint = ((high << 10) | (low)) + 0x10000;
|
||||
utf16_size = 2;
|
||||
}
|
||||
else{
|
||||
|
@ -314,26 +323,26 @@ utf16_to_utf8_minimal_checking(u8_4tech *dst, umem_4tech max_chars, u16_4tech *s
|
|||
u8_4tech d_fill[4];
|
||||
u32_4tech d_fill_count = 0;
|
||||
|
||||
if (code_point <= 0x7F){
|
||||
d_fill[0] = (u8_4tech)code_point;
|
||||
if (codepoint <= 0x7F){
|
||||
d_fill[0] = (u8_4tech)codepoint;
|
||||
d_fill_count = 1;
|
||||
}
|
||||
else if (code_point <= 0x7FF){
|
||||
d_fill[0] = (u8_4tech)(0xC0 | (code_point >> 6));
|
||||
d_fill[1] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
else if (codepoint <= 0x7FF){
|
||||
d_fill[0] = (u8_4tech)(0xC0 | (codepoint >> 6));
|
||||
d_fill[1] = (u8_4tech)(0x80 | (codepoint & 0x3F));
|
||||
d_fill_count = 2;
|
||||
}
|
||||
else if (code_point <= 0xFFFF){
|
||||
d_fill[0] = (u8_4tech)(0xE0 | (code_point >> 12));
|
||||
d_fill[1] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
|
||||
d_fill[2] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
else if (codepoint <= 0xFFFF){
|
||||
d_fill[0] = (u8_4tech)(0xE0 | (codepoint >> 12));
|
||||
d_fill[1] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F));
|
||||
d_fill[2] = (u8_4tech)(0x80 | (codepoint & 0x3F));
|
||||
d_fill_count = 3;
|
||||
}
|
||||
else if (code_point <= 0x10FFFF){
|
||||
d_fill[0] = (u8_4tech)(0xF0 | (code_point >> 18));
|
||||
d_fill[1] = (u8_4tech)(0x80 | ((code_point >> 12) & 0x3F));
|
||||
d_fill[2] = (u8_4tech)(0x80 | ((code_point >> 6) & 0x3F));
|
||||
d_fill[3] = (u8_4tech)(0x80 | (code_point & 0x3F));
|
||||
else if (codepoint <= 0x10FFFF){
|
||||
d_fill[0] = (u8_4tech)(0xF0 | (codepoint >> 18));
|
||||
d_fill[1] = (u8_4tech)(0x80 | ((codepoint >> 12) & 0x3F));
|
||||
d_fill[2] = (u8_4tech)(0x80 | ((codepoint >> 6) & 0x3F));
|
||||
d_fill[3] = (u8_4tech)(0x80 | (codepoint & 0x3F));
|
||||
d_fill_count = 4;
|
||||
}
|
||||
else{
|
||||
|
|
160
4ed.cpp
160
4ed.cpp
|
@ -235,7 +235,7 @@ do_feedback_message(System_Functions *system, Models *models, String value, b32
|
|||
for (View_Iter iter = file_view_iter_init(&models->layout, file, 0);
|
||||
file_view_iter_good(iter);
|
||||
iter = file_view_iter_next(iter)){
|
||||
view_cursor_move(iter.view, pos);
|
||||
view_cursor_move(system, iter.view, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -247,16 +247,16 @@ do_feedback_message(System_Functions *system, Models *models, String value, b32
|
|||
#define USE_FILE(n,v) Editing_File *n = (v)->file_data.file
|
||||
|
||||
|
||||
#define USE_PANEL(n) Panel *n = 0;{ \
|
||||
#define USE_PANEL(n) Panel *n = 0; do{ \
|
||||
i32 panel_index = command->models->layout.active_panel; \
|
||||
n = command->models->layout.panels + panel_index; \
|
||||
}
|
||||
}while(false)
|
||||
|
||||
#define USE_VIEW(n) View *n = 0;{ \
|
||||
i32 panel_index = command->models->layout.active_panel; \
|
||||
Panel *panel = command->models->layout.panels + panel_index; \
|
||||
n = panel->view; \
|
||||
}
|
||||
#define USE_VIEW(n) View *n = 0; do{ \
|
||||
i32 panel_index = command->models->layout.active_panel; \
|
||||
Panel *__panel__ = command->models->layout.panels + panel_index; \
|
||||
n = __panel__->view; \
|
||||
}while(false)
|
||||
|
||||
#define REQ_OPEN_VIEW(n) USE_VIEW(n); if (view_lock_level(n) > LockLevel_Open) return
|
||||
|
||||
|
@ -274,7 +274,7 @@ panel_make_empty(System_Functions *system, App_Vars *vars, Panel *panel){
|
|||
|
||||
Assert(panel->view == 0);
|
||||
new_view = live_set_alloc_view(&vars->live_set, panel, models);
|
||||
view_set_file(new_view.view, models->scratch_buffer, models);
|
||||
view_set_file(system, new_view.view, models->scratch_buffer, models);
|
||||
new_view.view->map = get_map(models, mapid_file);
|
||||
|
||||
return(new_view.view);
|
||||
|
@ -362,16 +362,15 @@ COMMAND_DECL(reopen){
|
|||
init_normal_file(system, models, file, buffer, size);
|
||||
|
||||
for (i32 i = 0; i < vptr_count; ++i){
|
||||
view_set_file(vptrs[i], file, models);
|
||||
view_set_file(system, vptrs[i], file, models);
|
||||
|
||||
int32_t line = line_number[i];
|
||||
int32_t character = column_number[i];
|
||||
|
||||
*vptrs[i]->edit_pos = edit_poss[i];
|
||||
Full_Cursor cursor = view_compute_cursor(vptrs[i], seek_line_char(line, character), 0);
|
||||
Full_Cursor cursor = view_compute_cursor(system, vptrs[i], seek_line_char(line, character), 0);
|
||||
|
||||
view_set_cursor(vptrs[i], cursor, true,
|
||||
file->settings.unwrapped_lines);
|
||||
view_set_cursor(vptrs[i], cursor, true, file->settings.unwrapped_lines);
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
@ -449,12 +448,11 @@ COMMAND_DECL(toggle_line_wrap){
|
|||
if (file->settings.unwrapped_lines){
|
||||
file->settings.unwrapped_lines = 0;
|
||||
view->edit_pos->scroll.target_x = 0;
|
||||
view_cursor_move(view, view->edit_pos->cursor.pos);
|
||||
}
|
||||
else{
|
||||
file->settings.unwrapped_lines = 1;
|
||||
view_cursor_move(view, view->edit_pos->cursor.pos);
|
||||
}
|
||||
view_cursor_move(system, view, view->edit_pos->cursor.pos);
|
||||
view_set_relative_scrolling(view, scrolling);
|
||||
}
|
||||
|
||||
|
@ -520,7 +518,7 @@ COMMAND_DECL(open_menu){
|
|||
COMMAND_DECL(open_debug){
|
||||
USE_VIEW(view);
|
||||
view_show_GUI(view, VUI_Debug);
|
||||
view->debug_vars = debug_vars_zero();
|
||||
view->debug_vars = null_debug_vars;
|
||||
}
|
||||
|
||||
COMMAND_DECL(user_callback){
|
||||
|
@ -633,9 +631,6 @@ app_hardcode_styles(Models *models){
|
|||
Style *styles = models->styles.styles;
|
||||
Style *style = styles + 1;
|
||||
|
||||
i16 fonts = 1;
|
||||
models->global_font.font_id = fonts + 0;
|
||||
|
||||
/////////////////
|
||||
style_set_name(style, make_lit_string("4coder"));
|
||||
|
||||
|
@ -967,7 +962,6 @@ enum Command_Line_Action{
|
|||
CLAct_WindowStreamMode,
|
||||
CLAct_FontSize,
|
||||
CLAct_FontStartHinting,
|
||||
CLAct_FontCustom,
|
||||
CLAct_Count
|
||||
};
|
||||
|
||||
|
@ -1015,8 +1009,6 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
|
|||
case 'u': action = CLAct_UserFile; strict = 0; break;
|
||||
case 'U': action = CLAct_UserFile; strict = 1; break;
|
||||
|
||||
case 'c': action = CLAct_FontCustom; break;
|
||||
|
||||
case 'd': action = CLAct_CustomDLL; strict = 0; break;
|
||||
case 'D': action = CLAct_CustomDLL; strict = 1; break;
|
||||
|
||||
|
@ -1120,16 +1112,6 @@ init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
|
|||
action = CLAct_Nothing;
|
||||
}break;
|
||||
|
||||
case CLAct_FontCustom:
|
||||
{
|
||||
if ((i + 3) <= clparams.argc){
|
||||
settings->custom_font_file = clparams.argv[i++];
|
||||
settings->custom_font_name = clparams.argv[i++];
|
||||
settings->custom_font_size = str_to_int_c(clparams.argv[i]);
|
||||
}
|
||||
action = CLAct_Nothing;
|
||||
}break;
|
||||
|
||||
case CLAct_FontStartHinting:
|
||||
{
|
||||
plat_settings->use_hinting = 1;
|
||||
|
@ -1163,8 +1145,6 @@ app_setup_memory(System_Functions *system, Application_Memory *memory){
|
|||
return(vars);
|
||||
}
|
||||
|
||||
static App_Settings null_app_settings = {0};
|
||||
|
||||
App_Read_Command_Line_Sig(app_read_command_line){
|
||||
i32 out_size = 0;
|
||||
App_Vars *vars = app_setup_memory(system, memory);
|
||||
|
@ -1215,11 +1195,8 @@ App_Init_Sig(app_init){
|
|||
models->app_links.cmd_context = &vars->command_data;
|
||||
|
||||
partition = &models->mem.part;
|
||||
target->partition = partition;
|
||||
|
||||
{
|
||||
i32 i;
|
||||
|
||||
panel_max_count = models->layout.panel_max_count = MAX_VIEWS;
|
||||
divider_max_count = panel_max_count - 1;
|
||||
models->layout.panel_count = 0;
|
||||
|
@ -1231,7 +1208,7 @@ App_Init_Sig(app_init){
|
|||
dll_init_sentinel(&models->layout.used_sentinel);
|
||||
|
||||
panel = panels;
|
||||
for (i = 0; i < panel_max_count; ++i, ++panel){
|
||||
for (i32 i = 0; i < panel_max_count; ++i, ++panel){
|
||||
dll_insert(&models->layout.free_sentinel, panel);
|
||||
}
|
||||
|
||||
|
@ -1239,7 +1216,7 @@ App_Init_Sig(app_init){
|
|||
models->layout.dividers = dividers;
|
||||
|
||||
div = dividers;
|
||||
for (i = 0; i < divider_max_count-1; ++i, ++div){
|
||||
for (i32 i = 0; i < divider_max_count-1; ++i, ++div){
|
||||
div->next = (div + 1);
|
||||
}
|
||||
div->next = 0;
|
||||
|
@ -1460,57 +1437,6 @@ App_Init_Sig(app_init){
|
|||
setup_ui_commands(&models->map_ui, &models->mem.part, global_map);
|
||||
}
|
||||
|
||||
// NOTE(allen): font setup
|
||||
{
|
||||
models->font_set = &target->font_set;
|
||||
|
||||
struct Font_Setup{
|
||||
char *c_file_name;
|
||||
i32 file_name_len;
|
||||
char *c_name;
|
||||
i32 name_len;
|
||||
i32 pt_size;
|
||||
};
|
||||
|
||||
i32 font_size = models->settings.font_size;
|
||||
|
||||
char *custom_font_file = models->settings.custom_font_file;
|
||||
char *custom_font_name = models->settings.custom_font_name;
|
||||
i32 custom_font_size = models->settings.custom_font_size;
|
||||
b32 use_custom_font = true;
|
||||
if (!custom_font_file){
|
||||
use_custom_font = false;
|
||||
custom_font_file = "";
|
||||
custom_font_name = "";
|
||||
}
|
||||
|
||||
if (font_size < 8) font_size = 8;
|
||||
|
||||
Font_Setup font_setup[] = {
|
||||
{literal("LiberationSans-Regular.ttf"), literal("Liberation Sans"), font_size},
|
||||
{literal("liberation-mono.ttf"), literal("Liberation Mono"), font_size},
|
||||
{literal("Hack-Regular.ttf"), literal("Hack"), font_size},
|
||||
{literal("CutiveMono-Regular.ttf"), literal("Cutive Mono"), font_size},
|
||||
{literal("Inconsolata-Regular.ttf"), literal("Inconsolata"), font_size},
|
||||
{custom_font_file, str_size(custom_font_file),
|
||||
custom_font_name, str_size(custom_font_name),
|
||||
custom_font_size},
|
||||
};
|
||||
i32 font_count = ArrayCount(font_setup);
|
||||
if (!use_custom_font){
|
||||
--font_count;
|
||||
}
|
||||
|
||||
font_set_init(models->font_set, partition, 16, 6);
|
||||
|
||||
for (i32 i = 0; i < font_count; ++i){
|
||||
String file_name = make_string(font_setup[i].c_file_name, font_setup[i].file_name_len);
|
||||
String name = make_string(font_setup[i].c_name, font_setup[i].name_len);
|
||||
i32 pt_size = font_setup[i].pt_size;
|
||||
font_set_add(models->font_set, file_name, name, pt_size);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): file setup
|
||||
working_set_init(&models->working_set, partition, &vars->models.mem.general);
|
||||
models->working_set.default_display_width = DEFAULT_DISPLAY_WIDTH;
|
||||
|
@ -1529,11 +1455,9 @@ App_Init_Sig(app_init){
|
|||
}
|
||||
|
||||
// NOTE(allen): style setup
|
||||
models->global_font_id = 1;
|
||||
app_hardcode_styles(models);
|
||||
|
||||
models->palette_size = 40;
|
||||
models->palette = push_array(partition, u32, models->palette_size);
|
||||
|
||||
// NOTE(allen): init first panel
|
||||
Command_Data *cmd = &vars->command_data;
|
||||
|
||||
|
@ -1556,8 +1480,8 @@ App_Init_Sig(app_init){
|
|||
};
|
||||
|
||||
File_Init init_files[] = {
|
||||
{ make_lit_string("*messages*"), &models->message_buffer, 1, },
|
||||
{ make_lit_string("*scratch*"), &models->scratch_buffer, 0, }
|
||||
{ make_lit_string("*messages*"), &models->message_buffer, true , },
|
||||
{ make_lit_string("*scratch*"), &models->scratch_buffer, false, }
|
||||
};
|
||||
|
||||
for (i32 i = 0; i < ArrayCount(init_files); ++i){
|
||||
|
@ -1622,8 +1546,7 @@ update_cli_handle_without_file(System_Functions *system, Models *models,
|
|||
}
|
||||
|
||||
internal i32
|
||||
update_cli_handle_with_file(System_Functions *system, Models *models,
|
||||
CLI_Handles *cli, Editing_File *file, char *dest, i32 max, b32 cursor_at_end){
|
||||
update_cli_handle_with_file(System_Functions *system, Models *models, CLI_Handles *cli, Editing_File *file, char *dest, i32 max, b32 cursor_at_end){
|
||||
i32 result = 0;
|
||||
u32 amount = 0;
|
||||
|
||||
|
@ -1648,7 +1571,7 @@ update_cli_handle_with_file(System_Functions *system, Models *models,
|
|||
for (View_Iter iter = file_view_iter_init(&models->layout, file, 0);
|
||||
file_view_iter_good(iter);
|
||||
iter = file_view_iter_next(iter)){
|
||||
view_cursor_move(iter.view, new_cursor);
|
||||
view_cursor_move(system, iter.view, new_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1657,12 +1580,11 @@ update_cli_handle_with_file(System_Functions *system, Models *models,
|
|||
|
||||
|
||||
App_Step_Sig(app_step){
|
||||
Application_Step_Result app_result = *result;
|
||||
Application_Step_Result app_result = *app_result_;
|
||||
app_result.animating = 0;
|
||||
|
||||
App_Vars *vars = (App_Vars*)memory->vars_memory;
|
||||
Models *models = &vars->models;
|
||||
target->partition = &models->mem.part;
|
||||
|
||||
// NOTE(allen): OS clipboard event handling
|
||||
String clipboard = input->clipboard;
|
||||
|
@ -1760,24 +1682,24 @@ App_Step_Sig(app_step){
|
|||
// NOTE(allen): detect mouse hover status
|
||||
i32 mx = input->mouse.x;
|
||||
i32 my = input->mouse.y;
|
||||
b32 mouse_in_edit_area = 0;
|
||||
b32 mouse_in_margin_area = 0;
|
||||
Panel *mouse_panel, *used_panels;
|
||||
b32 mouse_in_edit_area = false;
|
||||
b32 mouse_in_margin_area = false;
|
||||
|
||||
used_panels = &models->layout.used_sentinel;
|
||||
for (dll_items(mouse_panel, used_panels)){
|
||||
if (hit_check(mx, my, mouse_panel->inner)){
|
||||
mouse_in_edit_area = 1;
|
||||
break;
|
||||
Panel *mouse_panel = 0;
|
||||
{
|
||||
Panel *used_panels = &models->layout.used_sentinel, *panel = 0;
|
||||
for (dll_items(panel, used_panels)){
|
||||
if (hit_check(mx, my, panel->inner)){
|
||||
mouse_panel = panel;
|
||||
mouse_in_edit_area = true;
|
||||
break;
|
||||
}
|
||||
else if (hit_check(mx, my, panel->full)){
|
||||
mouse_panel = panel;
|
||||
mouse_in_margin_area = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hit_check(mx, my, mouse_panel->full)){
|
||||
mouse_in_margin_area = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mouse_in_edit_area || mouse_in_margin_area)){
|
||||
mouse_panel = 0;
|
||||
}
|
||||
|
||||
b32 mouse_on_divider = 0;
|
||||
|
@ -1954,7 +1876,7 @@ App_Step_Sig(app_step){
|
|||
}
|
||||
|
||||
if (i < models->layout.panel_count){
|
||||
view_set_file(panel->view, models->message_buffer, models);
|
||||
view_set_file(system, panel->view, models->message_buffer, models);
|
||||
view_show_file(panel->view);
|
||||
++i;
|
||||
panel = panel->next;
|
||||
|
@ -2269,7 +2191,7 @@ App_Step_Sig(app_step){
|
|||
|
||||
if (!gui_scroll_eq(scroll_vars, &ip_result.vars)){
|
||||
if (file_scroll){
|
||||
view_set_scroll(view, ip_result.vars);
|
||||
view_set_scroll(system, view, ip_result.vars);
|
||||
}
|
||||
else{
|
||||
*scroll_vars = ip_result.vars;
|
||||
|
@ -2720,7 +2642,7 @@ App_Step_Sig(app_step){
|
|||
app_result.lctrl_lalt_is_altgr = models->settings.lctrl_lalt_is_altgr;
|
||||
app_result.perform_kill = !models->keep_playing;
|
||||
|
||||
*result = app_result;
|
||||
*app_result_ = app_result;
|
||||
|
||||
// end-of-app_step
|
||||
}
|
||||
|
|
19
4ed.h
19
4ed.h
|
@ -64,12 +64,7 @@ typedef struct Plat_Settings{
|
|||
} Plat_Settings;
|
||||
|
||||
#define App_Read_Command_Line_Sig(name) \
|
||||
i32 name(System_Functions *system, \
|
||||
Application_Memory *memory, \
|
||||
String current_directory, \
|
||||
Plat_Settings *plat_settings, \
|
||||
char ***files, i32 **file_count, \
|
||||
Command_Line_Parameters clparams)
|
||||
i32 name(System_Functions *system, Application_Memory *memory, String current_directory, Plat_Settings *plat_settings, char ***files, i32 **file_count, Command_Line_Parameters clparams)
|
||||
|
||||
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
|
||||
|
||||
|
@ -110,12 +105,12 @@ struct Application_Step_Input{
|
|||
String clipboard;
|
||||
};
|
||||
|
||||
#define App_Step_Sig(name) void \
|
||||
name(System_Functions *system, \
|
||||
Render_Target *target, \
|
||||
Application_Memory *memory, \
|
||||
Application_Step_Input *input, \
|
||||
Application_Step_Result *result, \
|
||||
#define App_Step_Sig(name) void \
|
||||
name(System_Functions *system, \
|
||||
Render_Target *target, \
|
||||
Application_Memory *memory, \
|
||||
Application_Step_Input *input, \
|
||||
Application_Step_Result *app_result_, \
|
||||
Command_Line_Parameters params)
|
||||
|
||||
typedef App_Step_Sig(App_Step);
|
||||
|
|
|
@ -64,7 +64,7 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Command_Data *cm
|
|||
}
|
||||
|
||||
internal void
|
||||
fill_view_summary(View_Summary *view, View *vptr, Live_Views *live_set, Working_Set *working_set){
|
||||
fill_view_summary(System_Functions *system, View_Summary *view, View *vptr, Live_Views *live_set, Working_Set *working_set){
|
||||
Buffer_ID buffer_id = 0;
|
||||
File_Viewing_Data *data = &vptr->file_data;
|
||||
|
||||
|
@ -84,7 +84,7 @@ fill_view_summary(View_Summary *view, View *vptr, Live_Views *live_set, Working_
|
|||
|
||||
view->buffer_id = buffer_id;
|
||||
|
||||
view->mark = view_compute_cursor(vptr, seek_pos(vptr->edit_pos->mark), 0);
|
||||
view->mark = view_compute_cursor(system, vptr, seek_pos(vptr->edit_pos->mark), 0);
|
||||
view->cursor = vptr->edit_pos->cursor;
|
||||
view->preferred_x = vptr->edit_pos->preferred_x;
|
||||
|
||||
|
@ -96,8 +96,8 @@ fill_view_summary(View_Summary *view, View *vptr, Live_Views *live_set, Working_
|
|||
|
||||
|
||||
inline void
|
||||
fill_view_summary(View_Summary *view, View *vptr, Command_Data *cmd){
|
||||
fill_view_summary(view, vptr, &cmd->vars->live_set, &cmd->models->working_set);
|
||||
fill_view_summary(System_Functions *system, View_Summary *view, View *vptr, Command_Data *cmd){
|
||||
fill_view_summary(system, view, vptr, &cmd->vars->live_set, &cmd->models->working_set);
|
||||
}
|
||||
|
||||
internal Editing_File*
|
||||
|
@ -195,8 +195,7 @@ DOC_PARAM(command, The command parameter specifies the command that shall be exe
|
|||
DOC_PARAM(command_len, The parameter command_len specifies the length of the command string.)
|
||||
DOC_PARAM(flags, Flags for the behavior of the call are specified in the flags parameter.)
|
||||
DOC_RETURN(This call returns non-zero on success.)
|
||||
DOC(
|
||||
A call to exec_system_command executes a command as if called from the command line, and sends the output to a buffer. The buffer identifier can name a new buffer that does not exist, name a buffer that does exist, or provide the id of a buffer that does exist.
|
||||
DOC(A call to exec_system_command executes a command as if called from the command line, and sends the output to a buffer. The buffer identifier can name a new buffer that does not exist, name a buffer that does exist, or provide the id of a buffer that does exist.
|
||||
|
||||
If the buffer is not already in an open view and the view parameter is not NULL,
|
||||
then the provided view will display the output buffer.
|
||||
|
@ -316,8 +315,8 @@ DOC_SEE(Command_Line_Interface_Flag)
|
|||
command_string = make_string_terminated(part, command, command_len);
|
||||
}
|
||||
|
||||
if (vptr && bind_to_new_view){
|
||||
view_set_file(vptr, file, models);
|
||||
if (vptr != 0 && bind_to_new_view){
|
||||
view_set_file(system, vptr, file, models);
|
||||
view_show_file(vptr);
|
||||
}
|
||||
|
||||
|
@ -342,7 +341,7 @@ DOC_SEE(Command_Line_Interface_Flag)
|
|||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
done:;
|
||||
end_temp_memory(temp);
|
||||
return(result);
|
||||
}
|
||||
|
@ -877,10 +876,8 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
new_value = 48;
|
||||
}
|
||||
if (new_value != file->settings.display_width){
|
||||
i16 font_id = file->settings.font_id;
|
||||
Font_Info *font_info = get_font_info(models->font_set, font_id);
|
||||
Render_Font *font = font_info->font;
|
||||
file_set_width(models, file, new_value, font);
|
||||
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
|
||||
file_set_width(system, models, file, new_value, font);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -891,9 +888,8 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
new_value = 0;
|
||||
}
|
||||
if (new_value != file->settings.minimum_base_display_width){
|
||||
i16 font_id = file->settings.font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, font_id)->font;
|
||||
file_set_min_base_width(models, file, new_value, font);
|
||||
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
|
||||
file_set_min_base_width(system, models, file, new_value, font);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -977,13 +973,12 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
}
|
||||
|
||||
if (full_remeasure){
|
||||
i16 font_id = file->settings.font_id;
|
||||
Render_Font *font = get_font_info(models->font_set, font_id)->font;
|
||||
Render_Font *font = system->font.get_render_data_by_id(file->settings.font_id);
|
||||
|
||||
file_allocate_character_starts_as_needed(&models->mem.general, file);
|
||||
buffer_measure_character_starts(&file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
file_measure_wraps(models, file, font);
|
||||
file_update_cursor_positions(models, file);
|
||||
buffer_measure_character_starts(system, font, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
file_measure_wraps(system, models, file, font);
|
||||
file_update_cursor_positions(system, models, file);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -1304,25 +1299,25 @@ internal_get_view_first(Command_Data *cmd, View_Summary *view){
|
|||
Panel *panel = layout->used_sentinel.next;
|
||||
|
||||
Assert(panel != &layout->used_sentinel);
|
||||
fill_view_summary(view, panel->view, cmd);
|
||||
System_Functions *system = cmd->system;
|
||||
fill_view_summary(system, view, panel->view, cmd);
|
||||
}
|
||||
|
||||
internal void
|
||||
internal_get_view_next(Command_Data *cmd, View_Summary *view){
|
||||
System_Functions *system = cmd->system;
|
||||
Editing_Layout *layout = &cmd->models->layout;
|
||||
Live_Views *live_set = &cmd->vars->live_set;
|
||||
int32_t index = view->view_id - 1;
|
||||
View *vptr = 0;
|
||||
Panel *panel = 0;
|
||||
|
||||
if (index >= 0 && index < live_set->max){
|
||||
vptr = live_set->views + index;
|
||||
panel = vptr->panel;
|
||||
View *vptr = live_set->views + index;
|
||||
Panel *panel = vptr->panel;
|
||||
if (panel){
|
||||
panel = panel->next;
|
||||
}
|
||||
if (panel && panel != &layout->used_sentinel){
|
||||
fill_view_summary(view, panel->view, &cmd->vars->live_set, &cmd->models->working_set);
|
||||
fill_view_summary(system, view, panel->view, &cmd->vars->live_set, &cmd->models->working_set);
|
||||
}
|
||||
else{
|
||||
*view = null_view_summary;
|
||||
|
@ -1390,15 +1385,15 @@ DOC_RETURN(This call returns a summary that describes the indicated view if it i
|
|||
DOC_SEE(Access_Flag)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
View_Summary view = {0};
|
||||
Live_Views *live_set = cmd->live_set;
|
||||
i32 max = live_set->max;
|
||||
View *vptr = 0;
|
||||
|
||||
view_id -= 1;
|
||||
if (view_id >= 0 && view_id < max){
|
||||
vptr = live_set->views + view_id;
|
||||
fill_view_summary(&view, vptr, live_set, &cmd->models->working_set);
|
||||
View *vptr = live_set->views + view_id;
|
||||
fill_view_summary(system, &view, vptr, live_set, &cmd->models->working_set);
|
||||
if (!access_test(view.lock_flags, access)){
|
||||
view = null_view_summary;
|
||||
}
|
||||
|
@ -1416,13 +1411,13 @@ DOC_SEE(set_active_view)
|
|||
DOC_SEE(Access_Flag)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
|
||||
System_Functions *system = cmd->system;
|
||||
Panel *panel = cmd->models->layout.panels + cmd->models->layout.active_panel;
|
||||
|
||||
Assert(panel->view != 0);
|
||||
|
||||
View_Summary view = {0};
|
||||
fill_view_summary(&view, panel->view, &cmd->vars->live_set, &cmd->models->working_set);
|
||||
fill_view_summary(system, &view, panel->view, &cmd->vars->live_set, &cmd->models->working_set);
|
||||
if (!access_test(view.lock_flags, access)){
|
||||
view = null_view_summary;
|
||||
}
|
||||
|
@ -1483,7 +1478,7 @@ DOC_SEE(View_Split_Position)
|
|||
models->layout.active_panel = (i32)(split.panel - models->layout.panels);
|
||||
panel_make_empty(system, cmd->vars, split.panel);
|
||||
|
||||
fill_view_summary(&result, split.panel->view, cmd);
|
||||
fill_view_summary(system, &result, split.panel->view, cmd);
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
@ -1651,6 +1646,7 @@ DOC_RETURN(This call returns non-zero on success.)
|
|||
DOC_SEE(View_Setting_ID)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
View *vptr = imp_get_view(cmd, view);
|
||||
bool32 result = false;
|
||||
|
||||
|
@ -1673,7 +1669,7 @@ DOC_SEE(View_Setting_ID)
|
|||
}break;
|
||||
}
|
||||
|
||||
fill_view_summary(view, vptr, cmd);
|
||||
fill_view_summary(system, view, vptr, cmd);
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
@ -1724,16 +1720,16 @@ DOC_SEE(Buffer_Seek)
|
|||
DOC_SEE(Full_Cursor)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
View *vptr = imp_get_view(cmd, view);
|
||||
Editing_File *file = 0;
|
||||
bool32 result = false;
|
||||
|
||||
if (vptr){
|
||||
file = vptr->file_data.file;
|
||||
if (file && !file->is_loading){
|
||||
Editing_File *file = vptr->file_data.file;
|
||||
if (file != 0 && !file->is_loading){
|
||||
result = true;
|
||||
*cursor_out = view_compute_cursor(vptr, seek, 0);
|
||||
fill_view_summary(view, vptr, cmd);
|
||||
*cursor_out = view_compute_cursor(system, vptr, seek, 0);
|
||||
fill_view_summary(system, view, vptr, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1756,6 +1752,7 @@ cursor in the same column or x position.
|
|||
DOC_SEE(Buffer_Seek)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
View *vptr = imp_get_view(cmd, view);
|
||||
Editing_File *file = 0;
|
||||
bool32 result = false;
|
||||
|
@ -1765,9 +1762,9 @@ DOC_SEE(Buffer_Seek)
|
|||
Assert(file);
|
||||
if (!file->is_loading){
|
||||
result = true;
|
||||
Full_Cursor cursor = view_compute_cursor(vptr, seek, 0);
|
||||
Full_Cursor cursor = view_compute_cursor(system, vptr, seek, 0);
|
||||
view_set_cursor(vptr, cursor, set_preferred_x, file->settings.unwrapped_lines);
|
||||
fill_view_summary(view, vptr, cmd);
|
||||
fill_view_summary(system, view, vptr, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1781,6 +1778,7 @@ DOC(TODO)
|
|||
DOC_SEE(GUI_Scroll_Vars)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
View *vptr = imp_get_view(cmd, view);
|
||||
Editing_File *file = 0;
|
||||
bool32 result = false;
|
||||
|
@ -1789,8 +1787,8 @@ DOC_SEE(GUI_Scroll_Vars)
|
|||
file = vptr->file_data.file;
|
||||
if (file && !file->is_loading){
|
||||
result = true;
|
||||
view_set_scroll(vptr, scroll);
|
||||
fill_view_summary(view, vptr, cmd);
|
||||
view_set_scroll(system, vptr, scroll);
|
||||
fill_view_summary(system, view, vptr, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1807,6 +1805,7 @@ DOC(This call sets the the view's mark position.)
|
|||
DOC_SEE(Buffer_Seek)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
View *vptr = imp_get_view(cmd, view);
|
||||
Editing_File *file = 0;
|
||||
Full_Cursor cursor = {0};
|
||||
|
@ -1817,14 +1816,14 @@ DOC_SEE(Buffer_Seek)
|
|||
if (file && !file->is_loading){
|
||||
if (seek.type != buffer_seek_pos){
|
||||
result = true;
|
||||
cursor = view_compute_cursor(vptr, seek, 0);
|
||||
cursor = view_compute_cursor(system, vptr, seek, 0);
|
||||
vptr->edit_pos->mark = cursor.pos;
|
||||
}
|
||||
else{
|
||||
result = true;
|
||||
vptr->edit_pos->mark = seek.pos;
|
||||
}
|
||||
fill_view_summary(view, vptr, cmd);
|
||||
fill_view_summary(system, view, vptr, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1847,18 +1846,19 @@ and the turn_on set to false, will switch back to showing the cursor.
|
|||
)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
View *vptr = imp_get_view(cmd, view);
|
||||
bool32 result = false;
|
||||
|
||||
if (vptr){
|
||||
result = true;
|
||||
if (turn_on){
|
||||
view_set_temp_highlight(vptr, start, end);
|
||||
view_set_temp_highlight(system, vptr, start, end);
|
||||
}
|
||||
else{
|
||||
vptr->file_data.show_temp_highlight = 0;
|
||||
}
|
||||
fill_view_summary(view, vptr, cmd);
|
||||
fill_view_summary(system, view, vptr, cmd);
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
@ -1871,33 +1871,29 @@ DOC_PARAM(view, The view parameter specifies the view in which to display the bu
|
|||
DOC_PARAM(buffer_id, The buffer_id parameter specifies which buffer to show in the view.)
|
||||
DOC_PARAM(flags, The flags parameter specifies behaviors for setting the buffer.)
|
||||
DOC_RETURN(This call returns non-zero on success.)
|
||||
DOC
|
||||
(
|
||||
On success view_set_buffer sets the specified view's current buffer and
|
||||
cancels and dialogue shown in the view and displays the file.
|
||||
)
|
||||
DOC(On success view_set_buffer sets the specified view's current buffer and cancels and dialogue shown in the view and displays the file.)
|
||||
DOC_SEE(Set_Buffer_Flag)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
System_Functions *system = cmd->system;
|
||||
View *vptr = imp_get_view(cmd, view);
|
||||
Models *models = cmd->models;
|
||||
Editing_File *file = 0;
|
||||
bool32 result = false;
|
||||
|
||||
if (vptr){
|
||||
file = working_set_get_active_file(&models->working_set, buffer_id);
|
||||
Editing_File *file = working_set_get_active_file(&models->working_set, buffer_id);
|
||||
|
||||
if (file){
|
||||
if (file != 0){
|
||||
result = true;
|
||||
if (file != vptr->file_data.file){
|
||||
view_set_file(vptr, file, models);
|
||||
view_set_file(system, vptr, file, models);
|
||||
if (!(flags & SetBuffer_KeepOriginalGUI)){
|
||||
view_show_file(vptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fill_view_summary(view, vptr, cmd);
|
||||
fill_view_summary(system, view, vptr, cmd);
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
@ -2095,6 +2091,8 @@ DOC_PARAM(apply_to_all_files, If this is set all open files change to this font.
|
|||
durring the start hook because several files already exist at that time.)
|
||||
DOC(This call changes 4coder's default font to one of the built in fonts.)
|
||||
*/{
|
||||
|
||||
#if 0
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
Font_Set *set = cmd->models->font_set;
|
||||
|
||||
|
@ -2110,6 +2108,8 @@ DOC(This call changes 4coder's default font to one of the built in fonts.)
|
|||
global_font->font_id = font_id;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
API_EXPORT void
|
||||
|
@ -2120,6 +2120,8 @@ DOC_PARAM(name, The name parameter specifies the name of the font to begin using
|
|||
DOC_PARAM(len, The len parameter specifies the length of the name string.)
|
||||
DOC(This call sets the display font of a particular buffer.)
|
||||
*/{
|
||||
|
||||
#if 0
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
Models *models = cmd->models;
|
||||
Editing_File *file = imp_get_file(cmd, buffer);
|
||||
|
@ -2133,6 +2135,8 @@ DOC(This call sets the display font of a particular buffer.)
|
|||
file_set_font(models, file, font_id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
API_EXPORT bool32
|
||||
|
@ -2144,18 +2148,21 @@ DOC_PARAM(name_max, the capacity of name_out)
|
|||
DOC_RETURN(returns non-zero on success)
|
||||
*/
|
||||
{
|
||||
bool32 result = false;
|
||||
|
||||
#if 0
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
Models *models = cmd->models;
|
||||
Editing_File *file = imp_get_file(cmd, buffer);
|
||||
|
||||
bool32 result = 0;
|
||||
if (file){
|
||||
Font_Set *set = models->font_set;
|
||||
String name = make_string_cap(name_out, 0, name_max);
|
||||
if (font_set_get_name(set, file->settings.font_id, &name)){
|
||||
result = name.size;
|
||||
result = (name.size > 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ struct App_Settings{
|
|||
i32 custom_arg_start;
|
||||
i32 custom_arg_end;
|
||||
};
|
||||
global_const App_Settings null_app_settings = {0};
|
||||
|
||||
struct Debug_Input_Event{
|
||||
Key_Code key;
|
||||
|
@ -50,6 +51,8 @@ struct Models{
|
|||
Mem_Options mem;
|
||||
App_Settings settings;
|
||||
|
||||
Font_ID global_font_id;
|
||||
|
||||
Command_Map map_top;
|
||||
Command_Map map_file;
|
||||
Command_Map map_ui;
|
||||
|
@ -74,11 +77,8 @@ struct Models{
|
|||
Input_Filter_Function *input_filter;
|
||||
Scroll_Rule_Function *scroll_rule;
|
||||
|
||||
Font_Set *font_set;
|
||||
Style_Font global_font;
|
||||
Style_Library styles;
|
||||
u32 *palette;
|
||||
i32 palette_size;
|
||||
|
||||
Editing_Layout layout;
|
||||
Working_Set working_set;
|
||||
|
|
|
@ -35,24 +35,25 @@
|
|||
|
||||
#include "4ed_rendering.h"
|
||||
#include "4ed.h"
|
||||
#include "4ed_buffer_model.h"
|
||||
|
||||
#define FCPP_FORBID_MALLOC
|
||||
#include "4cpp/4cpp_lexer.h"
|
||||
|
||||
#include "4ed_doubly_linked_list.cpp"
|
||||
|
||||
#include "4ed_font_set.cpp"
|
||||
#include "4ed_translation.cpp"
|
||||
#include "4ed_rendering_helper.cpp"
|
||||
|
||||
#include "4ed_style.h"
|
||||
#include "4ed_style.cpp"
|
||||
#include "4ed_command.cpp"
|
||||
|
||||
#include "file/4coder_buffer.cpp"
|
||||
#include "file/4coder_undo.cpp"
|
||||
#include "file/4coder_file.cpp"
|
||||
#include "file/4coder_working_set.cpp"
|
||||
#include "file/4coder_hot_directory.cpp"
|
||||
#include "4ed_buffer.cpp"
|
||||
#include "4ed_undo.cpp"
|
||||
#include "4ed_file.cpp"
|
||||
#include "4ed_working_set.cpp"
|
||||
#include "4ed_hot_directory.cpp"
|
||||
|
||||
#include "4ed_gui.h"
|
||||
#include "4ed_gui.cpp"
|
||||
|
@ -61,5 +62,7 @@
|
|||
#include "4ed_file_view.cpp"
|
||||
#include "4ed.cpp"
|
||||
|
||||
#include "font/4coder_font_static_functions.cpp"
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
// Buffer low level operations
|
||||
//
|
||||
|
||||
#include "../file/4coder_font_data.h"
|
||||
#include "../4coder_helper/4coder_seek_types.h"
|
||||
#include "font/4coder_font_data.h"
|
||||
#include "4coder_helper/4coder_seek_types.h"
|
||||
|
||||
typedef struct Cursor_With_Index{
|
||||
i32 pos;
|
||||
|
@ -186,6 +186,8 @@ buffer_batch_edit_update_cursors(Cursor_With_Index *sorted_positions, i32 count,
|
|||
return(shift_amount);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
internal i32
|
||||
eol_convert_in(char *dest, char *src, i32 size){
|
||||
i32 i = 0, j = 0, k = 0;
|
||||
|
@ -271,256 +273,7 @@ eol_in_place_convert_out(char *data, i32 size, i32 max, i32 *size_out){
|
|||
return(result);
|
||||
}
|
||||
|
||||
// TODO(allen): ditch this shit yo
|
||||
inline i32
|
||||
is_whitespace(char c){
|
||||
i32 result;
|
||||
result = (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' || c == '\v');
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline i32
|
||||
is_alphanumeric_true(char c){
|
||||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9');
|
||||
}
|
||||
|
||||
inline i32
|
||||
is_alphanumeric(char c){
|
||||
return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_');
|
||||
}
|
||||
|
||||
inline i32
|
||||
is_upper(char c){
|
||||
return (c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
inline i32
|
||||
is_lower(char c){
|
||||
return (c >= 'a' && c <= 'z');
|
||||
}
|
||||
|
||||
inline char
|
||||
to_upper(char c){
|
||||
if (is_lower(c)){
|
||||
c += 'A' - 'a';
|
||||
}
|
||||
return(c);
|
||||
}
|
||||
|
||||
internal i32
|
||||
is_match(char *a, char *b, i32 len){
|
||||
i32 result = 1;
|
||||
for (;len > 0; --len, ++a, ++b)
|
||||
if (*a != *b) { result = 0; break; }
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal i32
|
||||
is_match_insensitive(char *a, char *b, i32 len){
|
||||
i32 result = 1;
|
||||
for (;len > 0; --len, ++a, ++b)
|
||||
if (to_upper(*a) != to_upper(*b)) { result = 0; break; }
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
//
|
||||
// Translation state for turning byte streams into unicode/trash byte streams
|
||||
//
|
||||
|
||||
struct Buffer_Model_Step{
|
||||
u32 type;
|
||||
u32 value;
|
||||
i32 i;
|
||||
u32 byte_length;
|
||||
};
|
||||
|
||||
enum{
|
||||
BufferModelUnit_None,
|
||||
BufferModelUnit_Codepoint,
|
||||
BufferModelUnit_Numbers,
|
||||
};
|
||||
|
||||
struct Buffer_Translating_State{
|
||||
u8 fill_buffer[4];
|
||||
u32 fill_start_i;
|
||||
u32 fill_i;
|
||||
u32 fill_expected;
|
||||
|
||||
u32 byte_class;
|
||||
b32 emit_type;
|
||||
b32 rebuffer_current;
|
||||
b32 emit_current_as_cp;
|
||||
|
||||
Buffer_Model_Step steps[5];
|
||||
Buffer_Model_Step step_current;
|
||||
u32 step_count;
|
||||
u32 step_j;
|
||||
|
||||
u32 codepoint;
|
||||
u32 codepoint_length;
|
||||
b32 do_codepoint;
|
||||
b32 do_numbers;
|
||||
|
||||
b32 do_newline;
|
||||
b32 do_codepoint_advance;
|
||||
b32 do_number_advance;
|
||||
};
|
||||
global_const Buffer_Translating_State null_buffer_translating_state = {0};
|
||||
|
||||
internal void
|
||||
translating_consume_byte(Buffer_Translating_State *tran, u8 ch, u32 i, u32 size){
|
||||
tran->byte_class = 0;
|
||||
if ((ch >= ' ' && ch < 0x7F) || ch == '\t' || ch == '\n' || ch == '\r'){
|
||||
tran->byte_class = 1;
|
||||
}
|
||||
else if (ch < 0xC0){
|
||||
tran->byte_class = 1000;
|
||||
}
|
||||
else if (ch < 0xE0){
|
||||
tran->byte_class = 2;
|
||||
}
|
||||
else if (ch < 0xF0){
|
||||
tran->byte_class = 3;
|
||||
}
|
||||
else{
|
||||
tran->byte_class = 4;
|
||||
}
|
||||
|
||||
tran->emit_type = BufferModelUnit_None;
|
||||
tran->rebuffer_current = false;
|
||||
tran->emit_current_as_cp = false;
|
||||
if (tran->fill_expected == 0){
|
||||
tran->fill_buffer[0] = ch;
|
||||
tran->fill_start_i = i;
|
||||
tran->fill_i = 1;
|
||||
|
||||
if (tran->byte_class == 1){
|
||||
tran->emit_type = BufferModelUnit_Codepoint;
|
||||
}
|
||||
else if (tran->byte_class == 0 || tran->byte_class == 1000){
|
||||
tran->emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
else{
|
||||
tran->fill_expected = tran->byte_class;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (tran->byte_class == 1000){
|
||||
tran->fill_buffer[tran->fill_i] = ch;
|
||||
++tran->fill_i;
|
||||
|
||||
if (tran->fill_i == tran->fill_expected){
|
||||
tran->emit_type = BufferModelUnit_Codepoint;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (tran->byte_class >= 2 && tran->byte_class <= 4){
|
||||
tran->rebuffer_current = true;
|
||||
}
|
||||
else if (tran->byte_class == 1){
|
||||
tran->emit_current_as_cp = true;
|
||||
}
|
||||
else{
|
||||
tran->fill_buffer[tran->fill_i] = ch;
|
||||
++tran->fill_i;
|
||||
}
|
||||
tran->emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
}
|
||||
|
||||
if (tran->emit_type == BufferModelUnit_None && i+1 == size){
|
||||
tran->emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
|
||||
tran->codepoint = 0;
|
||||
tran->codepoint_length = 0;
|
||||
tran->do_codepoint = false;
|
||||
tran->do_numbers = false;
|
||||
if (tran->emit_type == BufferModelUnit_Codepoint){
|
||||
tran->codepoint = utf8_to_u32_length_unchecked(tran->fill_buffer, &tran->codepoint_length);
|
||||
if ((tran->codepoint >= ' ' && tran->codepoint <= 255 && tran->codepoint != 127) || tran->codepoint == '\t' || tran->codepoint == '\n' || tran->codepoint == '\r'){
|
||||
tran->do_codepoint = true;
|
||||
}
|
||||
else{
|
||||
tran->do_numbers = true;
|
||||
}
|
||||
}
|
||||
else if (tran->emit_type == BufferModelUnit_Numbers){
|
||||
tran->do_numbers = true;
|
||||
}
|
||||
|
||||
Assert((tran->do_codepoint + tran->do_numbers) <= 1);
|
||||
|
||||
tran->step_count = 0;
|
||||
if (tran->do_codepoint){
|
||||
tran->steps[0].type = 1;
|
||||
tran->steps[0].value = tran->codepoint;
|
||||
tran->steps[0].i = tran->fill_start_i;
|
||||
tran->steps[0].byte_length = tran->codepoint_length;
|
||||
tran->step_count = 1;
|
||||
}
|
||||
else if (tran->do_numbers){
|
||||
for (u32 j = 0; j < tran->fill_i; ++j){
|
||||
tran->steps[j].type = 0;
|
||||
tran->steps[j].value = tran->fill_buffer[j];
|
||||
tran->steps[j].i = tran->fill_start_i + j;
|
||||
tran->steps[j].byte_length = 1;
|
||||
}
|
||||
tran->step_count = tran->fill_i;
|
||||
}
|
||||
|
||||
if (tran->do_codepoint || tran->do_numbers){
|
||||
tran->fill_start_i = 0;
|
||||
tran->fill_i = 0;
|
||||
tran->fill_expected = 0;
|
||||
}
|
||||
|
||||
if (tran->rebuffer_current){
|
||||
Assert(tran->do_codepoint || tran->do_numbers);
|
||||
|
||||
tran->fill_buffer[0] = ch;
|
||||
tran->fill_start_i = i;
|
||||
tran->fill_i = 1;
|
||||
tran->fill_expected = tran->byte_class;
|
||||
}
|
||||
else if (tran->emit_current_as_cp){
|
||||
Assert(tran->do_codepoint || tran->do_numbers);
|
||||
|
||||
tran->steps[tran->step_count].type = 1;
|
||||
tran->steps[tran->step_count].value = ch;
|
||||
tran->steps[tran->step_count].i = i;
|
||||
tran->steps[tran->step_count].byte_length = 1;
|
||||
++tran->step_count;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
translation_step_read(Buffer_Translating_State *tran){
|
||||
tran->do_newline = false;
|
||||
tran->do_codepoint_advance = false;
|
||||
tran->do_number_advance = false;
|
||||
if (tran->step_current.type == 1){
|
||||
switch (tran->step_current.value){
|
||||
case '\n':
|
||||
{
|
||||
tran->do_newline = true;
|
||||
}break;
|
||||
|
||||
default:
|
||||
{
|
||||
tran->do_codepoint_advance = true;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
tran->do_number_advance = true;
|
||||
}
|
||||
}
|
||||
|
||||
#define TRANSLATION_OUTPUT(t) (t)->step_j = 0; (t)->step_j < (t)->step_count; ++(t)->step_j
|
||||
#define TRANSLATION_GET_STEP(t) (t)->step_current = (t)->steps[(t)->step_j]; translation_step_read(t)
|
||||
//////////////////////////////////////
|
||||
|
||||
//
|
||||
// Implementation of the gap buffer
|
||||
|
@ -585,31 +338,30 @@ buffer_init_provide_page(Gap_Buffer_Init *init, void *page, i32 page_size){
|
|||
buffer->max = page_size;
|
||||
}
|
||||
|
||||
internal i32
|
||||
internal b32
|
||||
buffer_end_init(Gap_Buffer_Init *init, void *scratch, i32 scratch_size){
|
||||
Gap_Buffer *buffer = init->buffer;
|
||||
i32 osize1 = 0, size1 = 0, size2 = 0, size = init->size;
|
||||
i32 result = 0;
|
||||
b32 result = false;
|
||||
|
||||
if (buffer->data){
|
||||
if (buffer->max >= init->size){
|
||||
size2 = size >> 1;
|
||||
size1 = osize1 = size - size2;
|
||||
|
||||
if (size1 > 0){
|
||||
size1 = eol_convert_in(buffer->data, init->data, size1);
|
||||
if (size2 > 0){
|
||||
size2 = eol_convert_in(buffer->data + size1, init->data + osize1, size2);
|
||||
}
|
||||
if (buffer->data && buffer->max >= init->size){
|
||||
i32 size = init->size;
|
||||
i32 size2 = size >> 1;
|
||||
i32 osize1 = size - size2;
|
||||
i32 size1 = osize1;
|
||||
|
||||
if (size1 > 0){
|
||||
size1 = eol_convert_in(buffer->data, init->data, size1);
|
||||
if (size2 > 0){
|
||||
size2 = eol_convert_in(buffer->data + size1, init->data + osize1, size2);
|
||||
}
|
||||
|
||||
buffer->size1 = size1;
|
||||
buffer->size2 = size2;
|
||||
buffer->gap_size = buffer->max - size1 - size2;
|
||||
memmove(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2);
|
||||
|
||||
result = 1;
|
||||
}
|
||||
|
||||
buffer->size1 = size1;
|
||||
buffer->size2 = size2;
|
||||
buffer->gap_size = buffer->max - size1 - size2;
|
||||
memmove(buffer->data + size1 + buffer->gap_size, buffer->data + size1, size2);
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
@ -823,9 +575,9 @@ buffer_convert_out(Gap_Buffer *buffer, char *dest, i32 max){
|
|||
if (buffer_stringify_loop(&stream, buffer, 0, size)){
|
||||
b32 still_looping = 0;
|
||||
do{
|
||||
i32 size = stream.end - i;
|
||||
i32 chunk_size = stream.end - i;
|
||||
i32 out_size = 0;
|
||||
i32 result = eol_convert_out(dest + pos, max - pos, stream.data + i, size, &out_size);
|
||||
i32 result = eol_convert_out(dest + pos, max - pos, stream.data + i, chunk_size, &out_size);
|
||||
assert(result);
|
||||
i = stream.end;
|
||||
pos += out_size;
|
||||
|
@ -916,7 +668,7 @@ buffer_measure_starts(Buffer_Measure_Starts *state, Gap_Buffer *buffer){
|
|||
}
|
||||
|
||||
internal void
|
||||
buffer_measure_character_starts(Gap_Buffer *buffer, i32 *character_starts, i32 mode, i32 virtual_white){
|
||||
buffer_measure_character_starts(System_Functions *system, Render_Font *font, Gap_Buffer *buffer, i32 *character_starts, i32 mode, i32 virtual_white){
|
||||
assert(mode == 0);
|
||||
|
||||
Gap_Buffer_Stream stream = {0};
|
||||
|
@ -934,7 +686,8 @@ buffer_measure_character_starts(Gap_Buffer *buffer, i32 *character_starts, i32 m
|
|||
skipping_whitespace = 1;
|
||||
}
|
||||
|
||||
Buffer_Translating_State tran = {0};
|
||||
Translation_State tran = {0};
|
||||
Translation_Emits emits = {0};
|
||||
|
||||
stream.use_termination_character = 1;
|
||||
stream.terminator = '\n';
|
||||
|
@ -944,19 +697,19 @@ buffer_measure_character_starts(Gap_Buffer *buffer, i32 *character_starts, i32 m
|
|||
for (; i < stream.end; ++i){
|
||||
u8 ch = (u8)stream.data[i];
|
||||
|
||||
translating_consume_byte(&tran, ch, i, size);
|
||||
translating_fully_process_byte(system, font, &tran, ch, i, size, &emits);
|
||||
|
||||
for (TRANSLATION_OUTPUT(&tran)){
|
||||
TRANSLATION_GET_STEP(&tran);
|
||||
for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){
|
||||
TRANSLATION_DECL_GET_STEP(step, behavior, J, emits);
|
||||
|
||||
if (tran.do_newline){
|
||||
if (behavior.do_newline){
|
||||
++character_index;
|
||||
character_starts[line_index++] = character_index;
|
||||
if (virtual_white){
|
||||
skipping_whitespace = 1;
|
||||
}
|
||||
}
|
||||
else if (tran.do_codepoint_advance || tran.do_number_advance){
|
||||
else if (behavior.do_codepoint_advance || behavior.do_number_advance){
|
||||
if (ch != ' ' && ch != '\t'){
|
||||
skipping_whitespace = 0;
|
||||
}
|
||||
|
@ -993,6 +746,7 @@ struct Buffer_Layout_Stop{
|
|||
struct Buffer_Measure_Wrap_Params{
|
||||
Gap_Buffer *buffer;
|
||||
i32 *wrap_line_index;
|
||||
System_Functions *system;
|
||||
Render_Font *font;
|
||||
b32 virtual_white;
|
||||
};
|
||||
|
@ -1014,9 +768,11 @@ struct Buffer_Measure_Wrap_State{
|
|||
b32 did_wrap;
|
||||
b32 first_of_the_line;
|
||||
|
||||
u8 ch;
|
||||
|
||||
Buffer_Translating_State tran;
|
||||
Translation_State tran;
|
||||
Translation_Emits emits;
|
||||
u32 J;
|
||||
Buffer_Model_Step step;
|
||||
Buffer_Model_Behavior behavior;
|
||||
|
||||
i32 __pc__;
|
||||
};
|
||||
|
@ -1060,18 +816,20 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
|
|||
S.still_looping = 0;
|
||||
do{
|
||||
for (; S.i < S.stream.end; ++S.i){
|
||||
S.ch = (u8)S.stream.data[S.i];
|
||||
|
||||
if (S.ch != ' ' && S.ch != '\t'){
|
||||
S.skipping_whitespace = false;
|
||||
{
|
||||
u8 ch = (u8)S.stream.data[S.i];
|
||||
|
||||
if (ch != ' ' && ch != '\t'){
|
||||
S.skipping_whitespace = false;
|
||||
}
|
||||
|
||||
translating_fully_process_byte(params.system, params.font, &S.tran, ch, S.i, S.size, &S.emits);
|
||||
}
|
||||
|
||||
translating_consume_byte(&S.tran, S.ch, S.i, S.size);
|
||||
|
||||
for (TRANSLATION_OUTPUT(&S.tran)){
|
||||
TRANSLATION_GET_STEP(&S.tran);
|
||||
for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){
|
||||
TRANSLATION_GET_STEP(S.step, S.behavior, S.J, S.emits);
|
||||
|
||||
if (S.tran.do_newline){
|
||||
if (S.behavior.do_newline){
|
||||
++S.current_wrap_index;
|
||||
params.wrap_line_index[S.line_index++] = S.current_wrap_index;
|
||||
|
||||
|
@ -1090,14 +848,13 @@ buffer_measure_wrap_y(Buffer_Measure_Wrap_State *S_ptr, Buffer_Measure_Wrap_Para
|
|||
}
|
||||
S.first_of_the_line = 1;
|
||||
}
|
||||
else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){
|
||||
else if (S.behavior.do_number_advance || S.behavior.do_codepoint_advance){
|
||||
if (!S.skipping_whitespace){
|
||||
|
||||
if (S.tran.do_codepoint_advance){
|
||||
S.current_adv = get_codepoint_advance(params.font, S.tran.step_current.value);
|
||||
if (S.behavior.do_codepoint_advance){
|
||||
S.current_adv = font_get_glyph_advance(params.system, params.font, S.step.value);
|
||||
}
|
||||
else{
|
||||
S.current_adv = params.font->byte_advance;
|
||||
S.current_adv = font_get_byte_advance(params.font);
|
||||
}
|
||||
|
||||
S.did_wrap = false;
|
||||
|
@ -1228,7 +985,7 @@ buffer_remeasure_starts(Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 li
|
|||
}
|
||||
|
||||
internal void
|
||||
buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 *character_starts, i32 mode, i32 virtual_whitespace){
|
||||
buffer_remeasure_character_starts(System_Functions *system, Render_Font *font, Gap_Buffer *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 *character_starts, i32 mode, i32 virtual_whitespace){
|
||||
assert(mode == 0);
|
||||
|
||||
i32 new_line_count = buffer->line_count;
|
||||
|
@ -1266,7 +1023,8 @@ buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_e
|
|||
}
|
||||
|
||||
// Translation
|
||||
Buffer_Translating_State tran = {0};
|
||||
Translation_State tran = {0};
|
||||
Translation_Emits emits = {0};
|
||||
|
||||
stream.use_termination_character = 1;
|
||||
stream.terminator = '\n';
|
||||
|
@ -1275,12 +1033,12 @@ buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_e
|
|||
do{
|
||||
for (; char_i < stream.end; ++char_i){
|
||||
u8 ch = (u8)stream.data[char_i];
|
||||
translating_consume_byte(&tran, ch, char_i, size);
|
||||
translating_fully_process_byte(system, font, &tran, ch, char_i, size, &emits);
|
||||
|
||||
for (TRANSLATION_OUTPUT(&tran)){
|
||||
TRANSLATION_GET_STEP(&tran);
|
||||
for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){
|
||||
TRANSLATION_DECL_GET_STEP(step, behavior, J, emits);
|
||||
|
||||
if (tran.do_newline){
|
||||
if (behavior.do_newline){
|
||||
character_starts[line_i++] = last_char_start;
|
||||
++current_char_start;
|
||||
last_char_start = current_char_start;
|
||||
|
@ -1292,7 +1050,7 @@ buffer_remeasure_character_starts(Gap_Buffer *buffer, i32 line_start, i32 line_e
|
|||
goto buffer_remeasure_character_starts_end;
|
||||
}
|
||||
}
|
||||
else if (tran.do_codepoint_advance || tran.do_number_advance){
|
||||
else if (behavior.do_codepoint_advance || behavior.do_number_advance){
|
||||
if (ch != ' ' && ch != '\t'){
|
||||
skipping_whitespace = 0;
|
||||
}
|
||||
|
@ -1539,6 +1297,7 @@ buffer_partial_from_line_character(Gap_Buffer *buffer, i32 line, i32 character){
|
|||
struct Buffer_Cursor_Seek_Params{
|
||||
Gap_Buffer *buffer;
|
||||
Buffer_Seek seek;
|
||||
System_Functions *system;
|
||||
Render_Font *font;
|
||||
i32 *wrap_line_index;
|
||||
i32 *character_starts;
|
||||
|
@ -1561,9 +1320,15 @@ struct Buffer_Cursor_Seek_State{
|
|||
b32 first_of_the_line;
|
||||
b32 xy_seek;
|
||||
f32 ch_width;
|
||||
u8 ch;
|
||||
|
||||
Buffer_Translating_State tran;
|
||||
i32 font_height;
|
||||
|
||||
Translation_State tran;
|
||||
Translation_Emits emits;
|
||||
u32 J;
|
||||
Buffer_Model_Step step;
|
||||
Buffer_Model_Behavior behavior;
|
||||
|
||||
|
||||
i32 __pc__;
|
||||
};
|
||||
|
@ -1585,6 +1350,8 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
DrCase(4);
|
||||
}
|
||||
|
||||
S.font_height = font_get_height(params.font);
|
||||
|
||||
S.xy_seek = (params.seek.type == buffer_seek_wrapped_xy || params.seek.type == buffer_seek_unwrapped_xy);
|
||||
S.size = buffer_size(params.buffer);
|
||||
|
||||
|
@ -1594,9 +1361,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
switch (params.seek.type){
|
||||
case buffer_seek_pos:
|
||||
{
|
||||
if (params.seek.pos > S.size){
|
||||
params.seek.pos = S.size;
|
||||
}
|
||||
params.seek.pos = clamp(0, params.seek.pos, S.size);
|
||||
|
||||
line_index = buffer_get_line_index(params.buffer, params.seek.pos);
|
||||
}break;
|
||||
|
@ -1605,53 +1370,45 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
{
|
||||
i32 line_count = params.buffer->line_count;
|
||||
i32 max_character = params.character_starts[line_count] - 1;
|
||||
if (params.seek.pos > max_character){
|
||||
params.seek.pos = max_character;
|
||||
}
|
||||
params.seek.pos = clamp(0, params.seek.pos, max_character);
|
||||
|
||||
line_index = buffer_get_line_index_from_character_pos(params.character_starts, params.seek.pos,
|
||||
0, params.buffer->line_count);
|
||||
line_index = buffer_get_line_index_from_character_pos(params.character_starts, params.seek.pos, 0, params.buffer->line_count);
|
||||
}break;
|
||||
|
||||
case buffer_seek_line_char:
|
||||
{
|
||||
line_index = params.seek.line - 1;
|
||||
if (line_index >= params.buffer->line_count){
|
||||
line_index = params.buffer->line_count - 1;
|
||||
}
|
||||
if (line_index < 0){
|
||||
line_index = 0;
|
||||
}
|
||||
line_index = clamp_bottom(0, line_index);
|
||||
}break;
|
||||
|
||||
case buffer_seek_unwrapped_xy:
|
||||
{
|
||||
line_index = (i32)(params.seek.y / params.font->height);
|
||||
if (line_index >= params.buffer->line_count){
|
||||
line_index = params.buffer->line_count - 1;
|
||||
}
|
||||
if (line_index < 0){
|
||||
line_index = 0;
|
||||
}
|
||||
line_index = (i32)(params.seek.y / S.font_height);
|
||||
line_index = clamp_bottom(0, line_index);
|
||||
}break;
|
||||
|
||||
case buffer_seek_wrapped_xy:
|
||||
{
|
||||
line_index = buffer_get_line_index_from_wrapped_y(params.wrap_line_index, params.seek.y, params.font->height, 0, params.buffer->line_count);
|
||||
line_index = buffer_get_line_index_from_wrapped_y(params.wrap_line_index, params.seek.y, S.font_height, 0, params.buffer->line_count);
|
||||
}break;
|
||||
|
||||
default: InvalidCodePath;
|
||||
}
|
||||
|
||||
i32 safe_line_index = line_index;
|
||||
if (line_index >= params.buffer->line_count){
|
||||
safe_line_index = params.buffer->line_count-1;
|
||||
}
|
||||
|
||||
// Build the cursor hint
|
||||
S.next_cursor.pos = params.buffer->line_starts[line_index];
|
||||
S.next_cursor.character_pos = params.character_starts[line_index];
|
||||
S.next_cursor.pos = params.buffer->line_starts[safe_line_index];
|
||||
S.next_cursor.character_pos = params.character_starts[safe_line_index];
|
||||
S.next_cursor.line = line_index + 1;
|
||||
S.next_cursor.character = 1;
|
||||
S.next_cursor.wrap_line = params.wrap_line_index[line_index] + 1;
|
||||
S.next_cursor.unwrapped_y = (f32)(line_index * params.font->height);
|
||||
S.next_cursor.wrap_line = params.wrap_line_index[safe_line_index] + 1;
|
||||
S.next_cursor.unwrapped_y = (f32)(safe_line_index * S.font_height);
|
||||
S.next_cursor.unwrapped_x = 0;
|
||||
S.next_cursor.wrapped_y = (f32)(params.wrap_line_index[line_index] * params.font->height);
|
||||
S.next_cursor.wrapped_y = (f32)(params.wrap_line_index[safe_line_index] * S.font_height);
|
||||
S.next_cursor.wrapped_x = 0;
|
||||
}
|
||||
|
||||
|
@ -1672,9 +1429,9 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
if (buffer_stringify_loop(&S.stream, params.buffer, S.next_cursor.pos, S.size)){
|
||||
do{
|
||||
for (; S.next_cursor.pos < S.stream.end; ++S.next_cursor.pos){
|
||||
S.ch = (u8)S.stream.data[S.next_cursor.pos];
|
||||
u8 ch = (u8)S.stream.data[S.next_cursor.pos];
|
||||
|
||||
if (S.ch != ' ' && S.ch != '\t'){
|
||||
if (ch != ' ' && ch != '\t'){
|
||||
goto double_break_vwhite;
|
||||
}
|
||||
else{
|
||||
|
@ -1748,22 +1505,23 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
S.still_looping = 0;
|
||||
do{
|
||||
for (; S.i < S.stream.end; ++S.i){
|
||||
S.ch = (u8)S.stream.data[S.i];
|
||||
{
|
||||
u8 ch = (u8)S.stream.data[S.i];
|
||||
translating_fully_process_byte(params.system, params.font, &S.tran, ch, S.i, S.size, &S.emits);
|
||||
}
|
||||
|
||||
translating_consume_byte(&S.tran, S.ch, S.i, S.size);
|
||||
|
||||
for (TRANSLATION_OUTPUT(&S.tran)){
|
||||
TRANSLATION_GET_STEP(&S.tran);
|
||||
for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){
|
||||
TRANSLATION_GET_STEP(S.step, S.behavior, S.J, S.emits);
|
||||
|
||||
S.prev_cursor = S.this_cursor;
|
||||
S.this_cursor = S.next_cursor;
|
||||
|
||||
if (S.tran.do_newline){
|
||||
if (S.behavior.do_newline){
|
||||
++S.next_cursor.character_pos;
|
||||
++S.next_cursor.line;
|
||||
++S.next_cursor.wrap_line;
|
||||
S.next_cursor.unwrapped_y += params.font->height;
|
||||
S.next_cursor.wrapped_y += params.font->height;
|
||||
S.next_cursor.unwrapped_y += S.font_height;
|
||||
S.next_cursor.wrapped_y += S.font_height;
|
||||
S.next_cursor.character = 1;
|
||||
S.next_cursor.unwrapped_x = 0;
|
||||
|
||||
|
@ -1777,27 +1535,27 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
S.next_cursor.wrapped_x = line_shift;
|
||||
S.first_of_the_line = 1;
|
||||
}
|
||||
else if (S.tran.do_number_advance || S.tran.do_codepoint_advance){
|
||||
else if (S.behavior.do_number_advance || S.behavior.do_codepoint_advance){
|
||||
|
||||
if (S.tran.do_codepoint_advance){
|
||||
S.ch_width = get_codepoint_advance(params.font, S.tran.step_current.value);
|
||||
if (S.behavior.do_codepoint_advance){
|
||||
S.ch_width = font_get_glyph_advance(params.system, params.font, S.step.value);
|
||||
}
|
||||
else{
|
||||
S.ch_width = params.font->byte_advance;
|
||||
S.ch_width = font_get_byte_advance(params.font);
|
||||
}
|
||||
|
||||
if (S.tran.step_current.i >= S.wrap_unit_end){
|
||||
if (S.step.i >= S.wrap_unit_end){
|
||||
S_stop.status = BLStatus_NeedWrapDetermination;
|
||||
S_stop.line_index = S.next_cursor.line-1;
|
||||
S_stop.wrap_line_index = S.next_cursor.wrap_line-1;
|
||||
S_stop.pos = S.tran.step_current.i;
|
||||
S_stop.pos = S.step.i;
|
||||
S_stop.x = S.next_cursor.wrapped_x;
|
||||
DrYield(4, S_stop);
|
||||
|
||||
S.wrap_unit_end = wrap_unit_end;
|
||||
|
||||
if (do_wrap && !S.first_of_the_line){
|
||||
S.next_cursor.wrapped_y += params.font->height;
|
||||
S.next_cursor.wrapped_y += S.font_height;
|
||||
|
||||
++S.next_cursor.wrap_line;
|
||||
if (params.virtual_white){
|
||||
|
@ -1820,7 +1578,7 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
S.first_of_the_line = 0;
|
||||
}
|
||||
|
||||
S.next_cursor.pos += S.tran.step_current.byte_length;
|
||||
S.next_cursor.pos += S.step.byte_length;
|
||||
|
||||
f32 x = 0, px = 0, y = 0, py = 0;
|
||||
switch (params.seek.type){
|
||||
|
@ -1866,9 +1624,9 @@ buffer_cursor_seek(Buffer_Cursor_Seek_State *S_ptr, Buffer_Cursor_Seek_Params pa
|
|||
goto buffer_cursor_seek_end;
|
||||
}
|
||||
|
||||
if (y > params.seek.y - params.font->height && x >= params.seek.x){
|
||||
if (y > params.seek.y - S.font_height && x >= params.seek.x){
|
||||
if (!params.seek.round_down){
|
||||
if (py >= y && S.ch != '\n' && (params.seek.x - px) < (x - params.seek.x)){
|
||||
if (py >= y && !S.behavior.do_newline && (params.seek.x - px) < (x - params.seek.x)){
|
||||
S.this_cursor = S.prev_cursor;
|
||||
}
|
||||
goto buffer_cursor_seek_end;
|
||||
|
@ -1963,7 +1721,7 @@ enum Buffer_Render_Flag{
|
|||
|
||||
typedef struct Buffer_Render_Item{
|
||||
i32 index;
|
||||
u32 glyphid;
|
||||
u32 codepoint;
|
||||
u32 flags;
|
||||
f32 x0, y0;
|
||||
f32 x1, y1;
|
||||
|
@ -1972,23 +1730,26 @@ typedef struct Buffer_Render_Item{
|
|||
typedef struct Render_Item_Write{
|
||||
Buffer_Render_Item *item;
|
||||
f32 x, y;
|
||||
System_Functions *system;
|
||||
Render_Font *font;
|
||||
i32 font_height;
|
||||
f32 x_min;
|
||||
f32 x_max;
|
||||
} Render_Item_Write;
|
||||
|
||||
inline Render_Item_Write
|
||||
write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){
|
||||
f32 ch_width = get_codepoint_advance(write.font, glyphid);
|
||||
write_render_item(Render_Item_Write write, i32 index, u32 codepoint, u32 flags){
|
||||
|
||||
f32 ch_width = font_get_glyph_advance(write.system, write.font, codepoint);
|
||||
|
||||
if (write.x <= write.x_max && write.x + ch_width >= write.x_min){
|
||||
write.item->index = index;
|
||||
write.item->glyphid = glyphid;
|
||||
write.item->codepoint = codepoint;
|
||||
write.item->flags = flags;
|
||||
write.item->x0 = write.x;
|
||||
write.item->y0 = write.y;
|
||||
write.item->x1 = write.x + ch_width;
|
||||
write.item->y1 = write.y + write.font->height;
|
||||
write.item->y1 = write.y + write.font_height;
|
||||
|
||||
++write.item;
|
||||
}
|
||||
|
@ -1998,7 +1759,6 @@ write_render_item(Render_Item_Write write, i32 index, u32 glyphid, u32 flags){
|
|||
return(write);
|
||||
}
|
||||
|
||||
// TODO(allen): Reduce the number of parameters.
|
||||
struct Buffer_Render_Params{
|
||||
Gap_Buffer *buffer;
|
||||
Buffer_Render_Item *items;
|
||||
|
@ -2013,6 +1773,7 @@ struct Buffer_Render_Params{
|
|||
f32 height;
|
||||
Full_Cursor start_cursor;
|
||||
i32 wrapped;
|
||||
System_Functions *system;
|
||||
Render_Font *font;
|
||||
b32 virtual_white;
|
||||
i32 wrap_slashes;
|
||||
|
@ -2028,9 +1789,9 @@ struct Buffer_Render_State{
|
|||
f32 shift_y;
|
||||
|
||||
f32 ch_width;
|
||||
u8 ch;
|
||||
|
||||
Render_Item_Write write;
|
||||
f32 byte_advance;
|
||||
|
||||
i32 line;
|
||||
i32 wrap_line;
|
||||
|
@ -2038,7 +1799,11 @@ struct Buffer_Render_State{
|
|||
b32 first_of_the_line;
|
||||
i32 wrap_unit_end;
|
||||
|
||||
Buffer_Translating_State tran;
|
||||
Translation_State tran;
|
||||
Translation_Emits emits;
|
||||
u32 J;
|
||||
Buffer_Model_Step step;
|
||||
Buffer_Model_Behavior behavior;
|
||||
|
||||
i32 __pc__;
|
||||
};
|
||||
|
@ -2086,10 +1851,14 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
S.write.item = params.items;
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y = S.shift_y;
|
||||
S.write.system = params.system;
|
||||
S.write.font = params.font;
|
||||
S.write.font_height = font_get_height(params.font);
|
||||
S.write.x_min = params.port_x;
|
||||
S.write.x_max = params.port_x + params.clip_w;
|
||||
|
||||
S.byte_advance = font_get_byte_advance(params.font);
|
||||
|
||||
if (params.virtual_white){
|
||||
S.skipping_whitespace = 1;
|
||||
}
|
||||
|
@ -2099,17 +1868,19 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
if (buffer_stringify_loop(&S.stream, params.buffer, S.i, S.size)){
|
||||
do{
|
||||
for (; S.i < S.stream.end; ++S.i){
|
||||
S.ch = (u8)S.stream.data[S.i];
|
||||
translating_consume_byte(&S.tran, S.ch, S.i, S.size);
|
||||
{
|
||||
u8 ch = (u8)S.stream.data[S.i];
|
||||
translating_fully_process_byte(params.system, params.font, &S.tran, ch, S.i, S.size, &S.emits);
|
||||
}
|
||||
|
||||
for (TRANSLATION_OUTPUT(&S.tran)){
|
||||
TRANSLATION_GET_STEP(&S.tran);
|
||||
for (TRANSLATION_EMIT_LOOP(S.J, S.emits)){
|
||||
TRANSLATION_GET_STEP(S.step, S.behavior, S.J, S.emits);
|
||||
|
||||
if (!S.tran.do_newline && S.tran.step_current.i >= S.wrap_unit_end){
|
||||
if (!S.behavior.do_newline && S.step.i >= S.wrap_unit_end){
|
||||
S_stop.status = BLStatus_NeedWrapDetermination;
|
||||
S_stop.line_index = S.line;
|
||||
S_stop.wrap_line_index = S.wrap_line;
|
||||
S_stop.pos = S.tran.step_current.i;
|
||||
S_stop.pos = S.step.i;
|
||||
S_stop.x = S.write.x - S.shift_x;
|
||||
DrYield(4, S_stop);
|
||||
|
||||
|
@ -2129,7 +1900,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
switch (params.wrap_slashes){
|
||||
case WrapIndicator_Show_After_Line:
|
||||
{
|
||||
S.write = write_render_item(S.write, S.tran.step_current.i-1, '\\', BRFlag_Ghost_Character);
|
||||
S.write = write_render_item(S.write, S.step.i-1, '\\', BRFlag_Ghost_Character);
|
||||
}break;
|
||||
|
||||
case WrapIndicator_Show_At_Wrap_Edge:
|
||||
|
@ -2137,12 +1908,12 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
if (S.write.x < S.shift_x + params.width){
|
||||
S.write.x = S.shift_x + params.width;
|
||||
}
|
||||
S.write = write_render_item(S.write, S.tran.step_current.i-1, '\\', BRFlag_Ghost_Character);
|
||||
S.write = write_render_item(S.write, S.step.i-1, '\\', BRFlag_Ghost_Character);
|
||||
}break;
|
||||
}
|
||||
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y += params.font->height;
|
||||
S.write.y += S.write.font_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2152,8 +1923,8 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
}
|
||||
|
||||
S.first_of_the_line = false;
|
||||
if (S.tran.do_newline){
|
||||
S.write = write_render_item(S.write, S.tran.step_current.i, ' ', 0);
|
||||
if (S.behavior.do_newline){
|
||||
S.write = write_render_item(S.write, S.step.i, ' ', 0);
|
||||
|
||||
if (params.virtual_white){
|
||||
S_stop.status = BLStatus_NeedLineShift;
|
||||
|
@ -2168,18 +1939,18 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
++S.wrap_line;
|
||||
|
||||
S.write.x = S.shift_x + line_shift;
|
||||
S.write.y += params.font->height;
|
||||
S.write.y += S.write.font_height;
|
||||
|
||||
S.first_of_the_line = true;
|
||||
}
|
||||
else if (S.tran.do_codepoint_advance){
|
||||
u32 n = S.tran.step_current.value;
|
||||
else if (S.behavior.do_codepoint_advance){
|
||||
u32 n = S.step.value;
|
||||
if (n != ' ' && n != '\t'){
|
||||
S.skipping_whitespace = false;
|
||||
}
|
||||
|
||||
if (!S.skipping_whitespace){
|
||||
u32 I = S.tran.step_current.i;
|
||||
u32 I = S.step.i;
|
||||
switch (n){
|
||||
case '\r':
|
||||
{
|
||||
|
@ -2191,7 +1962,8 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
|
||||
case '\t':
|
||||
{
|
||||
S.ch_width = get_codepoint_advance(params.font, '\t');
|
||||
S.ch_width = font_get_glyph_advance(params.system, params.font, '\t');
|
||||
|
||||
f32 new_x = S.write.x + S.ch_width;
|
||||
S.write = write_render_item(S.write, I, ' ', 0);
|
||||
S.write.x = new_x;
|
||||
|
@ -2204,12 +1976,12 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (S.tran.do_number_advance){
|
||||
u8 n = (u8)S.tran.step_current.value;
|
||||
u32 I = S.tran.step_current.i;
|
||||
else if (S.behavior.do_number_advance){
|
||||
u8 n = (u8)S.step.value;
|
||||
u32 I = S.step.i;
|
||||
S.skipping_whitespace = false;
|
||||
|
||||
S.ch_width = params.font->byte_advance;
|
||||
S.ch_width = S.byte_advance;
|
||||
f32 new_x = S.write.x + S.ch_width;
|
||||
|
||||
u8 cs[3];
|
||||
|
@ -2229,7 +2001,7 @@ buffer_render_data(Buffer_Render_State *S_ptr, Buffer_Render_Params params, f32
|
|||
S.write.x = new_x;
|
||||
}
|
||||
|
||||
if (!S.skipping_whitespace && !S.tran.do_newline){
|
||||
if (!S.skipping_whitespace && !S.behavior.do_newline){
|
||||
S.first_of_the_line = false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 18.03.2017
|
||||
*
|
||||
* Abstract model for the describing the characters of a buffer.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_BUFFER_MODEL_H)
|
||||
#define FRED_BUFFER_MODEL_H
|
||||
|
||||
struct Buffer_Model_Step{
|
||||
u32 type;
|
||||
u32 value;
|
||||
i32 i;
|
||||
u32 byte_length;
|
||||
};
|
||||
|
||||
struct Buffer_Model_Behavior{
|
||||
b32 do_newline;
|
||||
b32 do_codepoint_advance;
|
||||
b32 do_number_advance;
|
||||
};
|
||||
|
||||
enum{
|
||||
BufferModelUnit_None,
|
||||
BufferModelUnit_Codepoint,
|
||||
BufferModelUnit_Numbers,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -95,13 +95,14 @@ struct Editing_File_Settings{
|
|||
i32 wrap_indicator;
|
||||
b32 dos_write_mode;
|
||||
b32 virtual_white;
|
||||
i16 font_id;
|
||||
Font_ID font_id;
|
||||
b8 unwrapped_lines;
|
||||
b8 tokens_exist;
|
||||
b8 is_initialized;
|
||||
b8 unimportant;
|
||||
b8 read_only;
|
||||
b8 never_kill;
|
||||
u8 pad[2];
|
||||
};
|
||||
global_const Editing_File_Settings null_editing_file_settings = {0};
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 20.07.2016
|
||||
*
|
||||
* File tracking API.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FILE_TRACK_4TECH_H)
|
||||
#define FILE_TRACK_4TECH_H
|
||||
|
||||
#if !defined(FILE_TRACK_LINK)
|
||||
# define FILE_TRACK_LINK static
|
||||
#endif
|
||||
|
||||
typedef struct{
|
||||
u8 opaque[128];
|
||||
} File_Track_System;
|
||||
|
||||
typedef i32 File_Track_Result;
|
||||
enum{
|
||||
FileTrack_Good,
|
||||
FileTrack_MemoryTooSmall,
|
||||
FileTrack_OutOfTableMemory,
|
||||
FileTrack_OutOfListenerMemory,
|
||||
FileTrack_NoMoreEvents,
|
||||
FileTrack_FileSystemError
|
||||
};
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
init_track_system(File_Track_System *system, Partition *scratch, void *table_memory, i32 table_memory_size, void *listener_memory, i32 listener_memory_size);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
add_listener(File_Track_System *system, Partition *scratch, u8 *filename);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
remove_listener(File_Track_System *system, Partition *scratch, u8 *filename);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
move_track_system(File_Track_System *system, Partition *scratch, void *mem, i32 size);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
expand_track_system_listeners(File_Track_System *system, Partition *scratch, void *mem, i32 size);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
get_change_event(File_Track_System *system, Partition *scratch, u8 *buffer, i32 max);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
shut_down_track_system(File_Track_System *system, Partition *scratch);
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
|
@ -1,45 +1,33 @@
|
|||
/*
|
||||
|
||||
Copy Right FourTech LLC, 2016
|
||||
All Rights Are Reserved
|
||||
|
||||
The OS agnostic file tracking API for applications
|
||||
that want to interact with potentially many files on
|
||||
the disk that could be changed by other applications.
|
||||
|
||||
Created on: 27.08.2016
|
||||
|
||||
*/
|
||||
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 20.08.2016
|
||||
*
|
||||
* File tracking shared.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#ifndef Assert
|
||||
# define Assert(c) do { if (!(c)) { *((int*)0) = 0xA11E; } } while (0)
|
||||
#endif
|
||||
|
||||
#ifndef ZeroStruct
|
||||
# define ZeroStruct(s) for (int32_t i = 0; i < sizeof(s); ++i) { ((char*)(&(s)))[i] = 0; }
|
||||
#endif
|
||||
|
||||
typedef struct{
|
||||
uint32_t id[4];
|
||||
u32 id[4];
|
||||
} File_Index;
|
||||
|
||||
typedef uint32_t rptr32;
|
||||
typedef u32 rptr32;
|
||||
|
||||
#define to_ptr(b,p) ((void*)((char*)b + p))
|
||||
#define to_rptr32(b,p) ((rptr32)((char*)(p) - (char*)(b)))
|
||||
|
||||
typedef struct {
|
||||
File_Index hash;
|
||||
uint32_t opaque[4];
|
||||
u32 opaque[4];
|
||||
} File_Track_Entry;
|
||||
global_const File_Track_Entry null_file_track_entry = {0};
|
||||
|
||||
typedef struct {
|
||||
int32_t size;
|
||||
uint32_t tracked_count;
|
||||
uint32_t max;
|
||||
i32 size;
|
||||
u32 tracked_count;
|
||||
u32 max;
|
||||
rptr32 file_table;
|
||||
} File_Track_Tables;
|
||||
|
||||
|
@ -50,13 +38,13 @@ typedef struct DLL_Node {
|
|||
|
||||
|
||||
|
||||
static File_Index
|
||||
internal File_Index
|
||||
zero_file_index(){
|
||||
File_Index a = {0};
|
||||
return(a);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
internal i32
|
||||
file_hash_is_zero(File_Index a){
|
||||
return ((a.id[0] == 0) &&
|
||||
(a.id[1] == 0) &&
|
||||
|
@ -64,7 +52,7 @@ file_hash_is_zero(File_Index a){
|
|||
(a.id[3] == 0));
|
||||
}
|
||||
|
||||
static int32_t
|
||||
internal i32
|
||||
file_hash_is_deleted(File_Index a){
|
||||
return ((a.id[0] == 0xFFFFFFFF) &&
|
||||
(a.id[1] == 0xFFFFFFFF) &&
|
||||
|
@ -72,7 +60,7 @@ file_hash_is_deleted(File_Index a){
|
|||
(a.id[3] == 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
static int32_t
|
||||
internal i32
|
||||
file_index_eq(File_Index a, File_Index b){
|
||||
return ((a.id[0] == b.id[0]) &&
|
||||
(a.id[1] == b.id[1]) &&
|
||||
|
@ -80,7 +68,7 @@ file_index_eq(File_Index a, File_Index b){
|
|||
(a.id[3] == b.id[3]));
|
||||
}
|
||||
|
||||
static void
|
||||
internal void
|
||||
insert_node(DLL_Node *pos, DLL_Node *node){
|
||||
node->prev = pos;
|
||||
node->next = pos->next;
|
||||
|
@ -88,19 +76,19 @@ insert_node(DLL_Node *pos, DLL_Node *node){
|
|||
node->next->prev = node;
|
||||
}
|
||||
|
||||
static void
|
||||
internal void
|
||||
remove_node(DLL_Node *node){
|
||||
node->next->prev = node->prev;
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
|
||||
static void
|
||||
internal void
|
||||
init_sentinel_node(DLL_Node *node){
|
||||
node->next = node;
|
||||
node->prev = node;
|
||||
}
|
||||
|
||||
static DLL_Node*
|
||||
internal DLL_Node*
|
||||
allocate_node(DLL_Node *sentinel){
|
||||
DLL_Node *result = 0;
|
||||
if (sentinel->next != sentinel){
|
||||
|
@ -113,17 +101,17 @@ allocate_node(DLL_Node *sentinel){
|
|||
#define FILE_ENTRY_COST (sizeof(File_Track_Entry))
|
||||
|
||||
|
||||
static int32_t
|
||||
tracking_system_has_space(File_Track_Tables *tables, int32_t new_count){
|
||||
uint32_t count = tables->tracked_count;
|
||||
uint32_t max = tables->max;
|
||||
int32_t result = ((count + new_count)*8 < max*7);
|
||||
internal i32
|
||||
tracking_system_has_space(File_Track_Tables *tables, i32 new_count){
|
||||
u32 count = tables->tracked_count;
|
||||
u32 max = tables->max;
|
||||
i32 result = ((count + new_count)*8 < max*7);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
internal i32
|
||||
entry_is_available(File_Track_Entry *entry){
|
||||
int32_t result = 0;
|
||||
i32 result = 0;
|
||||
if (entry){
|
||||
result =
|
||||
file_hash_is_zero(entry->hash) ||
|
||||
|
@ -132,12 +120,12 @@ entry_is_available(File_Track_Entry *entry){
|
|||
return (result);
|
||||
}
|
||||
|
||||
static File_Track_Entry*
|
||||
internal File_Track_Entry*
|
||||
tracking_system_lookup_entry(File_Track_Tables *tables, File_Index key){
|
||||
uint32_t hash = key.id[0];
|
||||
uint32_t max = tables->max;
|
||||
uint32_t index = (hash) % max;
|
||||
uint32_t start = index;
|
||||
u32 hash = key.id[0];
|
||||
u32 max = tables->max;
|
||||
u32 index = (hash) % max;
|
||||
u32 start = index;
|
||||
|
||||
File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table);
|
||||
|
||||
|
@ -169,7 +157,7 @@ tracking_system_lookup_entry(File_Track_Tables *tables, File_Index key){
|
|||
return(result);
|
||||
}
|
||||
|
||||
static File_Track_Entry*
|
||||
internal File_Track_Entry*
|
||||
get_file_entry(File_Track_Tables *tables, File_Index index){
|
||||
File_Track_Entry *entry = 0;
|
||||
|
||||
|
@ -181,11 +169,11 @@ get_file_entry(File_Track_Tables *tables, File_Index index){
|
|||
return(entry);
|
||||
}
|
||||
|
||||
static void
|
||||
internal void
|
||||
internal_free_slot(File_Track_Tables *tables, File_Track_Entry *entry){
|
||||
Assert(!entry_is_available(entry));
|
||||
|
||||
ZeroStruct(*entry);
|
||||
*entry = null_file_track_entry;
|
||||
entry->hash.id[0] = 0xFFFFFFFF;
|
||||
entry->hash.id[1] = 0xFFFFFFFF;
|
||||
entry->hash.id[2] = 0xFFFFFFFF;
|
||||
|
@ -194,27 +182,26 @@ internal_free_slot(File_Track_Tables *tables, File_Track_Entry *entry){
|
|||
--tables->tracked_count;
|
||||
}
|
||||
|
||||
static int32_t
|
||||
enough_memory_to_init_table(int32_t table_memory_size){
|
||||
int32_t result = (sizeof(File_Track_Tables) + FILE_ENTRY_COST*8 <= table_memory_size);
|
||||
internal i32
|
||||
enough_memory_to_init_table(i32 table_memory_size){
|
||||
i32 result = (sizeof(File_Track_Tables) + FILE_ENTRY_COST*8 <= table_memory_size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
static void
|
||||
init_table_memory(File_Track_Tables *tables, int32_t table_memory_size){
|
||||
internal void
|
||||
init_table_memory(File_Track_Tables *tables, i32 table_memory_size){
|
||||
tables->size = table_memory_size;
|
||||
tables->tracked_count = 0;
|
||||
|
||||
int32_t max_number_of_entries =
|
||||
(table_memory_size - sizeof(*tables)) / FILE_ENTRY_COST;
|
||||
i32 max_number_of_entries = (table_memory_size - sizeof(*tables)) / FILE_ENTRY_COST;
|
||||
|
||||
tables->file_table = sizeof(*tables);
|
||||
tables->max = max_number_of_entries;
|
||||
}
|
||||
|
||||
static File_Track_Result
|
||||
internal File_Track_Result
|
||||
move_table_memory(File_Track_Tables *original_tables,
|
||||
void *mem, int32_t size){
|
||||
void *mem, i32 size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
|
||||
if (original_tables->size < size){
|
||||
|
@ -224,24 +211,22 @@ move_table_memory(File_Track_Tables *original_tables,
|
|||
{
|
||||
tables->size = size;
|
||||
|
||||
int32_t likely_entry_size = FILE_ENTRY_COST;
|
||||
int32_t max_number_of_entries = (size - sizeof(*tables)) / likely_entry_size;
|
||||
i32 likely_entry_size = FILE_ENTRY_COST;
|
||||
i32 max_number_of_entries = (size - sizeof(*tables)) / likely_entry_size;
|
||||
|
||||
tables->file_table = sizeof(*tables);
|
||||
tables->max = max_number_of_entries;
|
||||
}
|
||||
|
||||
if (tables->max > original_tables->max){
|
||||
uint32_t original_max = original_tables->max;
|
||||
u32 original_max = original_tables->max;
|
||||
|
||||
// NOTE(allen): Rehash the tracking table
|
||||
{
|
||||
File_Track_Entry *entries = (File_Track_Entry*)
|
||||
to_ptr(original_tables, original_tables->file_table);
|
||||
|
||||
for (uint32_t index = 0;
|
||||
index < original_max;
|
||||
++index){
|
||||
for (u32 index = 0; index < original_max; ++index){
|
||||
File_Track_Entry *entry = entries + index;
|
||||
if (!entry_is_available(entry)){
|
||||
File_Index hash = entry->hash;
|
||||
|
@ -267,4 +252,5 @@ move_table_memory(File_Track_Tables *original_tables,
|
|||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
// BOTTOM
|
||||
|
File diff suppressed because it is too large
Load Diff
244
4ed_font_set.cpp
244
4ed_font_set.cpp
|
@ -1,244 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 18.12.2015
|
||||
*
|
||||
* Font set for 4coder
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
inline u32
|
||||
font_hash(String name){
|
||||
u32 x = 5381;
|
||||
char *p = name.str;
|
||||
for (i32 i = 0; i < name.size; ++i, ++p){
|
||||
x = ((x << 5) + x) ^ (*p);
|
||||
}
|
||||
return(x);
|
||||
}
|
||||
|
||||
inline void
|
||||
font__insert(Font_Slot *pos, Font_Slot *slot){
|
||||
Font_Slot *nex;
|
||||
nex = pos->next;
|
||||
|
||||
slot->next = nex;
|
||||
slot->prev = pos;
|
||||
nex->prev = slot;
|
||||
pos->next = slot;
|
||||
}
|
||||
|
||||
inline void
|
||||
font__remove(Font_Slot *slot){
|
||||
Font_Slot *n, *p;
|
||||
n = slot->next;
|
||||
p = slot->prev;
|
||||
|
||||
p->next = n;
|
||||
n->prev = p;
|
||||
}
|
||||
|
||||
inline Font_Slot
|
||||
font_slot_zero(){
|
||||
Font_Slot slot = {0};
|
||||
return(slot);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_init(Font_Set *set, Partition *partition, i32 max, i16 live_max){
|
||||
partition_align(partition, 8);
|
||||
set->info = push_array(partition, Font_Info, max);
|
||||
partition_align(partition, 8);
|
||||
set->entries = push_array(partition, Font_Table_Entry, max);
|
||||
set->count = 0;
|
||||
set->max = max;
|
||||
|
||||
partition_align(partition, 8);
|
||||
set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot)));
|
||||
|
||||
set->free_slots = font_slot_zero();
|
||||
set->used_slots = font_slot_zero();
|
||||
|
||||
dll_init_sentinel(&set->free_slots);
|
||||
dll_init_sentinel(&set->used_slots);
|
||||
|
||||
char *ptr = (char*)set->font_block;
|
||||
for (i32 i = 0; i < live_max; ++i){
|
||||
dll_insert(&set->free_slots, (Font_Slot*)ptr);
|
||||
ptr += sizeof(Font_Slot) + sizeof(Render_Font);
|
||||
}
|
||||
|
||||
set->font_used_flags = push_array(partition, b8, max);
|
||||
set->live_max = live_max;
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_can_add(Font_Set *set){
|
||||
b32 result = 0;
|
||||
if (set->count*8 < set->max*7) result = 1;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_add_hash(Font_Set *set, String name, i16 font_id){
|
||||
Font_Table_Entry entry;
|
||||
entry.hash = font_hash(name);
|
||||
entry.name = name;
|
||||
entry.font_id = font_id;
|
||||
|
||||
u32 i, j;
|
||||
i = entry.hash % set->max;
|
||||
j = i - 1;
|
||||
if (i <= 1) j += set->max;
|
||||
|
||||
for (; i != j; ++i){
|
||||
if (i == set->max) i = 0;
|
||||
if (set->entries[i].font_id == 0){
|
||||
set->entries[i] = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert(i != j);
|
||||
}
|
||||
|
||||
inline b32
|
||||
font_set_can_load(Font_Set *set){
|
||||
b32 result = (set->free_slots.next != &set->free_slots);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_load(Font_Set *set, i16 font_id){
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
Font_Slot *slot = set->free_slots.next;
|
||||
Assert(slot != &set->free_slots);
|
||||
font__remove(slot);
|
||||
font__insert(&set->used_slots, slot);
|
||||
|
||||
Render_Font *font = (Render_Font*)(slot + 1);
|
||||
set->font_load(font, info->filename.str, info->name.str, info->pt_size, 4, true);
|
||||
info->font = font;
|
||||
slot->font_id = font_id;
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_evict_lru(Font_Set *set){
|
||||
Font_Slot *slot = set->used_slots.prev;
|
||||
Assert(slot != &set->used_slots);
|
||||
|
||||
i16 font_id = slot->font_id;
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
Assert(((Font_Slot*)info->font) - 1 == slot);
|
||||
|
||||
set->release_font(info->font);
|
||||
|
||||
info->font = 0;
|
||||
slot->font_id = 0;
|
||||
font__remove(slot);
|
||||
font__insert(&set->free_slots, slot);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_use(Font_Set *set, i16 font_id){
|
||||
b8 already_used = set->font_used_flags[font_id-1];
|
||||
|
||||
if (!already_used){
|
||||
if (set->used_this_frame < set->live_max){
|
||||
++set->used_this_frame;
|
||||
set->font_used_flags[font_id-1] = 1;
|
||||
already_used = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (already_used){
|
||||
// TODO(allen): optimize if you don't mind!!!!
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
Font_Slot *slot;
|
||||
if (info->font == 0){
|
||||
if (!font_set_can_load(set)){
|
||||
font_set_evict_lru(set);
|
||||
}
|
||||
font_set_load(set, font_id);
|
||||
}
|
||||
slot = ((Font_Slot*)info->font) - 1;
|
||||
|
||||
font__remove(slot);
|
||||
font__insert(&set->used_slots, slot);
|
||||
}
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_add(Font_Set *set, String filename, String name, i32 pt_size){
|
||||
b32 result = 0;
|
||||
if (font_set_can_add(set)){
|
||||
Render_Font dummy_font = {0};
|
||||
i16 font_id = (i16)(++set->count);
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
info->filename = filename;
|
||||
info->name = name;
|
||||
info->pt_size = pt_size;
|
||||
set->font_load(&dummy_font, info->filename.str, info->name.str, info->pt_size, 4, false);
|
||||
//info->height = dummy_font.height;
|
||||
//info->advance = dummy_font.advance;
|
||||
|
||||
font_set_add_hash(set, name, font_id);
|
||||
|
||||
if (font_set_can_load(set)){
|
||||
font_set_load(set, font_id);
|
||||
}
|
||||
|
||||
result = 1;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_find_pos(Font_Set *set, String name, u32 *position){
|
||||
u32 hash = font_hash(name);
|
||||
u32 i = hash % set->max;
|
||||
u32 j = i - 1;
|
||||
if (j <= 1){
|
||||
j += set->max;
|
||||
}
|
||||
|
||||
b32 result = 0;
|
||||
for (; i != j; ++i){
|
||||
if (i == set->max){
|
||||
i = 0;
|
||||
}
|
||||
|
||||
Font_Table_Entry *entry = set->entries + i;
|
||||
if (entry->hash == hash){
|
||||
if (match_ss(name, entry->name)){
|
||||
result = 1;
|
||||
*position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_get_name(Font_Set *set, i16 font_id, String *name){
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
b32 result = copy_checked_ss(name, info->name);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_extract(Font_Set *set, String name, i16 *font_id){
|
||||
u32 position;
|
||||
b32 result = font_set_find_pos(set, name, &position);
|
||||
if (result){
|
||||
*font_id = set->entries[position].font_id;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -451,7 +451,7 @@ gui_do_color_button(GUI_Target *target, GUI_id id, u32 fore, u32 back, String te
|
|||
}
|
||||
|
||||
internal b32
|
||||
gui_do_font_button(GUI_Target *target, GUI_id id, i16 font_id, String text){
|
||||
gui_do_font_button(GUI_Target *target, GUI_id id, Font_ID font_id, String text){
|
||||
b32 result = 0;
|
||||
i32 font_id32 = font_id;
|
||||
GUI_Interactive *b = gui_push_button_command(target, guicom_font_button, id);
|
||||
|
|
47
4ed_math.h
47
4ed_math.h
|
@ -28,15 +28,15 @@ ABS(f32 x){
|
|||
|
||||
inline f32
|
||||
MOD(f32 x, i32 m){
|
||||
f32 whole, frac, r;
|
||||
frac = modff(x, &whole);
|
||||
r = ((i32)(whole) % m) + frac;
|
||||
f32 whole;
|
||||
f32 frac = modff(x, &whole);
|
||||
f32 r = ((i32)(whole) % m) + frac;
|
||||
return(r);
|
||||
}
|
||||
|
||||
inline f32
|
||||
SQRT(f32 x){
|
||||
f32 r = sqrt(x);
|
||||
f32 r = sqrtf(x);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
@ -431,18 +431,6 @@ unlerp(f32 a, f32 x, f32 b){
|
|||
return(r);
|
||||
}
|
||||
|
||||
inline f32
|
||||
clamp_bottom(f32 a, f32 n){
|
||||
if (n < a) n = a;
|
||||
return (n);
|
||||
}
|
||||
|
||||
inline f32
|
||||
clamp_top(f32 n, f32 z){
|
||||
if (n > z) n = z;
|
||||
return (n);
|
||||
}
|
||||
|
||||
inline f32
|
||||
clamp(f32 a, f32 n, f32 z){
|
||||
if (n < a) n = a;
|
||||
|
@ -450,18 +438,6 @@ clamp(f32 a, f32 n, f32 z){
|
|||
return (n);
|
||||
}
|
||||
|
||||
inline i32
|
||||
clamp_bottom(i32 a, i32 n){
|
||||
if (n < a) n = a;
|
||||
return (n);
|
||||
}
|
||||
|
||||
inline i32
|
||||
clamp_top(i32 n, i32 z){
|
||||
if (n > z) n = z;
|
||||
return (n);
|
||||
}
|
||||
|
||||
inline i32
|
||||
clamp(i32 a, i32 n, i32 z){
|
||||
if (n < a) n = a;
|
||||
|
@ -469,18 +445,6 @@ clamp(i32 a, i32 n, i32 z){
|
|||
return (n);
|
||||
}
|
||||
|
||||
inline u32
|
||||
clamp_bottom(u32 a, u32 n){
|
||||
if (n < a) n = a;
|
||||
return (n);
|
||||
}
|
||||
|
||||
inline u32
|
||||
clamp_top(u32 n, u32 z){
|
||||
if (n > z) n = z;
|
||||
return (n);
|
||||
}
|
||||
|
||||
inline u32
|
||||
clamp(u32 a, u32 n, u32 z){
|
||||
if (n < a) n = a;
|
||||
|
@ -488,6 +452,9 @@ clamp(u32 a, u32 n, u32 z){
|
|||
return (n);
|
||||
}
|
||||
|
||||
#define clamp_top(a,b) Min(a,b)
|
||||
#define clamp_bottom(a,b) Max(a,b)
|
||||
|
||||
/*
|
||||
* Color
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* Replacements for common memory block managing functions.
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 30.08.2016 (dd.mm.yyyy)
|
||||
* 30.08.2016
|
||||
*
|
||||
* Replacements for common memory block managing functions.
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
|
|
@ -12,54 +12,6 @@
|
|||
#ifndef FRED_RENDERING_H
|
||||
#define FRED_RENDERING_H
|
||||
|
||||
//
|
||||
// Fonts
|
||||
//
|
||||
|
||||
#include "file/4coder_font_data.h"
|
||||
|
||||
struct Font_Table_Entry{
|
||||
u32 hash;
|
||||
String name;
|
||||
i16 font_id;
|
||||
};
|
||||
|
||||
struct Font_Info{
|
||||
Render_Font *font;
|
||||
String filename;
|
||||
String name;
|
||||
i32 pt_size;
|
||||
};
|
||||
|
||||
struct Font_Slot{
|
||||
Font_Slot *next, *prev;
|
||||
i16 font_id;
|
||||
u8 padding[6];
|
||||
};
|
||||
|
||||
#define Font_Load_Sig(name) i32 name(Render_Font *font_out, char *filename, char *fontname, i32 pt_size, i32 tab_width, b32 store_texture)
|
||||
typedef Font_Load_Sig(Font_Load);
|
||||
|
||||
#define Release_Font_Sig(name) void name(Render_Font *font)
|
||||
typedef Release_Font_Sig(Release_Font);
|
||||
|
||||
struct Font_Set{
|
||||
Font_Info *info;
|
||||
Font_Table_Entry *entries;
|
||||
u32 count, max;
|
||||
|
||||
void *font_block;
|
||||
Font_Slot free_slots;
|
||||
Font_Slot used_slots;
|
||||
|
||||
Font_Load *font_load;
|
||||
Release_Font *release_font;
|
||||
|
||||
b8 *font_used_flags;
|
||||
i16 used_this_frame;
|
||||
i16 live_max;
|
||||
};
|
||||
|
||||
//
|
||||
// Render Commands
|
||||
//
|
||||
|
@ -92,16 +44,16 @@ struct Render_Piece_Gradient{
|
|||
struct Render_Piece_Glyph{
|
||||
Vec2 pos;
|
||||
u32 color;
|
||||
i16 font_id;
|
||||
u8 character;
|
||||
Font_ID font_id;
|
||||
u32 codepoint;
|
||||
};
|
||||
|
||||
struct Render_Piece_Glyph_Advance{
|
||||
Vec2 pos;
|
||||
u32 color;
|
||||
f32 advance;
|
||||
i16 font_id;
|
||||
u8 character;
|
||||
Font_ID font_id;
|
||||
u32 codepoint;
|
||||
};
|
||||
|
||||
struct Render_Piece_Change_Clip{
|
||||
|
@ -150,10 +102,6 @@ struct Render_Target{
|
|||
Draw_Push_Clip *push_clip;
|
||||
Draw_Pop_Clip *pop_clip;
|
||||
Draw_Push_Piece *push_piece;
|
||||
|
||||
// TODO(allen): Does the font set really belong here? Actually, do we still want it at all?
|
||||
Font_Set font_set;
|
||||
Partition *partition;
|
||||
};
|
||||
|
||||
#define DpiMultiplier(n,dpi) ((n) * (dpi) / 96)
|
||||
|
@ -168,12 +116,6 @@ rect_from_target(Render_Target *target){
|
|||
return(r);
|
||||
}
|
||||
|
||||
inline Font_Info*
|
||||
get_font_info(Font_Set *set, i16 font_id){
|
||||
Font_Info *result = set->info + font_id - 1;
|
||||
return(result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
|
@ -28,9 +28,6 @@ draw_change_clip(Render_Target *target, i32_Rect clip_box){
|
|||
|
||||
internal void
|
||||
begin_render_section(Render_Target *target, System_Functions *system){
|
||||
Font_Set *font_set = &target->font_set;
|
||||
font_set->used_this_frame = 0;
|
||||
memset(font_set->font_used_flags, 0, font_set->max);
|
||||
target->size = 0;
|
||||
target->clip_top = -1;
|
||||
|
||||
|
@ -116,38 +113,72 @@ font_predict_size(i32 pt_size){
|
|||
}
|
||||
|
||||
internal void
|
||||
font_draw_glyph(Render_Target *target, i16 font_id, i32 type, u8 character, f32 x, f32 y, u32 color){
|
||||
font_draw_glyph(Render_Target *target, Font_ID font_id, i32 type, u32 codepoint, f32 x, f32 y, u32 color){
|
||||
Render_Piece_Combined piece;
|
||||
piece.header.type = type;
|
||||
piece.glyph.pos.x = x;
|
||||
piece.glyph.pos.y = y;
|
||||
piece.glyph.color = color;
|
||||
piece.glyph.font_id = font_id;
|
||||
piece.glyph.character = character;
|
||||
piece.glyph.codepoint = codepoint;
|
||||
target->push_piece(target, piece);
|
||||
font_set_use(&target->font_set, font_id);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_draw_glyph(Render_Target *target, i16 font_id, u8 character, f32 x, f32 y, u32 color){
|
||||
font_draw_glyph(target, font_id, piece_type_glyph, character, x, y, color);
|
||||
font_draw_glyph(Render_Target *target, Font_ID font_id, u32 codepoint, f32 x, f32 y, u32 color){
|
||||
font_draw_glyph(target, font_id, piece_type_glyph, codepoint, x, y, color);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32 x_, i32 y_, u32 color){
|
||||
Font_Info *font_info = get_font_info(&target->font_set, font_id);
|
||||
Render_Font *font = font_info->font;
|
||||
draw_string_base(System_Functions *system, Render_Target *target, Font_ID font_id, i32 type, String str_, i32 x_, i32 y_, u32 color){
|
||||
f32 x = 0;
|
||||
|
||||
if (font){
|
||||
Render_Font *font = system->font.get_render_data_by_id(font_id);
|
||||
if (font != 0){
|
||||
f32 y = (f32)y_;
|
||||
x = (f32)x_;
|
||||
|
||||
f32 byte_advance = font->byte_advance;
|
||||
f32 byte_advance = font_get_byte_advance(font);
|
||||
f32 *sub_advances = font_get_byte_sub_advances(font);
|
||||
|
||||
u8 *str = (u8*)str_.str;
|
||||
u8 *str_end = str + str_.size;
|
||||
|
||||
Translation_State tran = {0};
|
||||
Translation_Emits emits = {0};
|
||||
|
||||
for (u32 i = 0; str < str_end; ++str, ++i){
|
||||
translating_fully_process_byte(system, font, &tran, *str, i, str_.size, &emits);
|
||||
|
||||
for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){
|
||||
TRANSLATION_DECL_GET_STEP(step, behavior, J, emits);
|
||||
|
||||
if (behavior.do_codepoint_advance){
|
||||
u32 codepoint = step.value;
|
||||
if (color != 0){
|
||||
font_draw_glyph(target, font_id, type, codepoint, x, y, color);
|
||||
}
|
||||
x += font_get_glyph_advance(system, font, codepoint);
|
||||
}
|
||||
else if (behavior.do_number_advance){
|
||||
u8 n = (u8)(step.value);
|
||||
if (color != 0){
|
||||
u8 cs[3];
|
||||
cs[0] = '\\';
|
||||
byte_to_ascii(n, cs+1);
|
||||
|
||||
f32 xx = x;
|
||||
for (u32 j = 0; j < 3; ++j){
|
||||
font_draw_glyph(target, font_id, type, cs[j], xx, y, color);
|
||||
xx += sub_advances[j];
|
||||
}
|
||||
}
|
||||
x += byte_advance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
for (;str < str_end;){
|
||||
u8 *byte = str;
|
||||
u32 codepoint = utf8_to_u32(&str, str_end);
|
||||
|
@ -170,7 +201,7 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32
|
|||
if (color != 0){
|
||||
font_draw_glyph(target, font_id, type, (u8)codepoint, x, y, color);
|
||||
}
|
||||
x += get_codepoint_advance(font, codepoint);
|
||||
x += font_get_glyph_advance(system, font, codepoint);
|
||||
}
|
||||
else if (do_numbers){
|
||||
for (;byte < str; ++byte){
|
||||
|
@ -180,10 +211,12 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32
|
|||
cs[0] = '\\';
|
||||
byte_to_ascii(n, cs+1);
|
||||
|
||||
f32 *advances = font_get_byte_sub_advances(font);
|
||||
|
||||
f32 xx = x;
|
||||
for (u32 j = 0; j < 3; ++j){
|
||||
font_draw_glyph(target, font_id, type, cs[j], xx, y, color);
|
||||
xx += byte_advance;
|
||||
xx += advances[j];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,47 +224,48 @@ draw_string_base(Render_Target *target, i16 font_id, i32 type, String str_, i32
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return(x);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string(Render_Target *target, i16 font_id, String str, i32 x, i32 y, u32 color){
|
||||
f32 w = draw_string_base(target, font_id, piece_type_glyph, str, x, y, color);
|
||||
draw_string(System_Functions *system, Render_Target *target, Font_ID font_id, String str, i32 x, i32 y, u32 color){
|
||||
f32 w = draw_string_base(system, target, font_id, piece_type_glyph, str, x, y, color);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string(Render_Target *target, i16 font_id, char *str, i32 x, i32 y, u32 color){
|
||||
draw_string(System_Functions *system, Render_Target *target, Font_ID font_id, char *str, i32 x, i32 y, u32 color){
|
||||
String string = make_string_slowly(str);
|
||||
f32 w = draw_string_base(target, font_id, piece_type_glyph, string, x, y, color);
|
||||
f32 w = draw_string_base(system, target, font_id, piece_type_glyph, string, x, y, color);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string_mono(Render_Target *target, i16 font_id, String str, i32 x, i32 y, f32 advance, u32 color){
|
||||
f32 w = draw_string_base(target, font_id, piece_type_mono_glyph, str, x, y, color);
|
||||
draw_string_mono(System_Functions *system, Render_Target *target, Font_ID font_id, String str, i32 x, i32 y, f32 advance, u32 color){
|
||||
f32 w = draw_string_base(system, target, font_id, piece_type_mono_glyph, str, x, y, color);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
draw_string_mono(Render_Target *target, i16 font_id, char *str, i32 x, i32 y, f32 advance, u32 color){
|
||||
draw_string_mono(System_Functions *system, Render_Target *target, Font_ID font_id, char *str, i32 x, i32 y, f32 advance, u32 color){
|
||||
String string = make_string_slowly(str);
|
||||
f32 w = draw_string_base(target, font_id, piece_type_mono_glyph, string, x, y, color);
|
||||
f32 w = draw_string_base(system, target, font_id, piece_type_mono_glyph, string, x, y, color);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
font_string_width(Render_Target *target, i16 font_id, String str){
|
||||
f32 w = draw_string_base(target, font_id, piece_type_glyph, str, 0, 0, 0);
|
||||
font_string_width(System_Functions *system, Render_Target *target, Font_ID font_id, String str){
|
||||
f32 w = draw_string_base(system, target, font_id, piece_type_glyph, str, 0, 0, 0);
|
||||
return(w);
|
||||
}
|
||||
|
||||
internal f32
|
||||
font_string_width(Render_Target *target, i16 font_id, char *str){
|
||||
font_string_width(System_Functions *system, Render_Target *target, Font_ID font_id, char *str){
|
||||
String string = make_string_slowly(str);
|
||||
f32 w = draw_string_base(target, font_id, piece_type_glyph, string, 0, 0, 0);
|
||||
f32 w = draw_string_base(system, target, font_id, piece_type_glyph, string, 0, 0, 0);
|
||||
return(w);
|
||||
}
|
||||
|
||||
|
|
BIN
4ed_site.ctm
BIN
4ed_site.ctm
Binary file not shown.
|
@ -10,7 +10,7 @@
|
|||
// TOP
|
||||
|
||||
struct Style_Font{
|
||||
i16 font_id;
|
||||
Font_ID font_id;
|
||||
};
|
||||
|
||||
struct Style{
|
||||
|
|
39
4ed_system.h
39
4ed_system.h
|
@ -9,33 +9,32 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_SYSTEM_INTERFACE_H)
|
||||
#define FCODER_SYSTEM_INTERFACE_H
|
||||
|
||||
#include "font/4coder_font_interface.h"
|
||||
|
||||
// types
|
||||
struct Plat_Handle{
|
||||
u32 d[4];
|
||||
};
|
||||
|
||||
static Plat_Handle null_plat_handle = {0};
|
||||
|
||||
inline int32_t
|
||||
inline b32
|
||||
handle_equal(Plat_Handle a, Plat_Handle b){
|
||||
int32_t result = (memcmp(&a, &b, sizeof(a)) == 0);
|
||||
b32 result = (memcmp(&a, &b, sizeof(a)) == 0);
|
||||
return(result);
|
||||
}
|
||||
|
||||
// files
|
||||
#define Sys_Set_File_List_Sig(name) void name(File_List *file_list, char *directory, char *canon_directory_out, u32 *canon_directory_size_out, u32 canon_directory_max)
|
||||
typedef Sys_Set_File_List_Sig(System_Set_File_List);
|
||||
|
||||
#define Sys_Get_Canonical_Sig(name) u32 name(char *filename, u32 len, char *buffer, u32 max)
|
||||
typedef Sys_Get_Canonical_Sig(System_Get_Canonical);
|
||||
|
||||
#define Sys_Add_Listener_Sig(name) b32 name(char *filename)
|
||||
typedef Sys_Add_Listener_Sig(System_Add_Listener);
|
||||
|
||||
#define Sys_Remove_Listener_Sig(name) b32 name(char *filename)
|
||||
typedef Sys_Remove_Listener_Sig(System_Remove_Listener);
|
||||
|
||||
#define Sys_Get_File_Change_Sig(name) i32 name(char *buffer, i32 max, b32 *mem_too_small, i32 *required_size)
|
||||
typedef Sys_Get_File_Change_Sig(System_Get_File_Change);
|
||||
|
||||
// file load/save
|
||||
#define Sys_Load_Handle_Sig(name) b32 name(char *filename, Plat_Handle *handle_out)
|
||||
typedef Sys_Load_Handle_Sig(System_Load_Handle);
|
||||
|
||||
|
@ -51,10 +50,21 @@ typedef Sys_Load_Close_Sig(System_Load_Close);
|
|||
#define Sys_Save_File_Sig(name) b32 name(char *filename, char *buffer, u32 size)
|
||||
typedef Sys_Save_File_Sig(System_Save_File);
|
||||
|
||||
// file changes
|
||||
#define Sys_Add_Listener_Sig(name) b32 name(char *filename)
|
||||
typedef Sys_Add_Listener_Sig(System_Add_Listener);
|
||||
|
||||
#define Sys_Remove_Listener_Sig(name) b32 name(char *filename)
|
||||
typedef Sys_Remove_Listener_Sig(System_Remove_Listener);
|
||||
|
||||
#define Sys_Get_File_Change_Sig(name) i32 name(char *buffer, i32 max, b32 *mem_too_small, i32 *required_size)
|
||||
typedef Sys_Get_File_Change_Sig(System_Get_File_Change);
|
||||
|
||||
// time
|
||||
#define Sys_Now_Time_Sig(name) u64 name()
|
||||
typedef Sys_Now_Time_Sig(System_Now_Time);
|
||||
|
||||
|
||||
// clipboard
|
||||
#define Sys_Post_Clipboard_Sig(name) void name(String str)
|
||||
typedef Sys_Post_Clipboard_Sig(System_Post_Clipboard);
|
||||
|
||||
|
@ -80,7 +90,6 @@ typedef Sys_CLI_Update_Step_Sig(System_CLI_Update_Step);
|
|||
typedef Sys_CLI_End_Update_Sig(System_CLI_End_Update);
|
||||
|
||||
// coroutine
|
||||
|
||||
#define Coroutine_Function_Sig(name) void name(struct Coroutine *coroutine)
|
||||
typedef Coroutine_Function_Sig(Coroutine_Function);
|
||||
|
||||
|
@ -230,6 +239,8 @@ typedef Sys_Send_Exit_Signal_Sig(System_Send_Exit_Signal);
|
|||
typedef INTERNAL_Sys_Get_Thread_States_Sig(INTERNAL_System_Get_Thread_States);
|
||||
|
||||
struct System_Functions{
|
||||
Font_Functions font;
|
||||
|
||||
// files (tracked api): 10
|
||||
System_Set_File_List *set_file_list;
|
||||
System_Get_Canonical *get_canonical;
|
||||
|
@ -284,5 +295,7 @@ struct System_Functions{
|
|||
INTERNAL_System_Get_Thread_States *internal_get_thread_states;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -9,9 +9,13 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_SYSTEM_SHARED_CPP)
|
||||
#define FCODER_SYSTEM_SHARED_CPP
|
||||
|
||||
#include "font/4coder_font_data.h"
|
||||
|
||||
//
|
||||
// Standard implementation of file system stuff
|
||||
// based on the file track layer.
|
||||
// Standard implementation of file system stuff based on the file track layer.
|
||||
//
|
||||
|
||||
struct Shared_Vars{
|
||||
|
@ -19,19 +23,25 @@ struct Shared_Vars{
|
|||
void *track_table;
|
||||
u32 track_table_size;
|
||||
u32 track_node_size;
|
||||
|
||||
Partition scratch;
|
||||
};
|
||||
|
||||
static Shared_Vars shared_vars;
|
||||
global Shared_Vars shared_vars;
|
||||
|
||||
internal void
|
||||
init_shared_vars(){
|
||||
shared_vars.track_table_size = (16 << 10);
|
||||
umem scratch_size = KB(128);
|
||||
void *scratch_memory = system_get_memory(scratch_size);
|
||||
shared_vars.scratch = make_part(scratch_memory, scratch_size);
|
||||
|
||||
shared_vars.track_table_size = KB(16);
|
||||
shared_vars.track_table = system_get_memory(shared_vars.track_table_size);
|
||||
|
||||
shared_vars.track_node_size = (16 << 10);
|
||||
shared_vars.track_node_size = KB(16);
|
||||
void *track_nodes = system_get_memory(shared_vars.track_node_size);
|
||||
|
||||
i32 track_result = init_track_system(&shared_vars.track, shared_vars.track_table, shared_vars.track_table_size, track_nodes, shared_vars.track_node_size);
|
||||
i32 track_result = init_track_system(&shared_vars.track, &shared_vars.scratch, shared_vars.track_table, shared_vars.track_table_size, track_nodes, shared_vars.track_node_size);
|
||||
|
||||
if (track_result != FileTrack_Good){
|
||||
exit(1);
|
||||
|
@ -47,7 +57,7 @@ handle_track_out_of_memory(i32 val){
|
|||
{
|
||||
u32 new_table_size = shared_vars.track_table_size*2;
|
||||
void *new_table = system_get_memory(new_table_size);
|
||||
move_track_system(&shared_vars.track, new_table, new_table_size);
|
||||
move_track_system(&shared_vars.track, &shared_vars.scratch, new_table, new_table_size);
|
||||
system_free_memory(shared_vars.track_table);
|
||||
shared_vars.track_table_size = new_table_size;
|
||||
shared_vars.track_table = new_table;
|
||||
|
@ -57,7 +67,7 @@ handle_track_out_of_memory(i32 val){
|
|||
{
|
||||
shared_vars.track_node_size *= 2;
|
||||
void *node_expansion = system_get_memory(shared_vars.track_node_size);
|
||||
expand_track_system_listeners(&shared_vars.track, node_expansion, shared_vars.track_node_size);
|
||||
expand_track_system_listeners(&shared_vars.track, &shared_vars.scratch, node_expansion, shared_vars.track_node_size);
|
||||
}break;
|
||||
|
||||
default: result = 1; break;
|
||||
|
@ -71,7 +81,7 @@ Sys_Add_Listener_Sig(system_add_listener){
|
|||
b32 result = 0;
|
||||
|
||||
for (;;){
|
||||
i32 track_result = add_listener(&shared_vars.track, filename);
|
||||
i32 track_result = add_listener(&shared_vars.track, &shared_vars.scratch, filename);
|
||||
if (handle_track_out_of_memory(track_result)){
|
||||
if (track_result == FileTrack_Good){
|
||||
result = 1;
|
||||
|
@ -86,7 +96,7 @@ Sys_Add_Listener_Sig(system_add_listener){
|
|||
internal
|
||||
Sys_Remove_Listener_Sig(system_remove_listener){
|
||||
i32 result = 0;
|
||||
i32 track_result = remove_listener(&shared_vars.track, filename);
|
||||
i32 track_result = remove_listener(&shared_vars.track, &shared_vars.scratch, filename);
|
||||
if (track_result == FileTrack_Good){
|
||||
result = 1;
|
||||
}
|
||||
|
@ -95,19 +105,19 @@ Sys_Remove_Listener_Sig(system_remove_listener){
|
|||
|
||||
internal
|
||||
Sys_Get_File_Change_Sig(system_get_file_change){
|
||||
i32 result = 0;
|
||||
b32 result = false;
|
||||
|
||||
i32 size = 0;
|
||||
i32 get_result = get_change_event(&shared_vars.track, buffer, max, &size);
|
||||
i32 get_result = get_change_event(&shared_vars.track, &shared_vars.scratch, buffer, max, &size);
|
||||
|
||||
*required_size = size;
|
||||
*mem_too_small = 0;
|
||||
*mem_too_small = false;
|
||||
if (get_result == FileTrack_Good){
|
||||
result = 1;
|
||||
result = true;
|
||||
}
|
||||
else if (get_result == FileTrack_MemoryTooSmall){
|
||||
*mem_too_small = 1;
|
||||
result = 1;
|
||||
*mem_too_small = true;
|
||||
result = true;
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
@ -182,8 +192,7 @@ internal void
|
|||
sysshared_partition_grow(Partition *part, i32 new_size){
|
||||
void *data = 0;
|
||||
if (new_size > part->max){
|
||||
// TODO(allen): attempt to grow in place by just
|
||||
// acquiring next vpages?!
|
||||
// TODO(allen): attempt to grow in place by just acquiring next vpages?!
|
||||
data = system_get_memory(new_size);
|
||||
memcpy(data, part->base, part->pos);
|
||||
system_free_memory(part->base);
|
||||
|
@ -218,7 +227,7 @@ sysshared_to_binary_path(String *out_filename, char *filename){
|
|||
translate_success = 1;
|
||||
}
|
||||
}
|
||||
return (translate_success);
|
||||
return(translate_success);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -421,9 +430,9 @@ get_exact_render_quad(Glyph_Bounds *b, i32 pw, i32 ph, float xpos, float ypos){
|
|||
}
|
||||
|
||||
inline void
|
||||
private_draw_glyph(Render_Target *target, Render_Font *font, u32 character, f32 x, f32 y, u32 color){
|
||||
Glyph_Data glyph = {0};
|
||||
if (get_codepoint_glyph_data(font, character, &glyph)){
|
||||
private_draw_glyph(System_Functions *system, Render_Target *target, Render_Font *font, u32 codepoint, f32 x, f32 y, u32 color){
|
||||
Glyph_Data glyph = font_get_glyph(system, font, codepoint);
|
||||
if (glyph.tex != 0){
|
||||
Render_Quad q = get_render_quad(&glyph.bounds, glyph.tex_width, glyph.tex_height, x, y);
|
||||
|
||||
draw_set_color(target, color);
|
||||
|
@ -440,9 +449,9 @@ private_draw_glyph(Render_Target *target, Render_Font *font, u32 character, f32
|
|||
}
|
||||
|
||||
inline void
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, f32 advance, u32 color){
|
||||
Glyph_Data glyph = {0};
|
||||
if (get_codepoint_glyph_data(font, character, &glyph)){
|
||||
private_draw_glyph_mono(System_Functions *system, Render_Target *target, Render_Font *font, u32 codepoint, f32 x, f32 y, f32 advance, u32 color){
|
||||
Glyph_Data glyph = font_get_glyph(system, font, codepoint);
|
||||
if (glyph.tex != 0){
|
||||
f32 left = glyph.bounds.x0;
|
||||
f32 right = glyph.bounds.x1;
|
||||
f32 width = (right - left);
|
||||
|
@ -466,12 +475,13 @@ private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character,
|
|||
}
|
||||
|
||||
inline void
|
||||
private_draw_glyph_mono(Render_Target *target, Render_Font *font, u8 character, f32 x, f32 y, u32 color){
|
||||
private_draw_glyph_mono(target, font, character, x, y, (f32)font->advance, color);
|
||||
private_draw_glyph_mono(System_Functions *system, Render_Target *target, Render_Font *font, u32 character, f32 x, f32 y, u32 color){
|
||||
f32 advance = (f32)font_get_advance(font);
|
||||
private_draw_glyph_mono(system, target, font, character, x, y, advance, color);
|
||||
}
|
||||
|
||||
internal void
|
||||
launch_rendering(Render_Target *target){
|
||||
launch_rendering(System_Functions *system, Render_Target *target){
|
||||
char *cursor = target->push_buffer;
|
||||
char *cursor_end = cursor + target->size;
|
||||
|
||||
|
@ -502,36 +512,32 @@ launch_rendering(Render_Target *target){
|
|||
{
|
||||
Render_Piece_Glyph *glyph = ExtractStruct(Render_Piece_Glyph);
|
||||
|
||||
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
|
||||
if (font){
|
||||
private_draw_glyph(target, font, glyph->character, glyph->pos.x, glyph->pos.y, glyph->color);
|
||||
}
|
||||
Render_Font *font = system->font.get_render_data_by_id(glyph->font_id);
|
||||
Assert(font != 0);
|
||||
private_draw_glyph(system, target, font, glyph->codepoint, glyph->pos.x, glyph->pos.y, glyph->color);
|
||||
}break;
|
||||
|
||||
case piece_type_mono_glyph:
|
||||
{
|
||||
Render_Piece_Glyph *glyph = ExtractStruct(Render_Piece_Glyph);
|
||||
|
||||
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
|
||||
if (font){
|
||||
private_draw_glyph_mono(target, font, glyph->character, glyph->pos.x, glyph->pos.y, glyph->color);
|
||||
}
|
||||
Render_Font *font = system->font.get_render_data_by_id(glyph->font_id);
|
||||
Assert(font != 0);
|
||||
private_draw_glyph_mono(system, target, font, glyph->codepoint, glyph->pos.x, glyph->pos.y, glyph->color);
|
||||
}break;
|
||||
|
||||
case piece_type_mono_glyph_advance:
|
||||
{
|
||||
Render_Piece_Glyph_Advance *glyph = ExtractStruct(Render_Piece_Glyph_Advance);
|
||||
|
||||
Render_Font *font = get_font_info(&target->font_set, glyph->font_id)->font;
|
||||
if (font){
|
||||
private_draw_glyph_mono(target, font, glyph->character, glyph->pos.x, glyph->pos.y, glyph->advance, glyph->color);
|
||||
}
|
||||
Render_Font *font = system->font.get_render_data_by_id(glyph->font_id);
|
||||
Assert(font != 0);
|
||||
private_draw_glyph_mono(system, target, font, glyph->codepoint, glyph->pos.x, glyph->pos.y, glyph->advance, glyph->color);
|
||||
}break;
|
||||
|
||||
case piece_type_change_clip:
|
||||
{
|
||||
Render_Piece_Change_Clip *clip =
|
||||
ExtractStruct(Render_Piece_Change_Clip);
|
||||
Render_Piece_Change_Clip *clip = ExtractStruct(Render_Piece_Change_Clip);
|
||||
draw_set_clip(target, clip->box);
|
||||
}break;
|
||||
}
|
||||
|
@ -545,77 +551,28 @@ launch_rendering(Render_Target *target){
|
|||
#undef internal
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_LCD_FILTER_H
|
||||
#define internal static
|
||||
|
||||
internal u32
|
||||
next_pow_of_2(u32 v){
|
||||
--v;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
return ++v;
|
||||
}
|
||||
|
||||
#define NUM_GLYPHS 256
|
||||
#define ENABLE_LCD_FILTER 0
|
||||
|
||||
internal b32
|
||||
font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size, i32 tab_width, b32 use_hinting){
|
||||
|
||||
memset(rf, 0, sizeof(*rf));
|
||||
|
||||
//TODO(inso): put stuff in linuxvars / init in main
|
||||
FT_Library ft;
|
||||
FT_Face face;
|
||||
b32 use_lcd_filter = 0;
|
||||
|
||||
FT_Init_FreeType(&ft);
|
||||
|
||||
//NOTE(inso): i'm not sure the LCD filter looks better, and it doesn't work perfectly with the coloring stuff
|
||||
// it will probably need shaders to work properly
|
||||
#if ENABLE_LCD_FILTER
|
||||
if(FT_Library_SetLcdFilter(ft, FT_LCD_FILTER_DEFAULT) == 0){
|
||||
puts("LCD Filter on");
|
||||
use_lcd_filter = 1;
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
#endif
|
||||
|
||||
FT_New_Face(ft, filename, 0, &face);
|
||||
|
||||
// set size & metrics
|
||||
FT_Size_RequestRec_ size = {};
|
||||
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
|
||||
size.height = pt_size << 6;
|
||||
FT_Request_Size(face, &size);
|
||||
|
||||
rf->loaded = 1;
|
||||
rf->ascent = ceil32 (face->size->metrics.ascender / 64.0f);
|
||||
rf->descent = floor32 (face->size->metrics.descender / 64.0f);
|
||||
rf->advance = ceil32 (face->size->metrics.max_advance / 64.0f);
|
||||
rf->height = ceil32 (face->size->metrics.height / 64.0f);
|
||||
rf->line_skip = rf->height - (rf->ascent - rf->descent);
|
||||
|
||||
rf->height -= rf->line_skip;
|
||||
rf->line_skip = 0;
|
||||
internal void
|
||||
font_load_page_inner(Partition *part, Render_Font *font, FT_Library ft, FT_Face face, b32 use_hinting, Glyph_Page *page, u32 page_number, i32 tab_width){
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
Assert(page != 0);
|
||||
page->page_number = page_number;
|
||||
|
||||
// prepare to read glyphs into a temporary texture buffer
|
||||
i32 max_glyph_w = face->size->metrics.x_ppem;
|
||||
i32 max_glyph_h = rf->height;
|
||||
i32 max_glyph_h = font_get_height(font);
|
||||
i32 tex_width = 64;
|
||||
i32 tex_height = 0;
|
||||
|
||||
// estimate upper bound on texture width
|
||||
do {
|
||||
tex_width *= 2;
|
||||
float glyphs_per_row = ceilf(tex_width / (float) max_glyph_w);
|
||||
float rows = ceilf(NUM_GLYPHS / glyphs_per_row);
|
||||
float rows = ceilf(ITEM_PER_FONT_PAGE / glyphs_per_row);
|
||||
tex_height = ceil32(rows * (max_glyph_h + 2));
|
||||
} while(tex_height > tex_width);
|
||||
|
||||
tex_height = next_pow_of_2(tex_height);
|
||||
tex_height = round_up_pot_u32(tex_height);
|
||||
|
||||
i32 pen_x = 0;
|
||||
i32 pen_y = 0;
|
||||
|
@ -623,132 +580,75 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
|
|||
u32* pixels = push_array(part, u32, tex_width * tex_height);
|
||||
memset(pixels, 0, tex_width * tex_height * sizeof(u32));
|
||||
|
||||
u32 ft_extra_flags = 0;
|
||||
if (use_lcd_filter){
|
||||
ft_extra_flags = FT_LOAD_TARGET_LCD;
|
||||
u32 ft_flags = FT_LOAD_RENDER;
|
||||
if (use_hinting){
|
||||
// NOTE(inso): FT_LOAD_TARGET_LIGHT does hinting only vertically, which looks nicer imo
|
||||
// maybe it could be exposed as an option for hinting, instead of just on/off.
|
||||
ft_flags |= FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT;
|
||||
}
|
||||
else{
|
||||
if (use_hinting){
|
||||
// NOTE(inso): FT_LOAD_TARGET_LIGHT does hinting only vertically, which looks nicer imo
|
||||
// maybe it could be exposed as an option for hinting, instead of just on/off.
|
||||
ft_extra_flags = FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT;
|
||||
}
|
||||
else{
|
||||
ft_extra_flags = (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
||||
}
|
||||
ft_flags |= (FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
|
||||
}
|
||||
|
||||
for(i32 i = 0; i < NUM_GLYPHS; ++i){
|
||||
if(FT_Load_Char(face, i, FT_LOAD_RENDER | ft_extra_flags) != 0) continue;
|
||||
// fill the texture
|
||||
u32 base_codepoint = (page_number << 8);
|
||||
Glyph_Bounds *glyphs = &page->glyphs[0];
|
||||
Glyph_Bounds *glyph_ptr = glyphs;
|
||||
|
||||
f32 *advances = &page->advance[0];
|
||||
f32 *advance_ptr = advances;
|
||||
for(u32 i = 0; i < ITEM_PER_FONT_PAGE; ++i, ++glyph_ptr, ++advance_ptr){
|
||||
u32 codepoint = i + base_codepoint;
|
||||
|
||||
i32 w = face->glyph->bitmap.width;
|
||||
i32 h = face->glyph->bitmap.rows;
|
||||
|
||||
// lcd filter produces RGB bitmaps, need to account for the extra components
|
||||
if(use_lcd_filter){
|
||||
w /= 3;
|
||||
}
|
||||
|
||||
// move to next line if necessary
|
||||
if(pen_x + w >= tex_width){
|
||||
pen_x = 0;
|
||||
pen_y += (max_glyph_h + 2);
|
||||
}
|
||||
|
||||
// set all this stuff the renderer needs
|
||||
Glyph_Bounds* c = 0;
|
||||
f32 *advance_ptr = 0;
|
||||
get_codepoint_memory(rf, i, &c, &advance_ptr);
|
||||
if (c != 0 && advance_ptr != 0){
|
||||
c->exists = true;
|
||||
if(FT_Load_Char(face, codepoint, ft_flags) == 0){
|
||||
i32 w = face->glyph->bitmap.width;
|
||||
i32 h = face->glyph->bitmap.rows;
|
||||
|
||||
c->x0 = (f32)(pen_x);
|
||||
c->y0 = (f32)(pen_y);
|
||||
c->x1 = (f32)(pen_x + w);
|
||||
c->y1 = (f32)(pen_y + h + 1);
|
||||
i32 ascent = font_get_ascent(font);
|
||||
|
||||
c->xoff = (f32)(face->glyph->bitmap_left);
|
||||
c->yoff = (f32)(rf->ascent - face->glyph->bitmap_top);
|
||||
// move to next line if necessary
|
||||
if(pen_x + w >= tex_width){
|
||||
pen_x = 0;
|
||||
pen_y += (max_glyph_h + 2);
|
||||
}
|
||||
|
||||
c->xoff2 = w + c->xoff;
|
||||
c->yoff2 = h + c->yoff + 1;
|
||||
// set all this stuff the renderer needs
|
||||
glyph_ptr->x0 = (f32)(pen_x);
|
||||
glyph_ptr->y0 = (f32)(pen_y);
|
||||
glyph_ptr->x1 = (f32)(pen_x + w);
|
||||
glyph_ptr->y1 = (f32)(pen_y + h + 1);
|
||||
|
||||
// TODO(allen): maybe advance data should be integers for a while...
|
||||
// I require the actual values to be integers anyway... hmm...
|
||||
f32 advance = (f32)ceil32(face->glyph->advance.x / 64.0f);
|
||||
*advance_ptr = advance;
|
||||
glyph_ptr->xoff = (f32)(face->glyph->bitmap_left);
|
||||
glyph_ptr->yoff = (f32)(ascent - face->glyph->bitmap_top);
|
||||
glyph_ptr->xoff2 = glyph_ptr->xoff + w;
|
||||
glyph_ptr->yoff2 = glyph_ptr->yoff + h + 1;
|
||||
|
||||
// TODO(allen): maybe advance data should be integers?
|
||||
*advance_ptr = (f32)ceil32(face->glyph->advance.x / 64.0f);
|
||||
|
||||
// write to texture atlas
|
||||
i32 pitch = face->glyph->bitmap.pitch;
|
||||
for(i32 j = 0; j < h; ++j){
|
||||
for(i32 i = 0; i < w; ++i){
|
||||
i32 x = pen_x + i;
|
||||
i32 y = pen_y + j;
|
||||
for(i32 Y = 0; Y < h; ++Y){
|
||||
for(i32 X = 0; X < w; ++X){
|
||||
i32 x = pen_x + X;
|
||||
i32 y = pen_y + Y;
|
||||
|
||||
if(use_lcd_filter){
|
||||
#if 1
|
||||
u8 a = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1];
|
||||
u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3 + 0];
|
||||
u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2];
|
||||
|
||||
pixels[y * tex_width + x] = (a << 24) | (b << 16) | (a << 8) | r;
|
||||
|
||||
#else
|
||||
|
||||
u8 r = face->glyph->bitmap.buffer[j * pitch + i * 3];
|
||||
u8 g = face->glyph->bitmap.buffer[j * pitch + i * 3 + 1];
|
||||
u8 b = face->glyph->bitmap.buffer[j * pitch + i * 3 + 2];
|
||||
u8 a = (u8)ROUND32((r + g + b) / 3.0f);
|
||||
|
||||
pixels[y * tex_width + x] = (a << 24) | (r << 16) | (g << 8) | b;
|
||||
#endif
|
||||
} else {
|
||||
pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101;
|
||||
}
|
||||
pixels[y * tex_width + x] = face->glyph->bitmap.buffer[Y * pitch + X] * 0x01010101;
|
||||
}
|
||||
}
|
||||
|
||||
pen_x = ceil32(c->x1 + 1);
|
||||
pen_x = ceil32(glyph_ptr->x1 + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(allen): Setup some basic spacing stuff.
|
||||
f32 space_adv = get_codepoint_advance(rf, ' ');
|
||||
f32 backslash_adv = get_codepoint_advance(rf, '\\');
|
||||
f32 r_adv = get_codepoint_advance(rf, 'r');
|
||||
|
||||
set_codepoint_advance(rf, '\n', space_adv);
|
||||
set_codepoint_advance(rf, '\r', backslash_adv + r_adv);
|
||||
set_codepoint_advance(rf, '\t', space_adv*tab_width);
|
||||
|
||||
f32 max_hex_advance = 0.f;
|
||||
for (u32 i = '0'; i <= '9'; ++i){
|
||||
f32 adv = get_codepoint_advance(rf, i);
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
for (u32 i = 'a'; i <= 'f'; ++i){
|
||||
f32 adv = get_codepoint_advance(rf, i);
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
for (u32 i = 'A'; i <= 'F'; ++i){
|
||||
f32 adv = get_codepoint_advance(rf, i);
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
|
||||
rf->byte_advance = backslash_adv + max_hex_advance*2;
|
||||
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
tex_height = next_pow_of_2(pen_y + max_glyph_h + 2);
|
||||
|
||||
u32 page_index = 0;
|
||||
rf->glyph_pages[page_index].tex_width = tex_width;
|
||||
rf->glyph_pages[page_index].tex_height = tex_height;
|
||||
|
||||
// upload texture
|
||||
u32 tex;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
tex_height = round_up_pot_u32(pen_y + max_glyph_h + 2);
|
||||
|
||||
page->tex_width = tex_width;
|
||||
page->tex_height = tex_height;
|
||||
|
||||
glGenTextures(1, &page->tex);
|
||||
glBindTexture(GL_TEXTURE_2D, page->tex);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
@ -756,30 +656,154 @@ font_load_freetype(Partition *part, Render_Font *rf, char *filename, i32 pt_size
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
|
||||
if(use_lcd_filter){
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels);
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0, GL_ALPHA, GL_UNSIGNED_INT, pixels);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
rf->glyph_pages[page_index].tex = tex;
|
||||
|
||||
rf->glyph_pages[page_index].exists = true;
|
||||
end_temp_memory(temp);
|
||||
|
||||
// whitespace spacing stuff
|
||||
if (page_number == 0){
|
||||
f32 space_adv = advances[' '];
|
||||
f32 backslash_adv = advances['\\'];
|
||||
f32 r_adv = advances['r'];
|
||||
|
||||
advances['\n'] = space_adv;
|
||||
advances['\r'] = backslash_adv + r_adv;
|
||||
advances['\t'] = space_adv*tab_width;
|
||||
}
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_load_page(System_Functions *system, Partition *part, Render_Font *font, Glyph_Page *page, u32 page_number, u32 pt_size, b32 use_hinting){
|
||||
|
||||
char *filename = font->filename;
|
||||
|
||||
// TODO(allen): Stop redoing all this init for each call.
|
||||
FT_Library ft;
|
||||
FT_Init_FreeType(&ft);
|
||||
|
||||
FT_Face face;
|
||||
FT_New_Face(ft, filename, 0, &face);
|
||||
|
||||
FT_Size_RequestRec_ size = {};
|
||||
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
|
||||
size.height = pt_size << 6;
|
||||
FT_Request_Size(face, &size);
|
||||
|
||||
// NOTE(allen): set texture and glyph data.
|
||||
font_load_page_inner(part, font, ft, face, use_hinting, page, page_number, 4);
|
||||
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
internal
|
||||
Release_Font_Sig(draw_release_font){
|
||||
for (u32 i = 0; i < ArrayCount(font->glyph_pages); ++i){
|
||||
Glyph_Page *page = &font->glyph_pages[i];
|
||||
if (page->exists){
|
||||
glDeleteTextures(1, &page->tex);
|
||||
internal b32
|
||||
font_load(System_Functions *system, Partition *part, Render_Font *font, i32 pt_size, b32 use_hinting){
|
||||
|
||||
char *filename = font->filename;
|
||||
|
||||
// TODO(allen): Stop redoing all this init for each call.
|
||||
FT_Library ft;
|
||||
FT_Init_FreeType(&ft);
|
||||
|
||||
FT_Face face;
|
||||
FT_New_Face(ft, filename, 0, &face);
|
||||
|
||||
FT_Size_RequestRec_ size = {};
|
||||
size.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
|
||||
size.height = pt_size << 6;
|
||||
FT_Request_Size(face, &size);
|
||||
|
||||
// set size & metrics
|
||||
font->ascent = ceil32 (face->size->metrics.ascender / 64.0f);
|
||||
font->descent = floor32 (face->size->metrics.descender / 64.0f);
|
||||
font->advance = ceil32 (face->size->metrics.max_advance / 64.0f);
|
||||
font->height = ceil32 (face->size->metrics.height / 64.0f);
|
||||
font->line_skip = font->height - (font->ascent - font->descent);
|
||||
|
||||
font->height -= font->line_skip;
|
||||
font->line_skip = 0;
|
||||
|
||||
// NOTE(allen): set texture and glyph data.
|
||||
Glyph_Page *page = font_get_or_make_page(system, font, 0);
|
||||
|
||||
// NOTE(allen): Setup some basic spacing stuff.
|
||||
f32 backslash_adv = page->advance['\\'];
|
||||
f32 max_hex_advance = 0.f;
|
||||
for (u32 i = '0'; i <= '9'; ++i){
|
||||
f32 adv = page->advance[i];
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
for (u32 i = 'a'; i <= 'f'; ++i){
|
||||
f32 adv = page->advance[i];
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
for (u32 i = 'A'; i <= 'F'; ++i){
|
||||
f32 adv = page->advance[i];
|
||||
max_hex_advance = Max(max_hex_advance, adv);
|
||||
}
|
||||
|
||||
font->byte_advance = backslash_adv + max_hex_advance*2;
|
||||
font->byte_sub_advances[0] = backslash_adv;
|
||||
font->byte_sub_advances[1] = max_hex_advance;
|
||||
font->byte_sub_advances[2] = max_hex_advance;
|
||||
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
internal void
|
||||
system_set_page(System_Functions *system, Partition *part, Render_Font *font, Glyph_Page *page, u32 page_number, u32 pt_size, b32 use_hinting){
|
||||
memset(page, 0, sizeof(*page));
|
||||
|
||||
if (part->base == 0){
|
||||
*part = sysshared_scratch_partition(MB(8));
|
||||
}
|
||||
|
||||
b32 success = false;
|
||||
for (u32 R = 0; R < 3; ++R){
|
||||
success = font_load_page(system, part, font, page, page_number, pt_size, use_hinting);
|
||||
if (success){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
sysshared_partition_double(part);
|
||||
}
|
||||
page->tex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
system_set_font(System_Functions *system, Partition *part, Render_Font *font, String filename, String name, u32 pt_size, b32 use_hinting){
|
||||
memset(font, 0, sizeof(*font));
|
||||
|
||||
copy_partial_cs(font->filename, sizeof(font->filename)-1, filename);
|
||||
font->filename_len = filename.size;
|
||||
font->filename[font->filename_len] = 0;
|
||||
copy_partial_cs(font->name, sizeof(font->name)-1, name);
|
||||
font->name_len = name.size;
|
||||
font->name[font->name_len] = 0;
|
||||
|
||||
if (part->base == 0){
|
||||
*part = sysshared_scratch_partition(MB(8));
|
||||
}
|
||||
|
||||
b32 success = false;
|
||||
for (u32 R = 0; R < 3; ++R){
|
||||
success = font_load(system, part, font, pt_size, use_hinting);
|
||||
if (success){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
sysshared_partition_double(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
// the application code, but system_shared.cpp
|
||||
// rely on the functions listed here.
|
||||
|
||||
#if !defined(FRED_SYSTEM_SHARED_H)
|
||||
#define FRED_SYSTEM_SHARED_H
|
||||
|
||||
struct File_Data{
|
||||
char *data;
|
||||
u32 size;
|
||||
|
@ -33,5 +36,7 @@ internal Sys_Get_Binary_Path_Sig(system_get_binary_path);
|
|||
|
||||
#define system_get_memory(size) system_get_memory_((size), __LINE__, __FILE__)
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -0,0 +1,244 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 11.03.2017
|
||||
*
|
||||
* Translation system for turning byte streams into a stream of buffer model steps.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "4ed_buffer_model.h"
|
||||
|
||||
struct Translation_State{
|
||||
u8 fill_buffer[4];
|
||||
u32 fill_start_i;
|
||||
u8 fill_i;
|
||||
u8 fill_expected;
|
||||
};
|
||||
global_const Translation_State null_buffer_translating_state = {0};
|
||||
|
||||
enum{
|
||||
TranLBH_None,
|
||||
TranLBH_Rebuffer,
|
||||
TranLBH_EmitAsCP,
|
||||
};
|
||||
struct Translation_Byte_Description{
|
||||
u8 byte_class;
|
||||
u8 last_byte_handler;
|
||||
u8 prelim_emit_type;
|
||||
};
|
||||
|
||||
struct Translation_Emit_Rule{
|
||||
u8 byte_class;
|
||||
u8 last_byte_handler;
|
||||
u8 emit_type;
|
||||
|
||||
u32 codepoint;
|
||||
u32 codepoint_length;
|
||||
};
|
||||
|
||||
struct Translation_Emits{
|
||||
Buffer_Model_Step steps[5];
|
||||
u32 step_count;
|
||||
};
|
||||
|
||||
#define SINGLE_BYTE_ERROR_CLASS max_u8
|
||||
|
||||
internal void
|
||||
translating_consume_byte(Translation_State *tran, u8 ch, u32 i, u32 size, Translation_Byte_Description *desc_out){
|
||||
desc_out->byte_class = 0;
|
||||
if ((ch >= ' ' && ch < 0x7F) || ch == '\t' || ch == '\n' || ch == '\r'){
|
||||
desc_out->byte_class = 1;
|
||||
}
|
||||
else if (ch < 0xC0){
|
||||
desc_out->byte_class = SINGLE_BYTE_ERROR_CLASS;
|
||||
}
|
||||
else if (ch < 0xE0){
|
||||
desc_out->byte_class = 2;
|
||||
}
|
||||
else if (ch < 0xF0){
|
||||
desc_out->byte_class = 3;
|
||||
}
|
||||
else{
|
||||
desc_out->byte_class = 4;
|
||||
}
|
||||
|
||||
desc_out->prelim_emit_type = BufferModelUnit_None;
|
||||
desc_out->last_byte_handler = TranLBH_None;
|
||||
if (tran->fill_expected == 0){
|
||||
tran->fill_buffer[0] = ch;
|
||||
tran->fill_start_i = i;
|
||||
tran->fill_i = 1;
|
||||
|
||||
if (desc_out->byte_class == 1){
|
||||
desc_out->prelim_emit_type = BufferModelUnit_Codepoint;
|
||||
}
|
||||
else if (desc_out->byte_class == 0 || desc_out->byte_class == SINGLE_BYTE_ERROR_CLASS){
|
||||
desc_out->prelim_emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
else{
|
||||
tran->fill_expected = desc_out->byte_class;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (desc_out->byte_class == SINGLE_BYTE_ERROR_CLASS){
|
||||
tran->fill_buffer[tran->fill_i] = ch;
|
||||
++tran->fill_i;
|
||||
|
||||
if (tran->fill_i == tran->fill_expected){
|
||||
desc_out->prelim_emit_type = BufferModelUnit_Codepoint;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (desc_out->byte_class >= 2 && desc_out->byte_class <= 4){
|
||||
desc_out->last_byte_handler = TranLBH_Rebuffer;
|
||||
}
|
||||
else if (desc_out->byte_class == 1){
|
||||
desc_out->last_byte_handler = TranLBH_EmitAsCP;
|
||||
}
|
||||
else{
|
||||
tran->fill_buffer[tran->fill_i] = ch;
|
||||
++tran->fill_i;
|
||||
}
|
||||
desc_out->prelim_emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc_out->prelim_emit_type == BufferModelUnit_None && i+1 == size){
|
||||
desc_out->prelim_emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
translating_select_emit_rule_ASCII(Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){
|
||||
type_out->byte_class = desc.byte_class;
|
||||
type_out->last_byte_handler = desc.last_byte_handler;
|
||||
type_out->emit_type = desc.prelim_emit_type;
|
||||
|
||||
type_out->codepoint = 0;
|
||||
type_out->codepoint_length = 0;
|
||||
if (desc.prelim_emit_type == BufferModelUnit_Codepoint){
|
||||
u32 cp = utf8_to_u32_length_unchecked(tran->fill_buffer, &type_out->codepoint_length);
|
||||
type_out->codepoint = cp;
|
||||
if (!(cp == '\n' || cp == '\t' || cp == '\r' || (cp >= ' ' && cp <= 255 && cp != 127))){
|
||||
type_out->emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
translating_select_emit_rule_with_font(System_Functions *system, Render_Font *font, Translation_State *tran, Translation_Byte_Description desc, Translation_Emit_Rule *type_out){
|
||||
type_out->byte_class = desc.byte_class;
|
||||
type_out->last_byte_handler = desc.last_byte_handler;
|
||||
type_out->emit_type = desc.prelim_emit_type;
|
||||
|
||||
type_out->codepoint = 0;
|
||||
type_out->codepoint_length = 0;
|
||||
if (desc.prelim_emit_type == BufferModelUnit_Codepoint){
|
||||
u32 cp = utf8_to_u32_length_unchecked(tran->fill_buffer, &type_out->codepoint_length);
|
||||
type_out->codepoint = cp;
|
||||
if (!font_can_render(system, font, cp)){
|
||||
type_out->emit_type = BufferModelUnit_Numbers;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
translating_generate_emits(Translation_State *tran, Translation_Emit_Rule emit_rule, u8 ch, u32 i, Translation_Emits *emits_out){
|
||||
emits_out->step_count = 0;
|
||||
switch (emit_rule.emit_type){
|
||||
default: goto skip_all;
|
||||
|
||||
case BufferModelUnit_Codepoint:
|
||||
{
|
||||
emits_out->steps[0].type = 1;
|
||||
emits_out->steps[0].value = emit_rule.codepoint;
|
||||
emits_out->steps[0].i = tran->fill_start_i;
|
||||
emits_out->steps[0].byte_length = emit_rule.codepoint_length;
|
||||
emits_out->step_count = 1;
|
||||
}break;
|
||||
|
||||
case BufferModelUnit_Numbers:
|
||||
{
|
||||
for (u32 j = 0; j < tran->fill_i; ++j){
|
||||
emits_out->steps[j].type = 0;
|
||||
emits_out->steps[j].value = tran->fill_buffer[j];
|
||||
emits_out->steps[j].i = tran->fill_start_i + j;
|
||||
emits_out->steps[j].byte_length = 1;
|
||||
}
|
||||
emits_out->step_count = tran->fill_i;
|
||||
}break;
|
||||
}
|
||||
|
||||
tran->fill_start_i = 0;
|
||||
tran->fill_i = 0;
|
||||
tran->fill_expected = 0;
|
||||
|
||||
switch (emit_rule.last_byte_handler){
|
||||
case TranLBH_Rebuffer:
|
||||
{
|
||||
tran->fill_buffer[0] = ch;
|
||||
tran->fill_start_i = i;
|
||||
tran->fill_i = 1;
|
||||
tran->fill_expected = emit_rule.byte_class;
|
||||
}break;
|
||||
|
||||
case TranLBH_EmitAsCP:
|
||||
{
|
||||
emits_out->steps[emits_out->step_count].type = 1;
|
||||
emits_out->steps[emits_out->step_count].value = ch;
|
||||
emits_out->steps[emits_out->step_count].i = i;
|
||||
emits_out->steps[emits_out->step_count].byte_length = 1;
|
||||
++emits_out->step_count;
|
||||
}break;
|
||||
}
|
||||
|
||||
skip_all:;
|
||||
}
|
||||
|
||||
internal void
|
||||
translating_fully_process_byte(System_Functions *system, Render_Font *font, Translation_State *tran, u8 ch, u32 i, u32 size, Translation_Emits *emits_out){
|
||||
Translation_Byte_Description description = {0};
|
||||
translating_consume_byte(tran, ch, i, size, &description);
|
||||
Translation_Emit_Rule emit_rule = {0};
|
||||
translating_select_emit_rule_with_font(system, font, tran, description, &emit_rule);
|
||||
translating_generate_emits(tran, emit_rule, ch, i, emits_out);
|
||||
}
|
||||
|
||||
internal void
|
||||
translation_step_read(Buffer_Model_Step step, Buffer_Model_Behavior *behavior_out){
|
||||
behavior_out->do_newline = false;
|
||||
behavior_out->do_codepoint_advance = false;
|
||||
behavior_out->do_number_advance = false;
|
||||
if (step.type == 1){
|
||||
switch (step.value){
|
||||
case '\n':
|
||||
{
|
||||
behavior_out->do_newline = true;
|
||||
}break;
|
||||
default:
|
||||
{
|
||||
behavior_out->do_codepoint_advance = true;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
else{
|
||||
behavior_out->do_number_advance = true;
|
||||
}
|
||||
}
|
||||
|
||||
#define TRANSLATION_DECL_EMIT_LOOP(_j,_emit) u32 _j = 0; _j < (_emit).step_count; ++_j
|
||||
#define TRANSLATION_DECL_GET_STEP(_step,_behav,_j,_emit) \
|
||||
Buffer_Model_Step _step = _emit.steps[_j]; Buffer_Model_Behavior _behav; \
|
||||
translation_step_read(_step, &_behav)
|
||||
|
||||
#define TRANSLATION_EMIT_LOOP(_j,_emit) _j = 0; _j < (_emit).step_count; ++_j
|
||||
#define TRANSLATION_GET_STEP(_step,_behav,_j,_emit)\
|
||||
(_step) = _emit.steps[_j]; translation_step_read((_step), &(_behav))
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
|
@ -67,24 +67,20 @@ tbl_name_compare(void *a, void *b, void *arg){
|
|||
|
||||
internal void
|
||||
working_set_extend_memory(Working_Set *working_set, Editing_File *new_space, i16 number_of_files){
|
||||
Buffer_Slot_ID id;
|
||||
i16 i, high_part;
|
||||
Editing_File *file_ptr;
|
||||
File_Node *free_sentinel;
|
||||
|
||||
Assert(working_set->array_count < working_set->array_max);
|
||||
|
||||
high_part = working_set->array_count++;
|
||||
i16 high_part = working_set->array_count++;
|
||||
working_set->file_arrays[high_part].files = new_space;
|
||||
working_set->file_arrays[high_part].size = number_of_files;
|
||||
|
||||
working_set->file_max += number_of_files;
|
||||
|
||||
Buffer_Slot_ID id = {0};
|
||||
id.part[1] = high_part;
|
||||
|
||||
file_ptr = new_space;
|
||||
free_sentinel = &working_set->free_sentinel;
|
||||
for (i = 0; i < number_of_files; ++i, ++file_ptr){
|
||||
Editing_File *file_ptr = new_space;
|
||||
File_Node *free_sentinel = &working_set->free_sentinel;
|
||||
for (i16 i = 0; i < number_of_files; ++i, ++file_ptr){
|
||||
id.part[0] = i;
|
||||
file_ptr->id = id;
|
||||
dll_insert(free_sentinel, &file_ptr->node);
|
|
@ -60,33 +60,44 @@ typedef double f64;
|
|||
#define Min(a,b) (((a)<(b))?(a):(b))
|
||||
|
||||
inline i32 ceil32(f32 v){
|
||||
return(((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) ));
|
||||
}
|
||||
|
||||
inline i32 floor32(f32 v){
|
||||
return(((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) ));
|
||||
}
|
||||
|
||||
inline i32 round32(f32 v){
|
||||
return(floor32(v + 0.5f));
|
||||
}
|
||||
|
||||
inline i32 trun32(f32 v){
|
||||
return((i32)(v));
|
||||
}
|
||||
|
||||
inline i32 div_ceil(i32 n, i32 d){
|
||||
return( ((n) % (d) != 0) + ((n) / (d)) );
|
||||
}
|
||||
|
||||
inline i32 l_round_up_i32(i32 x, i32 b){
|
||||
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
|
||||
}
|
||||
|
||||
inline u32 l_round_up_u32(u32 x, u32 b){
|
||||
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
|
||||
}
|
||||
|
||||
return(((v)>0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)+1.f)) ):( ((i32)(v)) ));
|
||||
}
|
||||
|
||||
inline i32 floor32(f32 v){
|
||||
return(((v)<0)?( (v == (i32)(v))?((i32)(v)):((i32)((v)-1.f)) ):( ((i32)(v)) ));
|
||||
}
|
||||
|
||||
inline i32 round32(f32 v){
|
||||
return(floor32(v + 0.5f));
|
||||
}
|
||||
|
||||
inline i32 trun32(f32 v){
|
||||
return((i32)(v));
|
||||
}
|
||||
|
||||
inline i32 div_ceil(i32 n, i32 d){
|
||||
return( ((n) % (d) != 0) + ((n) / (d)) );
|
||||
}
|
||||
|
||||
inline i32 l_round_up_i32(i32 x, i32 b){
|
||||
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
|
||||
}
|
||||
|
||||
inline u32 l_round_up_u32(u32 x, u32 b){
|
||||
return( ((x)+(b)-1) - (((x)+(b)-1)%(b)) );
|
||||
}
|
||||
|
||||
inline u32 round_up_pot_u32(u32 x){
|
||||
--x;
|
||||
x |= x >> 1;
|
||||
x |= x >> 2;
|
||||
x |= x >> 4;
|
||||
x |= x >> 8;
|
||||
x |= x >> 16;
|
||||
++x;
|
||||
return(x);
|
||||
}
|
||||
|
||||
#define STR__(s) #s
|
||||
#define STR_(s) STR__(s)
|
||||
|
||||
|
|
175
README.txt
175
README.txt
|
@ -1,175 +0,0 @@
|
|||
Distribution Date: 2.9.2016 (dd.mm.yyyy)
|
||||
|
||||
Thank you for contributing to the 4coder project!
|
||||
|
||||
To submit bug reports or to request particular features email editor@4coder.net.
|
||||
|
||||
Watch 4coder.net blog and @AllenWebster4th twitter for news about 4coder progress.
|
||||
|
||||
---------------------------------
|
||||
FAIR WARNING
|
||||
---------------------------------
|
||||
|
||||
THINGS WILL GET CRASHY FAST IF ANY .ttf FILES ARE MISSING.
|
||||
THIS EFFECT WILL ALSO OCCUR IF YOU LAUNCH FROM A DIRECTORY
|
||||
THAT DOESN'T CONTAIN THE .ttf FILES. (This problem will be
|
||||
fixed eventually).
|
||||
|
||||
This build is extremely "janky" for lack of a better term. From what limitted testing
|
||||
I have been able to do I think it should run on a Windows 7 machine. It has not been
|
||||
launched at all on any other version of Windows. I have done what I can to get rid of
|
||||
the bugs and crashes that would make it unusable, but there are certainly more in there
|
||||
if you start digging and pressing hard enough.
|
||||
|
||||
**Please USE SOURCE CONTROL WITH 4CODER for now**
|
||||
|
||||
-----------------------------------------------------
|
||||
INSTRUCTIONS FOR USE
|
||||
-----------------------------------------------------
|
||||
|
||||
****Command line options****
|
||||
4ed [<files-to-open>] [options]
|
||||
|
||||
-d/-D <filename> -- use a dll other than 4coder_custom.dll for your customizations
|
||||
-d -- if the file isn't found look for 4coder_custom.dll
|
||||
-D -- only look for the specified
|
||||
|
||||
-i <line-number> -- line number to jump to in first file to open specified on command line
|
||||
|
||||
-w <w, h> -- width and height of the 4coder window
|
||||
-p <x, y> -- position of the 4coder window
|
||||
|
||||
-W -- open in full screen, overrides -w and -p, although the size will still be the default size of the window
|
||||
|
||||
-T -- invoke special tool isntead of launching 4coder normally
|
||||
-T version : prints the 4coder version string
|
||||
|
||||
****Command Bindings****
|
||||
Basic Navigation:
|
||||
mouse left click - move cursor
|
||||
mouse right click - set mark
|
||||
arrows - move cursor
|
||||
home & end - move cursor to beginning/end of line
|
||||
page up & page down - move up/down by close to the height of the entire screen
|
||||
control + left/right - move cursor left/right to first whitespace
|
||||
control + up/down - move cursor up or down to first blank line
|
||||
|
||||
Fancy Navigation:
|
||||
control + f : begin find mode, uses interaction bar
|
||||
control + r : begin reverse-find mode, uses interaction bar
|
||||
|
||||
control + F : list all locations of a word in all open buffers, uses interaction bar
|
||||
> This command creates a *search* buffer that displays the locations and the line of each
|
||||
> occurence of the requested word. By positioning the cursor and pressing return the user
|
||||
> jump to the word's occurence.
|
||||
|
||||
While in find mode or reverse-find mode, pressing enter ends the mode
|
||||
leaving the cursor wherever the find highlighter is, and pressing escape
|
||||
ends the mode leaving the cursor wherever it was before the find mode began.
|
||||
|
||||
control + g - goto line number, uses interaction bar
|
||||
control + m - swap cursor and mark
|
||||
|
||||
control + e - center the view vertically on the cursor
|
||||
control + E - in a view with unwrapped lines move the view to a position just left of the cursor
|
||||
|
||||
Basic Editing:
|
||||
characters keys, delete, and backspace
|
||||
control + c : copy between cursor and mark
|
||||
control + x : cut between cursor and mark
|
||||
control + v : paste at cursor
|
||||
control + V : use after normal paste to cycle through older copied text
|
||||
control + d : delete between cursor and mark
|
||||
control + SPACE : set mark to cursor
|
||||
control + backspace : backspace one word
|
||||
control + delete : delete one word
|
||||
alt + backspace : snipe one word
|
||||
|
||||
Undo and History:
|
||||
control + z : undo
|
||||
control + y : redo
|
||||
control + h: history back step
|
||||
control + H: history forward step
|
||||
|
||||
Fancy Editing:
|
||||
control + u : to uppercase between cursor and mark
|
||||
control + j : to lowercase between cursor and mark
|
||||
control + q : query replace
|
||||
control + a : replace in range
|
||||
control + ~ : clean the trailing whitespace off of all lines
|
||||
|
||||
Fancy Editing in Code Files:
|
||||
control + [ : write "{}" pair with cursor in line between
|
||||
control + { : as control + [ with a semicolon after "}"
|
||||
control + } : as control + [ with a "break;" after "}"
|
||||
control + 0 : write "= {0};" at the cursor
|
||||
control + i : wrap the range specified by mark and cursor in #if 0 #endif
|
||||
|
||||
alt + 1 : if cursor is inside a string, treat the string as a filename and
|
||||
> try to open the file with that name in the other panel
|
||||
|
||||
Whitespace Boringness:
|
||||
Typing characters: },],),; and inserting newlines cause the line to autotab
|
||||
TAB: word complete
|
||||
control + TAB : auto indent lines between cursor and mark
|
||||
shift + TAB: auto indent cursor line
|
||||
control + 1 : set the file to dos mode for writing to disk
|
||||
control + ! : set the flie to nix mode for writing to disk
|
||||
|
||||
Viewing Options:
|
||||
alt + c - open theme selection UI
|
||||
alt + d - open debug view
|
||||
|
||||
control + p : vertically split the current panel (max 16)
|
||||
control + _ : horizontally split the current panel (max 16)
|
||||
control + P : close the currently selected panel
|
||||
control + , : switch to another panel
|
||||
|
||||
control + l : toggle line wrapping
|
||||
control + ? : toggle highlight whitespace mode
|
||||
|
||||
f2 : toggle mouse suppresion mode
|
||||
|
||||
alt + s : show the scrollbar in this view
|
||||
alt + w : hide the scrollbar in this view
|
||||
|
||||
Build Tools:
|
||||
alt + m :
|
||||
[On Windows] search in the current hot directory and up through all parent
|
||||
> directories for a build.bat, and execute that bat if it discovered, sending
|
||||
> output to the buffer *compilation*
|
||||
[On Linux] The behavior is similar but the search looks for build.sh and if that
|
||||
> fails it looks for a Makefile
|
||||
|
||||
alt + . : change to the build panel
|
||||
alt + , : close the build panel
|
||||
alt + n : goto the next error listed in the build panel
|
||||
alt + N : goto the previous error listed in the build panel
|
||||
alt + M : goto the first error listed in the build panel
|
||||
|
||||
alt + z : execute any command line command you specify and send the output to the buffer you specify
|
||||
alt + Z : repeat the command previously executed by the alt + z command
|
||||
|
||||
File Managing:
|
||||
control + n : create a new file, begins interactive input mode
|
||||
control + o : open file, begins interactive input mode
|
||||
alt + o : open file in other panel, same as control + o but runs first changes the active view
|
||||
control + O : reopen the current file
|
||||
(discarding any differences the live version has from the file system's version)
|
||||
control + s : save
|
||||
control + w : save as, begins interative input mode
|
||||
control + i : switch active file in this panel, begins interactive input mode
|
||||
control + k : kill (close) a file, begins interactive input mode
|
||||
control + K : kill (close) the file being viewed in the currently active panel
|
||||
|
||||
While in interactive input mode, there are several ways to select an option.
|
||||
The options can be clicked. One option is always highlighted and pressing
|
||||
return or tab will select the highlighted option. Arrow keys navigate the
|
||||
highlighted option. Typing in characters narrows down the list of options.
|
||||
|
||||
Menu UI
|
||||
Keyboard options:
|
||||
> left control + left alt act as AltGr
|
||||
|
||||
Theme selection UI
|
||||
esc - close UI view return to major view if one was open previously
|
167
README_body.txt
167
README_body.txt
|
@ -1,167 +0,0 @@
|
|||
---------------------------------
|
||||
FAIR WARNING
|
||||
---------------------------------
|
||||
|
||||
THINGS WILL GET CRASHY FAST IF ANY .ttf FILES ARE MISSING.
|
||||
THIS EFFECT WILL ALSO OCCUR IF YOU LAUNCH FROM A DIRECTORY
|
||||
THAT DOESN'T CONTAIN THE .ttf FILES. (This problem will be
|
||||
fixed eventually).
|
||||
|
||||
This build is extremely "janky" for lack of a better term. From what limitted testing
|
||||
I have been able to do I think it should run on a Windows 7 machine. It has not been
|
||||
launched at all on any other version of Windows. I have done what I can to get rid of
|
||||
the bugs and crashes that would make it unusable, but there are certainly more in there
|
||||
if you start digging and pressing hard enough.
|
||||
|
||||
**Please USE SOURCE CONTROL WITH 4CODER for now**
|
||||
|
||||
-----------------------------------------------------
|
||||
INSTRUCTIONS FOR USE
|
||||
-----------------------------------------------------
|
||||
|
||||
****Command line options****
|
||||
4ed [<files-to-open>] [options]
|
||||
|
||||
-d/-D <filename> -- use a dll other than 4coder_custom.dll for your customizations
|
||||
-d -- if the file isn't found look for 4coder_custom.dll
|
||||
-D -- only look for the specified
|
||||
|
||||
-i <line-number> -- line number to jump to in first file to open specified on command line
|
||||
|
||||
-w <w, h> -- width and height of the 4coder window
|
||||
-p <x, y> -- position of the 4coder window
|
||||
|
||||
-W -- open in full screen, overrides -w and -p, although the size will still be the default size of the window
|
||||
|
||||
-T -- invoke special tool isntead of launching 4coder normally
|
||||
-T version : prints the 4coder version string
|
||||
|
||||
****Command Bindings****
|
||||
Basic Navigation:
|
||||
mouse left click - move cursor
|
||||
mouse right click - set mark
|
||||
arrows - move cursor
|
||||
home & end - move cursor to beginning/end of line
|
||||
page up & page down - move up/down by close to the height of the entire screen
|
||||
control + left/right - move cursor left/right to first whitespace
|
||||
control + up/down - move cursor up or down to first blank line
|
||||
|
||||
Fancy Navigation:
|
||||
control + f : begin find mode, uses interaction bar
|
||||
control + r : begin reverse-find mode, uses interaction bar
|
||||
|
||||
control + F : list all locations of a word in all open buffers, uses interaction bar
|
||||
> This command creates a *search* buffer that displays the locations and the line of each
|
||||
> occurence of the requested word. By positioning the cursor and pressing return the user
|
||||
> jump to the word's occurence.
|
||||
|
||||
While in find mode or reverse-find mode, pressing enter ends the mode
|
||||
leaving the cursor wherever the find highlighter is, and pressing escape
|
||||
ends the mode leaving the cursor wherever it was before the find mode began.
|
||||
|
||||
control + g - goto line number, uses interaction bar
|
||||
control + m - swap cursor and mark
|
||||
|
||||
control + e - center the view vertically on the cursor
|
||||
control + E - in a view with unwrapped lines move the view to a position just left of the cursor
|
||||
|
||||
Basic Editing:
|
||||
characters keys, delete, and backspace
|
||||
control + c : copy between cursor and mark
|
||||
control + x : cut between cursor and mark
|
||||
control + v : paste at cursor
|
||||
control + V : use after normal paste to cycle through older copied text
|
||||
control + d : delete between cursor and mark
|
||||
control + SPACE : set mark to cursor
|
||||
control + backspace : backspace one word
|
||||
control + delete : delete one word
|
||||
alt + backspace : snipe one word
|
||||
|
||||
Undo and History:
|
||||
control + z : undo
|
||||
control + y : redo
|
||||
control + h: history back step
|
||||
control + H: history forward step
|
||||
|
||||
Fancy Editing:
|
||||
control + u : to uppercase between cursor and mark
|
||||
control + j : to lowercase between cursor and mark
|
||||
control + q : query replace
|
||||
control + a : replace in range
|
||||
control + ~ : clean the trailing whitespace off of all lines
|
||||
|
||||
Fancy Editing in Code Files:
|
||||
control + [ : write "{}" pair with cursor in line between
|
||||
control + { : as control + [ with a semicolon after "}"
|
||||
control + } : as control + [ with a "break;" after "}"
|
||||
control + 0 : write "= {0};" at the cursor
|
||||
control + i : wrap the range specified by mark and cursor in #if 0 #endif
|
||||
|
||||
alt + 1 : if cursor is inside a string, treat the string as a filename and
|
||||
> try to open the file with that name in the other panel
|
||||
|
||||
Whitespace Boringness:
|
||||
Typing characters: },],),; and inserting newlines cause the line to autotab
|
||||
TAB: word complete
|
||||
control + TAB : auto indent lines between cursor and mark
|
||||
shift + TAB: auto indent cursor line
|
||||
control + 1 : set the file to dos mode for writing to disk
|
||||
control + ! : set the flie to nix mode for writing to disk
|
||||
|
||||
Viewing Options:
|
||||
alt + c - open theme selection UI
|
||||
alt + d - open debug view
|
||||
|
||||
control + p : vertically split the current panel (max 16)
|
||||
control + _ : horizontally split the current panel (max 16)
|
||||
control + P : close the currently selected panel
|
||||
control + , : switch to another panel
|
||||
|
||||
control + l : toggle line wrapping
|
||||
control + ? : toggle highlight whitespace mode
|
||||
|
||||
f2 : toggle mouse suppresion mode
|
||||
|
||||
alt + s : show the scrollbar in this view
|
||||
alt + w : hide the scrollbar in this view
|
||||
|
||||
Build Tools:
|
||||
alt + m :
|
||||
[On Windows] search in the current hot directory and up through all parent
|
||||
> directories for a build.bat, and execute that bat if it discovered, sending
|
||||
> output to the buffer *compilation*
|
||||
[On Linux] The behavior is similar but the search looks for build.sh and if that
|
||||
> fails it looks for a Makefile
|
||||
|
||||
alt + . : change to the build panel
|
||||
alt + , : close the build panel
|
||||
alt + n : goto the next error listed in the build panel
|
||||
alt + N : goto the previous error listed in the build panel
|
||||
alt + M : goto the first error listed in the build panel
|
||||
|
||||
alt + z : execute any command line command you specify and send the output to the buffer you specify
|
||||
alt + Z : repeat the command previously executed by the alt + z command
|
||||
|
||||
File Managing:
|
||||
control + n : create a new file, begins interactive input mode
|
||||
control + o : open file, begins interactive input mode
|
||||
alt + o : open file in other panel, same as control + o but runs first changes the active view
|
||||
control + O : reopen the current file
|
||||
(discarding any differences the live version has from the file system's version)
|
||||
control + s : save
|
||||
control + w : save as, begins interative input mode
|
||||
control + i : switch active file in this panel, begins interactive input mode
|
||||
control + k : kill (close) a file, begins interactive input mode
|
||||
control + K : kill (close) the file being viewed in the currently active panel
|
||||
|
||||
While in interactive input mode, there are several ways to select an option.
|
||||
The options can be clicked. One option is always highlighted and pressing
|
||||
return or tab will select the highlighted option. Arrow keys navigate the
|
||||
highlighted option. Typing in characters narrows down the list of options.
|
||||
|
||||
Menu UI
|
||||
Keyboard options:
|
||||
> left control + left alt act as AltGr
|
||||
|
||||
Theme selection UI
|
||||
esc - close UI view return to major view if one was open previously
|
|
@ -11,7 +11,7 @@ SET BUILD_MODE=%1
|
|||
if "%BUILD_MODE%" == "" (SET BUILD_MODE="/DDEV_BUILD")
|
||||
|
||||
pushd ..\build
|
||||
cl %OPTS% ..\code\meta\build.cpp /Zi /Febuild %BUILD_MODE%
|
||||
cl %OPTS% kernel32.lib ..\code\meta\build.cpp /Zi /Febuild %BUILD_MODE%
|
||||
if %ERRORLEVEL% neq 0 (set FirstError=1)
|
||||
if %ERRORLEVEL% neq 0 (goto END)
|
||||
popd
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
@echo off
|
||||
|
||||
REM TODO(allen): Figure out a way to find vcvarsall for any MSVC version.
|
||||
IF NOT DEFINED LIB (call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" amd64)
|
||||
|
||||
SET SRC=%1
|
||||
|
@ -15,9 +16,10 @@ REM This stores the path of the buildsuper.bat script
|
|||
REM in CODE_HOME. This way you can always include the
|
||||
REM default files no matter where you store your code.
|
||||
REM And no matter how you call buildsuper.bat.
|
||||
|
||||
SET CODE_HOME=%~dp0
|
||||
|
||||
cl /I%CODE_HOME% %OPTS% %DEBUG% %SRC% /Fecustom_4coder %BUILD_DLL% %EXPORTS%
|
||||
cl %OPTS% /I"%CODE_HOME% " %DEBUG% "%SRC%" /Fecustom_4coder %BUILD_DLL% %EXPORTS%
|
||||
|
||||
REM file spammation preventation
|
||||
del *.exp
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 03.03.2017
|
||||
*
|
||||
* Font data type definitions.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_FONT_DATA_H)
|
||||
#define FCODER_FONT_DATA_H
|
||||
|
||||
#define FONT_PAGE_ITEMS 256
|
||||
|
||||
struct Glyph_Bounds{
|
||||
b32 exists;
|
||||
|
||||
f32 x0, x1;
|
||||
f32 y0, y1;
|
||||
|
||||
f32 xoff, yoff;
|
||||
f32 xoff2, yoff2;
|
||||
};
|
||||
|
||||
struct Glyph_Page{
|
||||
Glyph_Bounds glyphs[256];
|
||||
u32 tex;
|
||||
i32 tex_width, tex_height;
|
||||
b32 exists;
|
||||
};
|
||||
|
||||
struct Glyph_Data{
|
||||
Glyph_Bounds bounds;
|
||||
u32 tex;
|
||||
i32 tex_width, tex_height;
|
||||
};
|
||||
|
||||
struct Advance_Page{
|
||||
f32 advance[256];
|
||||
};
|
||||
|
||||
struct Render_Font{
|
||||
char name_[24];
|
||||
String name;
|
||||
b32 loaded;
|
||||
|
||||
Glyph_Page glyph_pages[1];
|
||||
Advance_Page advance_pages[1];
|
||||
|
||||
f32 byte_advance;
|
||||
i32 height, ascent, descent, line_skip;
|
||||
i32 advance;
|
||||
};
|
||||
|
||||
internal b32
|
||||
get_codepoint_can_render(Render_Font *font, u32 codepoint){
|
||||
b32 exists = false;
|
||||
if (codepoint < FONT_PAGE_ITEMS){
|
||||
exists = true;
|
||||
}
|
||||
return(exists);
|
||||
}
|
||||
|
||||
internal u32
|
||||
get_codepoint_page_index(Render_Font *font, u32 codepoint, u32 *page_base_codepoint){
|
||||
*page_base_codepoint = 0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
internal void
|
||||
get_codepoint_memory(Render_Font *font, u32 codepoint, Glyph_Bounds **bounds_mem_out, f32 **advance_mem_out){
|
||||
Glyph_Bounds *bounds = 0;
|
||||
f32 *advance = 0;
|
||||
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
u32 base_codepoint = 0;
|
||||
u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint);
|
||||
Glyph_Page *bounds_page = &font->glyph_pages[page_index];
|
||||
Advance_Page *advance_page = &font->advance_pages[page_index];
|
||||
u32 glyph_index = codepoint - base_codepoint;
|
||||
|
||||
bounds = &bounds_page->glyphs[glyph_index];
|
||||
advance = &advance_page->advance[glyph_index];
|
||||
}
|
||||
|
||||
*bounds_mem_out = bounds;
|
||||
*advance_mem_out = advance;
|
||||
}
|
||||
|
||||
internal b32
|
||||
get_codepoint_glyph_data(Render_Font *font, u32 codepoint, Glyph_Data *data_out){
|
||||
b32 success = false;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
u32 base_codepoint = 0;
|
||||
u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint);
|
||||
Glyph_Page *page = &font->glyph_pages[page_index];
|
||||
data_out->bounds = page->glyphs[codepoint - base_codepoint];
|
||||
data_out->tex = page->tex;
|
||||
data_out->tex_width = page->tex_width;
|
||||
data_out->tex_height = page->tex_height;
|
||||
success = true;
|
||||
}
|
||||
return(success);
|
||||
}
|
||||
|
||||
internal f32
|
||||
get_codepoint_advance(Render_Font *font, u32 codepoint){
|
||||
f32 advance = (f32)font->advance;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
u32 base_codepoint = 0;
|
||||
u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint);
|
||||
Advance_Page *page = &font->advance_pages[page_index];
|
||||
advance = page->advance[codepoint - base_codepoint];
|
||||
}
|
||||
return(advance);
|
||||
}
|
||||
|
||||
internal b32
|
||||
set_codepoint_advance(Render_Font *font, u32 codepoint, f32 value){
|
||||
b32 success = false;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
u32 base_codepoint = 0;
|
||||
u32 page_index = get_codepoint_page_index(font, codepoint, &base_codepoint);
|
||||
Advance_Page *page = &font->advance_pages[page_index];
|
||||
page->advance[codepoint - base_codepoint] = value;
|
||||
success = true;
|
||||
}
|
||||
return(success);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
|
||||
Copy Right FourTech LLC, 2016
|
||||
All Rights Are Reserved
|
||||
|
||||
The OS agnostic file tracking API for applications
|
||||
that want to interact with potentially many files on
|
||||
the disk that could be changed by other applications.
|
||||
|
||||
Created on: 20.07.2016
|
||||
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#ifndef FILE_TRACK_4TECH_H
|
||||
#define FILE_TRACK_4TECH_H
|
||||
|
||||
#ifndef FILE_TRACK_LINK
|
||||
#define FILE_TRACK_LINK static
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum{
|
||||
FileTrack_Good,
|
||||
FileTrack_MemoryTooSmall,
|
||||
FileTrack_OutOfTableMemory,
|
||||
FileTrack_OutOfListenerMemory,
|
||||
FileTrack_NoMoreEvents,
|
||||
FileTrack_FileSystemError
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
uint8_t opaque[128];
|
||||
} File_Track_System;
|
||||
|
||||
typedef int32_t File_Track_Result;
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
init_track_system(File_Track_System *system,
|
||||
void *table_memory, int32_t table_memory_size,
|
||||
void *listener_memory, int32_t listener_memory_size);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
add_listener(File_Track_System *system, char *filename);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
remove_listener(File_Track_System *system, char *filename);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
move_track_system(File_Track_System *system, void *mem, int32_t size);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
get_change_event(File_Track_System *system, char *buffer, int32_t max);
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
shut_down_track_system(File_Track_System *system);
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 03.03.2017
|
||||
*
|
||||
* Font data type definitions.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_FONT_DATA_H)
|
||||
#define FCODER_FONT_DATA_H
|
||||
|
||||
#define ITEM_PER_FONT_PAGE 256
|
||||
|
||||
struct Glyph_Bounds{
|
||||
f32 x0, x1;
|
||||
f32 y0, y1;
|
||||
f32 xoff, yoff;
|
||||
f32 xoff2, yoff2;
|
||||
};
|
||||
global_const Glyph_Bounds null_glyph_bounds = {0};
|
||||
|
||||
struct Glyph_Page{
|
||||
u32 page_number;
|
||||
f32 advance[ITEM_PER_FONT_PAGE];
|
||||
Glyph_Bounds glyphs[ITEM_PER_FONT_PAGE];
|
||||
u32 tex;
|
||||
i32 tex_width, tex_height;
|
||||
};
|
||||
|
||||
#define FONT_PAGE_EMPTY ((Glyph_Page*)0)
|
||||
#define FONT_PAGE_DELETED ((Glyph_Page*)(1))
|
||||
#define FONT_PAGE_MAX 0x1100
|
||||
|
||||
struct Render_Font{
|
||||
Glyph_Page **pages;
|
||||
u32 page_count, page_max;
|
||||
f32 byte_advance;
|
||||
f32 byte_sub_advances[3];
|
||||
i32 height, ascent, descent, line_skip, advance;
|
||||
|
||||
u32 filename_len;
|
||||
u32 name_len;
|
||||
char filename[256];
|
||||
char name[256];
|
||||
};
|
||||
|
||||
struct Glyph_Data{
|
||||
Glyph_Bounds bounds;
|
||||
u32 tex;
|
||||
i32 tex_width, tex_height;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 11.03.2017
|
||||
*
|
||||
* Font system interface.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_FONT_INTERFACE_H)
|
||||
#define FCODER_FONT_INTERFACE_H
|
||||
|
||||
typedef u32 Font_ID;
|
||||
|
||||
struct Render_Font;
|
||||
struct Glyph_Page;
|
||||
|
||||
#define Sys_Font_Get_Count_Sig(name_) u32 (name_)(void)
|
||||
typedef Sys_Font_Get_Count_Sig(Font_Get_Count_Function);
|
||||
|
||||
#define Sys_Font_Get_IDs_By_Index_Sig(name_) b32 (name_)(u32 first_index, u32 index_count, u32 *id_out)
|
||||
typedef Sys_Font_Get_IDs_By_Index_Sig(Font_Get_IDs_By_Index_Function);
|
||||
|
||||
#define Sys_Font_Get_Name_By_Index_Sig(name_) u32 (name_)(u32 font_index, char *str_out, u32 str_out_cap)
|
||||
typedef Sys_Font_Get_Name_By_Index_Sig(Font_Get_Name_By_Index_Function);
|
||||
|
||||
#define Sys_Font_Get_Name_By_ID_Sig(name_) u32 (name_)(u32 font_id, char *str_out, u32 str_out_cap)
|
||||
typedef Sys_Font_Get_Name_By_ID_Sig(Font_Get_Name_By_ID_Function);
|
||||
|
||||
#define Sys_Font_Get_Render_Data_By_ID_Sig(name_) Render_Font* (name_)(u32 font_id)
|
||||
typedef Sys_Font_Get_Render_Data_By_ID_Sig(Font_Get_Render_Data_By_ID_Function);
|
||||
|
||||
#define Sys_Font_Load_Page_Sig(name_) void (name_)(Render_Font *font, Glyph_Page *page, u32 page_number)
|
||||
typedef Sys_Font_Load_Page_Sig(Font_Load_Page_Function);
|
||||
|
||||
#define Sys_Font_Allocate_Sig(name_) void* (name_)(i32 size)
|
||||
typedef Sys_Font_Allocate_Sig(Font_Allocate_Function);
|
||||
|
||||
#define Sys_Font_Free_Sig(name_) void (name_)(void *ptr)
|
||||
typedef Sys_Font_Free_Sig(Font_Free_Function);
|
||||
|
||||
struct Font_Functions{
|
||||
Font_Get_Count_Function *get_count;
|
||||
Font_Get_IDs_By_Index_Function *get_ids_by_index;
|
||||
Font_Get_Name_By_Index_Function *get_name_by_index;
|
||||
Font_Get_Name_By_ID_Function *get_name_by_id;
|
||||
Font_Get_Render_Data_By_ID_Function *get_render_data_by_id;
|
||||
Font_Load_Page_Function *load_page;
|
||||
|
||||
Font_Allocate_Function *allocate;
|
||||
Font_Free_Function *free;
|
||||
};
|
||||
|
||||
internal f32 font_get_byte_advance(Render_Font *font);
|
||||
internal f32*font_get_byte_sub_advances(Render_Font *font);
|
||||
internal i32 font_get_height(Render_Font *font);
|
||||
internal i32 font_get_ascent(Render_Font *font);
|
||||
internal i32 font_get_descent(Render_Font *font);
|
||||
internal i32 font_get_line_skip(Render_Font *font);
|
||||
internal i32 font_get_advance(Render_Font *font);
|
||||
|
||||
internal b32 font_can_render(struct System_Functions *system, Render_Font *font, u32 codepoint);
|
||||
internal f32 font_get_glyph_advance(struct System_Functions *system, Render_Font *font, u32 codepoint);
|
||||
|
||||
struct Glyph_Data;
|
||||
internal Glyph_Data font_get_glyph(System_Functions *system, Render_Font *font, u32 codepoint);
|
||||
|
||||
internal Glyph_Page *font_get_or_make_page(struct System_Functions *system, Render_Font *font, u32 page_number);
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 13.03.2017
|
||||
*
|
||||
* Font system interface to the OS layer.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FCODER_FONT_INTERFACE_TO_OS_H)
|
||||
#define FCODER_FONT_INTERFACE_TO_OS_H
|
||||
|
||||
#define Sys_Font_Init_Sig(name_) void (name_)(Font_Functions *font, void *memory, umem memory_size, u32 font_size, b32 use_hinting)
|
||||
internal Sys_Font_Init_Sig(system_font_init);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,493 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 10.03.2017
|
||||
*
|
||||
* Where I save crappy old font stuff.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "font/4coder_font_data.h"
|
||||
|
||||
struct Font_Table_Entry{
|
||||
u32 hash;
|
||||
String name;
|
||||
Font_ID font_id;
|
||||
};
|
||||
|
||||
struct Font_Info{
|
||||
Render_Font *font;
|
||||
String filename;
|
||||
String name;
|
||||
i32 pt_size;
|
||||
};
|
||||
|
||||
struct Font_Slot{
|
||||
Font_Slot *next, *prev;
|
||||
Font_ID font_id;
|
||||
u8 padding[6];
|
||||
};
|
||||
global_const Font_Slot null_font_slot = {0};
|
||||
|
||||
#define Font_Load_Sig(name)\
|
||||
i32 name(Render_Font *font_out, char *filename, char *fontname, i32 pt_size, i32 tab_width, b32 store_texture)
|
||||
typedef Font_Load_Sig(Font_Load);
|
||||
|
||||
#define Font_Load_Page_Sig(name)\
|
||||
i32 name(Render_Font *font, Glyph_Page *page, char *filename, i32 pt_size, i32 tab_width)
|
||||
typedef Font_Load_Page_Sig(Font_Load_Page);
|
||||
|
||||
#define Release_Font_Sig(name) void name(Render_Font *font)
|
||||
typedef Release_Font_Sig(Release_Font);
|
||||
|
||||
struct Font_Set{
|
||||
Font_Info *info;
|
||||
Font_Table_Entry *entries;
|
||||
u32 count, max;
|
||||
|
||||
void *font_block;
|
||||
Font_Slot free_slots;
|
||||
Font_Slot used_slots;
|
||||
|
||||
Font_Load *font_load;
|
||||
Font_Load_Page *font_load_page;
|
||||
Release_Font *release_font;
|
||||
|
||||
b8 *font_used_flags;
|
||||
Font_ID used_this_frame;
|
||||
Font_ID live_max;
|
||||
};
|
||||
|
||||
inline Font_Info*
|
||||
get_font_info(Font_Set *set, Font_ID font_id){
|
||||
Font_Info *result = set->info + font_id - 1;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_begin_render(Font_Set *font_set){
|
||||
font_set->used_this_frame = 0;
|
||||
memset(font_set->font_used_flags, 0, font_set->max);
|
||||
}
|
||||
|
||||
inline u32
|
||||
font_hash(String name){
|
||||
u32 x = 5381;
|
||||
char *p = name.str;
|
||||
for (i32 i = 0; i < name.size; ++i, ++p){
|
||||
x = ((x << 5) + x) ^ (*p);
|
||||
}
|
||||
return(x);
|
||||
}
|
||||
|
||||
inline void
|
||||
font__insert(Font_Slot *pos, Font_Slot *slot){
|
||||
Font_Slot *nex;
|
||||
nex = pos->next;
|
||||
|
||||
slot->next = nex;
|
||||
slot->prev = pos;
|
||||
nex->prev = slot;
|
||||
pos->next = slot;
|
||||
}
|
||||
|
||||
inline void
|
||||
font__remove(Font_Slot *slot){
|
||||
Font_Slot *n, *p;
|
||||
n = slot->next;
|
||||
p = slot->prev;
|
||||
|
||||
p->next = n;
|
||||
n->prev = p;
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_init(Font_Set *set, Partition *partition, i32 max, Font_ID live_max){
|
||||
partition_align(partition, 8);
|
||||
set->info = push_array(partition, Font_Info, max);
|
||||
partition_align(partition, 8);
|
||||
set->entries = push_array(partition, Font_Table_Entry, max);
|
||||
set->count = 0;
|
||||
set->max = max;
|
||||
|
||||
partition_align(partition, 8);
|
||||
set->font_block = push_block(partition, live_max*(sizeof(Render_Font) + sizeof(Font_Slot)));
|
||||
|
||||
set->free_slots = null_font_slot;
|
||||
set->used_slots = null_font_slot;
|
||||
|
||||
dll_init_sentinel(&set->free_slots);
|
||||
dll_init_sentinel(&set->used_slots);
|
||||
|
||||
char *ptr = (char*)set->font_block;
|
||||
for (i32 i = 0; i < live_max; ++i){
|
||||
dll_insert(&set->free_slots, (Font_Slot*)ptr);
|
||||
ptr += sizeof(Font_Slot) + sizeof(Render_Font);
|
||||
}
|
||||
|
||||
set->font_used_flags = push_array(partition, b8, max);
|
||||
set->live_max = live_max;
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_can_add(Font_Set *set){
|
||||
b32 result = 0;
|
||||
if (set->count*8 < set->max*7) result = 1;
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_add_hash(Font_Set *set, String name, Font_ID font_id){
|
||||
Font_Table_Entry entry;
|
||||
entry.hash = font_hash(name);
|
||||
entry.name = name;
|
||||
entry.font_id = font_id;
|
||||
|
||||
u32 i = entry.hash % set->max;
|
||||
u32 j = i - 1;
|
||||
if (i <= 1) j += set->max;
|
||||
|
||||
for (; i != j; ++i){
|
||||
if (i == set->max) i = 0;
|
||||
if (set->entries[i].font_id == 0){
|
||||
set->entries[i] = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert(i != j);
|
||||
}
|
||||
|
||||
inline b32
|
||||
font_set_can_load(Font_Set *set){
|
||||
b32 result = (set->free_slots.next != &set->free_slots);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_load(Font_Set *set, Font_ID font_id){
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
Font_Slot *slot = set->free_slots.next;
|
||||
Assert(slot != &set->free_slots);
|
||||
font__remove(slot);
|
||||
font__insert(&set->used_slots, slot);
|
||||
|
||||
Render_Font *font = (Render_Font*)(slot + 1);
|
||||
set->font_load(font, info->filename.str, info->name.str, info->pt_size, 4, true);
|
||||
info->font = font;
|
||||
slot->font_id = font_id;
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_evict_lru(Font_Set *set){
|
||||
Font_Slot *slot = set->used_slots.prev;
|
||||
Assert(slot != &set->used_slots);
|
||||
|
||||
Font_ID font_id = slot->font_id;
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
Assert(((Font_Slot*)info->font) - 1 == slot);
|
||||
|
||||
set->release_font(info->font);
|
||||
|
||||
info->font = 0;
|
||||
slot->font_id = 0;
|
||||
font__remove(slot);
|
||||
font__insert(&set->free_slots, slot);
|
||||
}
|
||||
|
||||
internal void
|
||||
font_set_use(Font_Set *set, Font_ID font_id){
|
||||
b8 already_used = set->font_used_flags[font_id-1];
|
||||
|
||||
if (!already_used){
|
||||
if (set->used_this_frame < set->live_max){
|
||||
++set->used_this_frame;
|
||||
set->font_used_flags[font_id-1] = 1;
|
||||
already_used = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (already_used){
|
||||
// TODO(allen): optimize if you don't mind!!!!
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
Font_Slot *slot;
|
||||
if (info->font == 0){
|
||||
if (!font_set_can_load(set)){
|
||||
font_set_evict_lru(set);
|
||||
}
|
||||
font_set_load(set, font_id);
|
||||
}
|
||||
slot = ((Font_Slot*)info->font) - 1;
|
||||
|
||||
font__remove(slot);
|
||||
font__insert(&set->used_slots, slot);
|
||||
}
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_add(Font_Set *set, String filename, String name, i32 pt_size){
|
||||
b32 result = false;
|
||||
if (font_set_can_add(set)){
|
||||
Render_Font dummy_font = {0};
|
||||
Font_ID font_id = (i16)(++set->count);
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
info->filename = filename;
|
||||
info->name = name;
|
||||
info->pt_size = pt_size;
|
||||
set->font_load(&dummy_font, info->filename.str, info->name.str, info->pt_size, 4, false);
|
||||
|
||||
font_set_add_hash(set, name, font_id);
|
||||
|
||||
if (font_set_can_load(set)){
|
||||
font_set_load(set, font_id);
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_find_pos(Font_Set *set, String name, u32 *position){
|
||||
u32 hash = font_hash(name);
|
||||
u32 i = hash % set->max;
|
||||
u32 j = i - 1;
|
||||
if (j <= 1){
|
||||
j += set->max;
|
||||
}
|
||||
|
||||
b32 result = 0;
|
||||
for (; i != j; ++i){
|
||||
if (i == set->max){
|
||||
i = 0;
|
||||
}
|
||||
|
||||
Font_Table_Entry *entry = set->entries + i;
|
||||
if (entry->hash == hash){
|
||||
if (match_ss(name, entry->name)){
|
||||
result = 1;
|
||||
*position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_get_name(Font_Set *set, Font_ID font_id, String *name){
|
||||
Font_Info *info = get_font_info(set, font_id);
|
||||
b32 result = copy_checked_ss(name, info->name);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_set_extract(Font_Set *set, String name, Font_ID *font_id){
|
||||
u32 position;
|
||||
b32 result = font_set_find_pos(set, name, &position);
|
||||
if (result){
|
||||
*font_id = set->entries[position].font_id;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
|
||||
internal b32
|
||||
get_codepoint_can_render(Render_Font *font, u32 codepoint){
|
||||
b32 exists = false;
|
||||
if (codepoint < 0x10FFFF){
|
||||
exists = true;
|
||||
}
|
||||
return(exists);
|
||||
}
|
||||
|
||||
struct Codepoint_Indexes{
|
||||
b32 exists;
|
||||
u32 page_number;
|
||||
u32 glyph_index;
|
||||
};
|
||||
|
||||
internal Codepoint_Indexes
|
||||
get_codepoint_page_number(Render_Font *font, u32 codepoint){
|
||||
Codepoint_Indexes result = {0};
|
||||
u32 page_number = (codepoint >> 8);
|
||||
if (page_number <= 0x10FF){
|
||||
result.exists = true;
|
||||
result.page_number = page_number;
|
||||
result.glyph_index = (codepoint & 0x000000FF);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
#define MAX_PAGE_COUNT (u32)(0x1100)
|
||||
#define GLYPH_PAGE_EMPTY ((Glyph_Page*)(0))
|
||||
#define GLYPH_PAGE_DELETED ((Glyph_Page*)(max_u64))
|
||||
#define IS_REAL_FONT_PAGE(p) (((p) != GLYPH_PAGE_EMPTY) && ((p) != GLYPH_PAGE_DELETED))
|
||||
|
||||
internal Glyph_Page**
|
||||
font_lookup_page(Render_Font *font, u32 page_number, b32 find_empty_slot){
|
||||
Glyph_Page **result = 0;
|
||||
if (font->page_max > 0){
|
||||
u32 first_index = page_number % font->page_max;
|
||||
|
||||
u32 range_count = 0;
|
||||
u32 ranges[4];
|
||||
if (first_index == 0){
|
||||
ranges[0] = 0;
|
||||
ranges[1] = font->page_max;
|
||||
range_count = 2;
|
||||
}
|
||||
else{
|
||||
ranges[0] = first_index;
|
||||
ranges[1] = font->page_max;
|
||||
ranges[2] = 0;
|
||||
ranges[3] = first_index;
|
||||
range_count = 4;
|
||||
}
|
||||
|
||||
if (find_empty_slot){
|
||||
for(u32 j = 0; j < range_count; j += 2){
|
||||
u32 start = ranges[j];
|
||||
u32 stop = ranges[j+1];
|
||||
for (u32 i = start; i < stop; ++i){
|
||||
Glyph_Page *ptr = font->pages[i];
|
||||
if (ptr == GLYPH_PAGE_EMPTY || ptr == GLYPH_PAGE_DELETED){
|
||||
result = &font->pages[i];
|
||||
goto break2;
|
||||
}
|
||||
if (ptr->page_number == page_number){
|
||||
goto break2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(u32 j = 0; j < range_count; j += 2){
|
||||
u32 start = ranges[j];
|
||||
u32 stop = ranges[j+1];
|
||||
for (u32 i = start; i < stop; ++i){
|
||||
Glyph_Page *ptr = font->pages[i];
|
||||
if (ptr == GLYPH_PAGE_EMPTY){
|
||||
goto break2;
|
||||
}
|
||||
if (ptr != GLYPH_PAGE_DELETED){
|
||||
if (ptr->page_number == page_number){
|
||||
result = &font->pages[i];
|
||||
goto break2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break2:;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal Glyph_Page*
|
||||
font_get_or_make_page(Render_Font *font, u32 page_number){
|
||||
Glyph_Page *page = 0;
|
||||
if (page_number <= 0x10FF){
|
||||
Glyph_Page **page_ptr = font_lookup_page(font, page_number, false);
|
||||
page = 0;
|
||||
if (page_ptr != 0){
|
||||
page = *page_ptr;
|
||||
}
|
||||
|
||||
if (page == 0){
|
||||
u32 new_count = 1;
|
||||
if (font->page_max < MAX_PAGE_COUNT && (font->page_count+new_count)*3 < font->page_max*2){
|
||||
u32 new_page_max = (font->page_count+new_count)*3;
|
||||
new_page_max = clamp_top(new_page_max, MAX_PAGE_COUNT);
|
||||
Glyph_Page **new_pages = (Glyph_Page**)ALLOCATE(new_page_max * sizeof(Glyph_Page*));
|
||||
|
||||
u32 old_page_max = font->page_max;
|
||||
Glyph_Page **pages = font->pages;
|
||||
for (u32 i = 0; i < old_page_max; ++i){
|
||||
Glyph_Page *current_page = pages[i];
|
||||
if (current_page != GLYPH_PAGE_EMPTY && current_page != GLYPH_PAGE_DELETED){
|
||||
Glyph_Page **dest = font_lookup_page(font, current_page->page_number, true);
|
||||
Assert(dest != 0);
|
||||
*dest = current_page;
|
||||
}
|
||||
}
|
||||
|
||||
FREE(font->pages);
|
||||
font->pages = new_pages;
|
||||
font->page_max = new_page_max;
|
||||
}
|
||||
|
||||
Glyph_Page *new_page = (Glyph_Page*)ALLOCATE(sizeof(Glyph_Page));
|
||||
Glyph_Page **dest = font_lookup_page(font, page_number, true);
|
||||
*dest = new_page;
|
||||
++font->page_count;
|
||||
|
||||
//set->font_load_page(font, new_page, );
|
||||
}
|
||||
}
|
||||
return(page);
|
||||
}
|
||||
|
||||
internal void
|
||||
get_codepoint_memory(Render_Font *font, u32 codepoint, Glyph_Bounds **bounds_mem_out, f32 **advance_mem_out){
|
||||
Glyph_Bounds *bounds = 0;
|
||||
f32 *advance = 0;
|
||||
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint);
|
||||
Glyph_Page *page = font_get_or_make_page(font, indexes.page_number);
|
||||
bounds = &page->glyphs[indexes.glyph_index];
|
||||
advance = &page->advance[indexes.glyph_index];
|
||||
}
|
||||
|
||||
*bounds_mem_out = bounds;
|
||||
*advance_mem_out = advance;
|
||||
}
|
||||
|
||||
internal b32
|
||||
get_codepoint_glyph_data(Render_Font *font, u32 codepoint, Glyph_Data *data_out){
|
||||
b32 success = false;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint);
|
||||
Glyph_Page *page = font_get_or_make_page(font, indexes.page_number);
|
||||
data_out->bounds = page->glyphs[indexes.glyph_index];
|
||||
data_out->tex = page->tex;
|
||||
data_out->tex_width = page->tex_width;
|
||||
data_out->tex_height = page->tex_height;
|
||||
success = true;
|
||||
}
|
||||
return(success);
|
||||
}
|
||||
|
||||
internal f32
|
||||
get_codepoint_advance(Render_Font *font, u32 codepoint){
|
||||
f32 advance = (f32)font->advance;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint);
|
||||
Glyph_Page *page = font_get_or_make_page(font, indexes.page_number);
|
||||
advance = page->advance[indexes.glyph_index];
|
||||
}
|
||||
return(advance);
|
||||
}
|
||||
|
||||
internal b32
|
||||
set_codepoint_advance(Render_Font *font, u32 codepoint, f32 value){
|
||||
b32 success = false;
|
||||
if (get_codepoint_can_render(font, codepoint)){
|
||||
Codepoint_Indexes indexes = get_codepoint_page_number(font, codepoint);
|
||||
Glyph_Page *page = font_get_or_make_page(font, indexes.page_number);
|
||||
page->advance[indexes.glyph_index] = value;
|
||||
success = true;
|
||||
}
|
||||
return(success);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 11.03.2017
|
||||
*
|
||||
* Implements some basic getters for fonts set up to make the font type opaque.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "4coder_font_data.h"
|
||||
|
||||
internal f32
|
||||
font_get_byte_advance(Render_Font *font){
|
||||
return(font->byte_advance);
|
||||
}
|
||||
|
||||
internal f32*
|
||||
font_get_byte_sub_advances(Render_Font *font){
|
||||
return(font->byte_sub_advances);
|
||||
}
|
||||
|
||||
internal i32
|
||||
font_get_height(Render_Font *font){
|
||||
return(font->height);
|
||||
}
|
||||
|
||||
internal i32
|
||||
font_get_ascent(Render_Font *font){
|
||||
return(font->ascent);
|
||||
}
|
||||
|
||||
internal i32
|
||||
font_get_descent(Render_Font *font){
|
||||
return(font->descent);
|
||||
}
|
||||
|
||||
internal i32
|
||||
font_get_line_skip(Render_Font *font){
|
||||
return(font->line_skip);
|
||||
}
|
||||
|
||||
internal i32
|
||||
font_get_advance(Render_Font *font){
|
||||
return(font->advance);
|
||||
}
|
||||
|
||||
internal b32
|
||||
font_can_render(System_Functions *system, Render_Font *font, u32 codepoint){
|
||||
b32 result = false;
|
||||
u32 page_number = (codepoint >> 8);
|
||||
u32 glyph_index = codepoint & 0xFF;
|
||||
Glyph_Page *page = font_get_or_make_page(system, font, page_number);
|
||||
if (page != 0 && page->advance[glyph_index] > 0.f){
|
||||
result = true;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal f32
|
||||
font_get_glyph_advance(System_Functions *system, Render_Font *font, u32 codepoint){
|
||||
f32 result = 0.f;
|
||||
u32 page_number = (codepoint >> 8);
|
||||
u32 glyph_index = codepoint & 0xFF;
|
||||
Glyph_Page *page = font_get_or_make_page(system, font, page_number);
|
||||
if (page != 0 && page->advance[glyph_index] > 0.f){
|
||||
result = page->advance[glyph_index];
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal Glyph_Data
|
||||
font_get_glyph(System_Functions *system, Render_Font *font, u32 codepoint){
|
||||
Glyph_Data result = {0};
|
||||
u32 page_number = (codepoint >> 8);
|
||||
u32 glyph_index = codepoint & 0xFF;
|
||||
Glyph_Page *page = font_get_or_make_page(system, font, page_number);
|
||||
if (page != 0 && page->advance[glyph_index] > 0.f){
|
||||
result.bounds = page->glyphs[glyph_index];
|
||||
result.tex = page->tex;
|
||||
result.tex_width = page->tex_width;
|
||||
result.tex_height = page->tex_height;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal Glyph_Page**
|
||||
font_page_lookup(Render_Font *font, u32 page_number, b32 get_empty_slot){
|
||||
Glyph_Page **result = 0;
|
||||
|
||||
if (font->page_max > 0){
|
||||
u32 first_index = page_number % font->page_max;
|
||||
|
||||
u32 range_count = 0;
|
||||
u32 ranges[4];
|
||||
if (first_index == 0){
|
||||
ranges[0] = 0;
|
||||
ranges[1] = font->page_max;
|
||||
range_count = 2;
|
||||
}
|
||||
else{
|
||||
ranges[0] = first_index;
|
||||
ranges[1] = font->page_max;
|
||||
ranges[2] = 0;
|
||||
ranges[3] = first_index;
|
||||
range_count = 4;
|
||||
}
|
||||
|
||||
Glyph_Page **pages = font->pages;
|
||||
if (get_empty_slot){
|
||||
for (u32 j = 0; j < range_count; j += 2){
|
||||
u32 stop = ranges[j+1];
|
||||
for (u32 i = ranges[j]; i < stop; ++i){
|
||||
if (pages[i] == FONT_PAGE_EMPTY || pages[i] == FONT_PAGE_DELETED){
|
||||
result = &pages[i];
|
||||
goto break2;
|
||||
}
|
||||
if (pages[i]->page_number == page_number){
|
||||
goto break2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
for (u32 j = 0; j < range_count; j += 2){
|
||||
u32 stop = ranges[j+1];
|
||||
for (u32 i = ranges[j]; i < stop; ++i){
|
||||
if (pages[i] == FONT_PAGE_EMPTY){
|
||||
goto break2;
|
||||
}
|
||||
if (pages[i] != FONT_PAGE_DELETED && pages[i]->page_number == page_number){
|
||||
result = &pages[i];
|
||||
goto break2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break2:;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal Glyph_Page*
|
||||
font_get_or_make_page(System_Functions *system, Render_Font *font, u32 page_number){
|
||||
Glyph_Page *result = 0;
|
||||
if (page_number <= 0x10FF){
|
||||
Glyph_Page **page_get_result = font_page_lookup(font, page_number, false);
|
||||
|
||||
if (page_get_result == 0){
|
||||
b32 has_space = true;
|
||||
u32 new_page_count = 1;
|
||||
u32 new_max = (font->page_count+new_page_count)*3;
|
||||
if (font->page_max < FONT_PAGE_MAX && new_max > font->page_max*2){
|
||||
Glyph_Page **pages = (Glyph_Page**)system->font.allocate(sizeof(Glyph_Page*)*new_max);
|
||||
has_space = false;
|
||||
if (pages != 0){
|
||||
memset(pages, 0, sizeof(*pages)*new_max);
|
||||
u32 old_max = font->page_max;
|
||||
for (u32 i = 0; i < old_max; ++i){
|
||||
Glyph_Page *this_page = pages[i];
|
||||
if (this_page != FONT_PAGE_EMPTY && this_page != FONT_PAGE_DELETED){
|
||||
u32 this_page_number = this_page->page_number;
|
||||
Glyph_Page **dest = font_page_lookup(font, this_page_number, true);
|
||||
Assert(dest != 0);
|
||||
*dest = this_page;
|
||||
}
|
||||
}
|
||||
system->font.free(font->pages);
|
||||
font->pages = pages;
|
||||
font->page_max = new_max;
|
||||
has_space = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_space){
|
||||
Glyph_Page *new_page = (Glyph_Page*)system->font.allocate(sizeof(Glyph_Page));
|
||||
if (new_page != 0){
|
||||
Glyph_Page **dest = font_page_lookup(font, page_number, true);
|
||||
Assert(dest != 0);
|
||||
*dest = new_page;
|
||||
font->page_count += new_page_count;
|
||||
result = new_page;
|
||||
system->font.load_page(font, new_page, page_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = *page_get_result;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
101
linux_4ed.cpp
101
linux_4ed.cpp
|
@ -103,13 +103,14 @@
|
|||
#endif
|
||||
|
||||
#define SUPPORT_DPI 1
|
||||
#define LINUX_FONTS 1
|
||||
|
||||
#define InterlockedCompareExchange(dest, ex, comp) __sync_val_compare_and_swap((dest), (comp), (ex))
|
||||
|
||||
#include "filetrack/4tech_file_track_linux.c"
|
||||
#include "4ed_file_track.h"
|
||||
#include "4ed_system_shared.h"
|
||||
|
||||
#include "linux_4ed_file_track.cpp"
|
||||
|
||||
//
|
||||
// Linux structs / enums
|
||||
//
|
||||
|
@ -207,8 +208,6 @@ struct Linux_Vars{
|
|||
pthread_cond_t conds[8];
|
||||
sem_t thread_semaphore;
|
||||
|
||||
Partition font_part;
|
||||
|
||||
#if SUPPORT_DPI
|
||||
i32 dpi_x, dpi_y;
|
||||
#endif
|
||||
|
@ -1337,60 +1336,7 @@ INTERNAL_Sys_Get_Thread_States_Sig(internal_get_thread_states){
|
|||
//
|
||||
|
||||
#include "4ed_system_shared.cpp"
|
||||
#include "linux_font.cpp"
|
||||
|
||||
internal f32
|
||||
size_change(i32 dpi_x, i32 dpi_y){
|
||||
// TODO(allen): We're just hoping dpi_x == dpi_y for now I guess.
|
||||
f32 size_x = dpi_x / 96.f;
|
||||
f32 size_y = dpi_y / 96.f;
|
||||
f32 size_max = Max(size_x, size_y);
|
||||
return(size_max);
|
||||
}
|
||||
|
||||
internal
|
||||
Font_Load_Sig(system_draw_font_load){
|
||||
b32 success = 0;
|
||||
i32 attempts = 0;
|
||||
|
||||
LINUX_FN_DEBUG("%s, %dpt, tab_width: %d", filename, pt_size, tab_width);
|
||||
|
||||
if (linuxvars.font_part.base == 0){
|
||||
linuxvars.font_part = sysshared_scratch_partition(MB(8));
|
||||
}
|
||||
|
||||
i32 oversample = 2;
|
||||
|
||||
#if SUPPORT_DPI
|
||||
pt_size = round32(pt_size * size_change(linuxvars.dpi_x, linuxvars.dpi_y));
|
||||
#endif
|
||||
|
||||
for(; attempts < 3; ++attempts){
|
||||
#if LINUX_FONTS
|
||||
success = linux_font_load(&linuxvars.font_part, font_out, filename, pt_size, tab_width,
|
||||
linuxvars.settings.use_hinting);
|
||||
#else
|
||||
success = font_load(
|
||||
&linuxvars.font_part,
|
||||
font_out,
|
||||
filename,
|
||||
pt_size,
|
||||
tab_width,
|
||||
oversample,
|
||||
store_texture
|
||||
);
|
||||
#endif
|
||||
|
||||
if(success){
|
||||
break;
|
||||
} else {
|
||||
fprintf(stderr, "draw_font_load failed, %p %d\n", linuxvars.font_part.base, linuxvars.font_part.max);
|
||||
sysshared_partition_double(&linuxvars.font_part);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
#include "linux_4ed_fonts.cpp"
|
||||
|
||||
//
|
||||
// End of system funcs
|
||||
|
@ -1488,9 +1434,6 @@ LinuxLoadRenderCode(){
|
|||
linuxvars.target.push_clip = draw_push_clip;
|
||||
linuxvars.target.pop_clip = draw_pop_clip;
|
||||
linuxvars.target.push_piece = draw_push_piece;
|
||||
|
||||
linuxvars.target.font_set.font_load = system_draw_font_load;
|
||||
linuxvars.target.font_set.release_font = draw_release_font;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1499,7 +1442,7 @@ LinuxLoadRenderCode(){
|
|||
|
||||
internal void
|
||||
LinuxRedrawTarget(){
|
||||
launch_rendering(&linuxvars.target);
|
||||
launch_rendering(&linuxvars.system, &linuxvars.target);
|
||||
//glFlush();
|
||||
glXSwapBuffers(linuxvars.XDisplay, linuxvars.XWindow);
|
||||
}
|
||||
|
@ -2435,13 +2378,18 @@ LinuxGetXSettingsDPI(Display* dpy, int screen)
|
|||
// X11 window init
|
||||
//
|
||||
|
||||
internal i32
|
||||
size_change(i32 x, i32 y){
|
||||
f32 xs = x/96.f;
|
||||
f32 ys = y/96.f;
|
||||
f32 s = Min(xs, ys);
|
||||
i32 r = floor32(s);
|
||||
return(r);
|
||||
}
|
||||
|
||||
internal b32
|
||||
LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
|
||||
{
|
||||
// NOTE(allen): Here begins the linux screen setup stuff.
|
||||
// Behold the true nature of this wonderful OS:
|
||||
// (thanks again to Casey for providing this stuff)
|
||||
|
||||
#define BASE_W 800
|
||||
#define BASE_H 600
|
||||
|
||||
|
@ -2468,17 +2416,10 @@ LinuxX11WindowInit(int argc, char** argv, int* WinWidth, int* WinHeight)
|
|||
swa.backing_store = WhenMapped;
|
||||
swa.event_mask = StructureNotifyMask;
|
||||
swa.bit_gravity = NorthWestGravity;
|
||||
swa.colormap = XCreateColormap(linuxvars.XDisplay,
|
||||
RootWindow(linuxvars.XDisplay, Config.BestInfo.screen),
|
||||
Config.BestInfo.visual, AllocNone);
|
||||
swa.colormap = XCreateColormap(linuxvars.XDisplay, RootWindow(linuxvars.XDisplay, Config.BestInfo.screen), Config.BestInfo.visual, AllocNone);
|
||||
|
||||
linuxvars.XWindow =
|
||||
XCreateWindow(linuxvars.XDisplay,
|
||||
RootWindow(linuxvars.XDisplay, Config.BestInfo.screen),
|
||||
0, 0, *WinWidth, *WinHeight,
|
||||
0, Config.BestInfo.depth, InputOutput,
|
||||
Config.BestInfo.visual,
|
||||
CWBackingStore|CWBitGravity|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa);
|
||||
linuxvars.XWindow = XCreateWindow(linuxvars.XDisplay, RootWindow(linuxvars.XDisplay, Config.BestInfo.screen),
|
||||
0, 0, *WinWidth, *WinHeight, 0, Config.BestInfo.depth, InputOutput, Config.BestInfo.visual, CWBackingStore|CWBitGravity|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &swa);
|
||||
|
||||
if (!linuxvars.XWindow){
|
||||
LinuxFatalErrorMsg("XCreateWindow failed. Make sure your display is set up correctly.");
|
||||
|
@ -3241,6 +3182,12 @@ main(int argc, char **argv)
|
|||
}
|
||||
|
||||
|
||||
//
|
||||
// Font System Init
|
||||
//
|
||||
|
||||
system_font_init(&linuxvars.system.font, 0, 0, 16, true);
|
||||
|
||||
//
|
||||
// Epoll init
|
||||
//
|
||||
|
@ -3429,6 +3376,8 @@ main(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#include "font/4coder_font_static_functions.cpp"
|
||||
|
||||
// BOTTOM
|
||||
// vim: expandtab:ts=4:sts=4:sw=4
|
||||
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/*
|
||||
|
||||
The OS agnostic file tracking API for applications
|
||||
that want to interact with potentially many files on
|
||||
the disk that could be changed by other applications.
|
||||
|
||||
Created on: 29.08.2016
|
||||
|
||||
*/
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 20.07.2016
|
||||
*
|
||||
* File tracking linux.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "4tech_file_track.h"
|
||||
#include "4tech_file_track_general.c"
|
||||
#include "4ed_file_track.h"
|
||||
#include "4ed_file_track_general.cpp"
|
||||
|
||||
#include <libgen.h> // dirname
|
||||
|
||||
typedef struct {
|
||||
|
@ -32,61 +32,59 @@ typedef struct {
|
|||
#define to_tables(v) ((File_Track_Tables*)(v->tables))
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
init_track_system(File_Track_System *system,
|
||||
void *table_memory, int32_t table_memory_size,
|
||||
void *listener_memory, int32_t listener_memory_size){
|
||||
init_track_system(File_Track_System *system, Partition *scratch, void *table_memory, int32_t table_memory_size, void *listener_memory, int32_t listener_memory_size){
|
||||
File_Track_Result result = FileTrack_MemoryTooSmall;
|
||||
|
||||
|
||||
Assert(sizeof(Linux_File_Track_Vars) <= sizeof(File_Track_System));
|
||||
|
||||
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
|
||||
Assert(sizeof(Linux_File_Track_Entry) <= sizeof(File_Track_Entry));
|
||||
|
||||
|
||||
if (enough_memory_to_init_table(table_memory_size)){
|
||||
|
||||
|
||||
// NOTE(allen): Initialize main data tables
|
||||
vars->tables = (File_Track_Tables*) table_memory;
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
init_table_memory(tables, table_memory_size);
|
||||
|
||||
|
||||
vars->inotify = inotify_init1(IN_NONBLOCK);
|
||||
|
||||
|
||||
pthread_mutex_init(&vars->lock, NULL);
|
||||
|
||||
|
||||
vars->string_mem_begin = (char*)listener_memory;
|
||||
vars->string_mem_end = (char*)listener_memory + listener_memory_size;
|
||||
|
||||
|
||||
result = FileTrack_Good;
|
||||
}
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("result: %d", result);
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
add_listener(File_Track_System *system, char *filename){
|
||||
add_listener(File_Track_System *system, Partition *scratch, char *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
|
||||
if(tracking_system_has_space(tables, 1)){
|
||||
char *dir = dirname(strdupa(filename));
|
||||
size_t dir_len = strlen(dir) + 1;
|
||||
|
||||
|
||||
if(vars->string_mem_end - vars->string_mem_begin >= dir_len){
|
||||
int wd = inotify_add_watch(vars->inotify, dir, IN_CREATE | IN_DELETE | IN_MODIFY | IN_MOVE);
|
||||
|
||||
|
||||
if(wd != -1){
|
||||
File_Index key = { wd, 1 };
|
||||
File_Track_Entry *entry = tracking_system_lookup_entry(tables, key);
|
||||
Linux_File_Track_Entry *linux_entry = (Linux_File_Track_Entry*) entry;
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("map %s to wd %d", filename, wd);
|
||||
|
||||
|
||||
if(entry_is_available(entry)){
|
||||
linux_entry->hash = key;
|
||||
linux_entry->dir = vars->string_mem_begin;
|
||||
|
@ -107,26 +105,26 @@ add_listener(File_Track_System *system, char *filename){
|
|||
} else {
|
||||
result = FileTrack_OutOfTableMemory;
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("result: %d", result);
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
remove_listener(File_Track_System *system, char *filename){
|
||||
remove_listener(File_Track_System *system, Partition *scratch, char *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
File_Track_Entry *entries = (File_Track_Entry*) to_ptr(tables, tables->file_table);
|
||||
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
|
||||
char *dir = dirname(strdupa(filename));
|
||||
// NOTE(inso): this assumes the filename was previously added
|
||||
|
||||
|
||||
for(uint32_t i = 0; i < tables->max; ++i){
|
||||
Linux_File_Track_Entry *e = (Linux_File_Track_Entry*)(entries + i);
|
||||
if(e->hash.id[1] != 1) continue;
|
||||
|
@ -144,21 +142,21 @@ remove_listener(File_Track_System *system, char *filename){
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("result: %d", result);
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
move_track_system(File_Track_System *system, void *mem, int32_t size){
|
||||
move_track_system(File_Track_System *system, Partition *scratch, void *mem, int32_t size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
|
||||
{
|
||||
File_Track_Tables *original_tables = to_tables(vars);
|
||||
result = move_table_memory(original_tables, mem, size);
|
||||
|
@ -166,80 +164,80 @@ move_track_system(File_Track_System *system, void *mem, int32_t size){
|
|||
vars->tables = mem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("size: %d, %d", size, result);
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size){
|
||||
expand_track_system_listeners(File_Track_System *system, Partition *scratch, void *mem, int32_t size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
|
||||
// NOTE(inso): pointer to old string mem is lost here.
|
||||
// would need to keep it around if we want to free in the future
|
||||
|
||||
|
||||
// NOTE(inso): assuming PATH_MAX is a reasonable lower bound of extra memory to get
|
||||
|
||||
|
||||
if(size < PATH_MAX){
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
} else {
|
||||
vars->string_mem_begin = (char*) mem;
|
||||
vars->string_mem_end = (char*) mem + size;;
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("size: %d, result: %d", size, result);
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *size){
|
||||
get_change_event(File_Track_System *system, Partition *scratch, char *buffer, int32_t max, int32_t *size){
|
||||
File_Track_Result result = FileTrack_NoMoreEvents;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
|
||||
pthread_mutex_lock(&vars->lock);
|
||||
|
||||
|
||||
struct inotify_event *ev;
|
||||
char buff[sizeof(*ev) + NAME_MAX + 1] __attribute__((aligned(__alignof__(*ev))));
|
||||
|
||||
|
||||
// NOTE(inso): make sure we only read one event
|
||||
size_t read_count = sizeof(*ev);
|
||||
ssize_t n;
|
||||
|
||||
|
||||
do {
|
||||
n = read(vars->inotify, buff, read_count);
|
||||
read_count++;
|
||||
} while(n == -1 && errno == EINVAL);
|
||||
|
||||
|
||||
if(n == -1 && errno != EAGAIN){
|
||||
perror("inotify read");
|
||||
} else if(n > 0){
|
||||
ev = (struct inotify_event*) buff;
|
||||
|
||||
|
||||
File_Index key = { ev->wd, 1 };
|
||||
File_Track_Entry *entry = tracking_system_lookup_entry(tables, key);
|
||||
Linux_File_Track_Entry *linux_entry = (Linux_File_Track_Entry*) entry;
|
||||
|
||||
LINUX_FN_DEBUG("mask: %#x", ev->mask);
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("mask: %#x", ev->mask);
|
||||
|
||||
if(!entry_is_available(entry)){
|
||||
|
||||
|
||||
char* full_name = (char*) alloca(strlen(linux_entry->dir) + ev->len + 1);
|
||||
strcpy(full_name, linux_entry->dir);
|
||||
strcat(full_name, "/");
|
||||
strcat(full_name, ev->name);
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("event from wd %d (%s)", ev->wd, full_name);
|
||||
|
||||
|
||||
size_t full_name_size = strlen(full_name);
|
||||
if(max < full_name_size){
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
|
@ -254,26 +252,26 @@ get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *
|
|||
LINUX_FN_DEBUG("dead event from wd %d", ev->wd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_unlock(&vars->lock);
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
shut_down_track_system(File_Track_System *system){
|
||||
shut_down_track_system(File_Track_System *system, Partition *scratch){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Linux_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
|
||||
// NOTE(allen): Close all the global track system resources.
|
||||
if(close(vars->inotify) == -1){
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
|
||||
pthread_mutex_destroy(&vars->lock);
|
||||
|
||||
|
||||
LINUX_FN_DEBUG("result: %d", result);
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 09.02.2016
|
||||
*
|
||||
* Shared system functions
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "4ed_system_shared.h"
|
||||
#include "font/4coder_font_interface.h"
|
||||
#include "font/4coder_font_interface_to_os.h"
|
||||
#include "font/4coder_font_data.h"
|
||||
|
||||
struct Linux_Fonts{
|
||||
Partition part;
|
||||
Render_Font fonts[5];
|
||||
u32 font_count;
|
||||
};
|
||||
|
||||
global Linux_Fonts linux_fonts = {0};
|
||||
|
||||
internal
|
||||
Sys_Font_Get_Count_Sig(system_font_get_count){
|
||||
return(5);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Get_IDs_By_Index_Sig(system_font_get_ids_by_index){
|
||||
b32 result = false;
|
||||
u32 stop_index = first_index + index_count;
|
||||
if (stop_index <= linux_fonts.font_count){
|
||||
result = true;
|
||||
for (u32 i = first_index; i < stop_index; ++i){
|
||||
id_out[i-first_index] = i;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Get_Name_By_Index_Sig(system_font_get_name_by_index){
|
||||
u32 length = 0;
|
||||
if (font_index < linux_fonts.font_count){
|
||||
Render_Font *font = &linux_fonts.fonts[font_index];
|
||||
char *name = font->name;
|
||||
length = font->name_len;
|
||||
copy_partial_cs(str_out, str_out_cap, make_string(name, length));
|
||||
}
|
||||
return(length);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Get_Name_By_ID_Sig(system_font_get_name_by_id){
|
||||
u32 font_index = font_id;
|
||||
u32 result = system_font_get_name_by_index(font_index, str_out, str_out_cap);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Get_Render_Data_By_ID_Sig(system_font_get_render_data_by_id){
|
||||
Render_Font *result = 0;
|
||||
u32 font_index = font_id;
|
||||
if (font_index < linux_fonts.font_count){
|
||||
result = &linux_fonts.fonts[font_index];
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Load_Page_Sig(system_font_load_page){
|
||||
system_set_page(&linuxvars.system, &linux_fonts.part, font, page, page_number, 16, true);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Allocate_Sig(system_font_allocate){
|
||||
void *result = system_memory_allocate(size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Free_Sig(system_font_free){
|
||||
system_memory_free(ptr, 0);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Init_Sig(system_font_init){
|
||||
font->get_count = system_font_get_count;
|
||||
font->get_ids_by_index = system_font_get_ids_by_index;
|
||||
font->get_name_by_index = system_font_get_name_by_index;
|
||||
font->get_name_by_id = system_font_get_name_by_id;
|
||||
font->get_render_data_by_id = system_font_get_render_data_by_id;
|
||||
font->load_page = system_font_load_page;
|
||||
font->allocate = system_font_allocate;
|
||||
font->free = system_font_free;
|
||||
|
||||
font_size = clamp_bottom(8, font_size);
|
||||
|
||||
struct Font_Setup{
|
||||
char *c_filename;
|
||||
i32 filename_len;
|
||||
char *c_name;
|
||||
i32 name_len;
|
||||
u32 pt_size;
|
||||
};
|
||||
Font_Setup font_setup[] = {
|
||||
{literal("LiberationSans-Regular.ttf"), literal("Liberation Sans"), font_size},
|
||||
{literal("liberation-mono.ttf"), literal("Liberation Mono"), font_size},
|
||||
{literal("Hack-Regular.ttf"), literal("Hack"), font_size},
|
||||
{literal("CutiveMono-Regular.ttf"), literal("Cutive Mono"), font_size},
|
||||
{literal("Inconsolata-Regular.ttf"), literal("Inconsolata"), font_size},
|
||||
};
|
||||
|
||||
u32 font_count = Min(ArrayCount(linux_fonts.fonts), ArrayCount(font_setup));
|
||||
for (u32 i = 0; i < font_count; ++i){
|
||||
String filename = make_string(font_setup[i].c_filename, font_setup[i].filename_len);
|
||||
String name = make_string(font_setup[i].c_name, font_setup[i].name_len);
|
||||
u32 pt_size = font_setup[i].pt_size;
|
||||
Render_Font *render_font = &linux_fonts.fonts[i];
|
||||
|
||||
char full_filename_space[256];
|
||||
String full_filename = make_fixed_width_string(full_filename_space);
|
||||
sysshared_to_binary_path(&full_filename, filename.str);
|
||||
|
||||
system_set_font(&linuxvars.system, &linux_fonts.part, render_font, full_filename, name, pt_size, use_hinting);
|
||||
}
|
||||
|
||||
linux_fonts.font_count = font_count;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
|
@ -1,3 +1,15 @@
|
|||
/*
|
||||
* Insofaras
|
||||
*
|
||||
* ??.??.2016
|
||||
*
|
||||
* For getting the font files on Linux.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if 0
|
||||
#undef internal
|
||||
#include <fontconfig/fontconfig.h>
|
||||
#define internal static
|
||||
|
@ -8,26 +20,26 @@ static FcConfig* fc;
|
|||
internal char*
|
||||
linux_get_sys_font(char* name, i32 pt_size){
|
||||
char* result = 0;
|
||||
|
||||
|
||||
if(!fc){
|
||||
fc = FcInitLoadConfigAndFonts();
|
||||
}
|
||||
|
||||
|
||||
FcPattern* pat = FcPatternBuild(
|
||||
NULL,
|
||||
FC_POSTSCRIPT_NAME, FcTypeString, name,
|
||||
FC_SIZE, FcTypeDouble, (double)pt_size,
|
||||
FC_FONTFORMAT, FcTypeString, "TrueType",
|
||||
NULL
|
||||
);
|
||||
|
||||
);
|
||||
|
||||
FcConfigSubstitute(fc, pat, FcMatchPattern);
|
||||
FcDefaultSubstitute(pat);
|
||||
|
||||
|
||||
FcResult res;
|
||||
FcPattern* font = FcFontMatch(fc, pat, &res);
|
||||
FcChar8* fname = 0;
|
||||
|
||||
|
||||
if(font){
|
||||
FcPatternGetString(font, FC_FILE, 0, &fname);
|
||||
if(fname){
|
||||
|
@ -36,9 +48,9 @@ linux_get_sys_font(char* name, i32 pt_size){
|
|||
}
|
||||
FcPatternDestroy(font);
|
||||
}
|
||||
|
||||
|
||||
FcPatternDestroy(pat);
|
||||
|
||||
|
||||
if(!result){
|
||||
char space[1024];
|
||||
String str = make_fixed_width_string(space);
|
||||
|
@ -48,16 +60,16 @@ linux_get_sys_font(char* name, i32 pt_size){
|
|||
result = strdup(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
linux_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 tab_width, b32 use_hinting){
|
||||
b32 result = 0;
|
||||
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
|
||||
#if 0
|
||||
char* filename = linux_get_sys_font(name, pt_size);
|
||||
#else
|
||||
|
@ -67,22 +79,26 @@ linux_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 t
|
|||
sysshared_to_binary_path(&str, name);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (filename != 0){
|
||||
struct stat st;
|
||||
if(stat(filename, &st) == -1 || S_ISDIR(st.st_mode)){
|
||||
char buff[1024];
|
||||
|
||||
|
||||
// NOTE(inso): if/when you can load fonts from anywhere, the message should be changed.
|
||||
snprintf(buff, sizeof(buff), "Unable to load font '%s'. Make sure this file is in the same directory as the '4ed' executable.", filename);
|
||||
LinuxFatalErrorMsg(buff);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
result = font_load_freetype(part, rf, filename, pt_size, tab_width, use_hinting);
|
||||
}
|
||||
|
||||
|
||||
end_temp_memory(temp);
|
||||
|
||||
|
||||
return(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -21,8 +21,10 @@
|
|||
|
||||
#define IS_64BIT
|
||||
|
||||
#define LLU_CAST(n) (long long unsigned int)(n)
|
||||
|
||||
#define BEGIN_TIME_SECTION() uint64_t start = get_time()
|
||||
#define END_TIME_SECTION(n) uint64_t total = get_time() - start; printf("%-20s: %.2lu.%.6lu\n", (n), total/1000000, total%1000000);
|
||||
#define END_TIME_SECTION(n) uint64_t total = get_time() - start; printf("%-20s: %.2llu.%.6llu\n", (n), LLU_CAST(total/1000000), LLU_CAST(total%1000000));
|
||||
|
||||
//
|
||||
// 4coder specific
|
||||
|
@ -230,7 +232,7 @@ build_cl(u32 flags, char *code_path, char *code_file, char *out_path, char *out_
|
|||
swap_ptr(&line_prefix.build_options, &line_prefix.build_options_prev);
|
||||
|
||||
Temp_Dir temp = pushdir(out_path);
|
||||
systemf("%scl %s %s\\%s /Fe%s /link /INCREMENTAL:NO %s", line_prefix.build_options, line.build_options, code_path, code_file, out_file, link_line.build_options);
|
||||
systemf("%scl %s \"%s\\%s\" /Fe%s /link /INCREMENTAL:NO %s", line_prefix.build_options, line.build_options, code_path, code_file, out_file, link_line.build_options);
|
||||
popdir(temp);
|
||||
}
|
||||
|
||||
|
@ -351,7 +353,7 @@ buildsuper(char *code_path, char *out_path, char *filename, b32 x86_build){
|
|||
}
|
||||
#elif defined(IS_GCC)
|
||||
{
|
||||
systemf("\"%s/buildsuper.sh\" %s", code_path, filename);
|
||||
systemf("\"%s/buildsuper.sh\" \"%s\"", code_path, filename);
|
||||
}
|
||||
#else
|
||||
#error The build rule for this compiler is not ready
|
||||
|
@ -401,7 +403,7 @@ metagen(char *cdir){
|
|||
}
|
||||
|
||||
if (prev_error == 0){
|
||||
DECL_STR(cmd, META_DIR"/metagen");
|
||||
DECL_STR(cmd, META_DIR "/metagen");
|
||||
BEGIN_TIME_SECTION();
|
||||
execute_in_dir(cdir, cmd, 0);
|
||||
END_TIME_SECTION("run metagen");
|
||||
|
@ -468,7 +470,7 @@ build_main(char *cdir, u32 flags){
|
|||
{
|
||||
DECL_STR(file, "4ed_app_target.cpp");
|
||||
BEGIN_TIME_SECTION();
|
||||
build(OPTS | INCLUDES | SHARED_CODE | flags, cdir, file, dir, "4ed_app"DLL, "/EXPORT:app_get_functions");
|
||||
build(OPTS | INCLUDES | SHARED_CODE | flags, cdir, file, dir, "4ed_app" DLL, "/EXPORT:app_get_functions");
|
||||
END_TIME_SECTION("build 4ed_app");
|
||||
}
|
||||
|
||||
|
@ -624,11 +626,10 @@ package(char *cdir){
|
|||
clear_folder(par_dir);
|
||||
make_folder_if_missing(dir, "3rdparty");
|
||||
make_folder_if_missing(pack_dir, zip_dir);
|
||||
copy_file(build_dir, "4ed"EXE, dir, 0, 0);
|
||||
copy_file(build_dir, "4ed_app"DLL, dir, 0, 0);
|
||||
copy_file(build_dir, "4ed" EXE, dir, 0, 0);
|
||||
copy_file(build_dir, "4ed_app" DLL, dir, 0, 0);
|
||||
copy_all (pack_data_dir, "*", dir);
|
||||
copy_file(0, "README.txt", dir, 0, 0);
|
||||
copy_file(0, "TODO.txt", dir, 0, 0);
|
||||
//copy_file(0, "TODO.txt", dir, 0, 0);
|
||||
copy_file(data_dir, "release-config.4coder", dir, 0, "config.4coder");
|
||||
|
||||
get_4coder_dist_name(&str, true, zip_dir, tier, arch, "zip");
|
||||
|
@ -692,20 +693,17 @@ package(char *cdir){
|
|||
make_folder_if_missing(dir, "3rdparty");
|
||||
make_folder_if_missing(pack_dir, zip_dir);
|
||||
|
||||
copy_file(build_dir, "4ed"EXE, dir, 0, 0);
|
||||
//ONLY_WINDOWS(copy_file(build_dir, "4ed"PDB, dir, 0, 0));
|
||||
copy_file(build_dir, "4ed_app"DLL, dir, 0, 0);
|
||||
//ONLY_WINDOWS(copy_file(build_dir, "4ed_app"PDB, dir, 0, 0));
|
||||
copy_file(build_dir, "custom_4coder"DLL, dir, 0, 0);
|
||||
copy_file(build_dir, "4ed" EXE, dir, 0, 0);
|
||||
copy_file(build_dir, "4ed_app" DLL, dir, 0, 0);
|
||||
copy_file(build_dir, "custom_4coder" DLL, dir, 0, 0);
|
||||
|
||||
copy_all (pack_data_dir, "*", dir);
|
||||
copy_file(0, "README.txt", dir, 0, 0);
|
||||
copy_file(0, "TODO.txt", dir, 0, 0);
|
||||
//copy_file(0, "TODO.txt", dir, 0, 0);
|
||||
copy_file(data_dir, "release-config.4coder", dir, 0, "config.4coder");
|
||||
|
||||
copy_all(0, "4coder_*", dir);
|
||||
|
||||
copy_file(0, "buildsuper"BAT, dir, 0, 0);
|
||||
copy_file(0, "buildsuper" BAT, dir, 0, 0);
|
||||
|
||||
DECL_STR(custom_dir, "4coder_API");
|
||||
DECL_STR(custom_helper_dir, "4coder_helper");
|
||||
|
@ -720,18 +718,18 @@ package(char *cdir){
|
|||
};
|
||||
i32 dir_count = ArrayCount(dir_array);
|
||||
|
||||
for (i32 i = 0; i < dir_count; ++i){
|
||||
char *d = dir_array[i];
|
||||
for (i32 j = 0; j < dir_count; ++j){
|
||||
char *d = dir_array[j];
|
||||
make_folder_if_missing(dir, d);
|
||||
|
||||
char space[256];
|
||||
String str = make_fixed_width_string(space);
|
||||
append_sc(&str, dir);
|
||||
append_s_char(&str, platform_correct_slash);
|
||||
append_sc(&str, d);
|
||||
terminate_with_null(&str);
|
||||
String copy_name = make_fixed_width_string(space);
|
||||
append_sc(©_name, dir);
|
||||
append_s_char(©_name, platform_correct_slash);
|
||||
append_sc(©_name, d);
|
||||
terminate_with_null(©_name);
|
||||
|
||||
copy_all(d, "*", str.str);
|
||||
copy_all(d, "*", copy_name.str);
|
||||
}
|
||||
|
||||
get_4coder_dist_name(&str, true, zip_dir, tier, arch, "zip");
|
||||
|
|
|
@ -284,7 +284,7 @@ typedef enum Doc_Note_Type{
|
|||
} Doc_Note_Type;
|
||||
|
||||
static String
|
||||
doc_note_string[] = {
|
||||
defined_doc_notes[] = {
|
||||
make_lit_string("DOC_PARAM"),
|
||||
make_lit_string("DOC_RETURN"),
|
||||
make_lit_string("DOC"),
|
||||
|
@ -446,7 +446,7 @@ perform_doc_parse(Partition *part, String doc_string, Documentation *doc){
|
|||
}
|
||||
else{
|
||||
int32_t doc_note_type;
|
||||
if (string_set_match(doc_note_string, ArrayCount(doc_note_string), doc_note, &doc_note_type)){
|
||||
if (string_set_match(defined_doc_notes, ArrayCount(defined_doc_notes), doc_note, &doc_note_type)){
|
||||
|
||||
doc_parse_note_string(doc_string, &pos);
|
||||
|
||||
|
@ -480,7 +480,7 @@ perform_doc_parse(Partition *part, String doc_string, Documentation *doc){
|
|||
}
|
||||
else{
|
||||
int32_t doc_note_type;
|
||||
if (string_set_match(doc_note_string, ArrayCount(doc_note_string), doc_note, &doc_note_type)){
|
||||
if (string_set_match(defined_doc_notes, ArrayCount(defined_doc_notes), doc_note, &doc_note_type)){
|
||||
|
||||
String doc_note_string = doc_parse_note_string(doc_string, &pos);
|
||||
|
||||
|
@ -760,10 +760,10 @@ static int32_t
|
|||
enum_parse(Partition *part, Parse_Context *context, Item_Node *item){
|
||||
int32_t result = false;
|
||||
|
||||
String doc_string = {0};
|
||||
get_doc_string_from_prev(context, &doc_string);
|
||||
String parent_doc_string = {0};
|
||||
get_doc_string_from_prev(context, &parent_doc_string);
|
||||
|
||||
Cpp_Token *start_token = get_token(context);
|
||||
Cpp_Token *parent_start_token = get_token(context);
|
||||
Cpp_Token *token = 0;
|
||||
|
||||
for (; (token = get_token(context)) != 0; get_next_token(context)){
|
||||
|
@ -773,7 +773,7 @@ enum_parse(Partition *part, Parse_Context *context, Item_Node *item){
|
|||
}
|
||||
|
||||
if (token){
|
||||
String name = {0};
|
||||
String parent_name = {0};
|
||||
Cpp_Token *token_j = 0;
|
||||
|
||||
for (; (token_j = get_token(context)) != 0; get_prev_token(context)){
|
||||
|
@ -782,10 +782,10 @@ enum_parse(Partition *part, Parse_Context *context, Item_Node *item){
|
|||
}
|
||||
}
|
||||
|
||||
name = get_lexeme(*token_j, context->data);
|
||||
parent_name = get_lexeme(*token_j, context->data);
|
||||
|
||||
set_token(context, token);
|
||||
for (; (token = get_token(context)) > start_token; get_next_token(context)){
|
||||
for (; (token = get_token(context)) > parent_start_token; get_next_token(context)){
|
||||
if (token->type == CPP_TOKEN_BRACE_OPEN){
|
||||
break;
|
||||
}
|
||||
|
@ -855,8 +855,8 @@ enum_parse(Partition *part, Parse_Context *context, Item_Node *item){
|
|||
get_next_token(context);
|
||||
|
||||
item->t = Item_Enum;
|
||||
item->name = name;
|
||||
item->doc_string = doc_string;
|
||||
item->name = parent_name;
|
||||
item->doc_string = parent_doc_string;
|
||||
item->first_child = first_member;
|
||||
result = true;
|
||||
}
|
||||
|
@ -912,9 +912,9 @@ parameter_parse(Partition *part, char *data, Cpp_Token *args_start_token, Cpp_To
|
|||
param_name_token->start > param_string_start;
|
||||
--param_name_token){
|
||||
if (param_name_token->type == CPP_TOKEN_IDENTIFIER){
|
||||
int32_t start = param_name_token->start;
|
||||
int32_t size = param_name_token->size;
|
||||
breakdown.args[arg_index].param_name = make_string(data + start, size);
|
||||
int32_t name_start = param_name_token->start;
|
||||
int32_t name_size = param_name_token->size;
|
||||
breakdown.args[arg_index].param_name = make_string(data + name_start, name_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1190,7 +1190,7 @@ macro_parse(Partition *part, Parse_Context *context, Item_Node *item){
|
|||
}
|
||||
|
||||
static Meta_Unit
|
||||
compile_meta_unit(Partition *part, char *code_directory, char **files, Meta_Keywords *keywords, int32_t key_count){
|
||||
compile_meta_unit(Partition *part, char *code_directory, char **files, Meta_Keywords *meta_keywords, int32_t key_count){
|
||||
Meta_Unit unit = {0};
|
||||
|
||||
int32_t file_count = 0;
|
||||
|
@ -1232,8 +1232,8 @@ compile_meta_unit(Partition *part, char *code_directory, char **files, Meta_Keyw
|
|||
|
||||
String lexeme = get_lexeme(*token, context->data);
|
||||
int32_t match_index = 0;
|
||||
if (string_set_match_table(keywords, sizeof(*keywords), key_count, lexeme, &match_index)){
|
||||
Item_Type type = keywords[match_index].type;
|
||||
if (string_set_match_table(meta_keywords, sizeof(*meta_keywords), key_count, lexeme, &match_index)){
|
||||
Item_Type type = meta_keywords[match_index].type;
|
||||
|
||||
if (type > Item_Null && type < Item_Type_Count){
|
||||
++unit.set.count;
|
||||
|
@ -1265,8 +1265,8 @@ compile_meta_unit(Partition *part, char *code_directory, char **files, Meta_Keyw
|
|||
|
||||
String lexeme = get_lexeme(*token, context->data);
|
||||
int32_t match_index = 0;
|
||||
if (string_set_match_table(keywords, sizeof(*keywords), key_count, lexeme, &match_index)){
|
||||
Item_Type type = keywords[match_index].type;
|
||||
if (string_set_match_table(meta_keywords, sizeof(*meta_keywords), key_count, lexeme, &match_index)){
|
||||
Item_Type type = meta_keywords[match_index].type;
|
||||
|
||||
switch (type){
|
||||
case Item_Function:
|
||||
|
@ -1364,9 +1364,9 @@ compile_meta_unit(Partition *part, char *code_directory, char **files, Meta_Keyw
|
|||
}
|
||||
|
||||
static Meta_Unit
|
||||
compile_meta_unit(Partition *part, char *code_directory, char *file, Meta_Keywords *keywords, int32_t key_count){
|
||||
compile_meta_unit(Partition *part, char *code_directory, char *file, Meta_Keywords *meta_keywords, int32_t key_count){
|
||||
char *file_array[2] = {file, 0};
|
||||
Meta_Unit unit = compile_meta_unit(part, code_directory, file_array, keywords, key_count);
|
||||
Meta_Unit unit = compile_meta_unit(part, code_directory, file_array, meta_keywords, key_count);
|
||||
return(unit);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
|
||||
/*
|
||||
* For generating the header of the TODO files so I don't have to
|
||||
* keep doing that by hand and accidentally forgetting half the time.
|
||||
* -Allen
|
||||
* 12.05.2016 (dd.mm.yyyy)
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
char *header =
|
||||
"Distribution Date: %d.%d.%d (dd.mm.yyyy)\n"
|
||||
"\n"
|
||||
"Thank you for contributing to the 4coder project!\n"
|
||||
"\n"
|
||||
"To submit bug reports or to request particular features email editor@4coder.net.\n"
|
||||
"\n"
|
||||
"Watch 4coder.net blog and @AllenWebster4th twitter for news about 4coder progress.\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
typedef struct Readme_Variables{
|
||||
int32_t day, month, year;
|
||||
} Readme_Variables;
|
||||
|
||||
typedef struct File_Data{
|
||||
char *data;
|
||||
int32_t size;
|
||||
int32_t file_exists;
|
||||
} File_Data;
|
||||
|
||||
File_Data
|
||||
dump(char *file_name){
|
||||
File_Data result = {0};
|
||||
FILE *file = fopen(file_name, "rb");
|
||||
|
||||
if (file){
|
||||
result.file_exists = 1;
|
||||
fseek(file, 0, SEEK_END);
|
||||
result.size = ftell(file);
|
||||
if (result.size > 0){
|
||||
result.data = (char*)malloc(result.size + 1);
|
||||
result.data[result.size + 1] = 0;
|
||||
fseek(file, 0, SEEK_SET);
|
||||
fread(result.data, 1, result.size, file);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
void
|
||||
generate(char *file_name_out, char *file_name_body, Readme_Variables vars){
|
||||
File_Data in;
|
||||
FILE *out;
|
||||
|
||||
in = dump(file_name_body);
|
||||
|
||||
if (in.file_exists){
|
||||
out = fopen(file_name_out, "wb");
|
||||
fprintf(out, header, vars.day, vars.month,vars.year);
|
||||
if (in.size > 0){
|
||||
fprintf(out, "%s", in.data);
|
||||
}
|
||||
fclose(out);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(){
|
||||
time_t ctime;
|
||||
struct tm tm;
|
||||
Readme_Variables vars;
|
||||
|
||||
ctime = time(0);
|
||||
localtime_s(&tm, &ctime);
|
||||
|
||||
vars.day = tm.tm_mday;
|
||||
vars.month = tm.tm_mon + 1;
|
||||
vars.year = tm.tm_year + 1900;
|
||||
|
||||
generate("README.txt", "README_body.txt", vars);
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
1
|
||||
0
|
||||
63
|
||||
68
|
||||
|
||||
|
||||
|
|
Binary file not shown.
|
@ -970,6 +970,23 @@ This call returns non-zero on a successful copy.) */{
|
|||
return 1;
|
||||
}
|
||||
|
||||
CPP_NAME(copy_checked)
|
||||
API_EXPORT FSTRING_LINK b32_4tech
|
||||
copy_checked_cs(char *dest, i32_4tech dest_cap, String src)/*
|
||||
DOC(This call performs a copy from the src string to the dest string.
|
||||
The value dest_cap is checked before any coppying is done.
|
||||
This call returns non-zero on a successful copy.)
|
||||
*/{
|
||||
i32_4tech i;
|
||||
if (dest_cap < src.size){
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < src.size; ++i){
|
||||
dest[i] = src.str[i];
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
CPP_NAME(copy_partial)
|
||||
API_EXPORT FSTRING_LINK b32_4tech
|
||||
copy_partial_sc(String *dest, char *src)/*
|
||||
|
@ -995,9 +1012,9 @@ CPP_NAME(copy_partial)
|
|||
API_EXPORT FSTRING_LINK b32_4tech
|
||||
copy_partial_ss(String *dest, String src)/*
|
||||
DOC(This call performs a copy from the src string to the dest string.
|
||||
The memory_size of dest is checked if the entire copy cannot be performed,
|
||||
as many bytes as possible are coppied to dest. This call returns non-zero
|
||||
if the entire string is coppied to dest.) */{
|
||||
The memory_size of dest is checked. If the entire copy cannot be performed,
|
||||
as many bytes as possible are coppied to dest.
|
||||
This call returns non-zero if the entire string is coppied to dest.) */{
|
||||
char *dest_str = dest->str;
|
||||
i32_4tech memory_size = dest->memory_size;
|
||||
b32_4tech result = 0;
|
||||
|
@ -1009,7 +1026,28 @@ if the entire string is coppied to dest.) */{
|
|||
dest_str[i] = src.str[i];
|
||||
}
|
||||
dest->size = memory_size;
|
||||
return result;
|
||||
return(result);
|
||||
}
|
||||
|
||||
CPP_NAME(copy_partial)
|
||||
API_EXPORT FSTRING_LINK b32_4tech
|
||||
copy_partial_cs(char *dest, i32_4tech dest_cap, String src)/*
|
||||
DOC(This call performs a copy from the src string to the dest string.
|
||||
The value dest_cap is checked. If the entire copy cannot be performed,
|
||||
as many bytes as possible are coppied to dest.
|
||||
This call returns non-zero if the entire string is coppied to dest.)
|
||||
*/{
|
||||
b32_4tech result = 0;
|
||||
i32_4tech copy_size = dest_cap;
|
||||
i32_4tech i;
|
||||
if (dest_cap >= src.size){
|
||||
result = 1;
|
||||
copy_size = src.size;
|
||||
}
|
||||
for (i = 0; i < copy_size; ++i){
|
||||
dest[i] = src.str[i];
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
CPP_NAME(copy)
|
||||
|
|
164
win32_4ed.cpp
164
win32_4ed.cpp
|
@ -28,6 +28,12 @@
|
|||
// Program setup
|
||||
//
|
||||
|
||||
#define SUPPORT_DPI 1
|
||||
#define UNICODE
|
||||
|
||||
#define FPS 60
|
||||
#define frame_useconds (1000000 / FPS)
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "4tech_defines.h"
|
||||
|
@ -63,22 +69,19 @@
|
|||
|
||||
#define GL_TEXTURE_MAX_LEVEL 0x813D
|
||||
|
||||
#include "filetrack/4tech_file_track_win32.c"
|
||||
//////////////////////////////
|
||||
|
||||
#include "4ed_file_track.h"
|
||||
#include "4ed_system_shared.h"
|
||||
|
||||
#define SUPPORT_DPI 1
|
||||
#define USE_FT_FONTS 1
|
||||
|
||||
#define FPS 60
|
||||
#define frame_useconds (1000000 / FPS)
|
||||
|
||||
#define WM_4coder_ANIMATE (WM_USER + 0)
|
||||
|
||||
#include "win32_4ed_file_track.cpp"
|
||||
|
||||
//
|
||||
// Win32_Vars structs
|
||||
//
|
||||
|
||||
#define WM_4coder_ANIMATE (WM_USER + 0)
|
||||
|
||||
struct Thread_Context{
|
||||
u32 job_id;
|
||||
b32 running;
|
||||
|
@ -185,10 +188,8 @@ typedef struct Win32_Vars{
|
|||
b32 next_clipboard_is_self;
|
||||
DWORD clipboard_sequence;
|
||||
|
||||
|
||||
HWND window_handle;
|
||||
Render_Target target;
|
||||
Partition font_part;
|
||||
#if SUPPORT_DPI
|
||||
i32 dpi_x, dpi_y;
|
||||
#endif
|
||||
|
@ -333,9 +334,7 @@ Sys_Release_Lock_Sig(system_release_lock){
|
|||
|
||||
internal void
|
||||
system_wait_cv(i32 crit_id, i32 cv_id){
|
||||
SleepConditionVariableCS(win32vars.condition_vars + cv_id,
|
||||
win32vars.locks + crit_id,
|
||||
INFINITE);
|
||||
SleepConditionVariableCS(win32vars.condition_vars + cv_id, win32vars.locks + crit_id, INFINITE);
|
||||
}
|
||||
|
||||
internal void
|
||||
|
@ -372,9 +371,7 @@ JobThreadProc(LPVOID lpParameter){
|
|||
// wrapping by the queue wrap. That was super stupid what was that?
|
||||
// Now it just wraps by the queue wrap.
|
||||
u32 next_read_index = (read_index + 1) % QUEUE_WRAP;
|
||||
u32 safe_read_index =
|
||||
InterlockedCompareExchange(&queue->read_position,
|
||||
next_read_index, read_index);
|
||||
u32 safe_read_index = InterlockedCompareExchange(&queue->read_position, next_read_index, read_index);
|
||||
|
||||
if (safe_read_index == read_index){
|
||||
Full_Job_Data *full_job = queue->jobs + safe_read_index;
|
||||
|
@ -382,16 +379,13 @@ JobThreadProc(LPVOID lpParameter){
|
|||
// with the cancel job routine, which may try to cancel this job
|
||||
// at the same time that we try to run it
|
||||
|
||||
i32 safe_running_thread =
|
||||
InterlockedCompareExchange(&full_job->running_thread,
|
||||
thread->id, THREAD_NOT_ASSIGNED);
|
||||
i32 safe_running_thread =InterlockedCompareExchange(&full_job->running_thread, thread->id, THREAD_NOT_ASSIGNED);
|
||||
|
||||
if (safe_running_thread == THREAD_NOT_ASSIGNED){
|
||||
thread->job_id = full_job->id;
|
||||
thread->running = 1;
|
||||
|
||||
full_job->job.callback(&win32vars.system,
|
||||
thread, thread_memory, full_job->job.data);
|
||||
full_job->job.callback(&win32vars.system, thread, thread_memory, full_job->job.data);
|
||||
PostMessage(win32vars.window_handle, WM_4coder_ANIMATE, 0, 0);
|
||||
//full_job->running_thread = 0;
|
||||
thread->running = 0;
|
||||
|
@ -1392,75 +1386,7 @@ Sys_Send_Exit_Signal_Sig(system_send_exit_signal){
|
|||
|
||||
#include "4ed_system_shared.cpp"
|
||||
|
||||
#if USE_FT_FONTS
|
||||
# include "win32_ft_font.cpp"
|
||||
#endif
|
||||
|
||||
internal f32
|
||||
size_change(i32 dpi_x, i32 dpi_y){
|
||||
// TODO(allen): We're just hoping dpi_x == dpi_y for now I guess.
|
||||
f32 size_x = dpi_x / 96.f;
|
||||
f32 size_y = dpi_y / 96.f;
|
||||
f32 size_max = Max(size_x, size_y);
|
||||
return(size_max);
|
||||
}
|
||||
|
||||
internal
|
||||
Font_Load_Sig(system_draw_font_load){
|
||||
if (win32vars.font_part.base == 0){
|
||||
win32vars.font_part = Win32ScratchPartition(MB(8));
|
||||
}
|
||||
|
||||
i32 oversample = 2;
|
||||
AllowLocal(oversample);
|
||||
|
||||
#if SUPPORT_DPI
|
||||
pt_size = round32(pt_size * size_change(win32vars.dpi_x, win32vars.dpi_y));
|
||||
#endif
|
||||
|
||||
for (b32 success = 0; success == 0;){
|
||||
#if USE_WIN32_FONTS
|
||||
|
||||
success = win32_font_load(&win32vars.font_part,
|
||||
font_out,
|
||||
filename,
|
||||
fontname,
|
||||
pt_size,
|
||||
tab_width,
|
||||
oversample,
|
||||
store_texture);
|
||||
|
||||
#elif USE_FT_FONTS
|
||||
|
||||
success = win32_ft_font_load(&win32vars.font_part,
|
||||
font_out,
|
||||
filename,
|
||||
pt_size,
|
||||
tab_width,
|
||||
win32vars.settings.use_hinting);
|
||||
|
||||
#else
|
||||
|
||||
success = stb_font_load(&win32vars.font_part,
|
||||
font_out,
|
||||
filename,
|
||||
pt_size,
|
||||
tab_width,
|
||||
oversample,
|
||||
store_texture);
|
||||
|
||||
#endif
|
||||
|
||||
// TODO(allen): Make the growable partition something
|
||||
// that can just be passed directly to font load and
|
||||
// let it be grown there.
|
||||
if (!success){
|
||||
Win32ScratchPartitionDouble(&win32vars.font_part);
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
#include "win32_4ed_fonts.cpp"
|
||||
|
||||
//
|
||||
// Linkage to Custom and Application
|
||||
|
@ -1529,7 +1455,6 @@ Win32LoadSystemCode(){
|
|||
win32vars.system.is_fullscreen = system_is_fullscreen;win32vars.system.show_mouse_cursor = system_show_mouse_cursor;
|
||||
win32vars.system.send_exit_signal = system_send_exit_signal;
|
||||
|
||||
|
||||
#if FRED_INTERNAL
|
||||
win32vars.system.internal_get_thread_states = INTERNAL_get_thread_states;
|
||||
#endif
|
||||
|
@ -1540,9 +1465,6 @@ Win32LoadRenderCode(){
|
|||
win32vars.target.push_clip = draw_push_clip;
|
||||
win32vars.target.pop_clip = draw_pop_clip;
|
||||
win32vars.target.push_piece = draw_push_piece;
|
||||
|
||||
win32vars.target.font_set.font_load = system_draw_font_load;
|
||||
win32vars.target.font_set.release_font = draw_release_font;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1587,7 +1509,7 @@ Win32KeycodeInit(){
|
|||
|
||||
internal void
|
||||
Win32RedrawScreen(HDC hdc){
|
||||
launch_rendering(&win32vars.target);
|
||||
launch_rendering(&win32vars.system, &win32vars.target);
|
||||
glFlush();
|
||||
SwapBuffers(hdc);
|
||||
}
|
||||
|
@ -1912,7 +1834,7 @@ Win32Callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
|
|||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
win32vars.got_useful_event = 1;
|
||||
i16 rotation = GET_WHEEL_DELTA_WPARAM(wParam);
|
||||
Font_ID rotation = GET_WHEEL_DELTA_WPARAM(wParam);
|
||||
if (rotation > 0){
|
||||
win32vars.input_chunk.trans.mouse_wheel = 1;
|
||||
}
|
||||
|
@ -2103,11 +2025,10 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
|||
win32vars.target.max = MB(1);
|
||||
win32vars.target.push_buffer = (char*)system_get_memory(win32vars.target.max);
|
||||
|
||||
if (!memory_vars.vars_memory || !memory_vars.target_memory || !memory_vars.user_memory || !win32vars.target.push_buffer){
|
||||
if (memory_vars.vars_memory == 0 || memory_vars.target_memory == 0 || memory_vars.user_memory == 0 || win32vars.target.push_buffer == 0){
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// System and Application Layer Linkage
|
||||
//
|
||||
|
@ -2117,17 +2038,14 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
|||
}
|
||||
|
||||
Win32LoadSystemCode();
|
||||
|
||||
Win32LoadRenderCode();
|
||||
|
||||
|
||||
//
|
||||
// Shared Systems Init
|
||||
//
|
||||
|
||||
init_shared_vars();
|
||||
|
||||
|
||||
//
|
||||
// Read Command Line
|
||||
//
|
||||
|
@ -2151,7 +2069,6 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
|||
|
||||
sysshared_filter_real_files(files, file_count);
|
||||
|
||||
|
||||
//
|
||||
// Custom Layer Linkage
|
||||
//
|
||||
|
@ -2242,25 +2159,32 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
|||
exit(1);
|
||||
}
|
||||
|
||||
HDC hdc = GetDC(win32vars.window_handle);
|
||||
|
||||
{
|
||||
HDC hdc = GetDC(win32vars.window_handle);
|
||||
|
||||
#if SUPPORT_DPI
|
||||
// TODO(allen): not Windows XP compatible, how do I handle that?
|
||||
SetProcessDPIAware();
|
||||
|
||||
win32vars.dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
|
||||
win32vars.dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
// TODO(allen): not Windows XP compatible, how do I handle that?
|
||||
SetProcessDPIAware();
|
||||
|
||||
win32vars.dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
|
||||
win32vars.dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
|
||||
#else
|
||||
win32vars.dpi_x = 1;
|
||||
win32vars.dpi_y = 1;
|
||||
win32vars.dpi_x = 1;
|
||||
win32vars.dpi_y = 1;
|
||||
#endif
|
||||
|
||||
GetClientRect(win32vars.window_handle, &window_rect);
|
||||
ReleaseDC(win32vars.window_handle, hdc);
|
||||
|
||||
GetClientRect(win32vars.window_handle, &window_rect);
|
||||
ReleaseDC(win32vars.window_handle, hdc);
|
||||
}
|
||||
|
||||
Win32InitGL();
|
||||
Win32Resize(window_rect.right - window_rect.left, window_rect.bottom - window_rect.top);
|
||||
|
||||
//
|
||||
// Font System Init
|
||||
//
|
||||
|
||||
system_font_init(&win32vars.system.font, 0, 0, 16, true);
|
||||
|
||||
//
|
||||
// Misc System Initializations
|
||||
|
@ -2543,13 +2467,15 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS
|
|||
return(0);
|
||||
}
|
||||
|
||||
#include "font/4coder_font_static_functions.cpp"
|
||||
|
||||
#if 0
|
||||
// NOTE(allen): In case I want to switch back to a console
|
||||
// application at some point.
|
||||
int main(int argc, char **argv){
|
||||
HINSTANCE hInstance = GetModuleHandle(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
/*
|
||||
|
||||
The OS agnostic file tracking API for applications
|
||||
that want to interact with potentially many files on
|
||||
the disk that could be changed by other applications.
|
||||
|
||||
Created on: 20.07.2016
|
||||
|
||||
*/
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 20.07.2016
|
||||
*
|
||||
* File tracking win32.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "4tech_file_track.h"
|
||||
#include "4tech_file_track_general.c"
|
||||
#include "4ed_file_track.h"
|
||||
#include "4ed_file_track_general.cpp"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
typedef struct {
|
||||
OVERLAPPED overlapped;
|
||||
char result[2048];
|
||||
u16 result[1024];
|
||||
HANDLE dir;
|
||||
int32_t user_count;
|
||||
i32 user_count;
|
||||
} Win32_Directory_Listener;
|
||||
global_const OVERLAPPED null_overlapped = {0};
|
||||
|
||||
typedef struct {
|
||||
DLL_Node node;
|
||||
|
@ -44,9 +44,7 @@ typedef struct {
|
|||
#define to_tables(v) ((File_Track_Tables*)(v->tables))
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
init_track_system(File_Track_System *system,
|
||||
void *table_memory, int32_t table_memory_size,
|
||||
void *listener_memory, int32_t listener_memory_size){
|
||||
init_track_system(File_Track_System *system, void *table_memory, i32 table_memory_size, void *listener_memory, i32 listener_memory_size){
|
||||
File_Track_Result result = FileTrack_MemoryTooSmall;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
|
@ -65,8 +63,8 @@ init_track_system(File_Track_System *system,
|
|||
init_sentinel_node(&vars->free_sentinel);
|
||||
|
||||
Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)listener_memory;
|
||||
int32_t count = listener_memory_size / sizeof(Win32_Directory_Listener_Node);
|
||||
for (int32_t i = 0; i < count; ++i, ++listener){
|
||||
i32 count = listener_memory_size / sizeof(Win32_Directory_Listener_Node);
|
||||
for (i32 i = 0; i < count; ++i, ++listener){
|
||||
insert_node(&vars->free_sentinel, &listener->node);
|
||||
}
|
||||
}
|
||||
|
@ -83,30 +81,26 @@ init_track_system(File_Track_System *system,
|
|||
return(result);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
internal_get_parent_name(char *out, int32_t max, char *name){
|
||||
int32_t len, slash_i;
|
||||
|
||||
char *ptr = name;
|
||||
internal umem
|
||||
internal_utf8_file_to_utf16_parent(u16 *out, u32 max, u8 *name){
|
||||
u8 *ptr = name;
|
||||
for (; *ptr != 0; ++ptr);
|
||||
len = (int32_t)(ptr - name);
|
||||
umem len = (umem)(ptr - name);
|
||||
|
||||
// TODO(allen): make this system real
|
||||
Assert(len < max);
|
||||
|
||||
for (slash_i = len-1;
|
||||
slash_i > 0 && name[slash_i] != '\\' && name[slash_i] != '/';
|
||||
--slash_i);
|
||||
umem slash_i = len-1;
|
||||
for (;slash_i > 0 && name[slash_i] != '\\' && name[slash_i] != '/';--slash_i);
|
||||
|
||||
for (int32_t i = 0; i < slash_i; ++i){
|
||||
out[i] = name[i];
|
||||
}
|
||||
b32 error = false;
|
||||
slash_i = utf8_to_utf16_minimal_checking(out, max-1, name, len, &error);
|
||||
out[slash_i] = 0;
|
||||
|
||||
return(slash_i);
|
||||
}
|
||||
|
||||
static File_Index
|
||||
internal File_Index
|
||||
internal_get_file_index(BY_HANDLE_FILE_INFORMATION info){
|
||||
File_Index hash;
|
||||
hash.id[0] = info.nFileIndexLow;
|
||||
|
@ -128,7 +122,7 @@ FILE_NOTIFY_CHANGE_CREATION | \
|
|||
0)
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
add_listener(File_Track_System *system, char *filename){
|
||||
add_listener(File_Track_System *system, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
|
@ -137,10 +131,10 @@ add_listener(File_Track_System *system, char *filename){
|
|||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
// TODO(allen): make this real!
|
||||
char dir_name[1024];
|
||||
internal_get_parent_name(dir_name, sizeof(dir_name), filename);
|
||||
u16 dir_name[1024];
|
||||
internal_utf8_file_to_utf16_parent(dir_name, ArrayCount(dir_name), filename);
|
||||
|
||||
HANDLE dir = CreateFile(dir_name, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 0);
|
||||
HANDLE dir = CreateFile((LPCWSTR)dir_name, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 0);
|
||||
|
||||
if (dir != INVALID_HANDLE_VALUE){
|
||||
BY_HANDLE_FILE_INFORMATION dir_info = {0};
|
||||
|
@ -157,7 +151,7 @@ add_listener(File_Track_System *system, char *filename){
|
|||
allocate_node(&vars->free_sentinel);
|
||||
if (node){
|
||||
if (CreateIoCompletionPort(dir, vars->iocp, (ULONG_PTR)node, 1)){
|
||||
ZeroStruct(node->listener.overlapped);
|
||||
node->listener.overlapped = null_overlapped;
|
||||
if (ReadDirectoryChangesW(dir, node->listener.result, sizeof(node->listener.result), 1, FLAGS, 0, &node->listener.overlapped, 0)){
|
||||
node->listener.dir = dir;
|
||||
node->listener.user_count = 1;
|
||||
|
@ -210,57 +204,48 @@ add_listener(File_Track_System *system, char *filename){
|
|||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
remove_listener(File_Track_System *system, char *filename){
|
||||
remove_listener(File_Track_System *system, u8 *filename){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
EnterCriticalSection(&vars->table_lock);
|
||||
|
||||
{
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
// TODO(allen): make this real!
|
||||
u16 dir_name[1024];
|
||||
internal_utf8_file_to_utf16_parent(dir_name, ArrayCount(dir_name), filename);
|
||||
|
||||
HANDLE dir = CreateFile((LPCWSTR)dir_name, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, 0);
|
||||
|
||||
if (dir != INVALID_HANDLE_VALUE){
|
||||
BY_HANDLE_FILE_INFORMATION dir_info = {0};
|
||||
DWORD getinfo_result = GetFileInformationByHandle(dir, &dir_info);
|
||||
|
||||
// TODO(allen): make this real!
|
||||
char dir_name[1024];
|
||||
internal_get_parent_name(dir_name, sizeof(dir_name), filename);
|
||||
|
||||
HANDLE dir = CreateFile(
|
||||
dir_name,
|
||||
FILE_LIST_DIRECTORY,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
||||
0);
|
||||
|
||||
if (dir != INVALID_HANDLE_VALUE){
|
||||
BY_HANDLE_FILE_INFORMATION dir_info = {0};
|
||||
DWORD getinfo_result = GetFileInformationByHandle(dir, &dir_info);
|
||||
if (getinfo_result){
|
||||
File_Index dir_hash = internal_get_file_index(dir_info);
|
||||
File_Track_Entry *dir_lookup = tracking_system_lookup_entry(tables, dir_hash);
|
||||
Win32_File_Track_Entry *win32_dir = (Win32_File_Track_Entry*)dir_lookup;
|
||||
|
||||
if (getinfo_result){
|
||||
File_Index dir_hash = internal_get_file_index(dir_info);
|
||||
File_Track_Entry *dir_lookup = tracking_system_lookup_entry(tables, dir_hash);
|
||||
Win32_File_Track_Entry *win32_dir = (Win32_File_Track_Entry*)dir_lookup;
|
||||
|
||||
Assert(!entry_is_available(dir_lookup));
|
||||
Win32_Directory_Listener_Node *node = win32_dir->listener_node;
|
||||
--node->listener.user_count;
|
||||
|
||||
if (node->listener.user_count == 0){
|
||||
insert_node(&vars->free_sentinel, &node->node);
|
||||
CancelIo(win32_dir->dir);
|
||||
CloseHandle(win32_dir->dir);
|
||||
internal_free_slot(tables, dir_lookup);
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
Assert(!entry_is_available(dir_lookup));
|
||||
Win32_Directory_Listener_Node *node = win32_dir->listener_node;
|
||||
--node->listener.user_count;
|
||||
|
||||
CloseHandle(dir);
|
||||
if (node->listener.user_count == 0){
|
||||
insert_node(&vars->free_sentinel, &node->node);
|
||||
CancelIo(win32_dir->dir);
|
||||
CloseHandle(win32_dir->dir);
|
||||
internal_free_slot(tables, dir_lookup);
|
||||
}
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
CloseHandle(dir);
|
||||
}
|
||||
else{
|
||||
result = FileTrack_FileSystemError;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&vars->table_lock);
|
||||
|
@ -269,17 +254,15 @@ remove_listener(File_Track_System *system, char *filename){
|
|||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
move_track_system(File_Track_System *system, void *mem, int32_t size){
|
||||
move_track_system(File_Track_System *system, void *mem, i32 size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
EnterCriticalSection(&vars->table_lock);
|
||||
{
|
||||
File_Track_Tables *original_tables = to_tables(vars);
|
||||
result = move_table_memory(original_tables, mem, size);
|
||||
if (result == FileTrack_Good){
|
||||
vars->tables = mem;
|
||||
}
|
||||
File_Track_Tables *original_tables = to_tables(vars);
|
||||
result = move_table_memory(original_tables, mem, size);
|
||||
if (result == FileTrack_Good){
|
||||
vars->tables = mem;
|
||||
}
|
||||
LeaveCriticalSection(&vars->table_lock);
|
||||
|
||||
|
@ -287,7 +270,7 @@ move_track_system(File_Track_System *system, void *mem, int32_t size){
|
|||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size){
|
||||
expand_track_system_listeners(File_Track_System *system, void *mem, i32 size){
|
||||
File_Track_Result result = FileTrack_Good;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
|
@ -295,8 +278,8 @@ expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size
|
|||
|
||||
if (sizeof(Win32_Directory_Listener_Node) <= size){
|
||||
Win32_Directory_Listener_Node *listener = (Win32_Directory_Listener_Node*)mem;
|
||||
int32_t count = size / sizeof(Win32_Directory_Listener_Node);
|
||||
for (int32_t i = 0; i < count; ++i, ++listener){
|
||||
i32 count = size / sizeof(Win32_Directory_Listener_Node);
|
||||
for (i32 i = 0; i < count; ++i, ++listener){
|
||||
insert_node(&vars->free_sentinel, &listener->node);
|
||||
}
|
||||
}
|
||||
|
@ -310,99 +293,82 @@ expand_track_system_listeners(File_Track_System *system, void *mem, int32_t size
|
|||
}
|
||||
|
||||
FILE_TRACK_LINK File_Track_Result
|
||||
get_change_event(File_Track_System *system, char *buffer, int32_t max, int32_t *size){
|
||||
get_change_event(File_Track_System *system, u8 *buffer, i32 max, i32 *size){
|
||||
File_Track_Result result = FileTrack_NoMoreEvents;
|
||||
Win32_File_Track_Vars *vars = to_vars(system);
|
||||
|
||||
static int32_t has_buffered_event = 0;
|
||||
static DWORD offset = 0;
|
||||
static Win32_Directory_Listener listener;
|
||||
local_persist i32 has_buffered_event = 0;
|
||||
local_persist DWORD offset = 0;
|
||||
local_persist Win32_Directory_Listener listener = {0};
|
||||
|
||||
EnterCriticalSection(&vars->table_lock);
|
||||
|
||||
{
|
||||
OVERLAPPED *overlapped = 0;
|
||||
DWORD length = 0;
|
||||
ULONG_PTR key = 0;
|
||||
|
||||
int32_t has_result = 0;
|
||||
|
||||
if (has_buffered_event){
|
||||
has_buffered_event = 0;
|
||||
OVERLAPPED *overlapped = 0;
|
||||
DWORD length = 0;
|
||||
ULONG_PTR key = 0;
|
||||
|
||||
b32 has_result = 0;
|
||||
|
||||
if (has_buffered_event){
|
||||
has_buffered_event = 0;
|
||||
has_result = 1;
|
||||
}
|
||||
else{
|
||||
if (GetQueuedCompletionStatus(vars->iocp, &length, &key, &overlapped, 0)){
|
||||
Win32_Directory_Listener *listener_ptr = (Win32_Directory_Listener*)overlapped;
|
||||
|
||||
// NOTE(allen): Get a copy of the state of this node so we can set the node
|
||||
// to work listening for changes again right away.
|
||||
listener = *listener_ptr;
|
||||
|
||||
listener_ptr->overlapped = null_overlapped;
|
||||
ReadDirectoryChangesW(listener_ptr->dir, listener_ptr->result, sizeof(listener_ptr->result), 1, FLAGS, 0, &listener_ptr->overlapped, 0);
|
||||
|
||||
offset = 0;
|
||||
has_result = 1;
|
||||
}
|
||||
else{
|
||||
if (GetQueuedCompletionStatus(vars->iocp,
|
||||
&length,
|
||||
&key,
|
||||
&overlapped,
|
||||
0)){
|
||||
Win32_Directory_Listener *listener_ptr = (Win32_Directory_Listener*)overlapped;
|
||||
|
||||
// NOTE(allen): Get a copy of the state of this node so we can set the node
|
||||
// to work listening for changes again right away.
|
||||
listener = *listener_ptr;
|
||||
|
||||
ZeroStruct(listener_ptr->overlapped);
|
||||
ReadDirectoryChangesW(listener_ptr->dir,
|
||||
listener_ptr->result,
|
||||
sizeof(listener_ptr->result),
|
||||
1,
|
||||
FLAGS,
|
||||
0,
|
||||
&listener_ptr->overlapped,
|
||||
0);
|
||||
|
||||
offset = 0;
|
||||
has_result = 1;
|
||||
}
|
||||
|
||||
if (has_result){
|
||||
|
||||
FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*)(listener.result + offset);
|
||||
|
||||
i32 len = info->FileNameLength / 2;
|
||||
i32 dir_len = GetFinalPathNameByHandle(listener.dir, 0, 0, FILE_NAME_NORMALIZED);
|
||||
|
||||
i32 req_size = dir_len + 1 + len;
|
||||
*size = req_size;
|
||||
if (req_size < max){
|
||||
i32 pos = GetFinalPathNameByHandle(listener.dir, buffer, max, FILE_NAME_NORMALIZED);
|
||||
buffer[pos++] = '\\';
|
||||
|
||||
for (i32 i = 0; i < len; ++i, ++pos){
|
||||
buffer[pos] = (char)info->FileName[i];
|
||||
}
|
||||
|
||||
if (buffer[0] == '\\'){
|
||||
for (i32 i = 0; i+4 < pos; ++i){
|
||||
buffer[i] = buffer[i+4];
|
||||
}
|
||||
*size -= 4;
|
||||
}
|
||||
|
||||
result = FileTrack_Good;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): Need some way to stash this result so that if the
|
||||
// user comes back with more memory we can give them the change
|
||||
// notification they missed.
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
}
|
||||
|
||||
if (has_result){
|
||||
|
||||
FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*)(listener.result + offset);
|
||||
|
||||
int32_t len = info->FileNameLength / 2;
|
||||
int32_t dir_len = GetFinalPathNameByHandle(listener.dir, 0, 0,
|
||||
FILE_NAME_NORMALIZED);
|
||||
|
||||
int32_t req_size = dir_len + 1 + len;
|
||||
*size = req_size;
|
||||
if (req_size < max){
|
||||
int32_t pos = 0;
|
||||
|
||||
pos = GetFinalPathNameByHandle(listener.dir, buffer, max,
|
||||
FILE_NAME_NORMALIZED);
|
||||
buffer[pos++] = '\\';
|
||||
|
||||
for (int32_t i = 0; i < len; ++i, ++pos){
|
||||
buffer[pos] = (char)info->FileName[i];
|
||||
}
|
||||
|
||||
if (buffer[0] == '\\'){
|
||||
for (int32_t i = 0; i+4 < pos; ++i){
|
||||
buffer[i] = buffer[i+4];
|
||||
}
|
||||
*size -= 4;
|
||||
}
|
||||
|
||||
result = FileTrack_Good;
|
||||
}
|
||||
else{
|
||||
// TODO(allen): Need some way to stash this result so that if the
|
||||
// user comes back with more memory we can give them the change
|
||||
// notification they missed.
|
||||
result = FileTrack_MemoryTooSmall;
|
||||
}
|
||||
|
||||
if (info->NextEntryOffset != 0){
|
||||
// TODO(allen): We're not ready to handle this yet.
|
||||
// For now I am breaking. In the future, if there
|
||||
// are more results we should stash them and return
|
||||
// them in future calls.
|
||||
offset += info->NextEntryOffset;
|
||||
has_buffered_event = 1;
|
||||
}
|
||||
if (info->NextEntryOffset != 0){
|
||||
// TODO(allen): We're not ready to handle this yet.
|
||||
// For now I am breaking. In the future, if there
|
||||
// are more results we should stash them and return
|
||||
// them in future calls.
|
||||
offset += info->NextEntryOffset;
|
||||
has_buffered_event = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,9 +389,9 @@ shut_down_track_system(File_Track_System *system){
|
|||
File_Track_Tables *tables = to_tables(vars);
|
||||
|
||||
File_Track_Entry *entries = (File_Track_Entry*)to_ptr(tables, tables->file_table);
|
||||
uint32_t max = tables->max;
|
||||
u32 max = tables->max;
|
||||
|
||||
for (uint32_t index = 0; index < max; ++index){
|
||||
for (u32 index = 0; index < max; ++index){
|
||||
File_Track_Entry *entry = entries + index;
|
||||
|
||||
if (!entry_is_available(entry)){
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 09.02.2016
|
||||
*
|
||||
* Shared system functions
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#include "4ed_system_shared.h"
|
||||
#include "font/4coder_font_interface.h"
|
||||
#include "font/4coder_font_interface_to_os.h"
|
||||
#include "font/4coder_font_data.h"
|
||||
|
||||
struct Win32_Fonts{
|
||||
Partition part;
|
||||
Render_Font fonts[5];
|
||||
u32 font_count;
|
||||
};
|
||||
|
||||
global Win32_Fonts win32_fonts = {0};
|
||||
|
||||
internal
|
||||
Sys_Font_Get_Count_Sig(system_font_get_count){
|
||||
return(5);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Get_IDs_By_Index_Sig(system_font_get_ids_by_index){
|
||||
b32 result = false;
|
||||
u32 stop_index = first_index + index_count;
|
||||
if (stop_index <= win32_fonts.font_count){
|
||||
result = true;
|
||||
for (u32 i = first_index; i < stop_index; ++i){
|
||||
id_out[i-first_index] = i;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Get_Name_By_Index_Sig(system_font_get_name_by_index){
|
||||
u32 length = 0;
|
||||
if (font_index < win32_fonts.font_count){
|
||||
Render_Font *font = &win32_fonts.fonts[font_index];
|
||||
char *name = font->name;
|
||||
length = font->name_len;
|
||||
copy_partial_cs(str_out, str_out_cap, make_string(name, length));
|
||||
}
|
||||
return(length);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Get_Name_By_ID_Sig(system_font_get_name_by_id){
|
||||
u32 font_index = font_id;
|
||||
u32 result = system_font_get_name_by_index(font_index, str_out, str_out_cap);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Get_Render_Data_By_ID_Sig(system_font_get_render_data_by_id){
|
||||
Render_Font *result = 0;
|
||||
u32 font_index = font_id;
|
||||
if (font_index < win32_fonts.font_count){
|
||||
result = &win32_fonts.fonts[font_index];
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Load_Page_Sig(system_font_load_page){
|
||||
system_set_page(&win32vars.system, &win32_fonts.part, font, page, page_number, 16, true);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Allocate_Sig(system_font_allocate){
|
||||
void *result = system_memory_allocate(size);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Free_Sig(system_font_free){
|
||||
system_memory_free(ptr, 0);
|
||||
}
|
||||
|
||||
internal
|
||||
Sys_Font_Init_Sig(system_font_init){
|
||||
font->get_count = system_font_get_count;
|
||||
font->get_ids_by_index = system_font_get_ids_by_index;
|
||||
font->get_name_by_index = system_font_get_name_by_index;
|
||||
font->get_name_by_id = system_font_get_name_by_id;
|
||||
font->get_render_data_by_id = system_font_get_render_data_by_id;
|
||||
font->load_page = system_font_load_page;
|
||||
font->allocate = system_font_allocate;
|
||||
font->free = system_font_free;
|
||||
|
||||
font_size = clamp_bottom(8, font_size);
|
||||
|
||||
struct Font_Setup{
|
||||
char *c_filename;
|
||||
i32 filename_len;
|
||||
char *c_name;
|
||||
i32 name_len;
|
||||
u32 pt_size;
|
||||
};
|
||||
Font_Setup font_setup[] = {
|
||||
{literal("LiberationSans-Regular.ttf"), literal("Liberation Sans"), font_size},
|
||||
{literal("liberation-mono.ttf"), literal("Liberation Mono"), font_size},
|
||||
{literal("Hack-Regular.ttf"), literal("Hack"), font_size},
|
||||
{literal("CutiveMono-Regular.ttf"), literal("Cutive Mono"), font_size},
|
||||
{literal("Inconsolata-Regular.ttf"), literal("Inconsolata"), font_size},
|
||||
};
|
||||
|
||||
u32 font_count = Min(ArrayCount(win32_fonts.fonts), ArrayCount(font_setup));
|
||||
for (u32 i = 0; i < font_count; ++i){
|
||||
String filename = make_string(font_setup[i].c_filename, font_setup[i].filename_len);
|
||||
String name = make_string(font_setup[i].c_name, font_setup[i].name_len);
|
||||
u32 pt_size = font_setup[i].pt_size;
|
||||
Render_Font *render_font = &win32_fonts.fonts[i];
|
||||
|
||||
char full_filename_space[256];
|
||||
String full_filename = make_fixed_width_string(full_filename_space);
|
||||
sysshared_to_binary_path(&full_filename, filename.str);
|
||||
|
||||
system_set_font(&win32vars.system, &win32_fonts.part, render_font, full_filename, name, pt_size, use_hinting);
|
||||
}
|
||||
|
||||
win32_fonts.font_count = font_count;
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// NOTE(allen): Thanks to insofaras.
|
||||
// This is copy-pasted from some work he
|
||||
// did to get free type working on linux.
|
||||
// Once it is working on both sides it might
|
||||
// be possible to pull some parts out as
|
||||
// portable FT rendering.
|
||||
|
||||
internal b32
|
||||
win32_ft_font_load(Partition *part, Render_Font *rf, char *name, i32 pt_size, i32 tab_width, b32 use_hinting){
|
||||
|
||||
b32 result = 0;
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
char* filename = push_array(part, char, 256);
|
||||
|
||||
if (filename != 0){
|
||||
String str = make_string_cap(filename, 0, 256);
|
||||
sysshared_to_binary_path(&str, name);
|
||||
|
||||
result = font_load_freetype(part, rf, filename, pt_size, tab_width, use_hinting);
|
||||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
@ -79,6 +79,7 @@ wglGetExtensionsStringARB_Function(HDC hdc);
|
|||
typedef void CALL_CONVENTION
|
||||
GLDEBUGPROC_TYPE(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char * message, const GLvoid * userParam);
|
||||
|
||||
// TODO(allen): these don't belong here, but the organizational stuff is not fully in place yet.
|
||||
typedef GLDEBUGPROC_TYPE * GLDEBUGPROC;
|
||||
typedef void CALL_CONVENTION
|
||||
glDebugMessageControl_type(GLenum source, GLenum type, GLenum severity, GLsizei count, GLuint * ids, GLboolean enabled);
|
||||
|
|
Loading…
Reference in New Issue