got fonts working on Linux

master
Allen Webster 2017-03-19 14:25:12 -04:00
commit aeb43dcfb9
56 changed files with 3143 additions and 2985 deletions

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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;
}
}

37
4ed_buffer_model.h Normal file
View File

@ -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

View File

@ -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};

56
4ed_file_track.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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
*/

View File

@ -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

View File

@ -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

View File

@ -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);
}

Binary file not shown.

View File

@ -10,7 +10,7 @@
// TOP
struct Style_Font{
i16 font_id;
Font_ID font_id;
};
struct Style{

View File

@ -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

View File

@ -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

View File

@ -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

244
4ed_translation.cpp Normal file
View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

59
font/4coder_font_data.h Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

136
linux_4ed_fonts.cpp Normal file
View File

@ -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

View File

@ -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

View File

@ -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(&copy_name, dir);
append_s_char(&copy_name, platform_correct_slash);
append_sc(&copy_name, d);
terminate_with_null(&copy_name);
copy_all(d, "*", str.str);
copy_all(d, "*", copy_name.str);
}
get_4coder_dist_name(&str, true, zip_dir, tier, arch, "zip");

View File

@ -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);
}

View File

@ -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

View File

@ -1,5 +1,5 @@
1
0
63
68

Binary file not shown.

View File

@ -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)

View File

@ -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

View File

@ -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)){

134
win32_4ed_fonts.cpp Normal file
View File

@ -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

View File

@ -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);
}

View File

@ -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);