Merge branch 'master' of https://bitbucket.org/4coder/4coder
commit
9b4f29d4a7
|
@ -172,55 +172,57 @@ typedef struct File_List{
|
||||||
|
|
||||||
enum Command_ID{
|
enum Command_ID{
|
||||||
cmdid_null,
|
cmdid_null,
|
||||||
cmdid_write_character,
|
|
||||||
cmdid_seek_left,
|
cmdid_seek_left,
|
||||||
cmdid_seek_right,
|
cmdid_seek_right,
|
||||||
cmdid_seek_whitespace_up,
|
|
||||||
cmdid_seek_whitespace_down,
|
|
||||||
cmdid_center_view,
|
cmdid_center_view,
|
||||||
|
|
||||||
cmdid_word_complete,
|
cmdid_word_complete,
|
||||||
cmdid_set_mark,
|
|
||||||
cmdid_copy,
|
cmdid_copy,
|
||||||
cmdid_cut,
|
cmdid_cut,
|
||||||
cmdid_paste,
|
cmdid_paste,
|
||||||
cmdid_paste_next,
|
cmdid_paste_next,
|
||||||
cmdid_delete_range,
|
|
||||||
cmdid_undo,
|
cmdid_undo,
|
||||||
cmdid_redo,
|
cmdid_redo,
|
||||||
cmdid_history_backward,
|
cmdid_history_backward,
|
||||||
cmdid_history_forward,
|
cmdid_history_forward,
|
||||||
|
|
||||||
cmdid_interactive_new,
|
cmdid_interactive_new,
|
||||||
cmdid_interactive_open,
|
cmdid_interactive_open,
|
||||||
cmdid_reopen,
|
cmdid_reopen,
|
||||||
cmdid_save,
|
cmdid_save,
|
||||||
cmdid_change_active_panel,
|
|
||||||
cmdid_interactive_switch_buffer,
|
cmdid_interactive_switch_buffer,
|
||||||
cmdid_interactive_kill_buffer,
|
cmdid_interactive_kill_buffer,
|
||||||
cmdid_kill_buffer,
|
cmdid_kill_buffer,
|
||||||
cmdid_toggle_line_wrap,
|
|
||||||
cmdid_toggle_endline_mode,
|
cmdid_change_active_panel,
|
||||||
|
|
||||||
cmdid_to_uppercase,
|
cmdid_to_uppercase,
|
||||||
cmdid_to_lowercase,
|
cmdid_to_lowercase,
|
||||||
|
|
||||||
|
cmdid_toggle_line_wrap,
|
||||||
cmdid_toggle_show_whitespace,
|
cmdid_toggle_show_whitespace,
|
||||||
cmdid_clean_all_lines,
|
|
||||||
cmdid_eol_dosify,
|
cmdid_eol_dosify,
|
||||||
cmdid_eol_nixify,
|
cmdid_eol_nixify,
|
||||||
|
|
||||||
|
cmdid_clean_all_lines,
|
||||||
cmdid_auto_tab_range,
|
cmdid_auto_tab_range,
|
||||||
|
|
||||||
cmdid_open_panel_vsplit,
|
cmdid_open_panel_vsplit,
|
||||||
cmdid_open_panel_hsplit,
|
cmdid_open_panel_hsplit,
|
||||||
cmdid_close_panel,
|
cmdid_close_panel,
|
||||||
cmdid_move_left,
|
|
||||||
cmdid_move_right,
|
|
||||||
cmdid_delete,
|
|
||||||
cmdid_backspace,
|
|
||||||
cmdid_move_up,
|
|
||||||
cmdid_move_down,
|
|
||||||
cmdid_seek_end_of_line,
|
cmdid_seek_end_of_line,
|
||||||
cmdid_seek_beginning_of_line,
|
cmdid_seek_beginning_of_line,
|
||||||
cmdid_page_up,
|
cmdid_page_up,
|
||||||
cmdid_page_down,
|
cmdid_page_down,
|
||||||
cmdid_open_color_tweaker,
|
|
||||||
cmdid_cursor_mark_swap,
|
cmdid_cursor_mark_swap,
|
||||||
|
|
||||||
|
cmdid_open_color_tweaker,
|
||||||
cmdid_open_menu,
|
cmdid_open_menu,
|
||||||
cmdid_hide_scrollbar,
|
cmdid_hide_scrollbar,
|
||||||
cmdid_show_scrollbar,
|
cmdid_show_scrollbar,
|
||||||
|
@ -240,6 +242,7 @@ enum Param_ID{
|
||||||
par_lex_as_cpp_file,
|
par_lex_as_cpp_file,
|
||||||
par_wrap_lines,
|
par_wrap_lines,
|
||||||
par_key_mapid,
|
par_key_mapid,
|
||||||
|
par_show_whitespace,
|
||||||
par_cli_path,
|
par_cli_path,
|
||||||
par_cli_command,
|
par_cli_command,
|
||||||
par_clear_blank_lines,
|
par_clear_blank_lines,
|
||||||
|
@ -270,9 +273,9 @@ enum Special_Hook_ID{
|
||||||
_hook_scroll_rule = hook_type_count,
|
_hook_scroll_rule = hook_type_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE(allen): None of the members of *_Summary structs nor any of the
|
// None of the members of *_Summary structs nor any of the data pointed
|
||||||
// data pointed to by the members should be modified, I would have made
|
// to by the members should be modified, I would have made them all
|
||||||
// them all const... but that causes a lot problems for C++ reasons.
|
// const... but that causes a lot problems for C++ reasons.
|
||||||
struct Buffer_Summary{
|
struct Buffer_Summary{
|
||||||
int exists;
|
int exists;
|
||||||
int ready;
|
int ready;
|
||||||
|
@ -305,8 +308,9 @@ struct View_Summary{
|
||||||
Full_Cursor cursor;
|
Full_Cursor cursor;
|
||||||
Full_Cursor mark;
|
Full_Cursor mark;
|
||||||
float preferred_x;
|
float preferred_x;
|
||||||
int line_height;
|
float line_height;
|
||||||
int unwrapped_lines;
|
int unwrapped_lines;
|
||||||
|
int show_whitespace;
|
||||||
};
|
};
|
||||||
inline View_Summary
|
inline View_Summary
|
||||||
view_summary_zero(){
|
view_summary_zero(){
|
||||||
|
|
|
@ -11,12 +11,8 @@
|
||||||
#define GET_BUFFER_FIRST_SIG(n) Buffer_Summary n(Application_Links *app)
|
#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_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_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int index)
|
||||||
#define GET_ACTIVE_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app)
|
|
||||||
#define GET_PARAMETER_BUFFER_SIG(n) Buffer_Summary n(Application_Links *app, int param_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_BY_NAME_SIG(n) Buffer_Summary n(Application_Links *app, char *filename, int len)
|
||||||
#define BUFFER_SEEK_DELIMITER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
|
|
||||||
#define BUFFER_SEEK_STRING_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
|
||||||
#define BUFFER_SEEK_STRING_INSENSITIVE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
|
||||||
#define REFRESH_BUFFER_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer)
|
#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_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_REPLACE_RANGE_SIG(n) int n(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *str, int len)
|
||||||
|
@ -56,12 +52,8 @@ extern "C"{
|
||||||
typedef GET_BUFFER_FIRST_SIG(Get_Buffer_First_Function);
|
typedef GET_BUFFER_FIRST_SIG(Get_Buffer_First_Function);
|
||||||
typedef GET_BUFFER_NEXT_SIG(Get_Buffer_Next_Function);
|
typedef GET_BUFFER_NEXT_SIG(Get_Buffer_Next_Function);
|
||||||
typedef GET_BUFFER_SIG(Get_Buffer_Function);
|
typedef GET_BUFFER_SIG(Get_Buffer_Function);
|
||||||
typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function);
|
|
||||||
typedef GET_PARAMETER_BUFFER_SIG(Get_Parameter_Buffer_Function);
|
typedef GET_PARAMETER_BUFFER_SIG(Get_Parameter_Buffer_Function);
|
||||||
typedef GET_BUFFER_BY_NAME_SIG(Get_Buffer_By_Name_Function);
|
typedef GET_BUFFER_BY_NAME_SIG(Get_Buffer_By_Name_Function);
|
||||||
typedef BUFFER_SEEK_DELIMITER_SIG(Buffer_Seek_Delimiter_Function);
|
|
||||||
typedef BUFFER_SEEK_STRING_SIG(Buffer_Seek_String_Function);
|
|
||||||
typedef BUFFER_SEEK_STRING_INSENSITIVE_SIG(Buffer_Seek_String_Insensitive_Function);
|
|
||||||
typedef REFRESH_BUFFER_SIG(Refresh_Buffer_Function);
|
typedef REFRESH_BUFFER_SIG(Refresh_Buffer_Function);
|
||||||
typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function);
|
typedef BUFFER_READ_RANGE_SIG(Buffer_Read_Range_Function);
|
||||||
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
|
typedef BUFFER_REPLACE_RANGE_SIG(Buffer_Replace_Range_Function);
|
||||||
|
@ -104,12 +96,8 @@ struct Application_Links{
|
||||||
Get_Buffer_First_Function *get_buffer_first;
|
Get_Buffer_First_Function *get_buffer_first;
|
||||||
Get_Buffer_Next_Function *get_buffer_next;
|
Get_Buffer_Next_Function *get_buffer_next;
|
||||||
Get_Buffer_Function *get_buffer;
|
Get_Buffer_Function *get_buffer;
|
||||||
Get_Active_Buffer_Function *get_active_buffer;
|
|
||||||
Get_Parameter_Buffer_Function *get_parameter_buffer;
|
Get_Parameter_Buffer_Function *get_parameter_buffer;
|
||||||
Get_Buffer_By_Name_Function *get_buffer_by_name;
|
Get_Buffer_By_Name_Function *get_buffer_by_name;
|
||||||
Buffer_Seek_Delimiter_Function *buffer_seek_delimiter;
|
|
||||||
Buffer_Seek_String_Function *buffer_seek_string;
|
|
||||||
Buffer_Seek_String_Insensitive_Function *buffer_seek_string_insensitive;
|
|
||||||
Refresh_Buffer_Function *refresh_buffer;
|
Refresh_Buffer_Function *refresh_buffer;
|
||||||
Buffer_Read_Range_Function *buffer_read_range;
|
Buffer_Read_Range_Function *buffer_read_range;
|
||||||
Buffer_Replace_Range_Function *buffer_replace_range;
|
Buffer_Replace_Range_Function *buffer_replace_range;
|
||||||
|
|
|
@ -49,44 +49,6 @@ CUSTOM_COMMAND_SIG(switch_to_compilation){
|
||||||
app->view_set_buffer(app, &view, buffer.buffer_id);
|
app->view_set_buffer(app, &view, buffer.buffer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(move_up_10){
|
|
||||||
View_Summary view;
|
|
||||||
float x, y;
|
|
||||||
|
|
||||||
view = app->get_active_view(app);
|
|
||||||
x = view.preferred_x;
|
|
||||||
|
|
||||||
if (view.unwrapped_lines){
|
|
||||||
y = view.cursor.unwrapped_y;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
y = view.cursor.wrapped_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
y -= 10*view.line_height;
|
|
||||||
|
|
||||||
app->view_set_cursor(app, &view, seek_xy(x, y, 0, view.unwrapped_lines), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(move_down_10){
|
|
||||||
View_Summary view;
|
|
||||||
float x, y;
|
|
||||||
|
|
||||||
view = app->get_active_view(app);
|
|
||||||
x = view.preferred_x;
|
|
||||||
|
|
||||||
if (view.unwrapped_lines){
|
|
||||||
y = view.cursor.unwrapped_y;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
y = view.cursor.wrapped_y;
|
|
||||||
}
|
|
||||||
|
|
||||||
y += 10*view.line_height;
|
|
||||||
|
|
||||||
app->view_set_cursor(app, &view, seek_xy(x, y, 0, view.unwrapped_lines), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
|
CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
|
||||||
View_Summary view;
|
View_Summary view;
|
||||||
Buffer_Summary buffer;
|
Buffer_Summary buffer;
|
||||||
|
@ -142,6 +104,7 @@ CUSTOM_COMMAND_SIG(open_my_files){
|
||||||
push_parameter(app, par_name, literal("w:/4ed/data/test/basic.cpp"));
|
push_parameter(app, par_name, literal("w:/4ed/data/test/basic.cpp"));
|
||||||
exec_command(app, cmdid_interactive_open);
|
exec_command(app, cmdid_interactive_open);
|
||||||
|
|
||||||
|
#if 0
|
||||||
exec_command(app, cmdid_change_active_panel);
|
exec_command(app, cmdid_change_active_panel);
|
||||||
|
|
||||||
char my_file[256];
|
char my_file[256];
|
||||||
|
@ -157,6 +120,7 @@ CUSTOM_COMMAND_SIG(open_my_files){
|
||||||
exec_command(app, cmdid_interactive_open);
|
exec_command(app, cmdid_interactive_open);
|
||||||
|
|
||||||
exec_command(app, cmdid_change_active_panel);
|
exec_command(app, cmdid_change_active_panel);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(build_at_launch_location){
|
CUSTOM_COMMAND_SIG(build_at_launch_location){
|
||||||
|
@ -350,14 +314,14 @@ default_keys(Bind_Helper *context){
|
||||||
// into a buffer. If the code for the key is not an enum
|
// into a buffer. If the code for the key is not an enum
|
||||||
// value such as key_left or key_back then it is a vanilla key.
|
// value such as key_left or key_back then it is a vanilla key.
|
||||||
// It is possible to override this binding for individual keys.
|
// It is possible to override this binding for individual keys.
|
||||||
bind_vanilla_keys(context, cmdid_write_character);
|
bind_vanilla_keys(context, write_character);
|
||||||
|
|
||||||
bind(context, key_left, MDFR_NONE, cmdid_move_left);
|
bind(context, key_left, MDFR_NONE, move_left);
|
||||||
bind(context, key_right, MDFR_NONE, cmdid_move_right);
|
bind(context, key_right, MDFR_NONE, move_right);
|
||||||
bind(context, key_del, MDFR_NONE, cmdid_delete);
|
bind(context, key_del, MDFR_NONE, delete_char);
|
||||||
bind(context, key_back, MDFR_NONE, cmdid_backspace);
|
bind(context, key_back, MDFR_NONE, backspace_char);
|
||||||
bind(context, key_up, MDFR_NONE, cmdid_move_up);
|
bind(context, key_up, MDFR_NONE, move_up);
|
||||||
bind(context, key_down, MDFR_NONE, cmdid_move_down);
|
bind(context, key_down, MDFR_NONE, move_down);
|
||||||
bind(context, key_end, MDFR_NONE, cmdid_seek_end_of_line);
|
bind(context, key_end, MDFR_NONE, cmdid_seek_end_of_line);
|
||||||
bind(context, key_home, MDFR_NONE, cmdid_seek_beginning_of_line);
|
bind(context, key_home, MDFR_NONE, cmdid_seek_beginning_of_line);
|
||||||
bind(context, key_page_up, MDFR_NONE, cmdid_page_up);
|
bind(context, key_page_up, MDFR_NONE, cmdid_page_up);
|
||||||
|
@ -365,8 +329,8 @@ default_keys(Bind_Helper *context){
|
||||||
|
|
||||||
bind(context, key_right, MDFR_CTRL, seek_whitespace_right);
|
bind(context, key_right, MDFR_CTRL, seek_whitespace_right);
|
||||||
bind(context, key_left, MDFR_CTRL, seek_whitespace_left);
|
bind(context, key_left, MDFR_CTRL, seek_whitespace_left);
|
||||||
bind(context, key_up, MDFR_CTRL, cmdid_seek_whitespace_up);
|
bind(context, key_up, MDFR_CTRL, seek_whitespace_up);
|
||||||
bind(context, key_down, MDFR_CTRL, cmdid_seek_whitespace_down);
|
bind(context, key_down, MDFR_CTRL, seek_whitespace_down);
|
||||||
|
|
||||||
bind(context, key_up, MDFR_ALT, move_up_10);
|
bind(context, key_up, MDFR_ALT, move_up_10);
|
||||||
bind(context, key_down, MDFR_ALT, move_down_10);
|
bind(context, key_down, MDFR_ALT, move_down_10);
|
||||||
|
@ -374,19 +338,18 @@ default_keys(Bind_Helper *context){
|
||||||
bind(context, key_back, MDFR_CTRL, backspace_word);
|
bind(context, key_back, MDFR_CTRL, backspace_word);
|
||||||
bind(context, key_back, MDFR_ALT, snipe_token_or_word);
|
bind(context, key_back, MDFR_ALT, snipe_token_or_word);
|
||||||
|
|
||||||
bind(context, ' ', MDFR_CTRL, cmdid_set_mark);
|
bind(context, ' ', MDFR_CTRL, set_mark);
|
||||||
bind(context, 'a', MDFR_CTRL, replace_in_range);
|
bind(context, 'a', MDFR_CTRL, replace_in_range);
|
||||||
bind(context, 'c', MDFR_CTRL, cmdid_copy);
|
bind(context, 'c', MDFR_CTRL, cmdid_copy);
|
||||||
bind(context, 'd', MDFR_CTRL, cmdid_delete_range);
|
bind(context, 'd', MDFR_CTRL, delete_range);
|
||||||
bind(context, 'e', MDFR_CTRL, cmdid_center_view);
|
bind(context, 'e', MDFR_CTRL, cmdid_center_view);
|
||||||
bind(context, 'f', MDFR_CTRL, search);
|
bind(context, 'f', MDFR_CTRL, search);
|
||||||
bind(context, 'g', MDFR_CTRL, goto_line);
|
bind(context, 'g', MDFR_CTRL, goto_line);
|
||||||
bind(context, 'h', MDFR_CTRL, cmdid_history_backward);
|
bind(context, 'h', MDFR_CTRL, cmdid_history_backward);
|
||||||
bind(context, 'H', MDFR_CTRL, cmdid_history_forward);
|
bind(context, 'H', MDFR_CTRL, cmdid_history_forward);
|
||||||
bind(context, 'l', MDFR_CTRL, cmdid_toggle_line_wrap);
|
|
||||||
bind(context, 'j', MDFR_CTRL, cmdid_to_lowercase);
|
bind(context, 'j', MDFR_CTRL, cmdid_to_lowercase);
|
||||||
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);
|
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);
|
||||||
bind(context, 'L', MDFR_CTRL, cmdid_toggle_endline_mode);
|
bind(context, 'l', MDFR_CTRL, cmdid_toggle_line_wrap);
|
||||||
bind(context, 'm', MDFR_CTRL, cmdid_cursor_mark_swap);
|
bind(context, 'm', MDFR_CTRL, cmdid_cursor_mark_swap);
|
||||||
bind(context, 'O', MDFR_CTRL, cmdid_reopen);
|
bind(context, 'O', MDFR_CTRL, cmdid_reopen);
|
||||||
bind(context, 'q', MDFR_CTRL, query_replace);
|
bind(context, 'q', MDFR_CTRL, query_replace);
|
||||||
|
@ -409,7 +372,7 @@ default_keys(Bind_Helper *context){
|
||||||
bind(context, '~', MDFR_CTRL, cmdid_clean_all_lines);
|
bind(context, '~', MDFR_CTRL, cmdid_clean_all_lines);
|
||||||
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
|
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
|
||||||
bind(context, '\n', MDFR_SHIFT, write_and_auto_tab);
|
bind(context, '\n', MDFR_SHIFT, write_and_auto_tab);
|
||||||
bind(context, ' ', MDFR_SHIFT, cmdid_write_character);
|
bind(context, ' ', MDFR_SHIFT, write_character);
|
||||||
|
|
||||||
end_map(context);
|
end_map(context);
|
||||||
}
|
}
|
||||||
|
@ -434,94 +397,6 @@ get_bindings(void *data, int size){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Custom_Vars{
|
|
||||||
int initialized;
|
|
||||||
Partition part;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum View_Mode{
|
|
||||||
ViewMode_File,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct View_Vars{
|
|
||||||
int id;
|
|
||||||
View_Mode mode;
|
|
||||||
|
|
||||||
GUI_Scroll_Vars scroll;
|
|
||||||
i32_Rect scroll_region;
|
|
||||||
|
|
||||||
int buffer_id;
|
|
||||||
};
|
|
||||||
inline View_Vars
|
|
||||||
view_vars_zero(){
|
|
||||||
View_Vars vars = {0};
|
|
||||||
return(vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
view_routine(Application_Links *app, int view_id){
|
|
||||||
Custom_Vars *vars = (Custom_Vars*)app->memory;
|
|
||||||
View_Vars view = {0};
|
|
||||||
view.id = view_id;
|
|
||||||
|
|
||||||
int show_scrollbar = 1;
|
|
||||||
|
|
||||||
if (!vars->initialized){
|
|
||||||
vars->initialized = 1;
|
|
||||||
vars->part = make_part(app->memory, app->memory_size);
|
|
||||||
push_struct(&vars->part, Custom_Vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(;;){
|
|
||||||
Event_Message message = {0};
|
|
||||||
message = app->get_event_message(app);
|
|
||||||
|
|
||||||
switch (message.type){
|
|
||||||
case EM_Open_View:
|
|
||||||
{
|
|
||||||
view = view_vars_zero();
|
|
||||||
view.id = view_id;
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case EM_Frame:
|
|
||||||
{
|
|
||||||
GUI_Functions *guifn = app->get_gui_functions(app);
|
|
||||||
GUI *gui = app->get_gui(app, view_id);
|
|
||||||
|
|
||||||
guifn->begin(gui);
|
|
||||||
guifn->top_bar(gui);
|
|
||||||
|
|
||||||
switch (view.mode){
|
|
||||||
case ViewMode_File:
|
|
||||||
// TODO(allen): Overlapped widget
|
|
||||||
GUI_id scroll_id;
|
|
||||||
scroll_id.id[1] = view.mode;
|
|
||||||
scroll_id.id[0] = view.buffer_id;
|
|
||||||
|
|
||||||
guifn->get_scroll_vars(gui, scroll_id, &view.scroll,
|
|
||||||
&view.scroll_region);
|
|
||||||
guifn->begin_scrollable(gui, scroll_id, view.scroll,
|
|
||||||
144.f, show_scrollbar);
|
|
||||||
guifn->file(gui, view.buffer_id);
|
|
||||||
guifn->end_scrollable(gui);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
guifn->end(gui);
|
|
||||||
|
|
||||||
// TODO(allen): Put this code in charge of dispatching
|
|
||||||
// to the command or command coroutine or whatever.
|
|
||||||
|
|
||||||
// TODO(allen): Put this code in charge of when to process
|
|
||||||
// the GUI with input and retrieve new layout data.
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case EM_Close_View:
|
|
||||||
{}break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
|
@ -4,19 +4,293 @@
|
||||||
#define FCPP_STRING_IMPLEMENTATION
|
#define FCPP_STRING_IMPLEMENTATION
|
||||||
#include "4coder_string.h"
|
#include "4coder_string.h"
|
||||||
|
|
||||||
#define UseInterfacesThatArePhasingOut 0
|
|
||||||
#include "4coder_helper.h"
|
#include "4coder_helper.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
static void
|
inline float
|
||||||
write_string(Application_Links *app, String string){
|
get_view_y(View_Summary view){
|
||||||
Buffer_Summary buffer = app->get_active_buffer(app);
|
float y;
|
||||||
app->buffer_replace_range(app, &buffer, buffer.buffer_cursor_pos, buffer.buffer_cursor_pos, string.str, string.size);
|
if (view.unwrapped_lines){
|
||||||
|
y = view.cursor.unwrapped_y;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
y = view.cursor.wrapped_y;
|
||||||
|
}
|
||||||
|
return(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(write_increment){
|
inline float
|
||||||
write_string(app, make_lit_string("++"));
|
get_view_x(View_Summary view){
|
||||||
|
float x;
|
||||||
|
if (view.unwrapped_lines){
|
||||||
|
x = view.cursor.unwrapped_x;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
x = view.cursor.wrapped_x;
|
||||||
|
}
|
||||||
|
return(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Fundamental Editing
|
||||||
|
//
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(write_character){
|
||||||
|
View_Summary view = app->get_active_view(app);
|
||||||
|
|
||||||
|
User_Input in = app->get_command_input(app);
|
||||||
|
char character = 0;
|
||||||
|
|
||||||
|
if (in.type == UserInputKey){
|
||||||
|
character = in.key.character;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character != 0){
|
||||||
|
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||||
|
int pos = view.cursor.pos;
|
||||||
|
int next_pos = pos + 1;
|
||||||
|
app->buffer_replace_range(app, &buffer,
|
||||||
|
pos, pos, &character, 1);
|
||||||
|
app->view_set_cursor(app, &view, seek_pos(next_pos), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(delete_char){
|
||||||
|
View_Summary view = app->get_active_view(app);
|
||||||
|
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||||
|
|
||||||
|
int pos = view.cursor.pos;
|
||||||
|
if (0 < buffer.size && pos < buffer.size){
|
||||||
|
app->buffer_replace_range(app, &buffer,
|
||||||
|
pos, pos+1, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(backspace_char){
|
||||||
|
View_Summary view = app->get_active_view(app);
|
||||||
|
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||||
|
|
||||||
|
int pos = view.cursor.pos;
|
||||||
|
if (0 < pos && pos <= buffer.size){
|
||||||
|
app->buffer_replace_range(app, &buffer,
|
||||||
|
pos-1, pos, 0, 0);
|
||||||
|
|
||||||
|
app->view_set_cursor(app, &view, seek_pos(pos-1), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(set_mark){
|
||||||
|
View_Summary view = app->get_active_view(app);
|
||||||
|
|
||||||
|
app->view_set_mark(app, &view, seek_pos(view.cursor.pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(delete_range){
|
||||||
|
View_Summary view = app->get_active_view(app);
|
||||||
|
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||||
|
|
||||||
|
Range range = get_range(&view);
|
||||||
|
|
||||||
|
app->buffer_replace_range(app, &buffer,
|
||||||
|
range.min, range.max,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Basic Navigation
|
||||||
|
//
|
||||||
|
|
||||||
|
inline void
|
||||||
|
move_vertical(Application_Links *app, float line_multiplier){
|
||||||
|
View_Summary view = app->get_active_view(app);
|
||||||
|
|
||||||
|
float new_y = get_view_y(view) + line_multiplier*view.line_height;
|
||||||
|
float x = view.preferred_x;
|
||||||
|
|
||||||
|
app->view_set_cursor(app, &view,
|
||||||
|
seek_xy(x, new_y, false, view.unwrapped_lines),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(move_up){
|
||||||
|
move_vertical(app, -1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(move_down){
|
||||||
|
move_vertical(app, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(move_up_10){
|
||||||
|
move_vertical(app, -10.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(move_down_10){
|
||||||
|
move_vertical(app, 10.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(move_left){
|
||||||
|
View_Summary view = app->get_active_view(app);
|
||||||
|
int new_pos = view.cursor.pos - 1;
|
||||||
|
app->view_set_cursor(app, &view,
|
||||||
|
seek_pos(new_pos),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(move_right){
|
||||||
|
View_Summary view = app->get_active_view(app);
|
||||||
|
int new_pos = view.cursor.pos + 1;
|
||||||
|
app->view_set_cursor(app, &view,
|
||||||
|
seek_pos(new_pos),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Various Forms of Seek
|
||||||
|
//
|
||||||
|
|
||||||
|
static int
|
||||||
|
buffer_seek_whitespace_up(Application_Links *app, Buffer_Summary *buffer, int pos){
|
||||||
|
char chunk[1024];
|
||||||
|
int chunk_size = sizeof(chunk);
|
||||||
|
Stream_Chunk stream = {0};
|
||||||
|
|
||||||
|
int no_hard;
|
||||||
|
int still_looping;
|
||||||
|
char at_pos;
|
||||||
|
|
||||||
|
--pos;
|
||||||
|
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||||
|
// Step 1: Find the first non-whitespace character
|
||||||
|
// behind the current position.
|
||||||
|
still_looping = true;
|
||||||
|
do{
|
||||||
|
for (; pos >= stream.start; --pos){
|
||||||
|
at_pos = stream.data[pos];
|
||||||
|
if (!char_is_whitespace(at_pos)){
|
||||||
|
goto double_break_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = backward_stream_chunk(&stream);
|
||||||
|
} while(still_looping);
|
||||||
|
double_break_1:;
|
||||||
|
|
||||||
|
// Step 2: Continue scanning backward, at each '\n'
|
||||||
|
// mark the beginning of another line by setting
|
||||||
|
// no_hard to true, set it back to false if a
|
||||||
|
// non-whitespace character is discovered before
|
||||||
|
// the next '\n'
|
||||||
|
no_hard = false;
|
||||||
|
while (still_looping){
|
||||||
|
for (; pos >= stream.start; --pos){
|
||||||
|
at_pos = stream.data[pos];
|
||||||
|
if (at_pos == '\n'){
|
||||||
|
if (no_hard){
|
||||||
|
goto double_break_2;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
no_hard = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!char_is_whitespace(at_pos)){
|
||||||
|
no_hard = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = backward_stream_chunk(&stream);
|
||||||
|
}
|
||||||
|
double_break_2:;
|
||||||
|
|
||||||
|
if (pos != 0){
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
buffer_seek_whitespace_down(Application_Links *app, Buffer_Summary *buffer, int pos){
|
||||||
|
char chunk[1024];
|
||||||
|
int chunk_size = sizeof(chunk);
|
||||||
|
Stream_Chunk stream = {0};
|
||||||
|
|
||||||
|
int no_hard;
|
||||||
|
int prev_endline;
|
||||||
|
int still_looping;
|
||||||
|
char at_pos;
|
||||||
|
|
||||||
|
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||||
|
// Step 1: Find the first non-whitespace character
|
||||||
|
// ahead of the current position.
|
||||||
|
still_looping = true;
|
||||||
|
do{
|
||||||
|
for (; pos < stream.end; ++pos){
|
||||||
|
at_pos = stream.data[pos];
|
||||||
|
if (!char_is_whitespace(at_pos)){
|
||||||
|
goto double_break_1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = forward_stream_chunk(&stream);
|
||||||
|
} while(still_looping);
|
||||||
|
double_break_1:;
|
||||||
|
|
||||||
|
// Step 2: Continue scanning forward, at each '\n'
|
||||||
|
// mark it as the beginning of a new line by updating
|
||||||
|
// the prev_endline value. If another '\n' is found
|
||||||
|
// with non-whitespace then the previous line was
|
||||||
|
// all whitespace.
|
||||||
|
no_hard = false;
|
||||||
|
prev_endline = -1;
|
||||||
|
while(still_looping){
|
||||||
|
for (; pos < stream.end; ++pos){
|
||||||
|
at_pos = stream.data[pos];
|
||||||
|
if (at_pos == '\n'){
|
||||||
|
if (no_hard){
|
||||||
|
goto double_break_2;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
no_hard = true;
|
||||||
|
prev_endline = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!char_is_whitespace(at_pos)){
|
||||||
|
no_hard = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = forward_stream_chunk(&stream);
|
||||||
|
}
|
||||||
|
double_break_2:;
|
||||||
|
|
||||||
|
if (prev_endline == -1 || prev_endline+1 >= buffer->size){
|
||||||
|
pos = buffer->size;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
pos = prev_endline+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int new_pos = buffer_seek_whitespace_up(app, &buffer, view.cursor.pos);
|
||||||
|
app->view_set_cursor(app, &view,
|
||||||
|
seek_pos(new_pos),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
int new_pos = buffer_seek_whitespace_down(app, &buffer, view.cursor.pos);
|
||||||
|
app->view_set_cursor(app, &view,
|
||||||
|
seek_pos(new_pos),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -39,6 +313,23 @@ SEEK_COMMAND(alphanumeric, left, BoundryAlphanumeric)
|
||||||
SEEK_COMMAND(alphanumeric_or_camel, right, BoundryAlphanumeric | BoundryCamelCase)
|
SEEK_COMMAND(alphanumeric_or_camel, right, BoundryAlphanumeric | BoundryCamelCase)
|
||||||
SEEK_COMMAND(alphanumeric_or_camel, left, BoundryAlphanumeric | BoundryCamelCase)
|
SEEK_COMMAND(alphanumeric_or_camel, left, BoundryAlphanumeric | BoundryCamelCase)
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Special string writing commands
|
||||||
|
//
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_string(Application_Links *app, String string){
|
||||||
|
Buffer_Summary buffer = get_active_buffer(app);
|
||||||
|
app->buffer_replace_range(app, &buffer,
|
||||||
|
buffer.buffer_cursor_pos, buffer.buffer_cursor_pos,
|
||||||
|
string.str, string.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_COMMAND_SIG(write_increment){
|
||||||
|
write_string(app, make_lit_string("++"));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
long_braces(Application_Links *app, char *text, int size){
|
long_braces(Application_Links *app, char *text, int size){
|
||||||
View_Summary view;
|
View_Summary view;
|
||||||
|
@ -92,7 +383,7 @@ CUSTOM_COMMAND_SIG(if0_off){
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
view = app->get_active_view(app);
|
view = app->get_active_view(app);
|
||||||
buffer = app->get_active_buffer(app);
|
buffer = app->get_buffer(app, view.buffer_id);
|
||||||
|
|
||||||
range = get_range(&view);
|
range = get_range(&view);
|
||||||
pos = range.min;
|
pos = range.min;
|
||||||
|
@ -161,8 +452,8 @@ CUSTOM_COMMAND_SIG(open_file_in_quotes){
|
||||||
view = app->get_active_view(app);
|
view = app->get_active_view(app);
|
||||||
buffer = app->get_buffer(app, view.buffer_id);
|
buffer = app->get_buffer(app, view.buffer_id);
|
||||||
pos = view.cursor.pos;
|
pos = view.cursor.pos;
|
||||||
app->buffer_seek_delimiter(app, &buffer, pos, '"', 1, &end);
|
buffer_seek_delimiter_forward(app, &buffer, pos, '"', &end);
|
||||||
app->buffer_seek_delimiter(app, &buffer, pos, '"', 0, &start);
|
buffer_seek_delimiter_backward(app, &buffer, pos, '"', &start);
|
||||||
|
|
||||||
++start;
|
++start;
|
||||||
size = end - start;
|
size = end - start;
|
||||||
|
@ -286,13 +577,14 @@ isearch(Application_Links *app, int start_reversed){
|
||||||
if (in.key.keycode != key_back){
|
if (in.key.keycode != key_back){
|
||||||
int new_pos;
|
int new_pos;
|
||||||
if (reverse){
|
if (reverse){
|
||||||
// TODO(allen): Need a good way to allow users to implement seeks for themselves.
|
buffer_seek_string_insensitive_backward(app, &buffer, start_pos - 1,
|
||||||
app->buffer_seek_string_insensitive(app, &buffer, start_pos - 1, bar.string.str, bar.string.size, 0, &new_pos);
|
bar.string.str, bar.string.size, &new_pos);
|
||||||
if (new_pos >= 0){
|
if (new_pos >= 0){
|
||||||
if (step_backward){
|
if (step_backward){
|
||||||
pos = new_pos;
|
pos = new_pos;
|
||||||
start_pos = new_pos;
|
start_pos = new_pos;
|
||||||
app->buffer_seek_string_insensitive(app, &buffer, start_pos - 1, bar.string.str, bar.string.size, 0, &new_pos);
|
buffer_seek_string_insensitive_backward(app, &buffer, start_pos - 1,
|
||||||
|
bar.string.str, bar.string.size, &new_pos);
|
||||||
if (new_pos < 0) new_pos = start_pos;
|
if (new_pos < 0) new_pos = start_pos;
|
||||||
}
|
}
|
||||||
match.start = new_pos;
|
match.start = new_pos;
|
||||||
|
@ -300,12 +592,14 @@ isearch(Application_Links *app, int start_reversed){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
app->buffer_seek_string_insensitive(app, &buffer, start_pos + 1, bar.string.str, bar.string.size, 1, &new_pos);
|
buffer_seek_string_insensitive_forward(app, &buffer, start_pos + 1,
|
||||||
|
bar.string.str, bar.string.size, &new_pos);
|
||||||
if (new_pos < buffer.size){
|
if (new_pos < buffer.size){
|
||||||
if (step_forward){
|
if (step_forward){
|
||||||
pos = new_pos;
|
pos = new_pos;
|
||||||
start_pos = new_pos;
|
start_pos = new_pos;
|
||||||
app->buffer_seek_string_insensitive(app, &buffer, start_pos + 1, bar.string.str, bar.string.size, 1, &new_pos);
|
buffer_seek_string_insensitive_forward(app, &buffer, start_pos + 1,
|
||||||
|
bar.string.str, bar.string.size, &new_pos);
|
||||||
if (new_pos >= buffer.size) new_pos = start_pos;
|
if (new_pos >= buffer.size) new_pos = start_pos;
|
||||||
}
|
}
|
||||||
match.start = new_pos;
|
match.start = new_pos;
|
||||||
|
@ -365,14 +659,14 @@ CUSTOM_COMMAND_SIG(replace_in_range){
|
||||||
|
|
||||||
int pos, new_pos;
|
int pos, new_pos;
|
||||||
pos = range.min;
|
pos = range.min;
|
||||||
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
|
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
|
||||||
|
|
||||||
while (new_pos + r.size <= range.end){
|
while (new_pos + r.size <= range.end){
|
||||||
app->buffer_replace_range(app, &buffer, new_pos, new_pos + r.size, w.str, w.size);
|
app->buffer_replace_range(app, &buffer, new_pos, new_pos + r.size, w.str, w.size);
|
||||||
app->refresh_view(app, &view);
|
app->refresh_view(app, &view);
|
||||||
range = get_range(&view);
|
range = get_range(&view);
|
||||||
pos = new_pos + w.size;
|
pos = new_pos + w.size;
|
||||||
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
|
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,7 +704,7 @@ CUSTOM_COMMAND_SIG(query_replace){
|
||||||
buffer = app->get_buffer(app, view.buffer_id);
|
buffer = app->get_buffer(app, view.buffer_id);
|
||||||
|
|
||||||
pos = view.cursor.pos;
|
pos = view.cursor.pos;
|
||||||
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
|
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
|
||||||
|
|
||||||
User_Input in = {0};
|
User_Input in = {0};
|
||||||
while (new_pos < buffer.size){
|
while (new_pos < buffer.size){
|
||||||
|
@ -428,7 +722,7 @@ CUSTOM_COMMAND_SIG(query_replace){
|
||||||
pos = match.max;
|
pos = match.max;
|
||||||
}
|
}
|
||||||
|
|
||||||
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
|
buffer_seek_string_forward(app, &buffer, pos, r.str, r.size, &new_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
app->view_set_highlight(app, &view, 0, 0, 0);
|
app->view_set_highlight(app, &view, 0, 0, 0);
|
||||||
|
@ -663,14 +957,14 @@ CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(auto_tab_whole_file){
|
CUSTOM_COMMAND_SIG(auto_tab_whole_file){
|
||||||
Buffer_Summary buffer = app->get_active_buffer(app);
|
Buffer_Summary buffer = get_active_buffer(app);
|
||||||
push_parameter(app, par_range_start, 0);
|
push_parameter(app, par_range_start, 0);
|
||||||
push_parameter(app, par_range_end, buffer.size);
|
push_parameter(app, par_range_end, buffer.size);
|
||||||
exec_command(app, cmdid_auto_tab_range);
|
exec_command(app, cmdid_auto_tab_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(write_and_auto_tab){
|
CUSTOM_COMMAND_SIG(write_and_auto_tab){
|
||||||
exec_command(app, cmdid_write_character);
|
exec_command(app, write_character);
|
||||||
exec_command(app, auto_tab_line_at_cursor);
|
exec_command(app, auto_tab_line_at_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ struct GUI_Scroll_Vars{
|
||||||
float scroll_y;
|
float scroll_y;
|
||||||
float target_y;
|
float target_y;
|
||||||
float prev_target_y;
|
float prev_target_y;
|
||||||
float min_y, max_y;
|
float max_y;
|
||||||
|
|
||||||
float scroll_x;
|
float scroll_x;
|
||||||
float target_x;
|
float target_x;
|
||||||
|
|
358
4coder_helper.h
358
4coder_helper.h
|
@ -386,3 +386,361 @@ query_user_number(Application_Links *app, Query_Bar *bar){
|
||||||
}
|
}
|
||||||
|
|
||||||
inline String empty_string() {String Result = {}; return(Result);}
|
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);
|
||||||
|
return(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Stream_Chunk{
|
||||||
|
Application_Links *app;
|
||||||
|
Buffer_Summary *buffer;
|
||||||
|
|
||||||
|
char *base_data;
|
||||||
|
int start, end;
|
||||||
|
int data_size;
|
||||||
|
|
||||||
|
char *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
round_down(int x, int b){
|
||||||
|
int r = 0;
|
||||||
|
if (x >= 0){
|
||||||
|
r = x - (x % b);
|
||||||
|
}
|
||||||
|
return(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
round_up(int x, int b){
|
||||||
|
int r = 0;
|
||||||
|
if (x >= 0){
|
||||||
|
r = x - (x % b) + b;
|
||||||
|
}
|
||||||
|
return(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
init_stream_chunk(Stream_Chunk *chunk,
|
||||||
|
Application_Links *app, Buffer_Summary *buffer,
|
||||||
|
int pos, char *data, int size){
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
app->refresh_buffer(app, buffer);
|
||||||
|
if (pos >= 0 && pos < buffer->size && size > 0){
|
||||||
|
result = 1;
|
||||||
|
chunk->app = app;
|
||||||
|
chunk->buffer = buffer;
|
||||||
|
chunk->base_data = data;
|
||||||
|
chunk->data_size = size;
|
||||||
|
chunk->start = round_down(pos, size);
|
||||||
|
chunk->end = round_up(pos, size);
|
||||||
|
if (chunk->end > buffer->size){
|
||||||
|
chunk->end = buffer->size;
|
||||||
|
}
|
||||||
|
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||||
|
chunk->data = chunk->base_data - chunk->start;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
forward_stream_chunk(Stream_Chunk *chunk){
|
||||||
|
Application_Links *app = chunk->app;
|
||||||
|
Buffer_Summary *buffer = chunk->buffer;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
app->refresh_buffer(app, buffer);
|
||||||
|
if (chunk->end < buffer->size){
|
||||||
|
result = 1;
|
||||||
|
chunk->start = chunk->end;
|
||||||
|
chunk->end += chunk->data_size;
|
||||||
|
if (chunk->end > buffer->size){
|
||||||
|
chunk->end = buffer->size;
|
||||||
|
}
|
||||||
|
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||||
|
chunk->data = chunk->base_data - chunk->start;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
backward_stream_chunk(Stream_Chunk *chunk){
|
||||||
|
Application_Links *app = chunk->app;
|
||||||
|
Buffer_Summary *buffer = chunk->buffer;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
app->refresh_buffer(app, buffer);
|
||||||
|
if (chunk->start > 0){
|
||||||
|
result = 1;
|
||||||
|
chunk->end = chunk->start;
|
||||||
|
chunk->start -= chunk->data_size;
|
||||||
|
if (chunk->start < 0){
|
||||||
|
chunk->start = 0;
|
||||||
|
}
|
||||||
|
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
||||||
|
chunk->data = chunk->base_data - chunk->start;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
buffer_seek_delimiter_forward(Application_Links *app, Buffer_Summary *buffer,
|
||||||
|
int pos, char delim, int *result){
|
||||||
|
if (buffer->exists){
|
||||||
|
char chunk[1024];
|
||||||
|
int size = sizeof(chunk);
|
||||||
|
Stream_Chunk stream = {0};
|
||||||
|
|
||||||
|
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
|
||||||
|
int still_looping = 1;
|
||||||
|
do{
|
||||||
|
for(; pos < stream.end; ++pos){
|
||||||
|
char at_pos = stream.data[pos];
|
||||||
|
if (at_pos == delim){
|
||||||
|
*result = pos;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = forward_stream_chunk(&stream);
|
||||||
|
}while (still_looping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = buffer->size;
|
||||||
|
|
||||||
|
finished:;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
buffer_seek_delimiter_backward(Application_Links *app, Buffer_Summary *buffer,
|
||||||
|
int pos, char delim, int *result){
|
||||||
|
if (buffer->exists){
|
||||||
|
char chunk[1024];
|
||||||
|
int size = sizeof(chunk);
|
||||||
|
Stream_Chunk stream = {0};
|
||||||
|
|
||||||
|
if (init_stream_chunk(&stream, app, buffer, pos, chunk, size)){
|
||||||
|
int still_looping = 1;
|
||||||
|
do{
|
||||||
|
for(; pos >= stream.start; --pos){
|
||||||
|
char at_pos = stream.data[pos];
|
||||||
|
if (at_pos == delim){
|
||||||
|
*result = pos;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = backward_stream_chunk(&stream);
|
||||||
|
}while (still_looping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = 0;
|
||||||
|
|
||||||
|
finished:;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(allen): This duplication is driving me crazy... I've gotta
|
||||||
|
// upgrade the meta programming system another level.
|
||||||
|
|
||||||
|
// NOTE(allen): This is limitted to a string size of 512.
|
||||||
|
// You can push it up or do something more clever by just
|
||||||
|
// replacing char read_buffer[512]; with more memory.
|
||||||
|
void
|
||||||
|
buffer_seek_string_forward(Application_Links *app, Buffer_Summary *buffer,
|
||||||
|
int pos, char *str, int size, int *result){
|
||||||
|
char read_buffer[512];
|
||||||
|
char chunk[1024];
|
||||||
|
int chunk_size = sizeof(chunk);
|
||||||
|
Stream_Chunk stream = {0};
|
||||||
|
|
||||||
|
if (size <= 0){
|
||||||
|
*result = pos;
|
||||||
|
}
|
||||||
|
else if (size > sizeof(read_buffer)){
|
||||||
|
*result = pos;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (buffer->exists){
|
||||||
|
String read_str = make_fixed_width_string(read_buffer);
|
||||||
|
String needle_str = make_string(str, size);
|
||||||
|
char first_char = str[0];
|
||||||
|
|
||||||
|
read_str.size = size;
|
||||||
|
|
||||||
|
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||||
|
int still_looping = 1;
|
||||||
|
do{
|
||||||
|
for(; pos < stream.end; ++pos){
|
||||||
|
char at_pos = stream.data[pos];
|
||||||
|
if (at_pos == first_char){
|
||||||
|
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||||
|
if (match(needle_str, read_str)){
|
||||||
|
*result = pos;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = forward_stream_chunk(&stream);
|
||||||
|
}while (still_looping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = buffer->size;
|
||||||
|
|
||||||
|
finished:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(allen): This is limitted to a string size of 512.
|
||||||
|
// You can push it up or do something more clever by just
|
||||||
|
// replacing char read_buffer[512]; with more memory.
|
||||||
|
void
|
||||||
|
buffer_seek_string_backward(Application_Links *app, Buffer_Summary *buffer,
|
||||||
|
int pos, char *str, int size, int *result){
|
||||||
|
char read_buffer[512];
|
||||||
|
char chunk[1024];
|
||||||
|
int chunk_size = sizeof(chunk);
|
||||||
|
Stream_Chunk stream = {0};
|
||||||
|
|
||||||
|
if (size <= 0){
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
else if (size > sizeof(read_buffer)){
|
||||||
|
*result = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (buffer->exists){
|
||||||
|
String read_str = make_fixed_width_string(read_buffer);
|
||||||
|
String needle_str = make_string(str, size);
|
||||||
|
char first_char = str[0];
|
||||||
|
|
||||||
|
read_str.size = size;
|
||||||
|
|
||||||
|
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||||
|
int still_looping = 1;
|
||||||
|
do{
|
||||||
|
for(; pos >= stream.start; --pos){
|
||||||
|
char at_pos = stream.data[pos];
|
||||||
|
if (at_pos == first_char){
|
||||||
|
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||||
|
if (match(needle_str, read_str)){
|
||||||
|
*result = pos;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = backward_stream_chunk(&stream);
|
||||||
|
}while (still_looping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = 0;
|
||||||
|
|
||||||
|
finished:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(allen): This is limitted to a string size of 512.
|
||||||
|
// You can push it up or do something more clever by just
|
||||||
|
// replacing char read_buffer[512]; with more memory.
|
||||||
|
void
|
||||||
|
buffer_seek_string_insensitive_forward(Application_Links *app, Buffer_Summary *buffer,
|
||||||
|
int pos, char *str, int size, int *result){
|
||||||
|
char read_buffer[512];
|
||||||
|
char chunk[1024];
|
||||||
|
int chunk_size = sizeof(chunk);
|
||||||
|
Stream_Chunk stream = {0};
|
||||||
|
|
||||||
|
if (size <= 0){
|
||||||
|
*result = pos;
|
||||||
|
}
|
||||||
|
else if (size > sizeof(read_buffer)){
|
||||||
|
*result = pos;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (buffer->exists){
|
||||||
|
String read_str = make_fixed_width_string(read_buffer);
|
||||||
|
String needle_str = make_string(str, size);
|
||||||
|
char first_char = char_to_upper(str[0]);
|
||||||
|
|
||||||
|
read_str.size = size;
|
||||||
|
|
||||||
|
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||||
|
int still_looping = 1;
|
||||||
|
do{
|
||||||
|
for(; pos < stream.end; ++pos){
|
||||||
|
char at_pos = char_to_upper(stream.data[pos]);
|
||||||
|
if (at_pos == first_char){
|
||||||
|
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||||
|
if (match_insensitive(needle_str, read_str)){
|
||||||
|
*result = pos;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = forward_stream_chunk(&stream);
|
||||||
|
}while (still_looping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = buffer->size;
|
||||||
|
|
||||||
|
finished:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(allen): This is limitted to a string size of 512.
|
||||||
|
// You can push it up or do something more clever by just
|
||||||
|
// replacing char read_buffer[512]; with more memory.
|
||||||
|
void
|
||||||
|
buffer_seek_string_insensitive_backward(Application_Links *app, Buffer_Summary *buffer,
|
||||||
|
int pos, char *str, int size, int *result){
|
||||||
|
char read_buffer[512];
|
||||||
|
char chunk[1024];
|
||||||
|
int chunk_size = sizeof(chunk);
|
||||||
|
Stream_Chunk stream = {0};
|
||||||
|
|
||||||
|
if (size <= 0){
|
||||||
|
*result = -1;
|
||||||
|
}
|
||||||
|
else if (size > sizeof(read_buffer)){
|
||||||
|
*result = -1;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (buffer->exists){
|
||||||
|
String read_str = make_fixed_width_string(read_buffer);
|
||||||
|
String needle_str = make_string(str, size);
|
||||||
|
char first_char = char_to_upper(str[0]);
|
||||||
|
|
||||||
|
read_str.size = size;
|
||||||
|
|
||||||
|
if (init_stream_chunk(&stream, app, buffer, pos, chunk, chunk_size)){
|
||||||
|
int still_looping = 1;
|
||||||
|
do{
|
||||||
|
for(; pos >= stream.start; --pos){
|
||||||
|
char at_pos = char_to_upper(stream.data[pos]);
|
||||||
|
if (at_pos == first_char){
|
||||||
|
app->buffer_read_range(app, buffer, pos, pos+size, read_buffer);
|
||||||
|
if (match_insensitive(needle_str, read_str)){
|
||||||
|
*result = pos;
|
||||||
|
goto finished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
still_looping = backward_stream_chunk(&stream);
|
||||||
|
}while (still_looping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = -1;
|
||||||
|
|
||||||
|
finished:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -102,17 +102,17 @@ FSTRING_INLINE bool match_part(String a, char *b) { int x; return match_part
|
||||||
FSTRING_LINK bool match_part(char *a, String b);
|
FSTRING_LINK bool match_part(char *a, String b);
|
||||||
FSTRING_LINK bool match_part(String a, String b);
|
FSTRING_LINK bool match_part(String a, String b);
|
||||||
|
|
||||||
FSTRING_LINK bool match_unsensitive(char *a, char *b);
|
FSTRING_LINK bool match_insensitive(char *a, char *b);
|
||||||
FSTRING_LINK bool match_unsensitive(String a, char *b);
|
FSTRING_LINK bool match_insensitive(String a, char *b);
|
||||||
FSTRING_INLINE bool match_unsensitive(char *a, String b) { return match_unsensitive(b,a); }
|
FSTRING_INLINE bool match_insensitive(char *a, String b) { return match_insensitive(b,a); }
|
||||||
FSTRING_LINK bool match_unsensitive(String a, String b);
|
FSTRING_LINK bool match_insensitive(String a, String b);
|
||||||
|
|
||||||
FSTRING_LINK bool match_part_unsensitive(char *a, char *b, int *len);
|
FSTRING_LINK bool match_part_insensitive(char *a, char *b, int *len);
|
||||||
FSTRING_LINK bool match_part_unsensitive(String a, char *b, int *len);
|
FSTRING_LINK bool match_part_insensitive(String a, char *b, int *len);
|
||||||
FSTRING_INLINE bool match_part_unsensitive(char *a, char *b) { int x; return match_part(a,b,&x); }
|
FSTRING_INLINE bool match_part_insensitive(char *a, char *b) { int x; return match_part(a,b,&x); }
|
||||||
FSTRING_INLINE bool match_part_unsensitive(String a, char *b) { int x; return match_part(a,b,&x); }
|
FSTRING_INLINE bool match_part_insensitive(String a, char *b) { int x; return match_part(a,b,&x); }
|
||||||
FSTRING_LINK bool match_part_unsensitive(char *a, String b);
|
FSTRING_LINK bool match_part_insensitive(char *a, String b);
|
||||||
FSTRING_LINK bool match_part_unsensitive(String a, String b);
|
FSTRING_LINK bool match_part_insensitive(String a, String b);
|
||||||
|
|
||||||
FSTRING_LINK int find(char *s, int start, char c);
|
FSTRING_LINK int find(char *s, int start, char c);
|
||||||
FSTRING_LINK int find(String s, int start, char c);
|
FSTRING_LINK int find(String s, int start, char c);
|
||||||
|
@ -123,14 +123,14 @@ FSTRING_LINK int find_substr(char *s, int start, String seek);
|
||||||
FSTRING_LINK int find_substr(String s, int start, String seek);
|
FSTRING_LINK int find_substr(String s, int start, String seek);
|
||||||
FSTRING_LINK int rfind_substr(String s, int start, String seek);
|
FSTRING_LINK int rfind_substr(String s, int start, String seek);
|
||||||
|
|
||||||
FSTRING_LINK int find_substr_unsensitive(char *s, int start, String seek);
|
FSTRING_LINK int find_substr_insensitive(char *s, int start, String seek);
|
||||||
FSTRING_LINK int find_substr_unsensitive(String s, int start, String seek);
|
FSTRING_LINK int find_substr_insensitive(String s, int start, String seek);
|
||||||
|
|
||||||
FSTRING_INLINE bool has_substr(char *s, String seek) { return (s[find_substr(s, 0, seek)] != 0); }
|
FSTRING_INLINE bool has_substr(char *s, String seek) { return (s[find_substr(s, 0, seek)] != 0); }
|
||||||
FSTRING_INLINE bool has_substr(String s, String seek) { return (find_substr(s, 0, seek) < s.size); }
|
FSTRING_INLINE bool has_substr(String s, String seek) { return (find_substr(s, 0, seek) < s.size); }
|
||||||
|
|
||||||
FSTRING_INLINE bool has_substr_unsensitive(char *s, String seek) { return (s[find_substr_unsensitive(s, 0, seek)] != 0); }
|
FSTRING_INLINE bool has_substr_insensitive(char *s, String seek) { return (s[find_substr_insensitive(s, 0, seek)] != 0); }
|
||||||
FSTRING_INLINE bool has_substr_unsensitive(String s, String seek) { return (find_substr_unsensitive(s, 0, seek) < s.size); }
|
FSTRING_INLINE bool has_substr_insensitive(String s, String seek) { return (find_substr_insensitive(s, 0, seek) < s.size); }
|
||||||
|
|
||||||
FSTRING_LINK int int_to_str_size(int x);
|
FSTRING_LINK int int_to_str_size(int x);
|
||||||
FSTRING_LINK int int_to_str(int x, char *s_out);
|
FSTRING_LINK int int_to_str(int x, char *s_out);
|
||||||
|
@ -391,7 +391,7 @@ match_part(String a, String b){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK bool
|
FSTRING_LINK bool
|
||||||
match_unsensitive(char *a, char *b){
|
match_insensitive(char *a, char *b){
|
||||||
for (int i = 0;; ++i){
|
for (int i = 0;; ++i){
|
||||||
if (char_to_upper(a[i]) !=
|
if (char_to_upper(a[i]) !=
|
||||||
char_to_upper(b[i])){
|
char_to_upper(b[i])){
|
||||||
|
@ -404,7 +404,7 @@ match_unsensitive(char *a, char *b){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK bool
|
FSTRING_LINK bool
|
||||||
match_unsensitive(String a, char *b){
|
match_insensitive(String a, char *b){
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i < a.size; ++i){
|
for (; i < a.size; ++i){
|
||||||
if (char_to_upper(a.str[i]) !=
|
if (char_to_upper(a.str[i]) !=
|
||||||
|
@ -419,7 +419,7 @@ match_unsensitive(String a, char *b){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK bool
|
FSTRING_LINK bool
|
||||||
match_unsensitive(String a, String b){
|
match_insensitive(String a, String b){
|
||||||
if (a.size != b.size){
|
if (a.size != b.size){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -433,7 +433,7 @@ match_unsensitive(String a, String b){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK bool
|
FSTRING_LINK bool
|
||||||
match_part_unsensitive(char *a, char *b, int *len){
|
match_part_insensitive(char *a, char *b, int *len){
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; b[i] != 0; ++i){
|
for (i = 0; b[i] != 0; ++i){
|
||||||
if (char_to_upper(a[i]) != char_to_upper(b[i])){
|
if (char_to_upper(a[i]) != char_to_upper(b[i])){
|
||||||
|
@ -445,7 +445,7 @@ match_part_unsensitive(char *a, char *b, int *len){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK bool
|
FSTRING_LINK bool
|
||||||
match_part_unsensitive(String a, char *b, int *len){
|
match_part_insensitive(String a, char *b, int *len){
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; b[i] != 0; ++i){
|
for (i = 0; b[i] != 0; ++i){
|
||||||
if (char_to_upper(a.str[i]) != char_to_upper(b[i]) ||
|
if (char_to_upper(a.str[i]) != char_to_upper(b[i]) ||
|
||||||
|
@ -458,7 +458,7 @@ match_part_unsensitive(String a, char *b, int *len){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK bool
|
FSTRING_LINK bool
|
||||||
match_part_unsensitive(char *a, String b){
|
match_part_insensitive(char *a, String b){
|
||||||
for (int i = 0; i != b.size; ++i){
|
for (int i = 0; i != b.size; ++i){
|
||||||
if (char_to_upper(a[i]) != char_to_upper(b.str[i])){
|
if (char_to_upper(a[i]) != char_to_upper(b.str[i])){
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -468,7 +468,7 @@ match_part_unsensitive(char *a, String b){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK bool
|
FSTRING_LINK bool
|
||||||
match_part_unsensitive(String a, String b){
|
match_part_insensitive(String a, String b){
|
||||||
if (a.size < b.size){
|
if (a.size < b.size){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -602,7 +602,7 @@ rfind_substr(String str, int start, String seek){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK int
|
FSTRING_LINK int
|
||||||
find_substr_unsensitive(char *str, int start, String seek){
|
find_substr_insensitive(char *str, int start, String seek){
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
bool hit;
|
bool hit;
|
||||||
char a_upper, b_upper;
|
char a_upper, b_upper;
|
||||||
|
@ -630,7 +630,7 @@ find_substr_unsensitive(char *str, int start, String seek){
|
||||||
}
|
}
|
||||||
|
|
||||||
FSTRING_LINK int
|
FSTRING_LINK int
|
||||||
find_substr_unsensitive(String str, int start, String seek){
|
find_substr_insensitive(String str, int start, String seek){
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
int stop_at;
|
int stop_at;
|
||||||
bool hit;
|
bool hit;
|
||||||
|
@ -1217,8 +1217,8 @@ wildcard_match(Absolutes *absolutes, char *x, int case_sensitive){
|
||||||
match_part_func = match_part;
|
match_part_func = match_part;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
match_func = match_unsensitive;
|
match_func = match_insensitive;
|
||||||
match_part_func = match_part_unsensitive;
|
match_part_func = match_part_insensitive;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (absolutes->count == 1){
|
if (absolutes->count == 1){
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#define MAJOR 4
|
#define MAJOR 4
|
||||||
#define MINOR 0
|
#define MINOR 0
|
||||||
#define PATCH 6
|
#define PATCH 7
|
||||||
|
|
||||||
#define VN__(a,b,c) #a"."#b"."#c
|
#define VN__(a,b,c) #a"."#b"."#c
|
||||||
#define VN_(a,b,c) VN__(a,b,c)
|
#define VN_(a,b,c) VN__(a,b,c)
|
||||||
|
|
14
4cpp_lexer.h
14
4cpp_lexer.h
|
@ -65,6 +65,19 @@ NOTES ON USE:
|
||||||
|
|
||||||
#include "4cpp_lexer_types.h"
|
#include "4cpp_lexer_types.h"
|
||||||
|
|
||||||
|
struct Cpp_Lex_Data{
|
||||||
|
Cpp_Preprocessor_State pp_state;
|
||||||
|
int pos;
|
||||||
|
int complete;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cpp_Read_Result{
|
||||||
|
Cpp_Token token;
|
||||||
|
int pos;
|
||||||
|
char newline;
|
||||||
|
char has_result;
|
||||||
|
};
|
||||||
|
|
||||||
Cpp_File
|
Cpp_File
|
||||||
data_as_cpp_file(Data data){
|
data_as_cpp_file(Data data){
|
||||||
Cpp_File result;
|
Cpp_File result;
|
||||||
|
@ -140,7 +153,6 @@ FCPP_LINK bool cpp_push_token_no_merge(Cpp_Token_Stack *stack, Cpp_Token token);
|
||||||
FCPP_LINK bool cpp_push_token_nonalloc(Cpp_Token_Stack *stack, Cpp_Token token);
|
FCPP_LINK bool cpp_push_token_nonalloc(Cpp_Token_Stack *stack, Cpp_Token token);
|
||||||
|
|
||||||
inline Cpp_Lex_Data cpp_lex_data_zero() { Cpp_Lex_Data data = {(Cpp_Preprocessor_State)0}; return(data); }
|
inline Cpp_Lex_Data cpp_lex_data_zero() { Cpp_Lex_Data data = {(Cpp_Preprocessor_State)0}; return(data); }
|
||||||
inline Cpp_Token_Stack cpp_token_stack_zero() { Cpp_Token_Stack stack={0}; return(stack); }
|
|
||||||
|
|
||||||
FCPP_LINK Cpp_Read_Result cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex);
|
FCPP_LINK Cpp_Read_Result cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex);
|
||||||
|
|
||||||
|
|
|
@ -209,23 +209,15 @@ enum Cpp_Preprocessor_State{
|
||||||
CPP_LEX_PP_COUNT
|
CPP_LEX_PP_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Cpp_Lex_Data{
|
|
||||||
Cpp_Preprocessor_State pp_state;
|
|
||||||
int pos;
|
|
||||||
int complete;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Cpp_Read_Result{
|
|
||||||
Cpp_Token token;
|
|
||||||
int pos;
|
|
||||||
char newline;
|
|
||||||
char has_result;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Cpp_Token_Stack{
|
struct Cpp_Token_Stack{
|
||||||
Cpp_Token *tokens;
|
Cpp_Token *tokens;
|
||||||
int count, max_count;
|
int count, max_count;
|
||||||
};
|
};
|
||||||
|
inline Cpp_Token_Stack
|
||||||
|
cpp_token_stack_zero(){
|
||||||
|
Cpp_Token_Stack stack={0};
|
||||||
|
return(stack);
|
||||||
|
}
|
||||||
|
|
||||||
struct Cpp_Token_Merge{
|
struct Cpp_Token_Merge{
|
||||||
Cpp_Token new_token;
|
Cpp_Token new_token;
|
||||||
|
|
18
4ed.h
18
4ed.h
|
@ -81,17 +81,18 @@ struct Plat_Settings{
|
||||||
|
|
||||||
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
|
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
|
||||||
|
|
||||||
|
|
||||||
#define App_Init_Sig(name) void \
|
#define App_Init_Sig(name) void \
|
||||||
name(System_Functions *system, \
|
name(System_Functions *system, \
|
||||||
Render_Target *target, \
|
Render_Target *target, \
|
||||||
Application_Memory *memory, \
|
Application_Memory *memory, \
|
||||||
Exchange *exchange, \
|
|
||||||
String clipboard, \
|
String clipboard, \
|
||||||
String current_directory, \
|
String current_directory, \
|
||||||
Custom_API api)
|
Custom_API api)
|
||||||
|
|
||||||
typedef App_Init_Sig(App_Init);
|
typedef App_Init_Sig(App_Init);
|
||||||
|
|
||||||
|
|
||||||
enum Application_Mouse_Cursor{
|
enum Application_Mouse_Cursor{
|
||||||
APP_MOUSE_CURSOR_DEFAULT,
|
APP_MOUSE_CURSOR_DEFAULT,
|
||||||
APP_MOUSE_CURSOR_ARROW,
|
APP_MOUSE_CURSOR_ARROW,
|
||||||
|
@ -110,19 +111,24 @@ struct Application_Step_Result{
|
||||||
b32 animating;
|
b32 animating;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Application_Step_Input{
|
||||||
|
b32 first_step;
|
||||||
|
f32 dt;
|
||||||
|
Key_Input_Data keys;
|
||||||
|
Mouse_State mouse;
|
||||||
|
String clipboard;
|
||||||
|
};
|
||||||
|
|
||||||
#define App_Step_Sig(name) void \
|
#define App_Step_Sig(name) void \
|
||||||
name(System_Functions *system, \
|
name(System_Functions *system, \
|
||||||
Key_Input_Data *input, \
|
|
||||||
Mouse_State *mouse, \
|
|
||||||
Render_Target *target, \
|
Render_Target *target, \
|
||||||
Application_Memory *memory, \
|
Application_Memory *memory, \
|
||||||
Exchange *exchange, \
|
Application_Step_Input *input, \
|
||||||
String clipboard, \
|
|
||||||
f32 dt, b32 first_step, \
|
|
||||||
Application_Step_Result *result)
|
Application_Step_Result *result)
|
||||||
|
|
||||||
typedef App_Step_Sig(App_Step);
|
typedef App_Step_Sig(App_Step);
|
||||||
|
|
||||||
|
|
||||||
struct App_Functions{
|
struct App_Functions{
|
||||||
App_Read_Command_Line *read_command_line;
|
App_Read_Command_Line *read_command_line;
|
||||||
App_Init *init;
|
App_Init *init;
|
||||||
|
|
|
@ -58,16 +58,12 @@ struct Models{
|
||||||
char hot_dir_base_[256];
|
char hot_dir_base_[256];
|
||||||
Hot_Directory hot_directory;
|
Hot_Directory hot_directory;
|
||||||
|
|
||||||
Delay delay1, delay2;
|
|
||||||
|
|
||||||
Panel *prev_mouse_panel;
|
Panel *prev_mouse_panel;
|
||||||
|
|
||||||
Custom_API config_api;
|
Custom_API config_api;
|
||||||
Scroll_Rule_Function *scroll_rule;
|
Scroll_Rule_Function *scroll_rule;
|
||||||
|
|
||||||
#if 0
|
b32 keep_playing;
|
||||||
File_Exchange files;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
|
@ -39,12 +39,10 @@
|
||||||
|
|
||||||
#include "4ed_style.h"
|
#include "4ed_style.h"
|
||||||
#include "4ed_style.cpp"
|
#include "4ed_style.cpp"
|
||||||
#include "4ed_exchange.cpp"
|
|
||||||
#include "4ed_command.cpp"
|
#include "4ed_command.cpp"
|
||||||
#include "4ed_file.cpp"
|
#include "4ed_file.cpp"
|
||||||
#include "4ed_gui.cpp"
|
#include "4ed_gui.cpp"
|
||||||
#include "4ed_layout.cpp"
|
#include "4ed_layout.cpp"
|
||||||
#include "4ed_delay.cpp"
|
|
||||||
#include "4ed_app_models.h"
|
#include "4ed_app_models.h"
|
||||||
#include "4ed_file_view.cpp"
|
#include "4ed_file_view.cpp"
|
||||||
#include "4ed.cpp"
|
#include "4ed.cpp"
|
||||||
|
|
140
4ed_delay.cpp
140
4ed_delay.cpp
|
@ -1,140 +0,0 @@
|
||||||
enum Action_Type{
|
|
||||||
DACT_OPEN,
|
|
||||||
DACT_OPEN_BACKGROUND,
|
|
||||||
DACT_SET_LINE,
|
|
||||||
DACT_SAVE_AS,
|
|
||||||
DACT_SAVE,
|
|
||||||
DACT_NEW,
|
|
||||||
DACT_SWITCH,
|
|
||||||
DACT_TRY_KILL,
|
|
||||||
DACT_KILL,
|
|
||||||
DACT_TOUCH_FILE,
|
|
||||||
DACT_CLOSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Delayed_Action{
|
|
||||||
Action_Type type;
|
|
||||||
String string;
|
|
||||||
Panel* panel;
|
|
||||||
Editing_File* file;
|
|
||||||
i32 integer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Delay{
|
|
||||||
General_Memory* general;
|
|
||||||
Delayed_Action* acts;
|
|
||||||
i32 count;
|
|
||||||
i32 max;
|
|
||||||
};
|
|
||||||
|
|
||||||
internal String
|
|
||||||
str_alloc_copy(General_Memory *general, String str){
|
|
||||||
String result;
|
|
||||||
result.memory_size = str.memory_size + 1;
|
|
||||||
result.size = str.size;
|
|
||||||
result.str = (char*)general_memory_allocate(general, result.memory_size, 0);
|
|
||||||
memcpy(result.str, str.str, str.size);
|
|
||||||
result.str[result.size] = 0;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action
|
|
||||||
delayed_action_zero(){
|
|
||||||
Delayed_Action result = {(Action_Type)0};
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_(Delay *delay, Action_Type type){
|
|
||||||
Delayed_Action *result;
|
|
||||||
if (delay->count == delay->max){
|
|
||||||
delay->max *= 2;
|
|
||||||
delay->acts = (Delayed_Action*)general_memory_reallocate(delay->general, delay->acts, delay->count*sizeof(Delayed_Action), delay->max*sizeof(Delayed_Action), 0);
|
|
||||||
}
|
|
||||||
result = delay->acts + delay->count++;
|
|
||||||
*result = delayed_action_zero();
|
|
||||||
result->type = type;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_(Delay *delay, Action_Type type, String string){
|
|
||||||
Delayed_Action *result;
|
|
||||||
result = delayed_action_(delay, type);
|
|
||||||
result->string = str_alloc_copy(delay->general, string);
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_(Delay *delay, Action_Type type, Panel* panel){
|
|
||||||
Delayed_Action *result;
|
|
||||||
result = delayed_action_(delay, type);
|
|
||||||
result->panel = panel;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_(Delay *delay, Action_Type type, Editing_File* file){
|
|
||||||
Delayed_Action *result;
|
|
||||||
result = delayed_action_(delay, type);
|
|
||||||
result->file = file;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_(Delay *delay, Action_Type type, Editing_File* file, Panel* panel){
|
|
||||||
Delayed_Action *result;
|
|
||||||
result = delayed_action_(delay, type);
|
|
||||||
result->file = file;
|
|
||||||
result->panel = panel;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_(Delay *delay, Action_Type type, String string, Panel* panel){
|
|
||||||
Delayed_Action *result;
|
|
||||||
result = delayed_action_(delay, type);
|
|
||||||
result->string = str_alloc_copy(delay->general, string);
|
|
||||||
result->panel = panel;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_(Delay *delay, Action_Type type, String string, Editing_File* file){
|
|
||||||
Delayed_Action *result;
|
|
||||||
result = delayed_action_(delay, type);
|
|
||||||
result->string = str_alloc_copy(delay->general, string);
|
|
||||||
result->file = file;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_(Delay *delay, Action_Type type, Panel* panel, i32 integer){
|
|
||||||
Delayed_Action *result;
|
|
||||||
result = delayed_action_(delay, type);
|
|
||||||
result->panel = panel;
|
|
||||||
result->integer = integer;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Delayed_Action*
|
|
||||||
delayed_action_repush(Delay *delay, Delayed_Action *act){
|
|
||||||
Delayed_Action *new_act = delayed_action_(delay, (Action_Type)0);
|
|
||||||
*new_act = *act;
|
|
||||||
if (act->string.str){
|
|
||||||
new_act->string = str_alloc_copy(delay->general, act->string);
|
|
||||||
}
|
|
||||||
return(new_act);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define delayed_open(delay, ...) delayed_action_(delay, DACT_OPEN, ##__VA_ARGS__)
|
|
||||||
#define delayed_open_background(delay, ...) delayed_action_(delay, DACT_OPEN_BACKGROUND, ##__VA_ARGS__)
|
|
||||||
#define delayed_set_line(delay, ...) delayed_action_(delay, DACT_SET_LINE, ##__VA_ARGS__)
|
|
||||||
#define delayed_save_as(delay, ...) delayed_action_(delay, DACT_SAVE_AS, ##__VA_ARGS__)
|
|
||||||
#define delayed_save(delay, ...) delayed_action_(delay, DACT_SAVE, ##__VA_ARGS__)
|
|
||||||
#define delayed_new(delay, ...) delayed_action_(delay, DACT_NEW, ##__VA_ARGS__)
|
|
||||||
#define delayed_switch(delay, ...) delayed_action_(delay, DACT_SWITCH, ##__VA_ARGS__)
|
|
||||||
#define delayed_try_kill(delay, ...) delayed_action_(delay, DACT_TRY_KILL, ##__VA_ARGS__)
|
|
||||||
#define delayed_kill(delay, ...) delayed_action_(delay, DACT_KILL, ##__VA_ARGS__)
|
|
||||||
#define delayed_touch_file(delay, ...) delayed_action_(delay, DACT_TOUCH_FILE, ##__VA_ARGS__)
|
|
||||||
#define delayed_close(delay, ...) delayed_action_(delay, DACT_CLOSE, ##__VA_ARGS__)
|
|
|
@ -1,35 +0,0 @@
|
||||||
/*
|
|
||||||
* Mr. 4th Dimention - Allen Webster
|
|
||||||
*
|
|
||||||
* 9.12.2015
|
|
||||||
*
|
|
||||||
* Exchange stuff
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// TOP
|
|
||||||
|
|
||||||
// NOTE(allen): Uhhh.... is it just me or did it get awkward
|
|
||||||
// in here when I deleted all the file exchange stuff?
|
|
||||||
|
|
||||||
internal b32
|
|
||||||
queue_job_is_pending(Work_Queue *queue, u32 job_id){
|
|
||||||
b32 result;
|
|
||||||
u32 job_index;
|
|
||||||
Full_Job_Data *full_job;
|
|
||||||
|
|
||||||
job_index = job_id % QUEUE_WRAP;
|
|
||||||
full_job = queue->jobs + job_index;
|
|
||||||
|
|
||||||
Assert(full_job->id == job_id);
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
if (full_job->running_thread != 0){
|
|
||||||
result = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOTTOM
|
|
||||||
|
|
30
4ed_file.cpp
30
4ed_file.cpp
|
@ -111,9 +111,6 @@ struct Editing_File_Settings{
|
||||||
// NOTE(allen): This part of the Editing_File is cleared whenever
|
// NOTE(allen): This part of the Editing_File is cleared whenever
|
||||||
// the contents of the file is set.
|
// the contents of the file is set.
|
||||||
struct Editing_File_State{
|
struct Editing_File_State{
|
||||||
b32 is_dummy;
|
|
||||||
b32 is_loading;
|
|
||||||
|
|
||||||
i16 font_id;
|
i16 font_id;
|
||||||
Buffer_Type buffer;
|
Buffer_Type buffer;
|
||||||
|
|
||||||
|
@ -135,10 +132,6 @@ struct Editing_File_State{
|
||||||
u64 last_sys_write_time;
|
u64 last_sys_write_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Editing_File_Preload{
|
|
||||||
i32 start_line;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Editing_File_Name{
|
struct Editing_File_Name{
|
||||||
char live_name_[256];
|
char live_name_[256];
|
||||||
char source_path_[256];
|
char source_path_[256];
|
||||||
|
@ -168,9 +161,10 @@ struct Editing_File{
|
||||||
// NOTE(allen): node must be the first member of Editing_File!
|
// NOTE(allen): node must be the first member of Editing_File!
|
||||||
File_Node node;
|
File_Node node;
|
||||||
Editing_File_Settings settings;
|
Editing_File_Settings settings;
|
||||||
union{
|
struct{
|
||||||
|
b32 is_loading;
|
||||||
|
b32 is_dummy;
|
||||||
Editing_File_State state;
|
Editing_File_State state;
|
||||||
Editing_File_Preload preload;
|
|
||||||
};
|
};
|
||||||
Editing_File_Name name;
|
Editing_File_Name name;
|
||||||
Buffer_Slot_ID id;
|
Buffer_Slot_ID id;
|
||||||
|
@ -317,7 +311,7 @@ working_set_alloc_always(Working_Set *working_set, General_Memory *general){
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
working_set_free_file(Working_Set *working_set, Editing_File *file){
|
working_set_free_file(Working_Set *working_set, Editing_File *file){
|
||||||
file->state.is_dummy = 1;
|
file->is_dummy = 1;
|
||||||
dll_remove(&file->node);
|
dll_remove(&file->node);
|
||||||
dll_insert(&working_set->free_sentinel, &file->node);
|
dll_insert(&working_set->free_sentinel, &file->node);
|
||||||
--working_set->file_count;
|
--working_set->file_count;
|
||||||
|
@ -349,7 +343,7 @@ inline Editing_File*
|
||||||
working_set_get_active_file(Working_Set *working_set, Buffer_Slot_ID id){
|
working_set_get_active_file(Working_Set *working_set, Buffer_Slot_ID id){
|
||||||
Editing_File *result = 0;
|
Editing_File *result = 0;
|
||||||
result = working_set_index(working_set, id);
|
result = working_set_index(working_set, id);
|
||||||
if (result && result->state.is_dummy){
|
if (result && result->is_dummy){
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
|
@ -383,7 +377,7 @@ working_set_init(Working_Set *working_set, Partition *partition, General_Memory
|
||||||
|
|
||||||
null_file = working_set_index(working_set, 0);
|
null_file = working_set_index(working_set, 0);
|
||||||
dll_remove(&null_file->node);
|
dll_remove(&null_file->node);
|
||||||
null_file->state.is_dummy = 1;
|
null_file->is_dummy = 1;
|
||||||
++working_set->file_count;
|
++working_set->file_count;
|
||||||
|
|
||||||
table_size = working_set->file_max;
|
table_size = working_set->file_max;
|
||||||
|
@ -488,10 +482,12 @@ working_set_lookup_file(Working_Set *working_set, String string){
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
touch_file(Working_Set *working_set, Editing_File *file){
|
touch_file(Working_Set *working_set, Editing_File *file){
|
||||||
Assert(!file->state.is_dummy);
|
if (file){
|
||||||
|
Assert(!file->is_dummy);
|
||||||
dll_remove(&file->node);
|
dll_remove(&file->node);
|
||||||
dll_insert(&working_set->used_sentinel, &file->node);
|
dll_insert(&working_set->used_sentinel, &file->node);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Hot Directory
|
// Hot Directory
|
||||||
|
|
||||||
|
@ -586,6 +582,7 @@ filename_match(String query, Absolutes *absolutes, String filename, b32 case_sen
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
internal Hot_Directory_Match
|
internal Hot_Directory_Match
|
||||||
hot_directory_first_match(Hot_Directory *hot_directory,
|
hot_directory_first_match(Hot_Directory *hot_directory,
|
||||||
String str,
|
String str,
|
||||||
|
@ -609,7 +606,7 @@ hot_directory_first_match(Hot_Directory *hot_directory,
|
||||||
if (match(filename, str)) is_match = 1;
|
if (match(filename, str)) is_match = 1;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if (match_unsensitive(filename, str)) is_match = 1;
|
if (match_insensitive(filename, str)) is_match = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
@ -625,6 +622,7 @@ hot_directory_first_match(Hot_Directory *hot_directory,
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inline File_Sync_State
|
inline File_Sync_State
|
||||||
buffer_get_sync(Editing_File *file){
|
buffer_get_sync(Editing_File *file){
|
||||||
|
@ -648,7 +646,7 @@ buffer_needs_save(Editing_File *file){
|
||||||
inline b32
|
inline b32
|
||||||
file_is_ready(Editing_File *file){
|
file_is_ready(Editing_File *file){
|
||||||
b32 result = 0;
|
b32 result = 0;
|
||||||
if (file && file->state.is_loading == 0){
|
if (file && file->is_loading == 0){
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
|
@ -670,7 +668,7 @@ inline void
|
||||||
file_set_to_loading(Editing_File *file){
|
file_set_to_loading(Editing_File *file){
|
||||||
file->state = editing_file_state_zero();
|
file->state = editing_file_state_zero();
|
||||||
file->settings = editing_file_settings_zero();
|
file->settings = editing_file_settings_zero();
|
||||||
file->state.is_loading = 1;
|
file->is_loading = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -40,9 +40,9 @@ font__remove(Font_Slot *slot){
|
||||||
n->prev = p;
|
n->prev = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Font_Slot
|
inline Font_Slot
|
||||||
font_slot_zero(){
|
font_slot_zero(){
|
||||||
Font_Slot slot = {};
|
Font_Slot slot = {0};
|
||||||
return(slot);
|
return(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ font_set_load(Partition *partition, Font_Set *set, i16 font_id){
|
||||||
font__insert(&set->used_slots, slot);
|
font__insert(&set->used_slots, slot);
|
||||||
|
|
||||||
Render_Font *font = (Render_Font*)(slot + 1);
|
Render_Font *font = (Render_Font*)(slot + 1);
|
||||||
set->font_load(font, info->filename.str, info->pt_size, 4);
|
set->font_load(font, info->filename.str, info->pt_size, 4, 1);
|
||||||
info->font = font;
|
info->font = font;
|
||||||
slot->font_id = font_id;
|
slot->font_id = font_id;
|
||||||
}
|
}
|
||||||
|
@ -176,12 +176,16 @@ font_set_add(Partition *partition, Font_Set *set,
|
||||||
String filename, String name, i32 pt_size){
|
String filename, String name, i32 pt_size){
|
||||||
b32 result = 0;
|
b32 result = 0;
|
||||||
if (font_set_can_add(set)){
|
if (font_set_can_add(set)){
|
||||||
|
Render_Font dummy_font = {0};
|
||||||
i16 font_id = (i16)(++set->count);
|
i16 font_id = (i16)(++set->count);
|
||||||
Font_Info *info = get_font_info(set, font_id);
|
Font_Info *info = get_font_info(set, font_id);
|
||||||
info->filename = filename;
|
info->filename = filename;
|
||||||
info->name = name;
|
info->name = name;
|
||||||
info->pt_size = pt_size;
|
info->pt_size = pt_size;
|
||||||
set->font_info_load(partition, filename.str, pt_size, &info->height, &info->advance);
|
set->font_load(&dummy_font, info->filename.str, info->pt_size, 4, 0);
|
||||||
|
info->height = dummy_font.height;
|
||||||
|
info->advance = dummy_font.advance;
|
||||||
|
|
||||||
font_set_add_hash(set, name, font_id);
|
font_set_add_hash(set, name, font_id);
|
||||||
|
|
||||||
if (font_set_can_load(set)){
|
if (font_set_can_load(set)){
|
||||||
|
|
73
4ed_gui.cpp
73
4ed_gui.cpp
|
@ -171,8 +171,6 @@ struct GUI_Edit{
|
||||||
|
|
||||||
enum GUI_Command_Type{
|
enum GUI_Command_Type{
|
||||||
guicom_null,
|
guicom_null,
|
||||||
guicom_begin_overlap,
|
|
||||||
guicom_end_overlap,
|
|
||||||
guicom_begin_serial,
|
guicom_begin_serial,
|
||||||
guicom_end_serial,
|
guicom_end_serial,
|
||||||
guicom_top_bar,
|
guicom_top_bar,
|
||||||
|
@ -371,16 +369,6 @@ gui_push_string(GUI_Target *target, GUI_Header *h, String s){
|
||||||
gui_push_string(target, h, s, 0);
|
gui_push_string(target, h, s, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
|
||||||
gui_begin_overlap(GUI_Target *target){
|
|
||||||
gui_push_simple_command(target, guicom_begin_overlap);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
gui_end_overlap(GUI_Target *target){
|
|
||||||
gui_push_simple_command(target, guicom_end_overlap);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
gui_begin_serial_section(GUI_Target *target){
|
gui_begin_serial_section(GUI_Target *target){
|
||||||
gui_push_simple_command(target, guicom_begin_serial);
|
gui_push_simple_command(target, guicom_begin_serial);
|
||||||
|
@ -661,11 +649,7 @@ gui_get_scroll_vars(GUI_Target *target, GUI_id scroll_context_id, GUI_Scroll_Var
|
||||||
*vars_out = target->scroll_updated;
|
*vars_out = target->scroll_updated;
|
||||||
*region_out = target->region_updated;
|
*region_out = target->region_updated;
|
||||||
|
|
||||||
if (vars_out->target_y < vars_out->min_y) vars_out->target_y = vars_out->min_y;
|
vars_out->target_y = clamp(0.f, vars_out->target_y, vars_out->max_y);
|
||||||
if (vars_out->target_y > vars_out->max_y) vars_out->target_y = vars_out->max_y;
|
|
||||||
|
|
||||||
if (vars_out->scroll_y < vars_out->min_y) vars_out->scroll_y = vars_out->min_y;
|
|
||||||
if (vars_out->scroll_y > vars_out->max_y) vars_out->scroll_y = vars_out->max_y;
|
|
||||||
|
|
||||||
if (gui_id_eq(target->active, gui_id_scrollbar())){
|
if (gui_id_eq(target->active, gui_id_scrollbar())){
|
||||||
result = 1;
|
result = 1;
|
||||||
|
@ -724,7 +708,6 @@ gui_activate_scrolling(GUI_Target *target){
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GUI_Section{
|
struct GUI_Section{
|
||||||
b32 overlapped;
|
|
||||||
i32 max_v, v, top_v;
|
i32 max_v, v, top_v;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -739,7 +722,6 @@ struct GUI_Session{
|
||||||
i32_Rect full_rect;
|
i32_Rect full_rect;
|
||||||
i32_Rect rect;
|
i32_Rect rect;
|
||||||
|
|
||||||
f32 suggested_min_y;
|
|
||||||
f32 suggested_max_y;
|
f32 suggested_max_y;
|
||||||
i32 clip_y;
|
i32 clip_y;
|
||||||
|
|
||||||
|
@ -759,17 +741,11 @@ struct GUI_Session{
|
||||||
|
|
||||||
#define GUIScrollbarWidth 16
|
#define GUIScrollbarWidth 16
|
||||||
|
|
||||||
|
// TODO(allen): We can probably totally get rid of this now.
|
||||||
internal i32
|
internal i32
|
||||||
gui_session_get_eclipsed_y(GUI_Session *session){
|
gui_session_get_eclipsed_y(GUI_Session *session){
|
||||||
GUI_Section *section = session->sections;
|
i32 count = session->t + 1;
|
||||||
i32 count = session->t + 1, i;
|
i32 max_v = session->sections[count-1].top_v;
|
||||||
i32 max_v = 0;
|
|
||||||
for (i = 0; i < count; ++i, ++section){
|
|
||||||
if (section->overlapped){
|
|
||||||
max_v = Max(max_v, section->max_v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
max_v = Max(max_v, session->sections[count-1].top_v);
|
|
||||||
return(max_v);
|
return(max_v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -804,9 +780,7 @@ gui_session_init(GUI_Session *session, GUI_Target *target,
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
gui_section_end_item(GUI_Section *section, i32 v){
|
gui_section_end_item(GUI_Section *section, i32 v){
|
||||||
if (!section->overlapped){
|
|
||||||
section->v = v;
|
section->v = v;
|
||||||
}
|
|
||||||
if (section->max_v < v){
|
if (section->max_v < v){
|
||||||
section->max_v = v;
|
section->max_v = v;
|
||||||
}
|
}
|
||||||
|
@ -978,29 +952,10 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
||||||
switch (h->type){
|
switch (h->type){
|
||||||
case guicom_null: Assert(0); break;
|
case guicom_null: Assert(0); break;
|
||||||
|
|
||||||
case guicom_begin_overlap:
|
|
||||||
++session->t;
|
|
||||||
Assert(session->t < ArrayCount(session->sections));
|
|
||||||
new_section = &session->sections[session->t];
|
|
||||||
new_section->overlapped = 1;
|
|
||||||
new_section->v = y;
|
|
||||||
new_section->max_v = y;
|
|
||||||
new_section->top_v = y;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case guicom_end_overlap:
|
|
||||||
Assert(session->t > 0);
|
|
||||||
Assert(section->overlapped);
|
|
||||||
prev_section = &session->sections[--session->t];
|
|
||||||
end_v = section->max_v;
|
|
||||||
end_section = prev_section;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case guicom_begin_serial:
|
case guicom_begin_serial:
|
||||||
++session->t;
|
++session->t;
|
||||||
Assert(session->t < ArrayCount(session->sections));
|
Assert(session->t < ArrayCount(session->sections));
|
||||||
new_section = &session->sections[session->t];
|
new_section = &session->sections[session->t];
|
||||||
new_section->overlapped = 0;
|
|
||||||
new_section->v = y;
|
new_section->v = y;
|
||||||
new_section->max_v = y;
|
new_section->max_v = y;
|
||||||
new_section->top_v = y;
|
new_section->top_v = y;
|
||||||
|
@ -1008,7 +963,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
||||||
|
|
||||||
case guicom_end_serial:
|
case guicom_end_serial:
|
||||||
Assert(session->t > 0);
|
Assert(session->t > 0);
|
||||||
Assert(!section->overlapped);
|
|
||||||
prev_section = &session->sections[--session->t];
|
prev_section = &session->sections[--session->t];
|
||||||
end_v = section->max_v;
|
end_v = section->max_v;
|
||||||
end_section = prev_section;
|
end_section = prev_section;
|
||||||
|
@ -1110,7 +1064,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
||||||
|
|
||||||
case guicom_scrollable:
|
case guicom_scrollable:
|
||||||
Assert(session->is_scrollable == 0);
|
Assert(session->is_scrollable == 0);
|
||||||
Assert(!section->overlapped);
|
|
||||||
session->is_scrollable = 1;
|
session->is_scrollable = 1;
|
||||||
always_give_to_user = 1;
|
always_give_to_user = 1;
|
||||||
|
|
||||||
|
@ -1128,7 +1081,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
||||||
|
|
||||||
case guicom_scrollable_bar:
|
case guicom_scrollable_bar:
|
||||||
Assert(session->is_scrollable);
|
Assert(session->is_scrollable);
|
||||||
Assert(!section->overlapped);
|
|
||||||
give_to_user = 1;
|
give_to_user = 1;
|
||||||
rect.x1 = session->full_rect.x1;
|
rect.x1 = session->full_rect.x1;
|
||||||
rect.x0 = rect.x1 - GUIScrollbarWidth;
|
rect.x0 = rect.x1 - GUIScrollbarWidth;
|
||||||
|
@ -1151,7 +1103,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
||||||
|
|
||||||
case guicom_scrollable_top:
|
case guicom_scrollable_top:
|
||||||
Assert(session->is_scrollable);
|
Assert(session->is_scrollable);
|
||||||
Assert(!section->overlapped);
|
|
||||||
give_to_user = 1;
|
give_to_user = 1;
|
||||||
gui_scrollbar_top(session->scroll_rect, &rect);
|
gui_scrollbar_top(session->scroll_rect, &rect);
|
||||||
scroll_v = 0;
|
scroll_v = 0;
|
||||||
|
@ -1159,29 +1110,26 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
||||||
|
|
||||||
case guicom_scrollable_slider:
|
case guicom_scrollable_slider:
|
||||||
Assert(session->is_scrollable);
|
Assert(session->is_scrollable);
|
||||||
Assert(!section->overlapped);
|
|
||||||
give_to_user = 1;
|
give_to_user = 1;
|
||||||
|
|
||||||
lerp_space_scroll_v =
|
lerp_space_scroll_v =
|
||||||
unlerp((f32)target->scroll_original.min_y,
|
unlerp(0,
|
||||||
(f32)target->scroll_original.target_y,
|
(f32)target->scroll_original.target_y,
|
||||||
(f32)target->scroll_original.max_y);
|
(f32)target->scroll_original.max_y);
|
||||||
|
|
||||||
gui_scrollbar_slider(session->scroll_rect, &rect, lerp_space_scroll_v,
|
gui_scrollbar_slider(session->scroll_rect, &rect, lerp_space_scroll_v,
|
||||||
&session->scroll_top, &session->scroll_bottom,
|
&session->scroll_top, &session->scroll_bottom,
|
||||||
target->scroll_original.min_y, target->scroll_original.max_y);
|
0, target->scroll_original.max_y);
|
||||||
scroll_v = 0;
|
scroll_v = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case guicom_scrollable_invisible:
|
case guicom_scrollable_invisible:
|
||||||
Assert(session->is_scrollable);
|
Assert(session->is_scrollable);
|
||||||
Assert(!section->overlapped);
|
|
||||||
always_give_to_user = 1;
|
always_give_to_user = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case guicom_scrollable_bottom:
|
case guicom_scrollable_bottom:
|
||||||
Assert(session->is_scrollable);
|
Assert(session->is_scrollable);
|
||||||
Assert(!section->overlapped);
|
|
||||||
give_to_user = 1;
|
give_to_user = 1;
|
||||||
gui_scrollbar_bottom(session->scroll_rect, &rect);
|
gui_scrollbar_bottom(session->scroll_rect, &rect);
|
||||||
scroll_v = 0;
|
scroll_v = 0;
|
||||||
|
@ -1196,9 +1144,6 @@ gui_interpret(GUI_Target *target, GUI_Session *session, GUI_Header *h,
|
||||||
|
|
||||||
case guicom_end_scrollable_section:
|
case guicom_end_scrollable_section:
|
||||||
always_give_to_user = 1;
|
always_give_to_user = 1;
|
||||||
session->suggested_min_y =
|
|
||||||
-(f32)(gui_session_get_eclipsed_y(session) -
|
|
||||||
gui_session_get_current_top(session));
|
|
||||||
session->suggested_max_y =
|
session->suggested_max_y =
|
||||||
(f32)(session->scrollable_items_bottom -
|
(f32)(session->scrollable_items_bottom -
|
||||||
session->full_rect.y1 * .5f);
|
session->full_rect.y1 * .5f);
|
||||||
|
@ -1268,7 +1213,7 @@ internal GUI_View_Jump
|
||||||
gui_compute_view_jump(i32_Rect scroll_region, i32_Rect position){
|
gui_compute_view_jump(i32_Rect scroll_region, i32_Rect position){
|
||||||
GUI_View_Jump jump = {0};
|
GUI_View_Jump jump = {0};
|
||||||
i32 region_h = scroll_region.y1 - scroll_region.y0;
|
i32 region_h = scroll_region.y1 - scroll_region.y0;
|
||||||
jump.view_min = (f32)position.y1 - region_h - scroll_region.y0;
|
jump.view_min = (f32)position.y1 - scroll_region.y0 - region_h;
|
||||||
jump.view_max = (f32)position.y0 - scroll_region.y0;
|
jump.view_max = (f32)position.y0 - scroll_region.y0;
|
||||||
return(jump);
|
return(jump);
|
||||||
}
|
}
|
||||||
|
@ -1295,8 +1240,8 @@ gui_standard_list(GUI_Target *target, GUI_id id, GUI_Scroll_Vars *vars, i32_Rect
|
||||||
if (update->has_index_position){
|
if (update->has_index_position){
|
||||||
GUI_View_Jump jump =
|
GUI_View_Jump jump =
|
||||||
gui_compute_view_jump(scroll_region, update->index_position);
|
gui_compute_view_jump(scroll_region, update->index_position);
|
||||||
jump.view_min += 45.f;
|
jump.view_min = jump.view_min + 45.f;
|
||||||
jump.view_max -= 45.f;
|
jump.view_max = jump.view_max - 45.f;
|
||||||
*vars = gui_do_jump(target, jump, *vars);
|
*vars = gui_do_jump(target, jump, *vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
4ed_math.cpp
16
4ed_math.cpp
|
@ -464,9 +464,23 @@ unlerp(f32 a, f32 x, f32 b){
|
||||||
return(r);
|
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
|
inline f32
|
||||||
clamp(f32 a, f32 n, f32 z){
|
clamp(f32 a, f32 n, f32 z){
|
||||||
return (n<a)?(a):((n>z)?(z):n);
|
if (n < a) n = a;
|
||||||
|
else if (n > z) n = z;
|
||||||
|
return (n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -143,7 +143,9 @@ general_memory_attempt_merge(Bubble *left, Bubble *right){
|
||||||
internal void
|
internal void
|
||||||
general_memory_free(General_Memory *general, void *memory){
|
general_memory_free(General_Memory *general, void *memory){
|
||||||
Bubble *bubble = ((Bubble*)memory) - 1;
|
Bubble *bubble = ((Bubble*)memory) - 1;
|
||||||
Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
|
#if FRED_INTERNAL
|
||||||
|
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
|
||||||
|
#endif
|
||||||
bubble->flags &= ~MEM_BUBBLE_USED;
|
bubble->flags &= ~MEM_BUBBLE_USED;
|
||||||
bubble->type = 0;
|
bubble->type = 0;
|
||||||
Bubble *prev, *next;
|
Bubble *prev, *next;
|
||||||
|
@ -158,7 +160,9 @@ general_memory_reallocate(General_Memory *general, void *old, i32 old_size, i32
|
||||||
void *result = old;
|
void *result = old;
|
||||||
Bubble *bubble = ((Bubble*)old) - 1;
|
Bubble *bubble = ((Bubble*)old) - 1;
|
||||||
bubble->type = type;
|
bubble->type = type;
|
||||||
Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
|
#if FRED_INTERNAL
|
||||||
|
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
|
||||||
|
#endif
|
||||||
i32 additional_space = size - bubble->size;
|
i32 additional_space = size - bubble->size;
|
||||||
if (additional_space > 0){
|
if (additional_space > 0){
|
||||||
Bubble *next = bubble->next;
|
Bubble *next = bubble->next;
|
||||||
|
|
200
4ed_metagen.cpp
200
4ed_metagen.cpp
|
@ -143,184 +143,6 @@ char* generate_keycode_enum(){
|
||||||
return(filename);
|
return(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
char daction_enum_name[] = "Action_Type";
|
|
||||||
char *daction_enum[] = {
|
|
||||||
"OPEN",
|
|
||||||
"OPEN_BACKGROUND",
|
|
||||||
"SET_LINE",
|
|
||||||
"SAVE_AS",
|
|
||||||
"SAVE",
|
|
||||||
"NEW",
|
|
||||||
"SWITCH",
|
|
||||||
"TRY_KILL",
|
|
||||||
"KILL",
|
|
||||||
"TOUCH_FILE",
|
|
||||||
"CLOSE",
|
|
||||||
};
|
|
||||||
|
|
||||||
char str_alloc_copy[] =
|
|
||||||
"internal String\n"
|
|
||||||
"str_alloc_copy(General_Memory *general, String str){\n"
|
|
||||||
" String result;\n"
|
|
||||||
" result.memory_size = str.memory_size + 1;\n"
|
|
||||||
" result.size = str.size;\n"
|
|
||||||
" result.str = (char*)general_memory_allocate(general, result.memory_size, 0);\n"
|
|
||||||
" memcpy(result.str, str.str, str.size);\n"
|
|
||||||
" result.str[result.size] = 0;\n"
|
|
||||||
" return(result);\n"
|
|
||||||
"}\n\n";
|
|
||||||
|
|
||||||
char delayed_action_zero[] =
|
|
||||||
"inline Delayed_Action\n"
|
|
||||||
"delayed_action_zero(){\n"
|
|
||||||
" Delayed_Action result = {(Action_Type)0};\n"
|
|
||||||
" return(result);\n"
|
|
||||||
"}\n\n"
|
|
||||||
;
|
|
||||||
|
|
||||||
char daction_name[] = "Delayed_Action";
|
|
||||||
Struct_Field daction_fields[] = {
|
|
||||||
{"Action_Type", "type"},
|
|
||||||
};
|
|
||||||
Struct_Field daction_fields_primary[] = {
|
|
||||||
{"String", "string"},
|
|
||||||
{"Panel*", "panel"},
|
|
||||||
{"Editing_File*", "file"},
|
|
||||||
{"i32", "integer"},
|
|
||||||
};
|
|
||||||
enum Daction_Field_Handle{
|
|
||||||
dfph_null,
|
|
||||||
dfph_string,
|
|
||||||
dfph_panel,
|
|
||||||
dfph_file,
|
|
||||||
dfph_integer,
|
|
||||||
};
|
|
||||||
Daction_Field_Handle dact_param_sets[] = {
|
|
||||||
dfph_string, dfph_null,
|
|
||||||
dfph_panel, dfph_null,
|
|
||||||
dfph_file, dfph_null,
|
|
||||||
dfph_file, dfph_panel, dfph_null,
|
|
||||||
dfph_string, dfph_panel, dfph_null,
|
|
||||||
dfph_string, dfph_file, dfph_null,
|
|
||||||
dfph_panel, dfph_integer, dfph_null,
|
|
||||||
};
|
|
||||||
|
|
||||||
char delay_name[] = "Delay";
|
|
||||||
Struct_Field delay_fields[] = {
|
|
||||||
{"General_Memory*", "general"},
|
|
||||||
{"Delayed_Action*", "acts"},
|
|
||||||
{"i32", "count"},
|
|
||||||
{"i32", "max"},
|
|
||||||
};
|
|
||||||
|
|
||||||
char delayed_action_function_top[] =
|
|
||||||
"inline Delayed_Action*\n"
|
|
||||||
"delayed_action_(Delay *delay, Action_Type type";
|
|
||||||
|
|
||||||
char delayed_action_function_bottom[] =
|
|
||||||
"){\n"
|
|
||||||
" Delayed_Action *result;\n"
|
|
||||||
" if (delay->count == delay->max){\n"
|
|
||||||
" delay->max *= 2;\n"
|
|
||||||
" delay->acts = (Delayed_Action*)general_memory_reallocate("
|
|
||||||
"delay->general, delay->acts, delay->count*sizeof(Delayed_Action), delay->max*sizeof(Delayed_Action), 0);\n"
|
|
||||||
" }\n"
|
|
||||||
" result = delay->acts + delay->count++;\n"
|
|
||||||
" *result = delayed_action_zero();\n"
|
|
||||||
" result->type = type;\n"
|
|
||||||
" return(result);\n"
|
|
||||||
"}\n\n";
|
|
||||||
|
|
||||||
char delayed_action_special_param[] = ", %s %s";
|
|
||||||
|
|
||||||
char delayed_action_specialized_middle[] =
|
|
||||||
"){\n"
|
|
||||||
" Delayed_Action *result;\n"
|
|
||||||
" result = delayed_action_(delay, type);\n";
|
|
||||||
|
|
||||||
char delayed_action_special_line[] =
|
|
||||||
" result->%s = %s;\n";
|
|
||||||
|
|
||||||
char delayed_action_special_string_line[] =
|
|
||||||
" result->%s = str_alloc_copy(delay->general, %s);\n";
|
|
||||||
|
|
||||||
char delayed_action_specialized_bottom[] =
|
|
||||||
" return(result);\n"
|
|
||||||
"}\n\n";
|
|
||||||
|
|
||||||
char delayed_action_macro[] =
|
|
||||||
"#define delayed_%s(delay, ...) delayed_action_(delay, DACT_%s, ##__VA_ARGS__)\n";
|
|
||||||
|
|
||||||
char delayed_action_repush_function[] =
|
|
||||||
"inline Delayed_Action*\n"
|
|
||||||
"delayed_action_repush(Delay *delay, Delayed_Action *act){\n"
|
|
||||||
" Delayed_Action *new_act = delayed_action_(delay, (Action_Type)0);\n"
|
|
||||||
" *new_act = *act;\n"
|
|
||||||
" if (act->string.str){\n"
|
|
||||||
" new_act->string = str_alloc_copy(delay->general, act->string);\n"
|
|
||||||
" }\n"
|
|
||||||
" return(new_act);\n"
|
|
||||||
"}\n\n";
|
|
||||||
|
|
||||||
char* generate_delayed_action(){
|
|
||||||
FILE *file;
|
|
||||||
char *filename = "4ed_delay.cpp";
|
|
||||||
char scratch[256];
|
|
||||||
int i,j;
|
|
||||||
|
|
||||||
file = fopen(filename, "wb");
|
|
||||||
|
|
||||||
fprintf(file, "enum %s{\n", daction_enum_name);
|
|
||||||
for (i = 0; i < ArrayCount(daction_enum); ++i){
|
|
||||||
fprintf(file, " DACT_%s,\n", daction_enum[i]);
|
|
||||||
}
|
|
||||||
fprintf(file, "};\n\n");
|
|
||||||
|
|
||||||
struct_begin(file, daction_name);
|
|
||||||
struct_fields(file, daction_fields, ArrayCount(daction_fields));
|
|
||||||
struct_fields(file, daction_fields_primary, ArrayCount(daction_fields_primary));
|
|
||||||
struct_end(file);
|
|
||||||
|
|
||||||
struct_begin(file, delay_name);
|
|
||||||
struct_fields(file, delay_fields, ArrayCount(delay_fields));
|
|
||||||
struct_end(file);
|
|
||||||
|
|
||||||
fprintf(file, "%s", str_alloc_copy);
|
|
||||||
fprintf(file, "%s", delayed_action_zero);
|
|
||||||
fprintf(file, "%s%s", delayed_action_function_top, delayed_action_function_bottom);
|
|
||||||
|
|
||||||
for (i = 0; i < ArrayCount(dact_param_sets); ++i){
|
|
||||||
j = i;
|
|
||||||
fprintf(file, "%s", delayed_action_function_top);
|
|
||||||
for (; dact_param_sets[i] != dfph_null; ++i){
|
|
||||||
Struct_Field field = daction_fields_primary[dact_param_sets[i] - 1];
|
|
||||||
fprintf(file, delayed_action_special_param, field.type, field.name);
|
|
||||||
}
|
|
||||||
fprintf(file, "%s", delayed_action_specialized_middle);
|
|
||||||
for (; dact_param_sets[j] != dfph_null; ++j){
|
|
||||||
int handle = (int)(dact_param_sets[j]);
|
|
||||||
Struct_Field field = daction_fields_primary[handle - 1];
|
|
||||||
if (handle == dfph_string){
|
|
||||||
fprintf(file, delayed_action_special_string_line, field.name, field.name);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
fprintf(file, delayed_action_special_line, field.name, field.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fprintf(file, "%s", delayed_action_specialized_bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(file, "%s", delayed_action_repush_function);
|
|
||||||
|
|
||||||
for (i = 0; i < ArrayCount(daction_enum); ++i){
|
|
||||||
to_lower(daction_enum[i], scratch);
|
|
||||||
fprintf(file, delayed_action_macro, scratch, daction_enum[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
char* bar_style_fields[] = {
|
char* bar_style_fields[] = {
|
||||||
"bar",
|
"bar",
|
||||||
|
@ -456,6 +278,7 @@ char* generate_style(){
|
||||||
return(filename);
|
return(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
struct Function_Signature{
|
struct Function_Signature{
|
||||||
String name;
|
String name;
|
||||||
String ret;
|
String ret;
|
||||||
|
@ -653,6 +476,24 @@ generate_custom_headers(){
|
||||||
);
|
);
|
||||||
fprintf(file, "};\n");
|
fprintf(file, "};\n");
|
||||||
|
|
||||||
|
// TODO(allen): Generate app->function(app, ...) to function(app, ...) wrappers.
|
||||||
|
// Need to parse parameter names to do this.
|
||||||
|
#if 0
|
||||||
|
for (int i = 0; i < sig_count; ++i){
|
||||||
|
Function_Signature *sig = sigs + i;
|
||||||
|
|
||||||
|
copy_fast_unsafe(name_buffer, sig->name);
|
||||||
|
name_buffer[sig->name.size] = 0;
|
||||||
|
to_lower(name_buffer, name_buffer);
|
||||||
|
|
||||||
|
fprintf(file,
|
||||||
|
"inline %.*s\n"
|
||||||
|
"%s%.*s{ app->%s(",
|
||||||
|
sig->name.size, sig->name.str,
|
||||||
|
name_buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
return(filename);
|
return(filename);
|
||||||
|
@ -664,9 +505,6 @@ int main(){
|
||||||
filename = generate_keycode_enum();
|
filename = generate_keycode_enum();
|
||||||
printf("gen success: %s\n", filename);
|
printf("gen success: %s\n", filename);
|
||||||
|
|
||||||
filename = generate_delayed_action();
|
|
||||||
printf("gen success: %s\n", filename);
|
|
||||||
|
|
||||||
filename = generate_style();
|
filename = generate_style();
|
||||||
printf("gen success: %s\n", filename);
|
printf("gen success: %s\n", filename);
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,15 @@ draw_set_color(Render_Target *target, u32 color){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PutStruct(s,x) *(s*)(target->push_buffer + target->size) = x; target->size += sizeof(s)
|
inline void
|
||||||
|
draw_safe_push(Render_Target *target, i32 size, void *x){
|
||||||
|
if (size + target->size <= target->max){
|
||||||
|
memcpy(target->push_buffer + target->size, x, size);
|
||||||
|
target->size += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PutStruct(s,x) draw_safe_push(target, sizeof(s), &x)
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
draw_push_piece(Render_Target *target, Render_Piece_Combined piece){
|
draw_push_piece(Render_Target *target, Render_Piece_Combined piece){
|
||||||
|
@ -297,101 +305,17 @@ launch_rendering(Render_Target *target){
|
||||||
|
|
||||||
#undef ExtractStruct
|
#undef ExtractStruct
|
||||||
|
|
||||||
internal i32
|
// TODO(allen): Put the burden of translation outside
|
||||||
draw_font_info_load(Partition *partition,
|
// of this function (and other functions implementing
|
||||||
char *filename_untranslated,
|
// the same interface).
|
||||||
i32 pt_size, i32 *height, i32 *advance){
|
|
||||||
|
|
||||||
char space_[1024];
|
|
||||||
String filename = make_fixed_width_string(space_);
|
|
||||||
b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated);
|
|
||||||
if (!translate_success) return 0;
|
|
||||||
|
|
||||||
i32 result = 1;
|
|
||||||
File_Data file;
|
|
||||||
file = sysshared_load_file(filename.str);
|
|
||||||
|
|
||||||
Temp_Memory temp = begin_temp_memory(partition);
|
|
||||||
stbtt_packedchar *chardata = push_array(partition, stbtt_packedchar, 256);
|
|
||||||
|
|
||||||
i32 oversample = 2;
|
|
||||||
|
|
||||||
i32 tex_width, tex_height;
|
|
||||||
tex_width = pt_size*128*oversample;
|
|
||||||
tex_height = pt_size*2*oversample;
|
|
||||||
void *block = push_block(partition, tex_width * tex_height);
|
|
||||||
|
|
||||||
if (!file.data.data){
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
stbtt_fontinfo font;
|
|
||||||
if (!stbtt_InitFont(&font, (u8*)file.data.data, 0)){
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
i32 ascent, descent, line_gap;
|
|
||||||
f32 scale;
|
|
||||||
|
|
||||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
|
||||||
scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
|
||||||
|
|
||||||
f32 scaled_ascent, scaled_descent, scaled_line_gap;
|
|
||||||
|
|
||||||
scaled_ascent = scale*ascent;
|
|
||||||
scaled_descent = scale*descent;
|
|
||||||
scaled_line_gap = scale*line_gap;
|
|
||||||
|
|
||||||
i32 font_height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
|
|
||||||
|
|
||||||
stbtt_pack_context spc;
|
|
||||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height, tex_width, 1, partition)){
|
|
||||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
|
||||||
if (stbtt_PackFontRange(&spc, (u8*)file.data.data, 0,
|
|
||||||
STBTT_POINT_SIZE((f32)pt_size), 0, 128, chardata)){
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
stbtt_PackEnd(&spc);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
result = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result){
|
|
||||||
i32 max_advance = 0;
|
|
||||||
for (u8 code_point = 0; code_point < 128; ++code_point){
|
|
||||||
if (stbtt_FindGlyphIndex(&font, code_point) != 0){
|
|
||||||
i32 adv = CEIL32(chardata[code_point].xadvance);
|
|
||||||
if (max_advance < adv){
|
|
||||||
max_advance = adv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*height = font_height;
|
|
||||||
*advance = max_advance - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
system_free_memory(file.data.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
end_temp_memory(temp);
|
|
||||||
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal i32
|
internal i32
|
||||||
draw_font_load(Partition *part,
|
draw_font_load(Partition *part,
|
||||||
Render_Font *font_out,
|
Render_Font *font_out,
|
||||||
char *filename_untranslated,
|
char *filename_untranslated,
|
||||||
i32 pt_size,
|
i32 pt_size,
|
||||||
i32 tab_width,
|
i32 tab_width,
|
||||||
i32 oversample){
|
i32 oversample,
|
||||||
|
b32 store_texture){
|
||||||
|
|
||||||
char space_[1024];
|
char space_[1024];
|
||||||
String filename = make_fixed_width_string(space_);
|
String filename = make_fixed_width_string(space_);
|
||||||
|
@ -402,12 +326,6 @@ draw_font_load(Partition *part,
|
||||||
|
|
||||||
stbtt_packedchar *chardata = font_out->chardata;
|
stbtt_packedchar *chardata = font_out->chardata;
|
||||||
|
|
||||||
Temp_Memory temp = begin_temp_memory(part);
|
|
||||||
|
|
||||||
i32 tex_width = pt_size*16*oversample;
|
|
||||||
i32 tex_height = pt_size*16*oversample;
|
|
||||||
void *block = sysshared_push_block(part, tex_width * tex_height);
|
|
||||||
|
|
||||||
File_Data file = sysshared_load_file(filename.str);
|
File_Data file = sysshared_load_file(filename.str);
|
||||||
|
|
||||||
if (!file.data.data){
|
if (!file.data.data){
|
||||||
|
@ -420,30 +338,34 @@ draw_font_load(Partition *part,
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
memset(font_out, 0, sizeof(*font_out));
|
||||||
|
|
||||||
i32 ascent, descent, line_gap;
|
i32 ascent, descent, line_gap;
|
||||||
f32 scale;
|
|
||||||
|
|
||||||
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
stbtt_GetFontVMetrics(&font, &ascent, &descent, &line_gap);
|
||||||
scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
|
||||||
|
|
||||||
f32 scaled_ascent, scaled_descent, scaled_line_gap;
|
f32 scale = stbtt_ScaleForPixelHeight(&font, (f32)pt_size);
|
||||||
|
|
||||||
scaled_ascent = scale*ascent;
|
f32 scaled_ascent = scale*ascent;
|
||||||
scaled_descent = scale*descent;
|
f32 scaled_descent = scale*descent;
|
||||||
scaled_line_gap = scale*line_gap;
|
f32 scaled_line_gap = scale*line_gap;
|
||||||
|
|
||||||
font_out->height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
|
font_out->height = (i32)(scaled_ascent - scaled_descent + scaled_line_gap);
|
||||||
font_out->ascent = (i32)(scaled_ascent);
|
font_out->ascent = (i32)(scaled_ascent);
|
||||||
font_out->descent = (i32)(scaled_descent);
|
font_out->descent = (i32)(scaled_descent);
|
||||||
font_out->line_skip = (i32)(scaled_line_gap);
|
font_out->line_skip = (i32)(scaled_line_gap);
|
||||||
|
|
||||||
|
if (store_texture){
|
||||||
|
Temp_Memory temp = begin_temp_memory(part);
|
||||||
|
|
||||||
|
i32 tex_width = pt_size*16*oversample;
|
||||||
|
i32 tex_height = pt_size*16*oversample;
|
||||||
|
void *block = sysshared_push_block(part, tex_width * tex_height);
|
||||||
|
|
||||||
font_out->tex_width = tex_width;
|
font_out->tex_width = tex_width;
|
||||||
font_out->tex_height = tex_height;
|
font_out->tex_height = tex_height;
|
||||||
|
|
||||||
stbtt_pack_context spc;
|
stbtt_pack_context spc;
|
||||||
|
|
||||||
// TODO(allen): If this fails we can just expand the partition here now
|
|
||||||
// rather than forcing the user to do it.
|
|
||||||
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height,
|
if (stbtt_PackBegin(&spc, (u8*)block, tex_width, tex_height,
|
||||||
tex_width, 1, part)){
|
tex_width, 1, part)){
|
||||||
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
stbtt_PackSetOversampling(&spc, oversample, oversample);
|
||||||
|
@ -493,12 +415,12 @@ draw_font_load(Partition *part,
|
||||||
font_out->advance = max_advance - 1;
|
font_out->advance = max_advance - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
end_temp_memory(temp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
system_free_memory(file.data.data);
|
system_free_memory(file.data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
end_temp_memory(temp);
|
|
||||||
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,16 +115,11 @@ typedef Draw_Push_Piece_Sig(Draw_Push_Piece);
|
||||||
Render_Font *font_out, \
|
Render_Font *font_out, \
|
||||||
char *filename, \
|
char *filename, \
|
||||||
i32 pt_size, \
|
i32 pt_size, \
|
||||||
i32 tab_width)
|
i32 tab_width, \
|
||||||
|
b32 store_texture)
|
||||||
typedef Font_Load_Sig(Font_Load);
|
typedef Font_Load_Sig(Font_Load);
|
||||||
|
|
||||||
#define Font_Info_Load_Sig(name) i32 name( \
|
|
||||||
Partition *partition, \
|
|
||||||
char *filename, \
|
|
||||||
i32 pt_size, \
|
|
||||||
i32 *height, \
|
|
||||||
i32 *advance)
|
|
||||||
typedef Font_Info_Load_Sig(Font_Info_Load);
|
|
||||||
|
|
||||||
#define Release_Font_Sig(name) void name(Render_Font *font)
|
#define Release_Font_Sig(name) void name(Render_Font *font)
|
||||||
typedef Release_Font_Sig(Release_Font);
|
typedef Release_Font_Sig(Release_Font);
|
||||||
|
@ -158,7 +153,7 @@ struct Font_Set{
|
||||||
Font_Slot free_slots;
|
Font_Slot free_slots;
|
||||||
Font_Slot used_slots;
|
Font_Slot used_slots;
|
||||||
|
|
||||||
Font_Info_Load *font_info_load;
|
//Font_Info_Load *font_info_load;
|
||||||
Font_Load *font_load;
|
Font_Load *font_load;
|
||||||
Release_Font *release_font;
|
Release_Font *release_font;
|
||||||
|
|
||||||
|
|
40
4ed_system.h
40
4ed_system.h
|
@ -35,9 +35,16 @@ uhash_equal(Unique_Hash a, Unique_Hash b){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE(allen): These two time functions should return values
|
||||||
|
// in the same time space. There is no requirement about
|
||||||
|
// resolution but the higher the better. These functions
|
||||||
|
// should not be used for profiling purposes.
|
||||||
#define Sys_File_Time_Stamp_Sig(name) u64 name(char *filename)
|
#define Sys_File_Time_Stamp_Sig(name) u64 name(char *filename)
|
||||||
typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp);
|
typedef Sys_File_Time_Stamp_Sig(System_File_Time_Stamp);
|
||||||
|
|
||||||
|
#define Sys_Now_Time_Stamp_Sig(name) u64 name()
|
||||||
|
typedef Sys_Now_Time_Stamp_Sig(System_Now_Time_Stamp);
|
||||||
|
|
||||||
// TODO(allen): make directory a char* to signal that it must be null terminated
|
// TODO(allen): make directory a char* to signal that it must be null terminated
|
||||||
#define Sys_Set_File_List_Sig(name) void name(File_List *file_list, String directory)
|
#define Sys_Set_File_List_Sig(name) void name(File_List *file_list, String directory)
|
||||||
typedef Sys_Set_File_List_Sig(System_Set_File_List);
|
typedef Sys_Set_File_List_Sig(System_Set_File_List);
|
||||||
|
@ -66,13 +73,9 @@ typedef Sys_File_Load_End_Sig(System_File_Load_End);
|
||||||
#define Sys_File_Save_Sig(name) b32 name(char *filename, char *buffer, i32 size)
|
#define Sys_File_Save_Sig(name) b32 name(char *filename, char *buffer, i32 size)
|
||||||
typedef Sys_File_Save_Sig(System_File_Save);
|
typedef Sys_File_Save_Sig(System_File_Save);
|
||||||
|
|
||||||
|
|
||||||
#define Sys_Post_Clipboard_Sig(name) void name(String str)
|
#define Sys_Post_Clipboard_Sig(name) void name(String str)
|
||||||
typedef Sys_Post_Clipboard_Sig(System_Post_Clipboard);
|
typedef Sys_Post_Clipboard_Sig(System_Post_Clipboard);
|
||||||
|
|
||||||
#define Sys_Time_Sig(name) u64 name()
|
|
||||||
typedef Sys_Time_Sig(System_Time);
|
|
||||||
|
|
||||||
// cli
|
// cli
|
||||||
struct CLI_Handles{
|
struct CLI_Handles{
|
||||||
Plat_Handle proc;
|
Plat_Handle proc;
|
||||||
|
@ -155,14 +158,16 @@ struct Thread_Exchange;
|
||||||
struct System_Functions;
|
struct System_Functions;
|
||||||
|
|
||||||
#define Job_Callback_Sig(name) void name( \
|
#define Job_Callback_Sig(name) void name( \
|
||||||
System_Functions *system, Thread_Context *thread, Thread_Memory *memory, \
|
System_Functions *system, \
|
||||||
Thread_Exchange *exchange, void *data[2])
|
Thread_Context *thread, \
|
||||||
|
Thread_Memory *memory, \
|
||||||
|
void *data[2])
|
||||||
typedef Job_Callback_Sig(Job_Callback);
|
typedef Job_Callback_Sig(Job_Callback);
|
||||||
|
|
||||||
struct Job_Data{
|
struct Job_Data{
|
||||||
Job_Callback *callback;
|
Job_Callback *callback;
|
||||||
void *data[2];
|
void *data[2];
|
||||||
i32 memory_request;
|
//i32 memory_request;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Full_Job_Data{
|
struct Full_Job_Data{
|
||||||
|
@ -186,17 +191,15 @@ struct Work_Queue{
|
||||||
#define JOB_ID_WRAP (ArrayCount(queue->jobs) * 4)
|
#define JOB_ID_WRAP (ArrayCount(queue->jobs) * 4)
|
||||||
#define QUEUE_WRAP (ArrayCount(queue->jobs))
|
#define QUEUE_WRAP (ArrayCount(queue->jobs))
|
||||||
|
|
||||||
struct Thread_Exchange{
|
|
||||||
Work_Queue queues[THREAD_GROUP_COUNT];
|
|
||||||
volatile u32 force_redraw;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID group_id, Job_Data job)
|
#define Sys_Post_Job_Sig(name) u32 name(Thread_Group_ID group_id, Job_Data job)
|
||||||
typedef Sys_Post_Job_Sig(System_Post_Job);
|
typedef Sys_Post_Job_Sig(System_Post_Job);
|
||||||
|
|
||||||
#define Sys_Cancel_Job_Sig(name) void name(Thread_Group_ID group_id, u32 job_id)
|
#define Sys_Cancel_Job_Sig(name) void name(Thread_Group_ID group_id, u32 job_id)
|
||||||
typedef Sys_Cancel_Job_Sig(System_Cancel_Job);
|
typedef Sys_Cancel_Job_Sig(System_Cancel_Job);
|
||||||
|
|
||||||
|
#define Sys_Check_Cancel_Sig(name) b32 name(Thread_Context *thread)
|
||||||
|
typedef Sys_Check_Cancel_Sig(System_Check_Cancel);
|
||||||
|
|
||||||
#define Sys_Grow_Thread_Memory_Sig(name) void name(Thread_Memory *memory)
|
#define Sys_Grow_Thread_Memory_Sig(name) void name(Thread_Memory *memory)
|
||||||
typedef Sys_Grow_Thread_Memory_Sig(System_Grow_Thread_Memory);
|
typedef Sys_Grow_Thread_Memory_Sig(System_Grow_Thread_Memory);
|
||||||
|
|
||||||
|
@ -217,8 +220,9 @@ typedef INTERNAL_Sys_Get_Thread_States_Sig(INTERNAL_System_Get_Thread_States);
|
||||||
typedef INTERNAL_Sys_Debug_Message_Sig(INTERNAL_System_Debug_Message);
|
typedef INTERNAL_Sys_Debug_Message_Sig(INTERNAL_System_Debug_Message);
|
||||||
|
|
||||||
struct System_Functions{
|
struct System_Functions{
|
||||||
// files: 6
|
// files: 7
|
||||||
System_File_Time_Stamp *file_time_stamp;
|
System_File_Time_Stamp *file_time_stamp;
|
||||||
|
System_Now_Time_Stamp *now_time_stamp;
|
||||||
System_Set_File_List *set_file_list;
|
System_Set_File_List *set_file_list;
|
||||||
System_File_Unique_Hash *file_unique_hash;
|
System_File_Unique_Hash *file_unique_hash;
|
||||||
System_File_Track *file_track;
|
System_File_Track *file_track;
|
||||||
|
@ -235,9 +239,6 @@ struct System_Functions{
|
||||||
// clipboard: 1
|
// clipboard: 1
|
||||||
System_Post_Clipboard *post_clipboard;
|
System_Post_Clipboard *post_clipboard;
|
||||||
|
|
||||||
// time: 1
|
|
||||||
System_Time *time;
|
|
||||||
|
|
||||||
// coroutine: 4
|
// coroutine: 4
|
||||||
System_Create_Coroutine *create_coroutine;
|
System_Create_Coroutine *create_coroutine;
|
||||||
System_Launch_Coroutine *launch_coroutine;
|
System_Launch_Coroutine *launch_coroutine;
|
||||||
|
@ -250,9 +251,10 @@ struct System_Functions{
|
||||||
System_CLI_Update_Step *cli_update_step;
|
System_CLI_Update_Step *cli_update_step;
|
||||||
System_CLI_End_Update *cli_end_update;
|
System_CLI_End_Update *cli_end_update;
|
||||||
|
|
||||||
// threads: 5
|
// threads: 7
|
||||||
System_Post_Job *post_job;
|
System_Post_Job *post_job;
|
||||||
System_Cancel_Job *cancel_job;
|
System_Cancel_Job *cancel_job;
|
||||||
|
System_Check_Cancel *check_cancel;
|
||||||
System_Grow_Thread_Memory *grow_thread_memory;
|
System_Grow_Thread_Memory *grow_thread_memory;
|
||||||
System_Acquire_Lock *acquire_lock;
|
System_Acquire_Lock *acquire_lock;
|
||||||
System_Release_Lock *release_lock;
|
System_Release_Lock *release_lock;
|
||||||
|
@ -266,9 +268,5 @@ struct System_Functions{
|
||||||
char slash;
|
char slash;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Exchange{
|
|
||||||
Thread_Exchange thread;
|
|
||||||
};
|
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// NOTE(allen): This is an experiment, BUT remember a lot of people shit on templates.
|
// NOTE(allen): This is an experiment, BUT remember a lot of people shit on templates.
|
||||||
// So if you start getting a wiff of stupidity from this back out immediately!
|
// So if you start getting a wiff of stupidity from this back out immediately!
|
||||||
//
|
//
|
||||||
// experience 1: no badness, haven't seen any anoying template errors
|
// experience 1: no badness, haven't seen any annoying template errors
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -57,12 +57,13 @@ table_at_capacity(Table *table){
|
||||||
internal b32
|
internal b32
|
||||||
table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||||
u32 hash, *inspect;
|
u32 hash, *inspect;
|
||||||
i32 i;
|
i32 i, start;
|
||||||
|
|
||||||
Assert(table->count * 8 < table->max * 7);
|
Assert(table->count * 8 < table->max * 7);
|
||||||
|
|
||||||
hash = (hash_func(item, arg) | TableHashMin);
|
hash = (hash_func(item, arg) | TableHashMin);
|
||||||
i = hash % table->max;
|
i = hash % table->max;
|
||||||
|
start = i;
|
||||||
inspect = table->hash_array + i;
|
inspect = table->hash_array + i;
|
||||||
|
|
||||||
while (*inspect >= TableHashMin){
|
while (*inspect >= TableHashMin){
|
||||||
|
@ -77,6 +78,7 @@ table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare
|
||||||
i = 0;
|
i = 0;
|
||||||
inspect = table->hash_array;
|
inspect = table->hash_array;
|
||||||
}
|
}
|
||||||
|
Assert(i != start);
|
||||||
}
|
}
|
||||||
*inspect = hash;
|
*inspect = hash;
|
||||||
memcpy(table->data_array + i*table->item_size, item, table->item_size);
|
memcpy(table->data_array + i*table->item_size, item, table->item_size);
|
||||||
|
@ -88,12 +90,13 @@ table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare
|
||||||
internal b32
|
internal b32
|
||||||
table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index, Hash_Function *hash_func, Compare_Function *comp_func){
|
table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index, Hash_Function *hash_func, Compare_Function *comp_func){
|
||||||
u32 hash, *inspect;
|
u32 hash, *inspect;
|
||||||
i32 i;
|
i32 i, start;
|
||||||
|
|
||||||
Assert((table->count - 1) * 8 < table->max * 7);
|
Assert((table->count - 1) * 8 < table->max * 7);
|
||||||
|
|
||||||
hash = (hash_func(search_key, arg) | TableHashMin);
|
hash = (hash_func(search_key, arg) | TableHashMin);
|
||||||
i = hash % table->max;
|
i = hash % table->max;
|
||||||
|
start = i;
|
||||||
inspect = table->hash_array + i;
|
inspect = table->hash_array + i;
|
||||||
|
|
||||||
while (*inspect != TableHashEmpty){
|
while (*inspect != TableHashEmpty){
|
||||||
|
@ -110,6 +113,7 @@ table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index,
|
||||||
i = 0;
|
i = 0;
|
||||||
inspect = table->hash_array;
|
inspect = table->hash_array;
|
||||||
}
|
}
|
||||||
|
if (i == start) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Distribution Date: 24.5.2016 (dd.mm.yyyy)
|
Distribution Date: 31.5.2016 (dd.mm.yyyy)
|
||||||
|
|
||||||
Thank you for contributing to the 4coder project!
|
Thank you for contributing to the 4coder project!
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Distribution Date: 24.5.2016 (dd.mm.yyyy)
|
Distribution Date: 31.5.2016 (dd.mm.yyyy)
|
||||||
|
|
||||||
Thank you for contributing to the 4coder project!
|
Thank you for contributing to the 4coder project!
|
||||||
|
|
||||||
|
|
37
TODO.txt
37
TODO.txt
|
@ -1,7 +1,3 @@
|
||||||
|
|
||||||
; before shipping:
|
|
||||||
; [] make sure 4coder_handmade_hero.cpp works
|
|
||||||
|
|
||||||
; Started this list on: (18.01.2016)(dd.mm.yyyy)
|
; Started this list on: (18.01.2016)(dd.mm.yyyy)
|
||||||
; This list is an informal todo list, it may very well miss items
|
; This list is an informal todo list, it may very well miss items
|
||||||
; checked or unchecked, that I inted to do some day. It is included
|
; checked or unchecked, that I inted to do some day. It is included
|
||||||
|
@ -67,11 +63,15 @@
|
||||||
; [X] chronal's map setting issue
|
; [X] chronal's map setting issue
|
||||||
; [X] linux save jankieness
|
; [X] linux save jankieness
|
||||||
; [X] bouncing when scrolling down
|
; [X] bouncing when scrolling down
|
||||||
|
; [X] sometimes the main cursor is not the same width as the mark cursor in the same spot
|
||||||
|
; [X] tab character wrong width
|
||||||
|
; [X] miblo's off screen cursor thing
|
||||||
|
; [X] new file is messed up for code files, it never finishes parsing!
|
||||||
|
; [X] key presses that should be consumed in the GUI are now passed to the file!
|
||||||
|
; [X] paste snaps the cursor back into view!
|
||||||
|
;
|
||||||
; [] indication on failure to save
|
; [] indication on failure to save
|
||||||
; [] clean whitespace doesn't appear to be cleaning trailing whitespace anymore???
|
; [] clean whitespace doesn't appear to be cleaning trailing whitespace anymore???
|
||||||
; [] sometimes the main cursor is not the same width as the mark cursor in the same spot
|
|
||||||
; [] tab character wrong width
|
|
||||||
; [] miblo's off screen cursor thing
|
|
||||||
;
|
;
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -99,6 +99,9 @@
|
||||||
; [X] feedback messages
|
; [X] feedback messages
|
||||||
; [X] feedback message API
|
; [X] feedback message API
|
||||||
; [X] kill rect
|
; [X] kill rect
|
||||||
|
; [X] add high DPI support
|
||||||
|
;
|
||||||
|
; [] OS font rendering
|
||||||
;
|
;
|
||||||
; [] file status in custom API
|
; [] file status in custom API
|
||||||
; [] user file bar string
|
; [] user file bar string
|
||||||
|
@ -117,14 +120,13 @@
|
||||||
; [X] rewrite GUI
|
; [X] rewrite GUI
|
||||||
; [X] arrow navigation of GUIs
|
; [X] arrow navigation of GUIs
|
||||||
; [] GUI API
|
; [] GUI API
|
||||||
; [] text links -> arbitrary commands / callbacks?
|
|
||||||
;
|
;
|
||||||
; search related tech
|
; search related tech
|
||||||
; [X] replace word (incremental and/or in range)
|
; [X] replace word (incremental and/or in range)
|
||||||
|
; [X] caps insensitivety
|
||||||
; [] optimize search
|
; [] optimize search
|
||||||
; [] allow search wrap around beginning/end
|
; [] allow search wrap around beginning/end
|
||||||
; [] improved custom API for text "streams"
|
; [] improved custom API for text "streams"
|
||||||
; [] caps insensitivety
|
|
||||||
;
|
;
|
||||||
; theme related business
|
; theme related business
|
||||||
; [] fix the versioning system for themes
|
; [] fix the versioning system for themes
|
||||||
|
@ -173,12 +175,11 @@
|
||||||
|
|
||||||
; INTERNAL TODOS
|
; INTERNAL TODOS
|
||||||
; [X] switch building non-extensible version by statically linking to custom.cpp
|
; [X] switch building non-extensible version by statically linking to custom.cpp
|
||||||
|
; [X] pack fonts more squarely
|
||||||
; [] general parameter handling
|
; [] general parameter handling
|
||||||
; [] hashed string pool for clipboard/filenames/etc
|
; [] hashed string pool for clipboard/filenames/etc
|
||||||
; [] ask for clipboards to update by request, not on loop
|
|
||||||
; [] pack fonts more squarely
|
|
||||||
; [] setup tests through special tool
|
|
||||||
; [] new profiling/debugging system
|
; [] new profiling/debugging system
|
||||||
|
; [] change job canceling to a polling based thing
|
||||||
;
|
;
|
||||||
|
|
||||||
; EASY TODOS
|
; EASY TODOS
|
||||||
|
@ -192,7 +193,6 @@
|
||||||
|
|
||||||
; HARD BUGS
|
; HARD BUGS
|
||||||
; [X] reduce cpu consumption
|
; [X] reduce cpu consumption
|
||||||
; [?] minimize and reopen problem (reported by two users now, still not reproduced here)
|
|
||||||
; [X] repainting too slow for resize looks really dumb
|
; [X] repainting too slow for resize looks really dumb
|
||||||
; [] fyoucon's segfaults with malloc on win10
|
; [] fyoucon's segfaults with malloc on win10
|
||||||
; [] handling cursor in non-client part of window so it doesn't spaz
|
; [] handling cursor in non-client part of window so it doesn't spaz
|
||||||
|
@ -200,6 +200,17 @@
|
||||||
; [] how to get fast repaint (do I really need double buffering?)
|
; [] how to get fast repaint (do I really need double buffering?)
|
||||||
; [] history breaks when heavily used (disk swaping?)
|
; [] history breaks when heavily used (disk swaping?)
|
||||||
;
|
;
|
||||||
|
; [] minimize and reopen problem (reported by two users now, still not reproduced here)
|
||||||
|
;
|
||||||
|
|
||||||
|
; FANCY PANTS IDEAS
|
||||||
|
; [] pass messages to 'jobs' to try to avoid cancelling them
|
||||||
|
; if the job still thinks it should be cancelled it will say so
|
||||||
|
; but otherwise the job can try to incorporate the new info
|
||||||
|
; without throwing away the progress it has made so far.
|
||||||
|
;
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
; PORTING TODOS
|
; PORTING TODOS
|
||||||
; [X] command line parameters
|
; [X] command line parameters
|
||||||
|
|
|
@ -128,98 +128,6 @@ buffer_reverse_seek_delimiter(Buffer_Type *buffer, int pos, char delim){
|
||||||
return(pos);
|
return(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_4tech int
|
|
||||||
buffer_seek_whitespace_down(Buffer_Type *buffer, int pos){
|
|
||||||
Buffer_Stringify_Type loop;
|
|
||||||
char *data;
|
|
||||||
int end;
|
|
||||||
int size;
|
|
||||||
int no_hard;
|
|
||||||
int prev_endline;
|
|
||||||
|
|
||||||
size = buffer_size(buffer);
|
|
||||||
loop = buffer_stringify_loop(buffer, pos, size);
|
|
||||||
|
|
||||||
for (;buffer_stringify_good(&loop);
|
|
||||||
buffer_stringify_next(&loop)){
|
|
||||||
end = loop.size + loop.absolute_pos;
|
|
||||||
data = loop.data - loop.absolute_pos;
|
|
||||||
for (;pos < end; ++pos){
|
|
||||||
if (!is_whitespace(data[pos])) goto buffer_seek_whitespace_down_mid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_seek_whitespace_down_mid:
|
|
||||||
no_hard = 0;
|
|
||||||
prev_endline = -1;
|
|
||||||
for (;buffer_stringify_good(&loop);
|
|
||||||
buffer_stringify_next(&loop)){
|
|
||||||
end = loop.size + loop.absolute_pos;
|
|
||||||
data = loop.data - loop.absolute_pos;
|
|
||||||
for (; pos < end; ++pos){
|
|
||||||
if (data[pos] == '\n'){
|
|
||||||
if (no_hard) goto buffer_seek_whitespace_down_end;
|
|
||||||
else{
|
|
||||||
no_hard = 1;
|
|
||||||
prev_endline = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!is_whitespace(data[pos])){
|
|
||||||
no_hard = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_seek_whitespace_down_end:
|
|
||||||
if (prev_endline == -1 || prev_endline+1 >= size) pos = size;
|
|
||||||
else pos = prev_endline+1;
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech int
|
|
||||||
buffer_seek_whitespace_up(Buffer_Type *buffer, int pos){
|
|
||||||
Buffer_Backify_Type loop;
|
|
||||||
char *data;
|
|
||||||
int end;
|
|
||||||
int size;
|
|
||||||
int no_hard;
|
|
||||||
|
|
||||||
size = buffer_size(buffer);
|
|
||||||
loop = buffer_backify_loop(buffer, pos-1, 1);
|
|
||||||
|
|
||||||
for (;buffer_backify_good(&loop);
|
|
||||||
buffer_backify_next(&loop)){
|
|
||||||
end = loop.absolute_pos;
|
|
||||||
data = loop.data - loop.absolute_pos;
|
|
||||||
for (;pos >= end; --pos){
|
|
||||||
if (!is_whitespace(data[pos])) goto buffer_seek_whitespace_up_mid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_seek_whitespace_up_mid:
|
|
||||||
no_hard = 0;
|
|
||||||
for (;buffer_backify_good(&loop);
|
|
||||||
buffer_backify_next(&loop)){
|
|
||||||
end = loop.absolute_pos;
|
|
||||||
data = loop.data - loop.absolute_pos;
|
|
||||||
for (; pos >= end; --pos){
|
|
||||||
if (data[pos] == '\n'){
|
|
||||||
if (no_hard) goto buffer_seek_whitespace_up_end;
|
|
||||||
else no_hard = 1;
|
|
||||||
}
|
|
||||||
else if (!is_whitespace(data[pos])){
|
|
||||||
no_hard = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer_seek_whitespace_up_end:
|
|
||||||
if (pos != 0) ++pos;
|
|
||||||
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal_4tech int
|
internal_4tech int
|
||||||
buffer_seek_whitespace_right(Buffer_Type *buffer, int pos){
|
buffer_seek_whitespace_right(Buffer_Type *buffer, int pos){
|
||||||
Buffer_Stringify_Type loop;
|
Buffer_Stringify_Type loop;
|
||||||
|
@ -945,6 +853,8 @@ buffer_get_line_index_range(Buffer_Type *buffer, int pos, int l_bound, int u_bou
|
||||||
|
|
||||||
lines = buffer->line_starts;
|
lines = buffer->line_starts;
|
||||||
|
|
||||||
|
assert_4tech(lines != 0);
|
||||||
|
|
||||||
start = l_bound;
|
start = l_bound;
|
||||||
end = u_bound;
|
end = u_bound;
|
||||||
for (;;){
|
for (;;){
|
||||||
|
@ -964,8 +874,7 @@ buffer_get_line_index_range(Buffer_Type *buffer, int pos, int l_bound, int u_bou
|
||||||
|
|
||||||
inline_4tech int
|
inline_4tech int
|
||||||
buffer_get_line_index(Buffer_Type *buffer, int pos){
|
buffer_get_line_index(Buffer_Type *buffer, int pos){
|
||||||
int result;
|
int result = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count);
|
||||||
result = buffer_get_line_index_range(buffer, pos, 0, buffer->line_count);
|
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1313,6 +1222,42 @@ buffer_get_start_cursor(Buffer_Type *buffer, float *wraps, float scroll_y,
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BRFlag_Special_Character (1 << 0)
|
||||||
|
|
||||||
|
typedef struct Buffer_Render_Item{
|
||||||
|
int index;
|
||||||
|
unsigned short glyphid;
|
||||||
|
unsigned short flags;
|
||||||
|
float x0, y0;
|
||||||
|
float x1, y1;
|
||||||
|
} Buffer_Render_Item;
|
||||||
|
|
||||||
|
inline_4tech void
|
||||||
|
write_render_item(Buffer_Render_Item *item,
|
||||||
|
int index,
|
||||||
|
unsigned short glyphid,
|
||||||
|
float x, float y,
|
||||||
|
float w, float h){
|
||||||
|
item->index = index;
|
||||||
|
item->glyphid = glyphid;
|
||||||
|
item->x0 = x;
|
||||||
|
item->y0 = y;
|
||||||
|
item->x1 = x + w;
|
||||||
|
item->y1 = y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline_4tech float
|
||||||
|
write_render_item_inline(Buffer_Render_Item *item,
|
||||||
|
int index,
|
||||||
|
unsigned short glyphid,
|
||||||
|
float x, float y,
|
||||||
|
float *advance_data, float h){
|
||||||
|
float ch_width;
|
||||||
|
ch_width = measure_character(advance_data, (char)glyphid);
|
||||||
|
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
||||||
|
return(ch_width);
|
||||||
|
}
|
||||||
|
|
||||||
internal_4tech void
|
internal_4tech void
|
||||||
buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max, int *count,
|
buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max, int *count,
|
||||||
float port_x, float port_y,
|
float port_x, float port_y,
|
||||||
|
@ -1324,6 +1269,7 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
||||||
|
|
||||||
Buffer_Stringify_Type loop;
|
Buffer_Stringify_Type loop;
|
||||||
Buffer_Render_Item *item;
|
Buffer_Render_Item *item;
|
||||||
|
Buffer_Render_Item *item_end;
|
||||||
char *data;
|
char *data;
|
||||||
int size, end;
|
int size, end;
|
||||||
float shift_x, shift_y;
|
float shift_x, shift_y;
|
||||||
|
@ -1343,10 +1289,15 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
||||||
y = shift_y;
|
y = shift_y;
|
||||||
item_i = 0;
|
item_i = 0;
|
||||||
item = items + item_i;
|
item = items + item_i;
|
||||||
|
item_end = items + max;
|
||||||
|
|
||||||
|
// TODO(allen): What's the plan for when there is not enough space to store
|
||||||
|
// more render items? It seems like we should be able to use the view_x
|
||||||
|
// to skip items that are not in view right? That way I think it would
|
||||||
|
// just always fit in the buffer.
|
||||||
if (advance_data){
|
if (advance_data){
|
||||||
for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size);
|
for (loop = buffer_stringify_loop(buffer, start_cursor.pos, size);
|
||||||
buffer_stringify_good(&loop);
|
buffer_stringify_good(&loop) && item < item_end;
|
||||||
buffer_stringify_next(&loop)){
|
buffer_stringify_next(&loop)){
|
||||||
|
|
||||||
end = loop.size + loop.absolute_pos;
|
end = loop.size + loop.absolute_pos;
|
||||||
|
@ -1364,6 +1315,7 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
||||||
|
|
||||||
switch (ch){
|
switch (ch){
|
||||||
case '\n':
|
case '\n':
|
||||||
|
if (item < item_end){
|
||||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||||
item->flags = 0;
|
item->flags = 0;
|
||||||
++item_i;
|
++item_i;
|
||||||
|
@ -1371,64 +1323,79 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
||||||
|
|
||||||
x = shift_x;
|
x = shift_x;
|
||||||
y += font_height;
|
y += font_height;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
|
if (item < item_end){
|
||||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||||
item->flags = BRFlag_Special_Character;
|
item->flags = BRFlag_Special_Character;
|
||||||
++item_i;
|
++item_i;
|
||||||
++item;
|
++item;
|
||||||
x += ch_width;
|
x += ch_width;
|
||||||
|
|
||||||
|
if (item < item_end){
|
||||||
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height);
|
ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, font_height);
|
||||||
item->flags = BRFlag_Special_Character;
|
item->flags = BRFlag_Special_Character;
|
||||||
++item_i;
|
++item_i;
|
||||||
++item;
|
++item;
|
||||||
x += ch_width;
|
x += ch_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\r':
|
case '\r':
|
||||||
|
if (item < item_end){
|
||||||
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||||
item->flags = BRFlag_Special_Character;
|
item->flags = BRFlag_Special_Character;
|
||||||
++item_i;
|
++item_i;
|
||||||
++item;
|
++item;
|
||||||
x += ch_width;
|
x += ch_width;
|
||||||
|
|
||||||
|
if (item < item_end){
|
||||||
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height);
|
ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, font_height);
|
||||||
item->flags = BRFlag_Special_Character;
|
item->flags = BRFlag_Special_Character;
|
||||||
++item_i;
|
++item_i;
|
||||||
++item;
|
++item;
|
||||||
x += ch_width;
|
x += ch_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\t':
|
case '\t':
|
||||||
if (opts.show_slash_t){
|
if (opts.show_slash_t){
|
||||||
|
if (item < item_end){
|
||||||
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, font_height);
|
||||||
item->flags = BRFlag_Special_Character;
|
item->flags = BRFlag_Special_Character;
|
||||||
++item_i;
|
++item_i;
|
||||||
++item;
|
++item;
|
||||||
|
if (item < item_end){
|
||||||
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height);
|
write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, font_height);
|
||||||
item->flags = BRFlag_Special_Character;
|
item->flags = BRFlag_Special_Character;
|
||||||
++item_i;
|
++item_i;
|
||||||
++item;
|
++item;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
|
if (item < item_end){
|
||||||
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
write_render_item_inline(item, i, ' ', x, y, advance_data, font_height);
|
||||||
item->flags = 0;
|
item->flags = 0;
|
||||||
++item_i;
|
++item_i;
|
||||||
++item;
|
++item;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
x += ch_width;
|
x += ch_width;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (item < item_end){
|
||||||
write_render_item(item, i, ch, x, y, ch_width, font_height);
|
write_render_item(item, i, ch, x, y, ch_width, font_height);
|
||||||
item->flags = 0;
|
item->flags = 0;
|
||||||
++item_i;
|
++item_i;
|
||||||
++item;
|
++item;
|
||||||
x += ch_width;
|
x += ch_width;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (y > height + shift_y) goto buffer_get_render_data_end;
|
if (y > height + shift_y) goto buffer_get_render_data_end;
|
||||||
|
@ -1437,6 +1404,7 @@ buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max,
|
||||||
|
|
||||||
buffer_get_render_data_end:
|
buffer_get_render_data_end:
|
||||||
if (y <= height + shift_y || item == items){
|
if (y <= height + shift_y || item == items){
|
||||||
|
if (item < item_end){
|
||||||
ch = 0;
|
ch = 0;
|
||||||
ch_width = measure_character(advance_data, ' ');
|
ch_width = measure_character(advance_data, ' ');
|
||||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||||
|
@ -1445,7 +1413,9 @@ buffer_get_render_data_end:
|
||||||
x += ch_width;
|
x += ch_width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else{
|
else{
|
||||||
|
if (item < item_end){
|
||||||
ch = 0;
|
ch = 0;
|
||||||
ch_width = 0;
|
ch_width = 0;
|
||||||
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
write_render_item(item, size, ch, x, y, ch_width, font_height);
|
||||||
|
@ -1453,6 +1423,7 @@ buffer_get_render_data_end:
|
||||||
++item;
|
++item;
|
||||||
x += ch_width;
|
x += ch_width;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(allen): handle this with a control state
|
// TODO(allen): handle this with a control state
|
||||||
assert_4tech(item_i <= max);
|
assert_4tech(item_i <= max);
|
||||||
|
|
|
@ -88,36 +88,6 @@ typedef struct Buffer_Batch_State{
|
||||||
int shift_total;
|
int shift_total;
|
||||||
} Buffer_Batch_State;
|
} Buffer_Batch_State;
|
||||||
|
|
||||||
#define BRFlag_Special_Character (1 << 0)
|
|
||||||
|
|
||||||
typedef struct Buffer_Render_Item{
|
|
||||||
int index;
|
|
||||||
unsigned short glyphid;
|
|
||||||
unsigned short flags;
|
|
||||||
float x0, y0;
|
|
||||||
float x1, y1;
|
|
||||||
} Buffer_Render_Item;
|
|
||||||
|
|
||||||
inline_4tech void
|
|
||||||
write_render_item(Buffer_Render_Item *item, int index, unsigned short glyphid,
|
|
||||||
float x, float y, float w, float h){
|
|
||||||
item->index = index;
|
|
||||||
item->glyphid = glyphid;
|
|
||||||
item->x0 = x;
|
|
||||||
item->y0 = y;
|
|
||||||
item->x1 = x + w;
|
|
||||||
item->y1 = y + h;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline_4tech float
|
|
||||||
write_render_item_inline(Buffer_Render_Item *item, int index, unsigned short glyphid,
|
|
||||||
float x, float y, float *advance_data, float h){
|
|
||||||
float ch_width;
|
|
||||||
ch_width = measure_character(advance_data, (char)glyphid);
|
|
||||||
write_render_item(item, index, glyphid, x, y, ch_width, h);
|
|
||||||
return(ch_width);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline_4tech Full_Cursor
|
inline_4tech Full_Cursor
|
||||||
make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){
|
make_cursor_hint(int line_index, int *starts, float *wrap_ys, float font_height){
|
||||||
Full_Cursor hint;
|
Full_Cursor hint;
|
||||||
|
|
|
@ -21,8 +21,8 @@ if %ERRORLEVEL% neq 0 (set FirstError=1)
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd ..\build
|
pushd ..\build
|
||||||
call "..\code\buildsuper.bat" ..\code\4coder_default_bindings.cpp
|
REM call "..\code\buildsuper.bat" ..\code\4coder_default_bindings.cpp
|
||||||
REM call "..\code\buildsuper.bat" ..\code\power\4coder_experiments.cpp
|
call "..\code\buildsuper.bat" ..\code\power\4coder_experiments.cpp
|
||||||
REM call "..\code\buildsuper.bat" ..\code\power\4coder_casey.cpp
|
REM call "..\code\buildsuper.bat" ..\code\power\4coder_casey.cpp
|
||||||
if %ERRORLEVEL% neq 0 (set FirstError=1)
|
if %ERRORLEVEL% neq 0 (set FirstError=1)
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ SET OPTS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd
|
||||||
SET OPTS=%OPTS% /GR- /nologo
|
SET OPTS=%OPTS% /GR- /nologo
|
||||||
SET DEBUG=/Zi
|
SET DEBUG=/Zi
|
||||||
set BUILD_DLL=/LD /link /INCREMENTAL:NO /OPT:REF
|
set BUILD_DLL=/LD /link /INCREMENTAL:NO /OPT:REF
|
||||||
SET EXPORTS=/EXPORT:view_routine /EXPORT:get_bindings /EXPORT:get_alpha_4coder_version
|
SET EXPORTS=/EXPORT:get_bindings /EXPORT:get_alpha_4coder_version
|
||||||
|
|
||||||
REM SET LINKS=user32.lib gdi32.lib
|
REM SET LINKS=user32.lib gdi32.lib
|
||||||
SET LINKS=
|
SET LINKS=
|
||||||
|
|
|
@ -18,14 +18,12 @@ Buffer_Summary Get_Buffer_First(Application_Links *app)
|
||||||
void Get_Buffer_Next(Application_Links *app, Buffer_Summary *buffer)
|
void Get_Buffer_Next(Application_Links *app, Buffer_Summary *buffer)
|
||||||
|
|
||||||
Buffer_Summary Get_Buffer(Application_Links *app, int index)
|
Buffer_Summary Get_Buffer(Application_Links *app, int index)
|
||||||
Buffer_Summary Get_Active_Buffer(Application_Links *app)
|
|
||||||
Buffer_Summary Get_Parameter_Buffer(Application_Links *app, int param_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_By_Name(Application_Links *app, char *filename, int len)
|
||||||
|
|
||||||
// TODO(allen): Need more flexible seek system somehow. Regex? Just expose the text stream to the user?
|
//int Buffer_Seek_Delimiter(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
|
||||||
int Buffer_Seek_Delimiter(Application_Links *app, Buffer_Summary *buffer, int start, char delim, int seek_forward, int *out)
|
//int Buffer_Seek_String(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
||||||
int Buffer_Seek_String(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
//int Buffer_Seek_String_Insensitive(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
||||||
int Buffer_Seek_String_Insensitive(Application_Links *app, Buffer_Summary *buffer, int start, char *str, int len, int seek_forward, int *out)
|
|
||||||
|
|
||||||
int Refresh_Buffer(Application_Links *app, Buffer_Summary *buffer)
|
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_Read_Range(Application_Links *app, Buffer_Summary *buffer, int start, int end, char *out)
|
||||||
|
|
1186
linux_4ed.cpp
1186
linux_4ed.cpp
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
struct Custom_Vars{
|
||||||
|
int initialized;
|
||||||
|
Partition part;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum View_Mode{
|
||||||
|
ViewMode_File,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct View_Vars{
|
||||||
|
int id;
|
||||||
|
View_Mode mode;
|
||||||
|
|
||||||
|
GUI_Scroll_Vars scroll;
|
||||||
|
i32_Rect scroll_region;
|
||||||
|
|
||||||
|
int buffer_id;
|
||||||
|
};
|
||||||
|
inline View_Vars
|
||||||
|
view_vars_zero(){
|
||||||
|
View_Vars vars = {0};
|
||||||
|
return(vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
view_routine(Application_Links *app, int view_id){
|
||||||
|
Custom_Vars *vars = (Custom_Vars*)app->memory;
|
||||||
|
View_Vars view = {0};
|
||||||
|
view.id = view_id;
|
||||||
|
|
||||||
|
int show_scrollbar = 1;
|
||||||
|
|
||||||
|
if (!vars->initialized){
|
||||||
|
vars->initialized = 1;
|
||||||
|
vars->part = make_part(app->memory, app->memory_size);
|
||||||
|
push_struct(&vars->part, Custom_Vars);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
Event_Message message = {0};
|
||||||
|
message = app->get_event_message(app);
|
||||||
|
|
||||||
|
switch (message.type){
|
||||||
|
case EM_Open_View:
|
||||||
|
{
|
||||||
|
view = view_vars_zero();
|
||||||
|
view.id = view_id;
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case EM_Frame:
|
||||||
|
{
|
||||||
|
GUI_Functions *guifn = app->get_gui_functions(app);
|
||||||
|
GUI *gui = app->get_gui(app, view_id);
|
||||||
|
|
||||||
|
guifn->begin(gui);
|
||||||
|
guifn->top_bar(gui);
|
||||||
|
|
||||||
|
switch (view.mode){
|
||||||
|
case ViewMode_File:
|
||||||
|
// TODO(allen): Overlapped widget
|
||||||
|
GUI_id scroll_id;
|
||||||
|
scroll_id.id[1] = view.mode;
|
||||||
|
scroll_id.id[0] = view.buffer_id;
|
||||||
|
|
||||||
|
guifn->get_scroll_vars(gui, scroll_id, &view.scroll,
|
||||||
|
&view.scroll_region);
|
||||||
|
guifn->begin_scrollable(gui, scroll_id, view.scroll,
|
||||||
|
144.f, show_scrollbar);
|
||||||
|
guifn->file(gui, view.buffer_id);
|
||||||
|
guifn->end_scrollable(gui);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
guifn->end(gui);
|
||||||
|
|
||||||
|
// TODO(allen): Put this code in charge of dispatching
|
||||||
|
// to the command or command coroutine or whatever.
|
||||||
|
|
||||||
|
// TODO(allen): Put this code in charge of when to process
|
||||||
|
// the GUI with input and retrieve new layout data.
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case EM_Close_View:
|
||||||
|
{}break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -104,13 +104,11 @@
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "../4coder_default_include.cpp"
|
#include "../4coder_default_include.cpp"
|
||||||
|
|
||||||
enum maps{
|
|
||||||
my_code_map
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef Assert
|
#ifndef Assert
|
||||||
#define internal static
|
#define internal static
|
||||||
#define Assert assert
|
#define Assert assert
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#define NO_BINDING
|
#define NO_BINDING
|
||||||
#include "../4coder_default_bindings.cpp"
|
#include "../4coder_default_bindings.cpp"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
CUSTOM_COMMAND_SIG(kill_rect){
|
CUSTOM_COMMAND_SIG(kill_rect){
|
||||||
View_Summary view = app->get_active_view(app);
|
View_Summary view = app->get_active_view(app);
|
||||||
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
Buffer_Summary buffer = app->get_buffer(app, view.buffer_id);
|
||||||
|
@ -25,102 +27,6 @@ CUSTOM_COMMAND_SIG(kill_rect){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(allen): This stream stuff will be moved to helper if it looks
|
|
||||||
// like it will be helpful. So if you want to use it to build your own
|
|
||||||
// commands I suggest you move it there first.
|
|
||||||
struct Stream_Chunk{
|
|
||||||
Application_Links *app;
|
|
||||||
Buffer_Summary *buffer;
|
|
||||||
|
|
||||||
char *base_data;
|
|
||||||
int start, end;
|
|
||||||
int data_size;
|
|
||||||
|
|
||||||
char *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
round_down(int x, int b){
|
|
||||||
int r = 0;
|
|
||||||
if (x >= 0){
|
|
||||||
r = x - (x % b);
|
|
||||||
}
|
|
||||||
return(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
round_up(int x, int b){
|
|
||||||
int r = 0;
|
|
||||||
if (x >= 0){
|
|
||||||
r = x - (x % b) + b;
|
|
||||||
}
|
|
||||||
return(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
init_stream_chunk(Stream_Chunk *chunk,
|
|
||||||
Application_Links *app, Buffer_Summary *buffer,
|
|
||||||
int pos, char *data, int size){
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
app->refresh_buffer(app, buffer);
|
|
||||||
if (pos >= 0 && pos < buffer->size && size > 0){
|
|
||||||
result = 1;
|
|
||||||
chunk->app = app;
|
|
||||||
chunk->buffer = buffer;
|
|
||||||
chunk->base_data = data;
|
|
||||||
chunk->data_size = size;
|
|
||||||
chunk->start = round_down(pos, size);
|
|
||||||
chunk->end = round_up(pos, size);
|
|
||||||
if (chunk->end > buffer->size){
|
|
||||||
chunk->end = buffer->size;
|
|
||||||
}
|
|
||||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
|
||||||
chunk->data = chunk->base_data - chunk->start;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
forward_stream_chunk(Stream_Chunk *chunk){
|
|
||||||
Application_Links *app = chunk->app;
|
|
||||||
Buffer_Summary *buffer = chunk->buffer;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
app->refresh_buffer(app, buffer);
|
|
||||||
if (chunk->end < buffer->size){
|
|
||||||
result = 1;
|
|
||||||
chunk->start = chunk->end;
|
|
||||||
chunk->end += chunk->data_size;
|
|
||||||
if (chunk->end > buffer->size){
|
|
||||||
chunk->end = buffer->size;
|
|
||||||
}
|
|
||||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
|
||||||
chunk->data = chunk->base_data - chunk->start;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
backward_stream_chunk(Stream_Chunk *chunk){
|
|
||||||
Application_Links *app = chunk->app;
|
|
||||||
Buffer_Summary *buffer = chunk->buffer;
|
|
||||||
int result = 0;
|
|
||||||
|
|
||||||
app->refresh_buffer(app, buffer);
|
|
||||||
if (chunk->start > 0){
|
|
||||||
result = 1;
|
|
||||||
chunk->end = chunk->start;
|
|
||||||
chunk->start -= chunk->data_size;
|
|
||||||
if (chunk->start < 0){
|
|
||||||
chunk->start = 0;
|
|
||||||
}
|
|
||||||
app->buffer_read_range(app, buffer, chunk->start, chunk->end, chunk->base_data);
|
|
||||||
chunk->data = chunk->base_data - chunk->start;
|
|
||||||
}
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(allen): Both of these brace related commands would work better
|
// TODO(allen): Both of these brace related commands would work better
|
||||||
// if the API exposed access to the tokens in a code file.
|
// if the API exposed access to the tokens in a code file.
|
||||||
CUSTOM_COMMAND_SIG(mark_matching_brace){
|
CUSTOM_COMMAND_SIG(mark_matching_brace){
|
||||||
|
@ -144,7 +50,8 @@ CUSTOM_COMMAND_SIG(mark_matching_brace){
|
||||||
int nesting_counter = 0;
|
int nesting_counter = 0;
|
||||||
char at_cursor = 0;
|
char at_cursor = 0;
|
||||||
|
|
||||||
if (init_stream_chunk(&chunk, app, &buffer, i, chunk_space, sizeof(chunk_space))){
|
if (init_stream_chunk(&chunk, app, &buffer, i,
|
||||||
|
chunk_space, sizeof(chunk_space))){
|
||||||
|
|
||||||
// NOTE(allen): This is important! The data array is a pointer that is adjusted
|
// NOTE(allen): This is important! The data array is a pointer that is adjusted
|
||||||
// so that indexing it with "i" will put it with the chunk that is actually loaded.
|
// so that indexing it with "i" will put it with the chunk that is actually loaded.
|
||||||
|
@ -377,10 +284,5 @@ get_bindings(void *data, int size){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
view_routine(Application_Links *app, int view_id){
|
|
||||||
app->get_user_input(app, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,6 +4,7 @@
|
||||||
#ifndef FCPP_NEW_LEXER_INC
|
#ifndef FCPP_NEW_LEXER_INC
|
||||||
#define FCPP_NEW_LEXER_INC
|
#define FCPP_NEW_LEXER_INC
|
||||||
|
|
||||||
|
#include "..\4cpp_lexer_types.h"
|
||||||
#include "4cpp_lexer_fsms.h"
|
#include "4cpp_lexer_fsms.h"
|
||||||
#include "4cpp_lexer_tables.c"
|
#include "4cpp_lexer_tables.c"
|
||||||
|
|
||||||
|
@ -286,22 +287,35 @@ cpp_attempt_token_merge(Cpp_Token prev_token, Cpp_Token next_token){
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
lexer_link void
|
lexer_link int
|
||||||
cpp_push_token_nonalloc(Cpp_Token *out_tokens, int *token_i, Cpp_Token token){
|
cpp_place_token_nonalloc(Cpp_Token *out_tokens, int token_i, Cpp_Token token){
|
||||||
Cpp_Token_Merge merge = {(Cpp_Token_Type)0};
|
Cpp_Token_Merge merge = {(Cpp_Token_Type)0};
|
||||||
Cpp_Token prev_token = {(Cpp_Token_Type)0};
|
Cpp_Token prev_token = {(Cpp_Token_Type)0};
|
||||||
|
|
||||||
if (*token_i > 0){
|
if (token_i > 0){
|
||||||
prev_token = out_tokens[*token_i - 1];
|
prev_token = out_tokens[token_i - 1];
|
||||||
merge = new_lex::cpp_attempt_token_merge(prev_token, token);
|
merge = new_lex::cpp_attempt_token_merge(prev_token, token);
|
||||||
if (merge.did_merge){
|
if (merge.did_merge){
|
||||||
out_tokens[*token_i - 1] = merge.new_token;
|
out_tokens[token_i - 1] = merge.new_token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!merge.did_merge){
|
if (!merge.did_merge){
|
||||||
out_tokens[(*token_i)++] = token;
|
out_tokens[token_i++] = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return(token_i);
|
||||||
|
}
|
||||||
|
|
||||||
|
lexer_link bool
|
||||||
|
cpp_push_token_nonalloc(Cpp_Token_Stack *out_tokens, Cpp_Token token){
|
||||||
|
bool result = 0;
|
||||||
|
if (out_tokens->count == out_tokens->max_count){
|
||||||
|
out_tokens->count =
|
||||||
|
cpp_place_token_nonalloc(out_tokens->tokens, out_tokens->count, token);
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Lex_Data{
|
struct Lex_Data{
|
||||||
|
@ -311,15 +325,13 @@ struct Lex_Data{
|
||||||
|
|
||||||
int pos;
|
int pos;
|
||||||
int pos_overide;
|
int pos_overide;
|
||||||
|
int chunk_pos;
|
||||||
|
|
||||||
Lex_FSM fsm;
|
Lex_FSM fsm;
|
||||||
Whitespace_FSM wfsm;
|
Whitespace_FSM wfsm;
|
||||||
unsigned char pp_state;
|
unsigned char pp_state;
|
||||||
unsigned char completed;
|
unsigned char completed;
|
||||||
|
|
||||||
unsigned short *key_eq_classes;
|
|
||||||
unsigned char *key_table;
|
|
||||||
|
|
||||||
Cpp_Token token;
|
Cpp_Token token;
|
||||||
|
|
||||||
int __pc__;
|
int __pc__;
|
||||||
|
@ -335,6 +347,13 @@ struct Lex_Data{
|
||||||
token_stack_out->count = token_i;\
|
token_stack_out->count = token_i;\
|
||||||
*S_ptr = S; S_ptr->__pc__ = -1; return(n); }
|
*S_ptr = S; S_ptr->__pc__ = -1; return(n); }
|
||||||
|
|
||||||
|
enum Lex_Result{
|
||||||
|
LexFinished,
|
||||||
|
LexNeedChunk,
|
||||||
|
LexNeedTokenMemory,
|
||||||
|
LexHitTokenLimit
|
||||||
|
};
|
||||||
|
|
||||||
lexer_link int
|
lexer_link int
|
||||||
cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_stack_out){
|
cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_stack_out){
|
||||||
Lex_Data S = *S_ptr;
|
Lex_Data S = *S_ptr;
|
||||||
|
@ -347,8 +366,8 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
|
|
||||||
char c = 0;
|
char c = 0;
|
||||||
|
|
||||||
int end_pos = size + S.pos;
|
int end_pos = size + S.chunk_pos;
|
||||||
chunk -= S.pos;
|
chunk -= S.chunk_pos;
|
||||||
|
|
||||||
switch (S.__pc__){
|
switch (S.__pc__){
|
||||||
DrCase(1);
|
DrCase(1);
|
||||||
|
@ -357,7 +376,6 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
DrCase(4);
|
DrCase(4);
|
||||||
DrCase(5);
|
DrCase(5);
|
||||||
DrCase(6);
|
DrCase(6);
|
||||||
DrCase(7);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;){
|
for (;;){
|
||||||
|
@ -372,7 +390,8 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
S.wfsm.white_done = (S.wfsm.pp_state >= LSPP_count);
|
S.wfsm.white_done = (S.wfsm.pp_state >= LSPP_count);
|
||||||
|
|
||||||
if (S.wfsm.white_done == 0){
|
if (S.wfsm.white_done == 0){
|
||||||
DrYield(4, 1);
|
S.chunk_pos += size;
|
||||||
|
DrYield(4, LexNeedChunk);
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
@ -400,7 +419,8 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
S.fsm.emit_token = (S.fsm.state >= LS_count);
|
S.fsm.emit_token = (S.fsm.state >= LS_count);
|
||||||
|
|
||||||
if (S.fsm.emit_token == 0){
|
if (S.fsm.emit_token == 0){
|
||||||
DrYield(3, 1);
|
S.chunk_pos += size;
|
||||||
|
DrYield(3, LexNeedChunk);
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
@ -463,7 +483,8 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S.wfsm.white_done == 0){
|
if (S.wfsm.white_done == 0){
|
||||||
DrYield(1, 1);
|
S.chunk_pos += size;
|
||||||
|
DrYield(1, LexNeedChunk);
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
@ -485,42 +506,6 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
|
|
||||||
case LS_identifier:
|
case LS_identifier:
|
||||||
{
|
{
|
||||||
S.fsm.state = 0;
|
|
||||||
S.fsm.emit_token = 0;
|
|
||||||
S.fsm.sub_machine = 0;
|
|
||||||
--S.pos;
|
|
||||||
for (;;){
|
|
||||||
// TODO(allen): Need to drop down to the instructions to optimize
|
|
||||||
// this correctly I think. This looks like it will have more branches
|
|
||||||
// than it needs unless I am very careful.
|
|
||||||
for (; S.fsm.state < LSKEY_totally_finished && S.pos < end_pos;){
|
|
||||||
// TODO(allen): Rebase these super tables so that we don't have
|
|
||||||
// to do a subtract on the state.
|
|
||||||
S.key_table = key_tables[S.fsm.sub_machine];
|
|
||||||
S.key_eq_classes = key_eq_class_tables[S.fsm.sub_machine];
|
|
||||||
for (; S.fsm.state < LSKEY_table_transition && S.pos < end_pos;){
|
|
||||||
c = chunk[S.pos++];
|
|
||||||
S.fsm.state = S.key_table[S.fsm.state + S.key_eq_classes[c]];
|
|
||||||
}
|
|
||||||
if (S.fsm.state >= LSKEY_table_transition && S.fsm.state < LSKEY_totally_finished){
|
|
||||||
S.fsm.sub_machine = S.fsm.state - LSKEY_table_transition;
|
|
||||||
S.fsm.state = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
S.fsm.emit_token = (S.fsm.int_state >= LSKEY_totally_finished);
|
|
||||||
|
|
||||||
if (S.fsm.emit_token == 0){
|
|
||||||
DrYield(7, 1);
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
--S.pos;
|
|
||||||
|
|
||||||
// TODO(allen): do stuff regarding the actual type of the token
|
|
||||||
S.token.type = CPP_TOKEN_INTEGER_CONSTANT;
|
|
||||||
S.token.flags = 0;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
--S.pos;
|
--S.pos;
|
||||||
|
|
||||||
int word_size = S.pos - S.token_start;
|
int word_size = S.pos - S.token_start;
|
||||||
|
@ -553,8 +538,6 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
S.token.flags = 0;
|
S.token.flags = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case LS_pound:
|
case LS_pound:
|
||||||
|
@ -580,7 +563,8 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
S.fsm.emit_token = (S.fsm.int_state >= LSDIR_count);
|
S.fsm.emit_token = (S.fsm.int_state >= LSDIR_count);
|
||||||
|
|
||||||
if (S.fsm.emit_token == 0){
|
if (S.fsm.emit_token == 0){
|
||||||
DrYield(6, 1);
|
S.chunk_pos += size;
|
||||||
|
DrYield(6, LexNeedChunk);
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
@ -611,7 +595,8 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
S.fsm.emit_token = (S.fsm.int_state >= LSINT_count);
|
S.fsm.emit_token = (S.fsm.int_state >= LSINT_count);
|
||||||
|
|
||||||
if (S.fsm.emit_token == 0){
|
if (S.fsm.emit_token == 0){
|
||||||
DrYield(5, 1);
|
S.chunk_pos += size;
|
||||||
|
DrYield(5, LexNeedChunk);
|
||||||
}
|
}
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
@ -944,9 +929,9 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
}
|
}
|
||||||
S.token.state_flags = S.pp_state;
|
S.token.state_flags = S.pp_state;
|
||||||
|
|
||||||
cpp_push_token_nonalloc(out_tokens, &token_i, S.token);
|
token_i = cpp_place_token_nonalloc(out_tokens, token_i, S.token);
|
||||||
if (token_i == max_token_i){
|
if (token_i == max_token_i){
|
||||||
DrYield(2, 2);
|
DrYield(2, LexNeedTokenMemory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -957,13 +942,199 @@ cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size, Cpp_Token_Stack *token_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrReturn(0);
|
DrReturn(LexFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef DrYield
|
#undef DrYield
|
||||||
#undef DrReturn
|
#undef DrReturn
|
||||||
#undef DrCase
|
#undef DrCase
|
||||||
|
|
||||||
|
lexer_link int
|
||||||
|
cpp_lex_nonalloc(Lex_Data *S_ptr, char *chunk, int size,
|
||||||
|
Cpp_Token_Stack *token_stack_out, int max_tokens){
|
||||||
|
Cpp_Token_Stack temp_stack = *token_stack_out;
|
||||||
|
if (temp_stack.max_count > temp_stack.count + max_tokens){
|
||||||
|
temp_stack.max_count = temp_stack.count + max_tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = cpp_lex_nonalloc(S_ptr, chunk, size, &temp_stack);
|
||||||
|
|
||||||
|
token_stack_out->count = temp_stack.count;
|
||||||
|
|
||||||
|
if (result == LexNeedTokenMemory){
|
||||||
|
if (token_stack_out->count < token_stack_out->max_count){
|
||||||
|
result = LexHitTokenLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
lexer_link int
|
||||||
|
cpp_lex_size_nonalloc(Lex_Data *S_ptr, char *chunk, int size, int full_size,
|
||||||
|
Cpp_Token_Stack *token_stack_out){
|
||||||
|
int result = 0;
|
||||||
|
if (S_ptr->pos >= full_size){
|
||||||
|
char end_null = 0;
|
||||||
|
result = cpp_lex_nonalloc(S_ptr, &end_null, 1, token_stack_out);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result = cpp_lex_nonalloc(S_ptr, chunk, size, token_stack_out);
|
||||||
|
if (result == LexNeedChunk){
|
||||||
|
if (S_ptr->pos >= full_size){
|
||||||
|
char end_null = 0;
|
||||||
|
result = cpp_lex_nonalloc(S_ptr, &end_null, 1, token_stack_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
lexer_link int
|
||||||
|
cpp_lex_size_nonalloc(Lex_Data *S_ptr, char *chunk, int size, int full_size,
|
||||||
|
Cpp_Token_Stack *token_stack_out, int max_tokens){
|
||||||
|
Cpp_Token_Stack temp_stack = *token_stack_out;
|
||||||
|
if (temp_stack.max_count > temp_stack.count + max_tokens){
|
||||||
|
temp_stack.max_count = temp_stack.count + max_tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = cpp_lex_size_nonalloc(S_ptr, chunk, size, full_size,
|
||||||
|
&temp_stack);
|
||||||
|
|
||||||
|
token_stack_out->count = temp_stack.count;
|
||||||
|
|
||||||
|
if (result == LexNeedTokenMemory){
|
||||||
|
if (token_stack_out->count < token_stack_out->max_count){
|
||||||
|
result = LexHitTokenLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
lexer_link Cpp_Relex_State
|
||||||
|
cpp_relex_nonalloc_start(Cpp_File file, Cpp_Token_Stack *stack,
|
||||||
|
int start, int end, int amount, int tolerance){
|
||||||
|
Cpp_Relex_State state;
|
||||||
|
state.file = file;
|
||||||
|
state.stack = stack;
|
||||||
|
state.start = start;
|
||||||
|
state.end = end;
|
||||||
|
state.amount = amount;
|
||||||
|
state.tolerance = tolerance;
|
||||||
|
|
||||||
|
Cpp_Get_Token_Result result = new_lex::cpp_get_token(stack, start);
|
||||||
|
if (result.token_index <= 0){
|
||||||
|
state.start_token_i = 0;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
state.start_token_i = result.token_index-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = new_lex::cpp_get_token(stack, end);
|
||||||
|
if (result.token_index < 0) result.token_index = 0;
|
||||||
|
else if (end > stack->tokens[result.token_index].start) ++result.token_index;
|
||||||
|
state.end_token_i = result.token_index;
|
||||||
|
|
||||||
|
state.relex_start = stack->tokens[state.start_token_i].start;
|
||||||
|
if (start < state.relex_start) state.relex_start = start;
|
||||||
|
|
||||||
|
state.space_request = state.end_token_i - state.start_token_i + tolerance + 1;
|
||||||
|
|
||||||
|
return(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(allen): Eliminate this once we actually store the EOF token
|
||||||
|
// in the token stack.
|
||||||
|
inline Cpp_Token
|
||||||
|
cpp__get_token(Cpp_Token_Stack *stack, Cpp_Token *tokens, int size, int index){
|
||||||
|
Cpp_Token result;
|
||||||
|
if (index < stack->count){
|
||||||
|
result = tokens[index];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
result.start = size;
|
||||||
|
result.size = 0;
|
||||||
|
result.type = CPP_TOKEN_EOF;
|
||||||
|
result.flags = 0;
|
||||||
|
result.state_flags = 0;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FCPP_LINK bool
|
||||||
|
cpp_relex_nonalloc_main(Cpp_Relex_State *state, Cpp_Token_Stack *relex_stack, int *relex_end){
|
||||||
|
Cpp_Token_Stack *stack = state->stack;
|
||||||
|
Cpp_Token *tokens = stack->tokens;
|
||||||
|
|
||||||
|
new_lex::cpp_shift_token_starts(stack, state->end_token_i, state->amount);
|
||||||
|
|
||||||
|
Lex_Data lex = {};
|
||||||
|
lex.pp_state = cpp_token_get_pp_state(tokens[state->start_token_i].state_flags);
|
||||||
|
lex.pos = state->relex_start;
|
||||||
|
|
||||||
|
int relex_end_i = state->end_token_i;
|
||||||
|
Cpp_Token match_token = cpp__get_token(stack, tokens, state->file.size, relex_end_i);
|
||||||
|
Cpp_Token end_token = match_token;
|
||||||
|
bool went_too_far = 0;
|
||||||
|
|
||||||
|
for (;;){
|
||||||
|
Cpp_Read_Result read = cpp_lex_step(state->file, &lex);
|
||||||
|
if (read.has_result){
|
||||||
|
if (read.token.start == end_token.start &&
|
||||||
|
read.token.size == end_token.size &&
|
||||||
|
read.token.flags == end_token.flags &&
|
||||||
|
read.token.state_flags == end_token.state_flags){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cpp_push_token_nonalloc(relex_stack, read.token);
|
||||||
|
|
||||||
|
while (lex.pos > end_token.start && relex_end_i < stack->count){
|
||||||
|
++relex_end_i;
|
||||||
|
end_token = cpp__get_token(stack, tokens, state->file.size, relex_end_i);
|
||||||
|
}
|
||||||
|
if (relex_stack->count == relex_stack->max_count){
|
||||||
|
went_too_far = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lex.pos >= state->file.size) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!went_too_far){
|
||||||
|
if (relex_stack->count > 0){
|
||||||
|
if (state->start_token_i > 0){
|
||||||
|
Cpp_Token_Merge merge =
|
||||||
|
cpp_attempt_token_merge(tokens[state->start_token_i - 1],
|
||||||
|
relex_stack->tokens[0]);
|
||||||
|
if (merge.did_merge){
|
||||||
|
--state->start_token_i;
|
||||||
|
relex_stack->tokens[0] = merge.new_token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relex_end_i < state->stack->count){
|
||||||
|
Cpp_Token_Merge merge =
|
||||||
|
cpp_attempt_token_merge(relex_stack->tokens[relex_stack->count-1],
|
||||||
|
tokens[relex_end_i]);
|
||||||
|
if (merge.did_merge){
|
||||||
|
++relex_end_i;
|
||||||
|
relex_stack->tokens[relex_stack->count-1] = merge.new_token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*relex_end = relex_end_i;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
cpp_shift_token_starts(stack, state->end_token_i, -state->amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
return went_too_far;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO(allen): In what corner cases, such as invalid files
|
||||||
|
// does the new lexer suffer???
|
||||||
|
|
||||||
// TOP
|
// TOP
|
||||||
|
|
||||||
#include "../4ed_meta.h"
|
#include "../4ed_meta.h"
|
||||||
|
@ -204,7 +207,8 @@ end_t(Times *t){
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_experiment(Experiment *exp, char *filename, int verbose, int chunks){
|
run_experiment(Experiment *exp, char *filename, int verbose,
|
||||||
|
int chunks, int max_tokens){
|
||||||
String extension = {};
|
String extension = {};
|
||||||
Data file_data;
|
Data file_data;
|
||||||
Cpp_File file_cpp;
|
Cpp_File file_cpp;
|
||||||
|
@ -224,8 +228,8 @@ run_experiment(Experiment *exp, char *filename, int verbose, int chunks){
|
||||||
exp->correct_stack.count = 0;
|
exp->correct_stack.count = 0;
|
||||||
exp->testing_stack.count = 0;
|
exp->testing_stack.count = 0;
|
||||||
|
|
||||||
memset(exp->correct_stack.tokens, TOKEN_ARRAY_SIZE, 0);
|
memset(exp->correct_stack.tokens, 0, TOKEN_ARRAY_SIZE);
|
||||||
memset(exp->testing_stack.tokens, TOKEN_ARRAY_SIZE, 0);
|
memset(exp->testing_stack.tokens, 0, TOKEN_ARRAY_SIZE);
|
||||||
|
|
||||||
file_cpp.data = (char*)file_data.data;
|
file_cpp.data = (char*)file_data.data;
|
||||||
file_cpp.size = file_data.size;
|
file_cpp.size = file_data.size;
|
||||||
|
@ -239,8 +243,9 @@ run_experiment(Experiment *exp, char *filename, int verbose, int chunks){
|
||||||
cpp_lex_file_nonalloc(file_cpp, &exp->correct_stack, lex_data);
|
cpp_lex_file_nonalloc(file_cpp, &exp->correct_stack, lex_data);
|
||||||
time.handcoded += (__rdtsc() - start);
|
time.handcoded += (__rdtsc() - start);
|
||||||
|
|
||||||
start = __rdtsc();
|
if (max_tokens == 0){
|
||||||
if (chunks){
|
if (chunks){
|
||||||
|
start = __rdtsc();
|
||||||
int relevant_size = file_data.size + 1;
|
int relevant_size = file_data.size + 1;
|
||||||
is_last = 0;
|
is_last = 0;
|
||||||
for (k = 0; k < relevant_size; k += chunks){
|
for (k = 0; k < relevant_size; k += chunks){
|
||||||
|
@ -250,15 +255,75 @@ run_experiment(Experiment *exp, char *filename, int verbose, int chunks){
|
||||||
is_last = 1;
|
is_last = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = new_lex::cpp_lex_nonalloc(&ld, (char*)file_data.data + k, chunk_size, &exp->testing_stack);
|
int result =
|
||||||
if (result == 0 || result == 2) break;
|
new_lex::cpp_lex_nonalloc(&ld,
|
||||||
|
(char*)file_data.data + k, chunk_size,
|
||||||
|
&exp->testing_stack);
|
||||||
|
|
||||||
|
if (result == new_lex::LexFinished ||
|
||||||
|
result == new_lex::LexNeedTokenMemory) break;
|
||||||
|
}
|
||||||
|
time.fsm += (__rdtsc() - start);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
start = __rdtsc();
|
||||||
|
new_lex::cpp_lex_nonalloc(&ld,
|
||||||
|
(char*)file_data.data, file_data.size,
|
||||||
|
&exp->testing_stack);
|
||||||
|
time.fsm += (__rdtsc() - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
new_lex::cpp_lex_nonalloc(&ld, (char*)file_data.data, file_data.size, &exp->testing_stack);
|
if (chunks){
|
||||||
|
start = __rdtsc();
|
||||||
|
int relevant_size = file_data.size + 1;
|
||||||
|
is_last = 0;
|
||||||
|
for (k = 0; k < relevant_size; k += chunks){
|
||||||
|
chunk_size = chunks;
|
||||||
|
if (chunk_size + k >= relevant_size){
|
||||||
|
chunk_size = relevant_size - k;
|
||||||
|
is_last = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = 0;
|
||||||
|
int still_lexing = 1;
|
||||||
|
do{
|
||||||
|
result =
|
||||||
|
new_lex::cpp_lex_size_nonalloc(&ld,
|
||||||
|
(char*)file_data.data + k, chunk_size, file_data.size,
|
||||||
|
&exp->testing_stack,
|
||||||
|
max_tokens);
|
||||||
|
if (result == new_lex::LexFinished ||
|
||||||
|
result == new_lex::LexNeedTokenMemory ||
|
||||||
|
result == new_lex::LexNeedChunk){
|
||||||
|
still_lexing = 0;
|
||||||
|
}
|
||||||
|
} while(still_lexing);
|
||||||
|
|
||||||
|
|
||||||
|
if (result == new_lex::LexFinished ||
|
||||||
|
result == new_lex::LexNeedTokenMemory) break;
|
||||||
}
|
}
|
||||||
time.fsm += (__rdtsc() - start);
|
time.fsm += (__rdtsc() - start);
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
start = __rdtsc();
|
||||||
|
int still_lexing = 1;
|
||||||
|
do{
|
||||||
|
int result =
|
||||||
|
new_lex::cpp_lex_size_nonalloc(&ld,
|
||||||
|
(char*)file_data.data, file_data.size, file_data.size,
|
||||||
|
&exp->testing_stack,
|
||||||
|
max_tokens);
|
||||||
|
if (result == new_lex::LexFinished ||
|
||||||
|
result == new_lex::LexNeedTokenMemory){
|
||||||
|
still_lexing = 0;
|
||||||
|
}
|
||||||
|
} while(still_lexing);
|
||||||
|
time.fsm += (__rdtsc() - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(ld.tb);
|
free(ld.tb);
|
||||||
|
|
||||||
|
@ -338,11 +403,12 @@ show_time(Times t, int repeats, char *type){
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
int repeats = 1;
|
int repeats = 1;
|
||||||
int verbose_level = 1;
|
int verbose_level = 0;
|
||||||
int chunk_start = 0;
|
int chunk_start = 32;
|
||||||
int chunk_end = 0;
|
int chunk_end = 64;
|
||||||
#define TEST_FILE "parser_test1.cpp"
|
#define TEST_FILE "parser_test1.cpp"
|
||||||
#define SINGLE_ITEM 1
|
#define SINGLE_ITEM 0
|
||||||
|
int token_limit = 2;
|
||||||
|
|
||||||
int chunks = (chunk_start > 0 && chunk_start <= chunk_end);
|
int chunks = (chunk_start > 0 && chunk_start <= chunk_end);
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
@ -371,14 +437,14 @@ int main(){
|
||||||
begin_t(&chunk_exp_t);
|
begin_t(&chunk_exp_t);
|
||||||
printf("With chunks of %d\n", chunks);
|
printf("With chunks of %d\n", chunks);
|
||||||
for (c = chunk_start; c <= chunk_end; ++c){
|
for (c = chunk_start; c <= chunk_end; ++c){
|
||||||
run_experiment(&chunk_exp, BASE_DIR TEST_FILE, 1, c);
|
run_experiment(&chunk_exp, BASE_DIR TEST_FILE, 1, c, token_limit);
|
||||||
}
|
}
|
||||||
end_t(&chunk_exp_t);
|
end_t(&chunk_exp_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
begin_t(&exp_t);
|
begin_t(&exp_t);
|
||||||
printf("Unchunked\n");
|
printf("Unchunked\n");
|
||||||
run_experiment(&exp, BASE_DIR TEST_FILE, 1, 0);
|
run_experiment(&exp, BASE_DIR TEST_FILE, 1, 0, token_limit);
|
||||||
end_t(&exp_t);
|
end_t(&exp_t);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
@ -391,7 +457,7 @@ int main(){
|
||||||
if (chunks){
|
if (chunks){
|
||||||
begin_t(&chunk_exp_t);
|
begin_t(&chunk_exp_t);
|
||||||
for (c = chunk_start; c <= chunk_end; ++c){
|
for (c = chunk_start; c <= chunk_end; ++c){
|
||||||
run_experiment(&chunk_exp, all_files.infos[i].filename.str, verbose_level, c);
|
run_experiment(&chunk_exp, all_files.infos[i].filename.str, verbose_level, c, token_limit);
|
||||||
}
|
}
|
||||||
end_t(&chunk_exp_t);
|
end_t(&chunk_exp_t);
|
||||||
}
|
}
|
||||||
|
@ -399,11 +465,11 @@ int main(){
|
||||||
begin_t(&exp_t);
|
begin_t(&exp_t);
|
||||||
if (verbose_level == -1 && chunks){
|
if (verbose_level == -1 && chunks){
|
||||||
for (c = chunk_start; c <= chunk_end; ++c){
|
for (c = chunk_start; c <= chunk_end; ++c){
|
||||||
run_experiment(&exp, all_files.infos[i].filename.str, verbose_level, 0);
|
run_experiment(&exp, all_files.infos[i].filename.str, verbose_level, 0, token_limit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
run_experiment(&exp, all_files.infos[i].filename.str, verbose_level, 0);
|
run_experiment(&exp, all_files.infos[i].filename.str, verbose_level, 0, token_limit);
|
||||||
}
|
}
|
||||||
end_t(&exp_t);
|
end_t(&exp_t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -576,97 +576,6 @@ process_match_node(String_And_Flag *input, Match_Node *node, Match_Tree *tree, F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FSM_Stack
|
|
||||||
generate_keyword_fsms(){
|
|
||||||
Terminal_Lookup_Table terminal_table;
|
|
||||||
Cpp_Token_Type type;
|
|
||||||
|
|
||||||
Future_FSM_Stack unfinished_futures;
|
|
||||||
Match_Tree_Stack tree_stack;
|
|
||||||
FSM_Stack fsm_stack;
|
|
||||||
Match_Tree *tree;
|
|
||||||
FSM *fsm;
|
|
||||||
Future_FSM *future;
|
|
||||||
Match_Node *root_node;
|
|
||||||
FSM_State *root_state;
|
|
||||||
int i, j;
|
|
||||||
|
|
||||||
memset(terminal_table.type_to_state, 0, sizeof(terminal_table.type_to_state));
|
|
||||||
memset(terminal_table.state_to_type, 0, sizeof(terminal_table.state_to_type));
|
|
||||||
|
|
||||||
for (i = 0; i < ArrayCount(keyword_strings); ++i){
|
|
||||||
type = (Cpp_Token_Type)keyword_strings[i].flags;
|
|
||||||
if (terminal_table.type_to_state[type] == 0){
|
|
||||||
terminal_table.type_to_state[type] = terminal_table.state_count;
|
|
||||||
terminal_table.state_to_type[terminal_table.state_count] = type;
|
|
||||||
++terminal_table.state_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fsm_stack.max = 255;
|
|
||||||
fsm_stack.count = 0;
|
|
||||||
fsm_stack.fsms = (FSM*)malloc(sizeof(FSM)*fsm_stack.max);
|
|
||||||
fsm_stack.table_transition_state = 26;
|
|
||||||
|
|
||||||
tree_stack.max = 255;
|
|
||||||
tree_stack.count = 0;
|
|
||||||
tree_stack.trees = (Match_Tree*)malloc(sizeof(Match_Tree)*tree_stack.max);
|
|
||||||
|
|
||||||
unfinished_futures.max = 255;
|
|
||||||
unfinished_futures.count = 0;
|
|
||||||
unfinished_futures.futures = (Future_FSM*)malloc(sizeof(Future_FSM)*unfinished_futures.max);
|
|
||||||
|
|
||||||
fsm = get_fsm(&fsm_stack);
|
|
||||||
tree = get_tree(&tree_stack);
|
|
||||||
|
|
||||||
*fsm = fsm_init(200, fsm_stack.table_transition_state);
|
|
||||||
*tree = tree_init(200);
|
|
||||||
|
|
||||||
root_state = fsm_get_state(fsm, RealTerminateBase);
|
|
||||||
root_node = match_get_node(tree);
|
|
||||||
match_init_node(root_node, ArrayCount(keyword_strings));
|
|
||||||
for (i = 0; i < ArrayCount(keyword_strings); ++i){
|
|
||||||
root_node->words[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
root_node->count = ArrayCount(keyword_strings);
|
|
||||||
root_node->state = root_state;
|
|
||||||
root_node->index = -1;
|
|
||||||
|
|
||||||
push_future_fsm(&unfinished_futures, root_node);
|
|
||||||
process_match_node(keyword_strings, root_node, tree, fsm, &terminal_table, 2, &unfinished_futures);
|
|
||||||
|
|
||||||
for (i = 1; i < unfinished_futures.count; ++i){
|
|
||||||
future = unfinished_futures.futures + i;
|
|
||||||
|
|
||||||
fsm = get_fsm(&fsm_stack);
|
|
||||||
tree = get_tree(&tree_stack);
|
|
||||||
|
|
||||||
assert((int)(fsm - fsm_stack.fsms) == i);
|
|
||||||
|
|
||||||
*fsm = fsm_init(200, fsm_stack.table_transition_state);
|
|
||||||
*tree = tree_init(200);
|
|
||||||
|
|
||||||
root_state = fsm_get_state(fsm, RealTerminateBase);
|
|
||||||
root_node = match_get_node(tree);
|
|
||||||
match_copy_init_node(root_node, future->source);
|
|
||||||
root_node->state = root_state;
|
|
||||||
|
|
||||||
for (j = 0; j < root_node->count; ++j){
|
|
||||||
char space[1024];
|
|
||||||
sprintf(space, "%s\n", keyword_strings[root_node->words[j]].str);
|
|
||||||
fsm_add_comment(fsm, space);
|
|
||||||
}
|
|
||||||
|
|
||||||
process_match_node(keyword_strings, root_node, tree, fsm, &terminal_table, 12, &unfinished_futures);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(fsm_stack.count < 255);
|
|
||||||
fsm_stack.final_state = fsm_stack.table_transition_state + (unsigned char)fsm_stack.count;
|
|
||||||
|
|
||||||
return(fsm_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
Whitespace_FSM
|
Whitespace_FSM
|
||||||
whitespace_skip_fsm(Whitespace_FSM wfsm, char c){
|
whitespace_skip_fsm(Whitespace_FSM wfsm, char c){
|
||||||
if (wfsm.pp_state != LSPP_default){
|
if (wfsm.pp_state != LSPP_default){
|
||||||
|
@ -781,7 +690,6 @@ main_fsm(Lex_FSM fsm, unsigned char pp_state, unsigned char c){
|
||||||
case LS_default:
|
case LS_default:
|
||||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'){
|
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'){
|
||||||
fsm.state = LS_identifier;
|
fsm.state = LS_identifier;
|
||||||
fsm.emit_token = 1;
|
|
||||||
}
|
}
|
||||||
else if (c >= '1' && c <= '9'){
|
else if (c >= '1' && c <= '9'){
|
||||||
fsm.state = LS_number;
|
fsm.state = LS_number;
|
||||||
|
@ -849,13 +757,11 @@ main_fsm(Lex_FSM fsm, unsigned char pp_state, unsigned char c){
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if 0
|
|
||||||
case LS_identifier:
|
case LS_identifier:
|
||||||
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')){
|
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_')){
|
||||||
fsm.emit_token = 1;
|
fsm.emit_token = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
case LS_pound:
|
case LS_pound:
|
||||||
switch (c){
|
switch (c){
|
||||||
|
@ -1405,39 +1311,6 @@ main(){
|
||||||
render_variable(file, "unsigned char", "LSDIR_count", pp_directive_fsm.count);
|
render_variable(file, "unsigned char", "LSDIR_count", pp_directive_fsm.count);
|
||||||
render_variable(file, "unsigned char", "pp_directive_terminal_base", pp_directive_fsm.terminal_base);
|
render_variable(file, "unsigned char", "pp_directive_terminal_base", pp_directive_fsm.terminal_base);
|
||||||
|
|
||||||
FSM_Stack keyword_fsms = generate_keyword_fsms();
|
|
||||||
|
|
||||||
char name[1024];
|
|
||||||
for (int i = 0; i < keyword_fsms.count; ++i){
|
|
||||||
FSM_Tables partial_keywords_table =
|
|
||||||
generate_table_from_abstract_fsm(keyword_fsms.fsms[i], keyword_fsms.final_state);
|
|
||||||
if (keyword_fsms.fsms[i].comment){
|
|
||||||
render_comment(file, keyword_fsms.fsms[i].comment);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(name, "keyword_part_%d_table", i);
|
|
||||||
render_fsm_table(file, partial_keywords_table, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
begin_ptr_table(file, "short", "key_eq_class_tables");
|
|
||||||
for (int i = 0; i < keyword_fsms.count; ++i){
|
|
||||||
sprintf(name, "keyword_part_%d_table_eq_classes", i);
|
|
||||||
do_table_item_direct(file, name, "");
|
|
||||||
end_row(file);
|
|
||||||
}
|
|
||||||
end_table(file);
|
|
||||||
|
|
||||||
begin_ptr_table(file, "char", "key_tables");
|
|
||||||
for (int i = 0; i < keyword_fsms.count; ++i){
|
|
||||||
sprintf(name, "keyword_part_%d_table_table", i);
|
|
||||||
do_table_item_direct(file, name, "");
|
|
||||||
end_row(file);
|
|
||||||
}
|
|
||||||
end_table(file);
|
|
||||||
|
|
||||||
fprintf(file, "#define LSKEY_table_transition %d\n", (int)(keyword_fsms.table_transition_state));
|
|
||||||
fprintf(file, "#define LSKEY_totally_finished %d\n", (int)(keyword_fsms.final_state));
|
|
||||||
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
1423
win32_4ed.cpp
1423
win32_4ed.cpp
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Mr. 4th Dimention - Allen Webster
|
||||||
|
*
|
||||||
|
* 12.12.2014
|
||||||
|
*
|
||||||
|
* Win32 font rendering for nicer fonts
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TOP
|
||||||
|
|
||||||
|
internal i32
|
||||||
|
win32_draw_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_);
|
||||||
|
b32 translate_success = sysshared_to_binary_path(&filename, filename_untranslated);
|
||||||
|
if (!translate_success) return 0;
|
||||||
|
|
||||||
|
i32 result = 0;
|
||||||
|
|
||||||
|
AddFontResourceEx(filename.str, FR_PRIVATE, 0);
|
||||||
|
|
||||||
|
HFONT font_handle =
|
||||||
|
CreateFontA(pt_size, 0, 0, 0,
|
||||||
|
FW_NORMAL, // WEIGHT
|
||||||
|
FALSE, // ITALICS
|
||||||
|
FALSE, // UNDERLINE
|
||||||
|
FALSE, // STRIKE-OUT
|
||||||
|
ANSI_CHARSET,
|
||||||
|
OUT_DEFAULT_PRECIS,
|
||||||
|
CLIP_DEFAULT_PRECIS,
|
||||||
|
ANTIALIASED_QUALITY,
|
||||||
|
DEFAULT_PITCH|FF_DONTCARE,
|
||||||
|
filename.str);
|
||||||
|
|
||||||
|
if (font_handle){
|
||||||
|
HDC dc = CreateCompatibleDC(0);
|
||||||
|
|
||||||
|
if (dc){
|
||||||
|
// TODO(allen): Have to get metrics
|
||||||
|
|
||||||
|
result = 1;
|
||||||
|
|
||||||
|
if (store_texture){
|
||||||
|
i32 tex_width = pt_size*16*oversample;
|
||||||
|
i32 tex_height = pt_size*16*oversample;
|
||||||
|
|
||||||
|
HBITAMP bitmap = CreateCompatibleBitmap(dc, tex_width, tex_height);
|
||||||
|
|
||||||
|
// TODO(allen): pack each glyph into a texture
|
||||||
|
// and generate the equivalent data output by stb
|
||||||
|
// in the stbtt_packedchar array.
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteObject(font_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOTTOM
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue