From e9c5f895754ea10decadd2a76fd4a1b4abf7b044 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Mon, 20 Jun 2016 16:34:48 -0400 Subject: [PATCH] new protection API --- 4coder_custom.h | 11 +- 4coder_custom_api.h | 26 ++-- 4coder_default_bindings.cpp | 27 ++-- 4coder_default_include.cpp | 278 +++++++++++++++++++---------------- 4coder_helper.h | 24 +-- 4ed.cpp | 2 +- 4ed_api_implementation.cpp | 275 +++++++++++++++++++--------------- 4ed_file_view.cpp | 32 +++- 4ed_metagen.cpp | 1 + 4ed_rendering.cpp | 14 +- custom_api_spec.cpp | 38 ++--- linux_4ed.cpp | 2 +- power/4coder_casey.cpp | 49 +++--- power/4coder_experiments.cpp | 15 +- win32_4ed.cpp | 40 +++-- win32_ft_font.cpp | 242 ++++++++++++++++++++++++++++++ 16 files changed, 726 insertions(+), 350 deletions(-) create mode 100644 win32_ft_font.cpp diff --git a/4coder_custom.h b/4coder_custom.h index 5098406b..11b50cca 100644 --- a/4coder_custom.h +++ b/4coder_custom.h @@ -203,6 +203,7 @@ struct Buffer_Summary{ int exists; int ready; int buffer_id; + unsigned int lock_flags; int size; @@ -225,8 +226,7 @@ struct View_Summary{ int exists; int view_id; int buffer_id; - int locked_buffer_id; - int hidden_buffer_id; + unsigned int lock_flags; Full_Cursor cursor; Full_Cursor mark; @@ -281,6 +281,13 @@ struct Theme_Color{ unsigned int color; }; +enum Access_Types{ + AccessOpen = 0x0, + AccessProtected = 0x1, + AccessHidden = 0x2, + AccessAll = 0xFF +}; + #define VIEW_ROUTINE_SIG(name) void name(struct Application_Links *app, int view_id) #define GET_BINDING_DATA(name) int name(void *data, int size) diff --git a/4coder_custom_api.h b/4coder_custom_api.h index 3d635e85..51eead1a 100644 --- a/4coder_custom_api.h +++ b/4coder_custom_api.h @@ -9,23 +9,23 @@ #define CLIPBOARD_POST_SIG(n) int n(Application_Links *app, char *str, int len) #define CLIPBOARD_COUNT_SIG(n) int n(Application_Links *app) #define CLIPBOARD_INDEX_SIG(n) int n(Application_Links *app, int index, char *out, int len) -#define GET_BUFFER_FIRST_SIG(n) Buffer_Summary n(Application_Links *app) -#define GET_BUFFER_NEXT_SIG(n) void n(Application_Links *app, Buffer_Summary *buffer) -#define GET_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int index) -#define GET_PARAMETER_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int param_index) -#define GET_BUFFER_BY_NAME_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int len) +#define GET_BUFFER_FIRST_SIG(n) Buffer_Summary n(Application_Links *app, unsigned int access) +#define GET_BUFFER_NEXT_SIG(n) void n(Application_Links *app, Buffer_Summary *buffer, unsigned int access) +#define GET_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int index, unsigned int access) +#define GET_PARAMETER_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int param_index, unsigned int access) +#define GET_BUFFER_BY_NAME_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int len, unsigned int access) #define REFRESH_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer) #define BUFFER_READ_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out) -#define BUFFER_REPLACE_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len) #define BUFFER_SEEK_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start_pos, int seek_forward, unsigned int flags) +#define BUFFER_REPLACE_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len) #define BUFFER_SET_SETTING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int setting, int value) #define CREATE_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int filename_len, int do_in_background) #define SAVE_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, char *filename, int filename_len) #define KILL_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Identifier buffer, int always_kill, int view_id) -#define GET_VIEW_FIRST_SIG(n) View_Summary n(Application_Links *app) -#define GET_VIEW_NEXT_SIG(n) void n(Application_Links *app, View_Summary *view) -#define GET_VIEW_SIG(n) View_Summary n(Application_Links *app, int index) -#define GET_ACTIVE_VIEW_SIG(n) View_Summary n(Application_Links *app) +#define GET_VIEW_FIRST_SIG(n) View_Summary n(Application_Links *app, unsigned int access) +#define GET_VIEW_NEXT_SIG(n) void n(Application_Links *app, View_Summary *view, unsigned int access) +#define GET_VIEW_SIG(n) View_Summary n(Application_Links *app, int index, unsigned int access) +#define GET_ACTIVE_VIEW_SIG(n) View_Summary n(Application_Links *app, unsigned int access) #define REFRESH_VIEW_SIG(n) int n(Application_Links *app, View_Summary *view) #define VIEW_AUTO_TAB_SIG(n) int n(Application_Links *app, View_Summary *view, int start, int end, int tab_width, unsigned int flags) #define VIEW_COMPUTE_CURSOR_SIG(n) Full_Cursor n(Application_Links *app, View_Summary *view, Buffer_Seek seek) @@ -66,8 +66,8 @@ extern "C"{ typedef GET_BUFFER_BY_NAME_SIG(Get_Buffer_By_Name_Function); typedef REFRESH_BUFFER_SIG(Refresh_Buffer_Function); typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function); - typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function); typedef BUFFER_SEEK_SIG(Buffer_Seek_Function); + typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function); typedef BUFFER_SET_SETTING_SIG(Buffer_Set_Setting_Function); typedef CREATE_BUFFER_SIG(Create_Buffer_Function); typedef SAVE_BUFFER_SIG(Save_Buffer_Function); @@ -119,8 +119,8 @@ struct Application_Links{ Get_Buffer_By_Name_Function *get_buffer_by_name; Refresh_Buffer_Function *refresh_buffer; Buffer_Read_Range_Function *buffer_read_range; - Buffer_Replace_Range_Function *buffer_replace_range; Buffer_Seek_Function *buffer_seek; + Buffer_Replace_Range_Function *buffer_replace_range; Buffer_Set_Setting_Function *buffer_set_setting; Create_Buffer_Function *create_buffer; Save_Buffer_Function *save_buffer; @@ -174,8 +174,8 @@ app_links->get_parameter_buffer = external_get_parameter_buffer;\ app_links->get_buffer_by_name = external_get_buffer_by_name;\ app_links->refresh_buffer = external_refresh_buffer;\ app_links->buffer_read_range = external_buffer_read_range;\ -app_links->buffer_replace_range = external_buffer_replace_range;\ app_links->buffer_seek = external_buffer_seek;\ +app_links->buffer_replace_range = external_buffer_replace_range;\ app_links->buffer_set_setting = external_buffer_set_setting;\ app_links->create_buffer = external_create_buffer;\ app_links->save_buffer = external_save_buffer;\ diff --git a/4coder_default_bindings.cpp b/4coder_default_bindings.cpp index 72d7874c..517d1bd4 100644 --- a/4coder_default_bindings.cpp +++ b/4coder_default_bindings.cpp @@ -39,13 +39,14 @@ CUSTOM_COMMAND_SIG(write_capital){ CUSTOM_COMMAND_SIG(switch_to_compilation){ View_Summary view; Buffer_Summary buffer; - + char name[] = "*compilation*"; int name_size = sizeof(name)-1; - - view = app->get_active_view(app); - buffer = app->get_buffer_by_name(app, name, name_size); - + + unsigned int access = AccessOpen; + view = app->get_active_view(app, access); + buffer = app->get_buffer_by_name(app, name, name_size, access); + app->view_set_buffer(app, &view, buffer.buffer_id); } @@ -57,7 +58,8 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){ String string; int is_first, i; - view = app->get_active_view(app); + unsigned int access = AccessOpen; + view = app->get_active_view(app, access); cursor = view.cursor; exec_command(app, seek_token_left); @@ -71,8 +73,8 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){ string.str = (char*)app->memory; string.size = range.max - range.min; assert(string.size < app->memory_size); - - buffer = app->get_buffer(app, view.buffer_id); + + buffer = app->get_buffer(app, view.buffer_id, access); app->buffer_read_range(app, &buffer, range.min, range.max, string.str); is_first = 1; @@ -95,13 +97,15 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){ CUSTOM_COMMAND_SIG(open_my_files){ // TODO(allen|a4.0.8): comment - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected|AccessHidden; + View_Summary view = app->get_active_view(app, access); view_open_file(app, &view, literal("w:/4ed/data/test/basic.cpp"), false); } CUSTOM_COMMAND_SIG(build_at_launch_location){ // TODO(allen|a4.0.8): comment - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected|AccessHidden; + View_Summary view = app->get_active_view(app, access); app->exec_system_command(app, &view, buffer_identifier(literal("*compilation*")), literal("."), @@ -139,7 +143,8 @@ HOOK_SIG(my_file_settings){ // opened hook. The file created hook is guaranteed to have only // and exactly one buffer parameter. In normal command callbacks // there are no parameter buffers. - Buffer_Summary buffer = app->get_parameter_buffer(app, 0); + unsigned int access = AccessProtected|AccessHidden; + Buffer_Summary buffer = app->get_parameter_buffer(app, 0, access); assert(buffer.exists); int treat_as_code = 0; diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index 40fa2a8f..de878b2e 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -37,7 +37,8 @@ get_view_x(View_Summary view){ // CUSTOM_COMMAND_SIG(write_character){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); User_Input in = app->get_command_input(app); char character = 0; @@ -47,7 +48,8 @@ CUSTOM_COMMAND_SIG(write_character){ } if (character != 0){ - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); + int pos = view.cursor.pos; int next_pos = pos + 1; app->buffer_replace_range(app, &buffer, @@ -57,8 +59,9 @@ CUSTOM_COMMAND_SIG(write_character){ } CUSTOM_COMMAND_SIG(delete_char){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int pos = view.cursor.pos; if (0 < buffer.size && pos < buffer.size){ @@ -68,8 +71,9 @@ CUSTOM_COMMAND_SIG(delete_char){ } CUSTOM_COMMAND_SIG(backspace_char){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int pos = view.cursor.pos; if (0 < pos && pos <= buffer.size){ @@ -81,7 +85,8 @@ CUSTOM_COMMAND_SIG(backspace_char){ } CUSTOM_COMMAND_SIG(set_mark){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); app->view_set_mark(app, &view, seek_pos(view.cursor.pos)); // TODO(allen): Just expose the preferred_x seperately @@ -89,7 +94,8 @@ CUSTOM_COMMAND_SIG(set_mark){ } CUSTOM_COMMAND_SIG(cursor_mark_swap){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); int cursor = view.cursor.pos; int mark = view.mark.pos; @@ -99,8 +105,9 @@ CUSTOM_COMMAND_SIG(cursor_mark_swap){ } CUSTOM_COMMAND_SIG(delete_range){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); Range range = get_range(&view); @@ -139,40 +146,37 @@ get_relative_xy(View_Summary *view, int x, int y, float *x_out, float *y_out){ } CUSTOM_COMMAND_SIG(click_set_cursor){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); - // TODO(allen): Need a better system for - // weeding out views in a hidden state. - if (view.locked_buffer_id != 0){ - Mouse_State mouse = app->get_mouse_state(app); - float rx = 0, ry = 0; - if (get_relative_xy(&view, mouse.x, mouse.y, &rx, &ry)){ - app->view_set_cursor(app, &view, - seek_xy(rx, ry, true, - view.unwrapped_lines), - true); - } + Mouse_State mouse = app->get_mouse_state(app); + float rx = 0, ry = 0; + if (get_relative_xy(&view, mouse.x, mouse.y, &rx, &ry)){ + app->view_set_cursor(app, &view, + seek_xy(rx, ry, true, + view.unwrapped_lines), + true); } } CUSTOM_COMMAND_SIG(click_set_mark){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); - if (view.locked_buffer_id != 0){ - Mouse_State mouse = app->get_mouse_state(app); - float rx = 0, ry = 0; - if (get_relative_xy(&view, mouse.x, mouse.y, &rx, &ry)){ - app->view_set_mark(app, &view, - seek_xy(rx, ry, true, - view.unwrapped_lines) - ); - } + Mouse_State mouse = app->get_mouse_state(app); + float rx = 0, ry = 0; + if (get_relative_xy(&view, mouse.x, mouse.y, &rx, &ry)){ + app->view_set_mark(app, &view, + seek_xy(rx, ry, true, + view.unwrapped_lines) + ); } } inline void move_vertical(Application_Links *app, float line_multiplier){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); float new_y = get_view_y(view) + line_multiplier*view.line_height; float x = view.preferred_x; @@ -200,7 +204,8 @@ CUSTOM_COMMAND_SIG(move_down_10){ CUSTOM_COMMAND_SIG(move_left){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); int new_pos = view.cursor.pos - 1; app->view_set_cursor(app, &view, seek_pos(new_pos), @@ -208,7 +213,8 @@ CUSTOM_COMMAND_SIG(move_left){ } CUSTOM_COMMAND_SIG(move_right){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); int new_pos = view.cursor.pos + 1; app->view_set_cursor(app, &view, seek_pos(new_pos), @@ -221,9 +227,10 @@ CUSTOM_COMMAND_SIG(move_right){ // static int -clipboard_copy(Application_Links *app, int start, int end, Buffer_Summary *buffer_out){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.locked_buffer_id); +clipboard_copy(Application_Links *app, int start, int end, Buffer_Summary *buffer_out, + unsigned int access){ + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int result = false; if (0 <= start && start <= end && end <= buffer.size){ @@ -242,11 +249,12 @@ clipboard_copy(Application_Links *app, int start, int end, Buffer_Summary *buffe } static int -clipboard_cut(Application_Links *app, int start, int end, Buffer_Summary *buffer_out){ +clipboard_cut(Application_Links *app, int start, int end, Buffer_Summary *buffer_out, + unsigned int access){ Buffer_Summary buffer = {0}; int result = false; - if (clipboard_copy(app, start, end, &buffer)){ + if (clipboard_copy(app, start, end, &buffer, access)){ app->buffer_replace_range(app, &buffer, start, end, 0, 0); if (buffer_out){*buffer_out = buffer;} } @@ -255,15 +263,17 @@ clipboard_cut(Application_Links *app, int start, int end, Buffer_Summary *buffer } CUSTOM_COMMAND_SIG(copy){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); Range range = get_range(&view); - clipboard_copy(app, range.min, range.max, 0); + clipboard_copy(app, range.min, range.max, 0, access); } CUSTOM_COMMAND_SIG(cut){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); Range range = get_range(&view); - clipboard_cut(app, range.min, range.max, 0); + clipboard_cut(app, range.min, range.max, 0, access); } struct View_Paste_Index{ @@ -274,9 +284,10 @@ View_Paste_Index view_paste_index_[16]; View_Paste_Index *view_paste_index = view_paste_index_ - 1; CUSTOM_COMMAND_SIG(paste){ + unsigned int access = AccessOpen; int count = app->clipboard_count(app); if (count > 0){ - View_Summary view = app->get_active_view(app); + View_Summary view = app->get_active_view(app, access); // NOTE(allen): THIS is a very temporary poop-sauce // system that I just threw in to get this working. @@ -296,7 +307,7 @@ CUSTOM_COMMAND_SIG(paste){ if (str){ app->clipboard_index(app, paste_index, str, len); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int pos = view.cursor.pos; app->buffer_replace_range(app, &buffer, pos, pos, str, len); app->view_set_mark(app, &view, seek_pos(pos)); @@ -312,9 +323,10 @@ CUSTOM_COMMAND_SIG(paste){ } CUSTOM_COMMAND_SIG(paste_next){ + unsigned int access = AccessOpen; int count = app->clipboard_count(app); if (count > 0){ - View_Summary view = app->get_active_view(app); + View_Summary view = app->get_active_view(app, access); // NOTE(allen): THIS is a very temporary poop-sauce // system that I just threw in to get this working. @@ -335,7 +347,7 @@ CUSTOM_COMMAND_SIG(paste_next){ if (str){ app->clipboard_index(app, paste_index, str, len); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); Range range = get_range(&view); int pos = range.min; @@ -483,8 +495,9 @@ buffer_seek_whitespace_down(Application_Links *app, Buffer_Summary *buffer, int } CUSTOM_COMMAND_SIG(seek_whitespace_up){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.locked_buffer_id); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int new_pos = buffer_seek_whitespace_up(app, &buffer, view.cursor.pos); app->view_set_cursor(app, &view, @@ -493,8 +506,9 @@ CUSTOM_COMMAND_SIG(seek_whitespace_up){ } CUSTOM_COMMAND_SIG(seek_whitespace_down){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.locked_buffer_id); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int new_pos = buffer_seek_whitespace_down(app, &buffer, view.cursor.pos); app->view_set_cursor(app, &view, @@ -567,16 +581,18 @@ seek_line_beginning(Application_Links *app, Buffer_Summary *buffer, int pos){ } CUSTOM_COMMAND_SIG(seek_end_of_line){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.locked_buffer_id); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int new_pos = seek_line_end(app, &buffer, view.cursor.pos); app->view_set_cursor(app, &view, seek_pos(new_pos), true); } CUSTOM_COMMAND_SIG(seek_beginning_of_line){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.locked_buffer_id); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int new_pos = seek_line_beginning(app, &buffer, view.cursor.pos); app->view_set_cursor(app, &view, seek_pos(new_pos), true); @@ -584,8 +600,9 @@ CUSTOM_COMMAND_SIG(seek_beginning_of_line){ static void basic_seek(Application_Links *app, int seek_type, unsigned int flags){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.locked_buffer_id); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int pos = app->buffer_seek(app, &buffer, view.cursor.pos, seek_type, flags); app->view_set_cursor(app, &view, seek_pos(pos), true); } @@ -617,7 +634,8 @@ SEEK_COMMAND(alphanumeric_or_camel, left, BoundryAlphanumeric | BoundryCamelCas static void write_string(Application_Links *app, String string){ - Buffer_Summary buffer = get_active_buffer(app); + unsigned int access = AccessOpen; + Buffer_Summary buffer = get_active_buffer(app, access); app->buffer_replace_range(app, &buffer, buffer.buffer_cursor_pos, buffer.buffer_cursor_pos, string.str, string.size); @@ -633,13 +651,11 @@ CUSTOM_COMMAND_SIG(write_increment){ static void long_braces(Application_Links *app, char *text, int size){ - View_Summary view; - Buffer_Summary buffer; + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int pos; - view = app->get_active_view(app); - buffer = app->get_buffer(app, view.buffer_id); - pos = view.cursor.pos; app->buffer_replace_range(app, &buffer, pos, pos, text, size); app->view_set_cursor(app, &view, seek_pos(pos + 2), true); @@ -671,6 +687,8 @@ CUSTOM_COMMAND_SIG(open_long_braces_break){ // TODO(allen): Have this thing check if it is on // a blank line and insert newlines as needed. CUSTOM_COMMAND_SIG(if0_off){ + unsigned int access = AccessOpen; + View_Summary view; Buffer_Summary buffer; @@ -683,8 +701,8 @@ CUSTOM_COMMAND_SIG(if0_off){ Range range; int pos; - view = app->get_active_view(app); - buffer = app->get_buffer(app, view.buffer_id); + view = app->get_active_view(app, access); + buffer = app->get_buffer(app, view.buffer_id, access); range = get_range(&view); pos = range.min; @@ -709,44 +727,50 @@ CUSTOM_COMMAND_SIG(if0_off){ } CUSTOM_COMMAND_SIG(backspace_word){ + unsigned int access = AccessOpen; + View_Summary view; Buffer_Summary buffer; int pos2, pos1; - view = app->get_active_view(app); + view = app->get_active_view(app, access); pos2 = view.cursor.pos; exec_command(app, seek_alphanumeric_left); app->refresh_view(app, &view); pos1 = view.cursor.pos; - buffer = app->get_buffer(app, view.buffer_id); + buffer = app->get_buffer(app, view.buffer_id, access); app->buffer_replace_range(app, &buffer, pos1, pos2, 0, 0); } CUSTOM_COMMAND_SIG(delete_word){ + unsigned int access = AccessOpen; + View_Summary view; Buffer_Summary buffer; int pos2, pos1; - view = app->get_active_view(app); + view = app->get_active_view(app, access); pos1 = view.cursor.pos; exec_command(app, seek_alphanumeric_right); app->refresh_view(app, &view); pos2 = view.cursor.pos; - buffer = app->get_buffer(app, view.buffer_id); + buffer = app->get_buffer(app, view.buffer_id, access); app->buffer_replace_range(app, &buffer, pos1, pos2, 0, 0); } CUSTOM_COMMAND_SIG(snipe_token_or_word){ + unsigned int access = AccessOpen; + View_Summary view; Buffer_Summary buffer; int pos1, pos2; - view = app->get_active_view(app); - buffer = app->get_buffer(app, view.buffer_id); + view = app->get_active_view(app, access); + buffer = app->get_buffer(app, view.buffer_id, access); pos1 = app->buffer_seek(app, &buffer, view.cursor.pos, false, BoundryToken | BoundryWhitespace); @@ -757,13 +781,15 @@ CUSTOM_COMMAND_SIG(snipe_token_or_word){ } CUSTOM_COMMAND_SIG(open_file_in_quotes){ + unsigned int access = AccessProtected; + View_Summary view; Buffer_Summary buffer; char short_file_name[128]; int pos, start, end, size; - view = app->get_active_view(app); - buffer = app->get_buffer(app, view.buffer_id); + view = app->get_active_view(app, access); + buffer = app->get_buffer(app, view.buffer_id, access); pos = view.cursor.pos; buffer_seek_delimiter_forward(app, &buffer, pos, '"', &end); buffer_seek_delimiter_backward(app, &buffer, pos, '"', &start); @@ -793,16 +819,18 @@ CUSTOM_COMMAND_SIG(save_as){ } CUSTOM_COMMAND_SIG(goto_line){ + unsigned int access = AccessProtected; + int line_number; Query_Bar bar; char string_space[256]; - + bar.prompt = make_lit_string("Goto Line: "); bar.string = make_fixed_width_string(string_space); - + if (query_user_number(app, &bar)){ line_number = str_to_int(bar.string); - active_view_to_line(app, line_number); + active_view_to_line(app, access, line_number); } } @@ -811,14 +839,13 @@ CUSTOM_COMMAND_SIG(reverse_search); static void isearch(Application_Links *app, int start_reversed){ - View_Summary view; - Buffer_Summary buffer; + unsigned int access = AccessProtected; + + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); User_Input in; Query_Bar bar; - view = app->get_active_view(app); - buffer = app->get_buffer(app, view.locked_buffer_id); - if (!buffer.exists) return; if (app->start_query_bar(app, &bar, 0) == 0) return; @@ -945,33 +972,31 @@ CUSTOM_COMMAND_SIG(replace_in_range){ char replace_space[1024]; replace.prompt = make_lit_string("Replace: "); replace.string = make_fixed_width_string(replace_space); - + Query_Bar with; char with_space[1024]; with.prompt = make_lit_string("With: "); with.string = make_fixed_width_string(with_space); - + if (!query_user_string(app, &replace)) return; if (replace.string.size == 0) return; - + if (!query_user_string(app, &with)) return; - + String r, w; r = replace.string; w = with.string; - - Buffer_Summary buffer; - View_Summary view; - - view = app->get_active_view(app); - buffer = app->get_buffer(app, view.buffer_id); - + + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); + Range range = get_range(&view); - + int pos, new_pos; pos = range.min; buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos); - + while (new_pos + r.size <= range.end){ app->buffer_replace_range(app, &buffer, new_pos, new_pos + r.size, w.str, w.size); app->refresh_view(app, &view); @@ -986,45 +1011,46 @@ CUSTOM_COMMAND_SIG(query_replace){ char replace_space[1024]; replace.prompt = make_lit_string("Replace: "); replace.string = make_fixed_width_string(replace_space); - + Query_Bar with; char with_space[1024]; with.prompt = make_lit_string("With: "); with.string = make_fixed_width_string(with_space); - + if (!query_user_string(app, &replace)) return; if (replace.string.size == 0) return; - + if (!query_user_string(app, &with)) return; - + String r, w; r = replace.string; w = with.string; - + Query_Bar bar; Buffer_Summary buffer; View_Summary view; int pos, new_pos; - + bar.prompt = make_lit_string("Replace? (y)es, (n)ext, (esc)\n"); bar.string = empty_string(); - + app->start_query_bar(app, &bar, 0); - - view = app->get_active_view(app); - buffer = app->get_buffer(app, view.buffer_id); - + + unsigned int access = AccessOpen; + view = app->get_active_view(app, access); + buffer = app->get_buffer(app, view.buffer_id, access); + pos = view.cursor.pos; buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos); - + User_Input in = {0}; while (new_pos < buffer.size){ Range match = make_range(new_pos, new_pos + r.size); app->view_set_highlight(app, &view, match.min, match.max, 1); - + in = app->get_user_input(app, EventOnAnyKey, EventOnButton); if (in.abort || in.key.keycode == key_esc || !key_is_unmodified(&in.key)) break; - + if (in.key.character == 'y' || in.key.character == 'Y' || in.key.character == '\n' || in.key.character == '\t'){ app->buffer_replace_range(app, &buffer, match.min, match.max, w.str, w.size); pos = match.start + w.size; @@ -1032,13 +1058,13 @@ CUSTOM_COMMAND_SIG(query_replace){ else{ pos = match.max; } - + buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos); } - + app->view_set_highlight(app, &view, 0, 0, 0); if (in.abort) return; - + app->view_set_cursor(app, &view, seek_pos(pos), 1); } @@ -1051,9 +1077,10 @@ CUSTOM_COMMAND_SIG(close_all_code){ int buffers_to_close[2048]; int buffers_to_close_count = 0; - for (buffer = app->get_buffer_first(app); + unsigned int access = AccessProtected|AccessHidden; + for (buffer = app->get_buffer_first(app, access); buffer.exists; - app->get_buffer_next(app, &buffer)){ + app->get_buffer_next(app, &buffer, access)){ extension = file_extension(make_string(buffer.file_name, buffer.file_name_len)); if (match(extension, make_lit_string("cpp")) || @@ -1123,8 +1150,8 @@ CUSTOM_COMMAND_SIG(execute_any_cli){ hot_directory = make_fixed_width_string(hot_directory_space); hot_directory.size = app->directory_get_hot(app, hot_directory.str, hot_directory.memory_size); - // TODO(allen): provide command line call - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected|AccessHidden; + View_Summary view = app->get_active_view(app, access); // TODO(allen): Make this work without null terminators terminate_with_null(&bar_out.string); @@ -1147,7 +1174,8 @@ CUSTOM_COMMAND_SIG(execute_previous_cli){ hot_directory = make_string_slowly(hot_directory_space); if (out_buffer.size > 0 && cmd.size > 0 && hot_directory.size > 0){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessProtected|AccessHidden; + View_Summary view = app->get_active_view(app, access); app->exec_system_command(app, &view, buffer_identifier(out_buffer.str, out_buffer.size), @@ -1257,7 +1285,8 @@ CUSTOM_COMMAND_SIG(build_search){ append(&command, "build"); append(&command, '"'); - View_Summary view = app->get_active_view(app); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); terminate_with_null(&dir); terminate_with_null(&command); @@ -1267,7 +1296,7 @@ CUSTOM_COMMAND_SIG(build_search){ dir.str, dir.size, command.str, command.size, CLI_OverlapWithConflict); - + return; } dir.size = old_size; @@ -1281,7 +1310,8 @@ CUSTOM_COMMAND_SIG(build_search){ } CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); app->view_auto_tab(app, &view, view.cursor.pos, view.cursor.pos, @@ -1290,8 +1320,9 @@ CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){ } CUSTOM_COMMAND_SIG(auto_tab_whole_file){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); app->view_auto_tab(app, &view, 0, buffer.size, @@ -1300,7 +1331,8 @@ CUSTOM_COMMAND_SIG(auto_tab_whole_file){ } CUSTOM_COMMAND_SIG(auto_tab_range){ - View_Summary view = app->get_active_view(app); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); Range range = get_range(&view); app->view_auto_tab(app, &view, diff --git a/4coder_helper.h b/4coder_helper.h index 40f45efb..e2f54c22 100644 --- a/4coder_helper.h +++ b/4coder_helper.h @@ -241,9 +241,9 @@ exec_command(Application_Links *app, Custom_Command_Function *func){ } inline void -active_view_to_line(Application_Links *app, int line_number){ +active_view_to_line(Application_Links *app, unsigned int access, int line_number){ View_Summary view; - view = app->get_active_view(app); + view = app->get_active_view(app, access); // NOTE(allen|a3.4.4): We don't have to worry about whether this is a valid line number. // When it's not possible to place a cursor at the position for whatever reason it will set the @@ -255,11 +255,15 @@ inline View_Summary get_first_view_with_buffer(Application_Links *app, int buffer_id){ View_Summary result = {}; View_Summary test = {}; - - for(test = app->get_view_first(app); + + unsigned int access = AccessProtected|AccessHidden; + for(test = app->get_view_first(app, access); test.exists; - app->get_view_next(app, &test)){ - if(test.locked_buffer_id == buffer_id){ + app->get_view_next(app, &test, access)){ + + Buffer_Summary buffer = app->get_buffer(app, test.buffer_id, access); + + if(buffer.buffer_id == buffer_id){ result = test; break; } @@ -352,9 +356,9 @@ query_user_number(Application_Links *app, Query_Bar *bar){ inline String empty_string() {String Result = {}; return(Result);} inline Buffer_Summary -get_active_buffer(Application_Links *app){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); +get_active_buffer(Application_Links *app, unsigned int access){ + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); return(buffer); } @@ -729,7 +733,7 @@ static int view_open_file(Application_Links *app, View_Summary *view, char *filename, int filename_len, int do_in_background){ int result = false; - Buffer_Summary buffer = app->get_buffer_by_name(app, filename, filename_len); + Buffer_Summary buffer = app->get_buffer_by_name(app, filename, filename_len, AccessProtected|AccessHidden); if (buffer.exists){ app->view_set_buffer(app, view, buffer.buffer_id); result = true; diff --git a/4ed.cpp b/4ed.cpp index 4a7081c5..5b2442b7 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -260,7 +260,7 @@ do_feedback_message(System_Functions *system, Models *models, String value){ #define USE_FILE(n,v) Editing_File *n = (v)->file_data.file #define REQ_OPEN_VIEW(n) View *n = command->panel->view; if (view_lock_level(n) > LockLevel_Open) return -#define REQ_READABLE_VIEW(n) View *n = command->panel->view; if (view_lock_level(n) > LockLevel_NoWrite) return +#define REQ_READABLE_VIEW(n) View *n = command->panel->view; if (view_lock_level(n) > LockLevel_Protected) return #define REQ_FILE(n,v) Editing_File *n = (v)->file_data.file; if (!n) return #define REQ_FILE_HISTORY(n,v) Editing_File *n = (v)->file_data.file; if (!n || !n->state.undo.undo.edits) return diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 13e3f482..cc5cf204 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -4,6 +4,17 @@ The implementation for the custom API // TOP +inline b32 +access_test(u32 lock_flags, u32 access_flags){ + b32 result = 0; + + if ((lock_flags & ~access_flags) == 0){ + result = 1; + } + + return(result); +} + internal void fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *working_set){ *buffer = buffer_summary_zero(); @@ -22,6 +33,11 @@ fill_buffer_summary(Buffer_Summary *buffer, Editing_File *file, Working_Set *wor buffer->buffer_name = file->name.live_name.str; buffer->map_id = file->settings.base_map_id; + + buffer->lock_flags = 0; + if (file->settings.read_only){ + buffer->lock_flags |= AccessProtected; + } } } @@ -33,8 +49,9 @@ 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){ - i32 lock_level; int buffer_id; + File_Viewing_Data *data = &vptr->file_data; + *view = view_summary_zero(); if (vptr->in_use){ @@ -43,32 +60,12 @@ fill_view_summary(View_Summary *view, View *vptr, Live_Views *live_set, Working_ view->line_height = (float)(vptr->line_height); view->unwrapped_lines = vptr->file_data.unwrapped_lines; view->show_whitespace = vptr->file_data.show_whitespace; + view->lock_flags = view_lock_flags(vptr); - - if (vptr->file_data.file){ - lock_level = view_lock_level(vptr); + if (data->file){ buffer_id = vptr->file_data.file->id.id; - if (lock_level <= 0){ - view->buffer_id = buffer_id; - } - else{ - view->buffer_id = 0; - } - - if (lock_level <= 1){ - view->locked_buffer_id = buffer_id; - } - else{ - view->locked_buffer_id = 0; - } - - if (lock_level <= 2){ - view->hidden_buffer_id = buffer_id; - } - else{ - view->hidden_buffer_id = 0; - } + view->buffer_id = buffer_id; view->mark = view_compute_cursor_from_pos(vptr, vptr->recent->mark); view->cursor = vptr->recent->cursor; @@ -384,19 +381,15 @@ CLIPBOARD_INDEX_SIG(external_clipboard_index){ return(size); } -GET_BUFFER_FIRST_SIG(external_get_buffer_first){ - Command_Data *cmd = (Command_Data*)app->cmd_context; - Working_Set *working_set = &cmd->models->working_set; - Buffer_Summary result = {}; +internal void +internal_get_buffer_first(Working_Set *working_set, Buffer_Summary *buffer){ if (working_set->file_count > 0){ - fill_buffer_summary(&result, (Editing_File*)working_set->used_sentinel.next, working_set); + fill_buffer_summary(buffer, (Editing_File*)working_set->used_sentinel.next, working_set); } - return(result); } -GET_BUFFER_NEXT_SIG(external_get_buffer_next){ - Command_Data *cmd = (Command_Data*)app->cmd_context; - Working_Set *working_set = &cmd->models->working_set; +internal void +internal_get_buffer_next(Working_Set *working_set, Buffer_Summary *buffer){ Editing_File *file; file = working_set_get_active_file(working_set, buffer->buffer_id); @@ -409,6 +402,29 @@ GET_BUFFER_NEXT_SIG(external_get_buffer_next){ } } +GET_BUFFER_FIRST_SIG(external_get_buffer_first){ + Command_Data *cmd = (Command_Data*)app->cmd_context; + Working_Set *working_set = &cmd->models->working_set; + Buffer_Summary result = {}; + + internal_get_buffer_first(working_set, &result); + while (result.exists && !access_test(result.lock_flags, access)){ + internal_get_buffer_next(working_set, &result); + } + + return(result); +} + +GET_BUFFER_NEXT_SIG(external_get_buffer_next){ + Command_Data *cmd = (Command_Data*)app->cmd_context; + Working_Set *working_set = &cmd->models->working_set; + + internal_get_buffer_next(working_set, buffer); + while (buffer->exists && !access_test(buffer->lock_flags, access)){ + internal_get_buffer_next(working_set, buffer); + } +} + GET_BUFFER_SIG(external_get_buffer){ Command_Data *cmd = (Command_Data*)app->cmd_context; Working_Set *working_set = &cmd->models->working_set; @@ -418,6 +434,9 @@ GET_BUFFER_SIG(external_get_buffer){ file = working_set_get_active_file(working_set, index); if (file){ fill_buffer_summary(&buffer, file, working_set); + if (!access_test(buffer.lock_flags, access)){ + buffer = buffer_summary_zero(); + } } return(buffer); @@ -429,7 +448,7 @@ GET_PARAMETER_BUFFER_SIG(external_get_parameter_buffer){ Buffer_Summary buffer = {}; if (param_index >= 0 && param_index < models->buffer_param_count){ - buffer = external_get_buffer(app, models->buffer_param_indices[param_index]); + buffer = external_get_buffer(app, models->buffer_param_indices[param_index], access); } return(buffer); @@ -444,6 +463,9 @@ GET_BUFFER_BY_NAME_SIG(external_get_buffer_by_name){ file = working_set_contains(cmd->system, working_set, make_string(filename, len)); if (file && !file->is_dummy){ fill_buffer_summary(&buffer, file, working_set); + if (!access_test(buffer.lock_flags, access)){ + buffer = buffer_summary_zero(); + } } return(buffer); @@ -451,7 +473,7 @@ GET_BUFFER_BY_NAME_SIG(external_get_buffer_by_name){ REFRESH_BUFFER_SIG(external_refresh_buffer){ int result; - *buffer = external_get_buffer(app, buffer->buffer_id); + *buffer = external_get_buffer(app, buffer->buffer_id, AccessAll); result = buffer->exists; return(result); } @@ -465,84 +487,82 @@ BUFFER_SEEK_SIG(external_buffer_seek){ if (file){ // TODO(allen): reduce duplication? - { - i32 size = buffer_size(&file->state.buffer); - i32 pos[4] = {0}; - i32 new_pos = 0; + i32 size = buffer_size(&file->state.buffer); + i32 pos[4] = {0}; + i32 new_pos = 0; + + if (start_pos < 0){ + start_pos = 0; + } + else if (start_pos > size){ + start_pos = size; + } + + if (seek_forward){ + for (i32 i = 0; i < ArrayCount(pos); ++i) pos[i] = size; - if (start_pos < 0){ - start_pos = 0; - } - else if (start_pos > size){ - start_pos = size; + if (flags & (1)){ + pos[0] = buffer_seek_whitespace_right(&file->state.buffer, start_pos); } - if (seek_forward){ - for (i32 i = 0; i < ArrayCount(pos); ++i) pos[i] = size; - - if (flags & (1)){ - pos[0] = buffer_seek_whitespace_right(&file->state.buffer, start_pos); - } - - if (flags & (1 << 1)){ - if (file->state.tokens_complete){ - pos[1] = seek_token_right(&file->state.token_stack, start_pos); - } - else{ - pos[1] = buffer_seek_whitespace_right(&file->state.buffer, start_pos); - } - } - - if (flags & (1 << 2)){ - pos[2] = buffer_seek_alphanumeric_right(&file->state.buffer, start_pos); - if (flags & (1 << 3)){ - pos[3] = buffer_seek_range_camel_right(&file->state.buffer, start_pos, pos[2]); - } + if (flags & (1 << 1)){ + if (file->state.tokens_complete){ + pos[1] = seek_token_right(&file->state.token_stack, start_pos); } else{ - if (flags & (1 << 3)){ - pos[3] = buffer_seek_alphanumeric_or_camel_right(&file->state.buffer, start_pos); - } + pos[1] = buffer_seek_whitespace_right(&file->state.buffer, start_pos); } - - new_pos = size; - for (i32 i = 0; i < ArrayCount(pos); ++i){ - if (pos[i] < new_pos) new_pos = pos[i]; + } + + if (flags & (1 << 2)){ + pos[2] = buffer_seek_alphanumeric_right(&file->state.buffer, start_pos); + if (flags & (1 << 3)){ + pos[3] = buffer_seek_range_camel_right(&file->state.buffer, start_pos, pos[2]); } } else{ - if (flags & (1)){ - pos[0] = buffer_seek_whitespace_left(&file->state.buffer, start_pos); - } - - if (flags & (1 << 1)){ - if (file->state.tokens_complete){ - pos[1] = seek_token_left(&file->state.token_stack, start_pos); - } - else{ - pos[1] = buffer_seek_whitespace_left(&file->state.buffer, start_pos); - } - } - - if (flags & (1 << 2)){ - pos[2] = buffer_seek_alphanumeric_left(&file->state.buffer, start_pos); - if (flags & (1 << 3)){ - pos[3] = buffer_seek_range_camel_left(&file->state.buffer, start_pos, pos[2]); - } - } - else{ - if (flags & (1 << 3)){ - pos[3] = buffer_seek_alphanumeric_or_camel_left(&file->state.buffer, start_pos); - } - } - - new_pos = 0; - for (i32 i = 0; i < ArrayCount(pos); ++i){ - if (pos[i] > new_pos) new_pos = pos[i]; + if (flags & (1 << 3)){ + pos[3] = buffer_seek_alphanumeric_or_camel_right(&file->state.buffer, start_pos); } } - result = new_pos; + + new_pos = size; + for (i32 i = 0; i < ArrayCount(pos); ++i){ + if (pos[i] < new_pos) new_pos = pos[i]; + } } + else{ + if (flags & (1)){ + pos[0] = buffer_seek_whitespace_left(&file->state.buffer, start_pos); + } + + if (flags & (1 << 1)){ + if (file->state.tokens_complete){ + pos[1] = seek_token_left(&file->state.token_stack, start_pos); + } + else{ + pos[1] = buffer_seek_whitespace_left(&file->state.buffer, start_pos); + } + } + + if (flags & (1 << 2)){ + pos[2] = buffer_seek_alphanumeric_left(&file->state.buffer, start_pos); + if (flags & (1 << 3)){ + pos[3] = buffer_seek_range_camel_left(&file->state.buffer, start_pos, pos[2]); + } + } + else{ + if (flags & (1 << 3)){ + pos[3] = buffer_seek_alphanumeric_or_camel_left(&file->state.buffer, start_pos); + } + } + + new_pos = 0; + for (i32 i = 0; i < ArrayCount(pos); ++i){ + if (pos[i] > new_pos) new_pos = pos[i]; + } + } + result = new_pos; fill_buffer_summary(buffer, file, cmd); } @@ -766,31 +786,29 @@ KILL_BUFFER_SIG(external_kill_buffer){ return(result); } -GET_VIEW_FIRST_SIG(external_get_view_first){ - Command_Data *cmd = (Command_Data*)app->cmd_context; +internal void +internal_get_view_first(Command_Data *cmd, View_Summary *view){ Editing_Layout *layout = &cmd->models->layout; - View_Summary view = {}; - Panel *panel = layout->used_sentinel.next; Assert(panel != &layout->used_sentinel); - fill_view_summary(&view, panel->view, cmd); - - return(view); + fill_view_summary(view, panel->view, cmd); } -GET_VIEW_NEXT_SIG(external_get_view_next){ - Command_Data *cmd = (Command_Data*)app->cmd_context; +internal void +internal_get_view_next(Command_Data *cmd, View_Summary *view){ Editing_Layout *layout = &cmd->models->layout; Live_Views *live_set = &cmd->vars->live_set; - View *vptr; - Panel *panel; int 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; - if (panel) panel = panel->next; + 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); } @@ -803,17 +821,41 @@ GET_VIEW_NEXT_SIG(external_get_view_next){ } } +GET_VIEW_FIRST_SIG(external_get_view_first){ + Command_Data *cmd = (Command_Data*)app->cmd_context; + View_Summary view = {}; + + internal_get_view_first(cmd, &view); + while (view.exists && !access_test(view.lock_flags, access)){ + internal_get_view_next(cmd, &view); + } + + return(view); +} + +GET_VIEW_NEXT_SIG(external_get_view_next){ + Command_Data *cmd = (Command_Data*)app->cmd_context; + + internal_get_view_next(cmd, view); + while (view->exists && !access_test(view->lock_flags, access)){ + internal_get_view_next(cmd, view); + } +} + GET_VIEW_SIG(external_get_view){ Command_Data *cmd = (Command_Data*)app->cmd_context; View_Summary view = {}; Live_Views *live_set = cmd->live_set; int max = live_set->max; - View *vptr; + View *vptr = 0; index -= 1; if (index >= 0 && index < max){ vptr = live_set->views + index; fill_view_summary(&view, vptr, live_set, &cmd->models->working_set); + if (!access_test(view.lock_flags, access)){ + view = view_summary_zero(); + } } return(view); @@ -823,12 +865,15 @@ GET_ACTIVE_VIEW_SIG(external_get_active_view){ Command_Data *cmd = (Command_Data*)app->cmd_context; View_Summary view = {}; fill_view_summary(&view, cmd->view, &cmd->vars->live_set, &cmd->models->working_set); + if (!access_test(view.lock_flags, access)){ + view = view_summary_zero(); + } return(view); } REFRESH_VIEW_SIG(external_refresh_view){ int result; - *view = external_get_view(app, view->view_id); + *view = external_get_view(app, view->view_id, AccessAll); result = view->exists; return(result); } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 355d1032..0377cb8c 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -300,16 +300,36 @@ struct Live_Views{ i32 count, max; }; -#define LockLevel_Open 0 -#define LockLevel_NoWrite 1 -#define LockLevel_NoUpdate 2 +enum Lock_Level{ + LockLevel_Open = 0, + LockLevel_Protected = 1, + LockLevel_Hidden = 2 +}; + +inline u32 +view_lock_flags(View *view){ + u32 result = AccessOpen; + File_Viewing_Data *data = &view->file_data; + if (view->showing_ui != VUI_None){ + result |= AccessHidden; + } + if (data->file_locked || + (data->file && data->file->settings.read_only)){ + result |= AccessProtected; + } + return(result); +} inline i32 view_lock_level(View *view){ i32 result = LockLevel_Open; - File_Viewing_Data *data = &view->file_data; - if (view->showing_ui != VUI_None) result = LockLevel_NoUpdate; - else if (data->file_locked || (data->file && data->file->settings.read_only)) result = LockLevel_NoWrite; + u32 flags = view_lock_flags(view); + if (flags & AccessHidden){ + result = LockLevel_Hidden; + } + else if (flags & AccessProtected){ + result = LockLevel_Protected; + } return(result); } diff --git a/4ed_metagen.cpp b/4ed_metagen.cpp index b2aa3916..944cd501 100644 --- a/4ed_metagen.cpp +++ b/4ed_metagen.cpp @@ -434,6 +434,7 @@ generate_custom_headers(){ if (parse.size > 0){ pos = find(parse, 0, '('); sig->name = substr(parse, 0, pos); + sig->name = chop_whitespace(sig->name); parse = substr(parse, pos); if (parse.size > 0){ diff --git a/4ed_rendering.cpp b/4ed_rendering.cpp index f1fc53aa..ef315f7d 100644 --- a/4ed_rendering.cpp +++ b/4ed_rendering.cpp @@ -362,13 +362,13 @@ part_free(void *ptr, void *context){ // of this function (and other functions implementing // the same interface). internal i32 -draw_font_load(Partition *part, - Render_Font *font_out, - char *filename_untranslated, - i32 pt_size, - i32 tab_width, - i32 oversample, - b32 store_texture){ +font_load(Partition *part, + Render_Font *font_out, + char *filename_untranslated, + i32 pt_size, + i32 tab_width, + i32 oversample, + b32 store_texture){ char space_[1024]; String filename = make_fixed_width_string(space_); diff --git a/custom_api_spec.cpp b/custom_api_spec.cpp index 784c8c71..3e867ca1 100644 --- a/custom_api_spec.cpp +++ b/custom_api_spec.cpp @@ -17,18 +17,19 @@ int Clipboard_Count(Application_Links *app); int Clipboard_Index(Application_Links *app, int index, char *out, int len); // Direct buffer manipulation -Buffer_Summary Get_Buffer_First(Application_Links *app); -void Get_Buffer_Next(Application_Links *app, Buffer_Summary *buffer); +Buffer_Summary Get_Buffer_First(Application_Links *app, unsigned int access); +void Get_Buffer_Next(Application_Links *app, Buffer_Summary *buffer, unsigned int access); -Buffer_Summary Get_Buffer(Application_Links *app, int index); -Buffer_Summary Get_Parameter_Buffer(Application_Links *app, int param_index); -Buffer_Summary Get_Buffer_By_Name(Application_Links *app, char *filename, int len); +Buffer_Summary Get_Buffer(Application_Links *app, int index, unsigned int access); +Buffer_Summary Get_Parameter_Buffer(Application_Links *app, int param_index, unsigned int access); +Buffer_Summary Get_Buffer_By_Name(Application_Links *app, char *filename, int len, unsigned int access); int Refresh_Buffer(Application_Links *app, Buffer_Summary *buffer); -int Buffer_Read_Range(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out); -int Buffer_Replace_Range(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len); +int Buffer_Read_Range(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out); int Buffer_Seek(Application_Links *app, Buffer_Summary *buffer, int start_pos, int seek_forward, unsigned int flags); + +int Buffer_Replace_Range(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len); int Buffer_Set_Setting(Application_Links *app, Buffer_Summary *buffer, int setting, int value); Buffer_Summary Create_Buffer(Application_Links *app, char *filename, int filename_len, int do_in_background); @@ -36,23 +37,22 @@ int Save_Buffer(Application_Links *app, Buffer_Summary *buffer, char *filename, int Kill_Buffer(Application_Links *app, Buffer_Identifier buffer, int always_kill, int view_id); // View manipulation -View_Summary Get_View_First(Application_Links *app); -void Get_View_Next(Application_Links *app, View_Summary *view); +View_Summary Get_View_First(Application_Links *app, unsigned int access); +void Get_View_Next(Application_Links *app, View_Summary *view, unsigned int access); -View_Summary Get_View(Application_Links *app, int index); -View_Summary Get_Active_View(Application_Links *app); +View_Summary Get_View(Application_Links *app, int index, unsigned int access); +View_Summary Get_Active_View(Application_Links *app, unsigned int access); int Refresh_View(Application_Links *app, View_Summary *view); -int View_Auto_Tab(Application_Links *app, View_Summary *view, int start, int end, int tab_width, unsigned int flags); -Full_Cursor View_Compute_Cursor(Application_Links *app, View_Summary *view, Buffer_Seek seek); -int View_Set_Cursor(Application_Links *app, View_Summary *view, Buffer_Seek seek, int set_preferred_x); -int View_Set_Mark(Application_Links *app, View_Summary *view, Buffer_Seek seek); -int View_Set_Highlight(Application_Links *app, View_Summary *view, int start, int end, int turn_on); -int View_Set_Buffer(Application_Links *app, View_Summary *view, int buffer_id); - +int View_Auto_Tab (Application_Links *app, View_Summary *view, int start, int end, int tab_width, unsigned int flags); +Full_Cursor View_Compute_Cursor (Application_Links *app, View_Summary *view, Buffer_Seek seek); +int View_Set_Cursor (Application_Links *app, View_Summary *view, Buffer_Seek seek, int set_preferred_x); +int View_Set_Mark (Application_Links *app, View_Summary *view, Buffer_Seek seek); +int View_Set_Highlight (Application_Links *app, View_Summary *view, int start, int end, int turn_on); +int View_Set_Buffer (Application_Links *app, View_Summary *view, int buffer_id); // TODO(allen): Switch from ticks to seconds. -int View_Post_Fade(Application_Links *app, View_Summary *view, int ticks, int start, int end, unsigned int color); +int View_Post_Fade (Application_Links *app, View_Summary *view, int ticks, int start, int end, unsigned int color); // TODO(allen): // Get rid of this temporary hack ass soon ass possible. diff --git a/linux_4ed.cpp b/linux_4ed.cpp index 03f03f54..c5865fc3 100644 --- a/linux_4ed.cpp +++ b/linux_4ed.cpp @@ -1162,7 +1162,7 @@ Font_Load_Sig(system_draw_font_load){ #if LINUX_FONTS success = linux_font_load(font_out, filename, pt_size, tab_width); #else - success = draw_font_load( + success = font_load( &linuxvars.font_part, font_out, filename, diff --git a/power/4coder_casey.cpp b/power/4coder_casey.cpp index 208d02be..12ae3486 100644 --- a/power/4coder_casey.cpp +++ b/power/4coder_casey.cpp @@ -402,7 +402,8 @@ CUSTOM_COMMAND_SIG(casey_switch_buffer_other_window) internal void DeleteAfterCommand(struct Application_Links *app, unsigned long long CommandID) { - View_Summary view = app->get_active_view(app); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); int pos2 = view.cursor.pos; if (CommandID < cmdid_count){ @@ -416,7 +417,7 @@ DeleteAfterCommand(struct Application_Links *app, unsigned long long CommandID) Range range = make_range(pos1, pos2); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); app->buffer_replace_range(app, &buffer, range.min, range.max, 0, 0); } @@ -432,7 +433,8 @@ CUSTOM_COMMAND_SIG(casey_delete_token_right) CUSTOM_COMMAND_SIG(casey_kill_to_end_of_line) { - View_Summary view = app->get_active_view(app); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); int pos2 = view.cursor.pos; exec_command(app, seek_end_of_line); @@ -445,7 +447,7 @@ CUSTOM_COMMAND_SIG(casey_kill_to_end_of_line) range.max += 1; } - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); app->buffer_replace_range(app, &buffer, range.min, range.max, 0, 0); exec_command(app, auto_tab_line_at_cursor); } @@ -496,9 +498,10 @@ SwitchToOrLoadFile(struct Application_Links *app, String FileName, bool CreateIf switch_to_result Result = {}; SanitizeSlashes(FileName); - - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer_by_name(app, FileName.str, FileName.size); + + unsigned int access = AccessAll; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer_by_name(app, FileName.str, FileName.size, access); Result.view = view; Result.buffer = buffer; @@ -523,7 +526,7 @@ SwitchToOrLoadFile(struct Application_Links *app, String FileName, bool CreateIf // This returns false if the open fails. view_open_file(app, &view, expand_str(FileName), false); - Result.buffer = app->get_buffer_by_name(app, FileName.str, FileName.size); + Result.buffer = app->get_buffer_by_name(app, FileName.str, FileName.size, access); Result.Loaded = true; Result.Switched = true; @@ -575,8 +578,9 @@ CUSTOM_COMMAND_SIG(casey_build_search) CUSTOM_COMMAND_SIG(casey_find_corresponding_file) { - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); String extension = file_extension(make_string(buffer.file_name, buffer.file_name_len)); if (extension.str) @@ -630,11 +634,12 @@ CUSTOM_COMMAND_SIG(casey_find_corresponding_file) CUSTOM_COMMAND_SIG(casey_find_corresponding_file_other_window) { - View_Summary old_view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, old_view.buffer_id); + unsigned int access = AccessProtected; + View_Summary old_view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, old_view.buffer_id, access); exec_command(app, cmdid_change_active_panel); - View_Summary new_view = app->get_active_view(app); + View_Summary new_view = app->get_active_view(app, AccessAll); app->view_set_buffer(app, &new_view, buffer.buffer_id); // exec_command(app, casey_find_corresponding_file); @@ -646,9 +651,10 @@ CUSTOM_COMMAND_SIG(casey_save_and_make_without_asking) Buffer_Summary buffer = {}; - for(buffer = app->get_buffer_first(app); + unsigned int access = AccessAll; + for(buffer = app->get_buffer_first(app, access); buffer.exists; - app->get_buffer_next(app, &buffer)) + app->get_buffer_next(app, &buffer, access)) { #if 0 push_parameter(app, par_name, buffer.file_name, buffer.file_name_len); @@ -712,7 +718,8 @@ CUSTOM_COMMAND_SIG(casey_save_and_make_without_asking) if(append(&command, "build.bat")) { - View_Summary view = app->get_active_view(app); + unsigned int access = AccessAll; + View_Summary view = app->get_active_view(app, access); app->exec_system_command(app, &view, buffer_identifier(GlobalCompilationBufferName, (int)strlen(GlobalCompilationBufferName)), dir.str, dir.size, @@ -843,7 +850,7 @@ casey_parse_error(Application_Links *app, Buffer_Summary buffer, View_Summary vi internal void casey_seek_error_dy(Application_Links *app, int dy) { - Buffer_Summary Buffer = app->get_buffer_by_name(app, GlobalCompilationBufferName, (int)strlen(GlobalCompilationBufferName)); + Buffer_Summary Buffer = app->get_buffer_by_name(app, GlobalCompilationBufferName, (int)strlen(GlobalCompilationBufferName), AccessAll); View_Summary compilation_view = get_first_view_with_buffer(app, Buffer.buffer_id); // NOTE(casey): First get the current error (which may be none, if we've never parsed before) @@ -1068,7 +1075,8 @@ ParseCalc(tokenizer *Tokenizer) CUSTOM_COMMAND_SIG(casey_quick_calc) { - View_Summary view = app->get_active_view(app); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); Range range = get_range(&view); @@ -1076,7 +1084,7 @@ CUSTOM_COMMAND_SIG(casey_quick_calc) char *Stuff = (char *)malloc(Size + 1); Stuff[Size] = 0; - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); app->buffer_read_range(app, &buffer, range.min, range.max, Stuff); tokenizer Tokenizer = {Stuff}; @@ -1331,7 +1339,8 @@ HOOK_SIG(casey_file_settings) // received through functions like this app->get_parameter_buffer. // This is different from the past where this hook got a buffer // from app->get_active_buffer. - Buffer_Summary buffer = app->get_parameter_buffer(app, 0); + unsigned int access = AccessAll; + Buffer_Summary buffer = app->get_parameter_buffer(app, 0, access); int treat_as_code = 0; int treat_as_project = 0; diff --git a/power/4coder_experiments.cpp b/power/4coder_experiments.cpp index 06b77398..1068d7bd 100644 --- a/power/4coder_experiments.cpp +++ b/power/4coder_experiments.cpp @@ -7,8 +7,9 @@ #include CUSTOM_COMMAND_SIG(kill_rect){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + unsigned int access = AccessOpen; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); Full_Cursor cursor; Buffer_Rect rect = get_rect(&view); @@ -30,8 +31,9 @@ CUSTOM_COMMAND_SIG(kill_rect){ // TODO(allen): Both of these brace related commands would work better // if the API exposed access to the tokens in a code file. CUSTOM_COMMAND_SIG(mark_matching_brace){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int start_pos = view.cursor.pos; @@ -110,8 +112,9 @@ CUSTOM_COMMAND_SIG(mark_matching_brace){ } CUSTOM_COMMAND_SIG(cursor_to_surrounding_scope){ - View_Summary view = app->get_active_view(app); - Buffer_Summary buffer = app->get_buffer(app, view.buffer_id); + unsigned int access = AccessProtected; + View_Summary view = app->get_active_view(app, access); + Buffer_Summary buffer = app->get_buffer(app, view.buffer_id, access); int start_pos = view.cursor.pos - 1; diff --git a/win32_4ed.cpp b/win32_4ed.cpp index c820c626..9f28d93b 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -30,6 +30,7 @@ #define SUPPORT_DPI 1 #define USE_WIN32_FONTS 0 +#define USE_FT_FONTS 0 #define FPS 60 #define frame_useconds (1000000 / FPS) @@ -1146,8 +1147,11 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){ #include "system_shared.cpp" #include "4ed_rendering.cpp" + #if USE_WIN32_FONTS -#include "win32_font.cpp" +# include "win32_font.cpp" +#elif USE_FT_FONTS +# include "win32_ft_font.cpp" #endif internal f32 @@ -1174,24 +1178,28 @@ Font_Load_Sig(system_draw_font_load){ for (b32 success = 0; success == 0;){ #if USE_WIN32_FONTS - success = win32_draw_font_load(&win32vars.font_part, - font_out, - filename, - fontname, - pt_size, - tab_width, - oversample, - store_texture); + 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(); #else - success = draw_font_load(&win32vars.font_part, - font_out, - filename, - pt_size, - tab_width, - oversample, - store_texture); + success = font_load(&win32vars.font_part, + font_out, + filename, + pt_size, + tab_width, + oversample, + store_texture); #endif diff --git a/win32_ft_font.cpp b/win32_ft_font.cpp new file mode 100644 index 00000000..bc8fa1c2 --- /dev/null +++ b/win32_ft_font.cpp @@ -0,0 +1,242 @@ +// 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. + + +#undef internal +#include +#include +#include FT_FREETYPE_H +#include FT_LCD_FILTER_H +#define internal static + +//TODO(inso): put in linuxvars +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){ + result = strdup((char*)fname); + fprintf(stderr, "Got system font from FontConfig: %s\n", result); + } + FcPatternDestroy(font); + } + + FcPatternDestroy(pat); + + if(!result){ + char space[1024]; + String str = make_fixed_width_string(space); + if(sysshared_to_binary_path(&str, name)){ + result = strdup(space); + } else { + result = strdup(name); + } + } + + return result; +} + +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 128 +#define ENABLE_LCD_FILTER 0 + +internal b32 +win32_ft_font_load(Render_Font *rf, char *name, i32 pt_size, i32 tab_width){ + +#if 0 + char* filename = linux_get_sys_font(name, pt_size); +#else + char* filename = (char*)malloc(256); + String str = make_string(filename, 0, 256); + sysshared_to_binary_path(&str, name); +#endif + + 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 +#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_REAL_DIM; + size.height = pt_size << 6; + FT_Request_Size(face, &size); + + rf->loaded = 1; + rf->ascent = face->size->metrics.ascender / 64.0f; + rf->descent = face->size->metrics.descender / 64.0f; + rf->advance = face->size->metrics.max_advance / 64.0f; + rf->height = face->size->metrics.height / 64.0f; + rf->line_skip = rf->height - (rf->ascent - rf->descent); + + int max_glyph_w = face->size->metrics.x_ppem; + int max_glyph_h = rf->height; + int tex_width = 64; + int 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); + tex_height = rows * (max_glyph_h + 2); + } while(tex_height > tex_width); + + tex_height = next_pow_of_2(tex_height); + + int pen_x = 0; + int pen_y = 0; + + u32* pixels = (u32*) calloc(tex_width * tex_height, sizeof(u32)); + + // XXX: test if AUTOHINT looks better or not + const u32 ft_extra_flags = use_lcd_filter ? FT_LOAD_TARGET_LCD : FT_LOAD_FORCE_AUTOHINT; + + for(int i = 0; i < NUM_GLYPHS; ++i){ + if(FT_Load_Char(face, i, FT_LOAD_RENDER | ft_extra_flags) != 0) continue; + + int w = face->glyph->bitmap.width; + int 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 + stbtt_packedchar* c = rf->chardata + i; + + c->x0 = pen_x; + c->y0 = pen_y; + c->x1 = pen_x + w; + c->y1 = pen_y + h + 1; + + c->xoff = face->glyph->bitmap_left; + c->yoff = -face->glyph->bitmap_top; + + c->xoff2 = w + c->xoff; + c->yoff2 = h + c->yoff + 1; + + c->xadvance = face->glyph->advance.x >> 6; + + rf->advance_data[i] = c->xadvance; + rf->glyphs[i].exists = 1; + + + int pitch = face->glyph->bitmap.pitch; + + // write to texture atlas + for(int j = 0; j < h; ++j){ + for(int i = 0; i < w; ++i){ + int x = pen_x + i; + int y = pen_y + j; + + if(use_lcd_filter){ + 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 = (r + g + b) / 3.0f; + + pixels[y * tex_width + x] = (a << 24) | (r << 16) | (g << 8) | b; + } else { + pixels[y * tex_width + x] = face->glyph->bitmap.buffer[j * pitch + i] * 0x1010101; + } + } + } + + pen_x = c->x1 + 1; + } + + rf->chardata['\r'] = rf->chardata[' ']; + rf->chardata['\n'] = rf->chardata[' ']; + rf->chardata['\t'] = rf->chardata[' ']; + rf->chardata['\t'].xadvance *= tab_width; + + FT_Done_FreeType(ft); + + tex_height = next_pow_of_2(pen_y + max_glyph_h + 2); + + rf->tex_width = tex_width; + rf->tex_height = tex_height; + + // upload texture + glGenTextures(1, &rf->tex); + glBindTexture(GL_TEXTURE_2D, rf->tex); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + 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); + } + + glBindTexture(GL_TEXTURE_2D, 0); + + free(pixels); + free(filename); + + return 1; +}