Lots more organizational stuff: h/cpp separation for all cpp files, splitting stuff out of 4ed_view.cpp
parent
17704c6036
commit
f6ce7477c4
159
4ed.cpp
159
4ed.cpp
|
@ -191,50 +191,6 @@ global_const char messages[] =
|
|||
#define DEFAULT_DISPLAY_WIDTH 672
|
||||
#define DEFAULT_MINIMUM_BASE_DISPLAY_WIDTH 550
|
||||
|
||||
enum App_State{
|
||||
APP_STATE_EDIT,
|
||||
APP_STATE_RESIZING,
|
||||
// never below this
|
||||
APP_STATE_COUNT
|
||||
};
|
||||
|
||||
struct App_State_Resizing{
|
||||
Panel_Divider *divider;
|
||||
};
|
||||
|
||||
struct Command_Data{
|
||||
Models *models;
|
||||
struct App_Vars *vars;
|
||||
System_Functions *system;
|
||||
Live_Views *live_set;
|
||||
|
||||
i32 screen_width;
|
||||
i32 screen_height;
|
||||
|
||||
Key_Event_Data key;
|
||||
};
|
||||
|
||||
enum Input_Types{
|
||||
Input_AnyKey,
|
||||
Input_Esc,
|
||||
Input_MouseMove,
|
||||
Input_MouseLeftButton,
|
||||
Input_MouseRightButton,
|
||||
Input_MouseWheel,
|
||||
Input_Count
|
||||
};
|
||||
|
||||
struct Consumption_Record{
|
||||
b32 consumed;
|
||||
char consumer[32];
|
||||
};
|
||||
|
||||
struct Available_Input{
|
||||
Key_Input_Data *keys;
|
||||
Mouse_State *mouse;
|
||||
Consumption_Record records[Input_Count];
|
||||
};
|
||||
|
||||
internal Available_Input
|
||||
init_available_input(Key_Input_Data *keys, Mouse_State *mouse){
|
||||
Available_Input result = {0};
|
||||
|
@ -313,28 +269,6 @@ consume_input(Available_Input *available, i32 input_type, char *consumer){
|
|||
}
|
||||
}
|
||||
|
||||
struct App_Vars{
|
||||
Models models;
|
||||
|
||||
CLI_List cli_processes;
|
||||
|
||||
App_State state;
|
||||
App_State_Resizing resizing;
|
||||
|
||||
Command_Data command_data;
|
||||
|
||||
Available_Input available_input;
|
||||
};
|
||||
|
||||
enum Coroutine_Type{
|
||||
Co_View,
|
||||
Co_Command
|
||||
};
|
||||
struct App_Coroutine_State{
|
||||
void *co;
|
||||
i32 type;
|
||||
};
|
||||
|
||||
inline App_Coroutine_State
|
||||
get_state(Application_Links *app){
|
||||
App_Coroutine_State state = {0};
|
||||
|
@ -377,10 +311,11 @@ app_resume_coroutine(System_Functions *system, Application_Links *app, Coroutine
|
|||
}
|
||||
|
||||
inline void
|
||||
output_file_append(System_Functions *system, Models *models, Editing_File *file, String value, b32 cursor_at_end){
|
||||
output_file_append(System_Functions *system, Models *models, Editing_File *file, String value){
|
||||
if (!file->is_dummy){
|
||||
i32 end = buffer_size(&file->state.buffer);
|
||||
file_replace_range(system, models, file, end, end, value.str, value.size);
|
||||
edit_single(system, models, file,
|
||||
end, end, value.str, value.size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,7 +324,7 @@ do_feedback_message(System_Functions *system, Models *models, String value, b32
|
|||
Editing_File *file = models->message_buffer;
|
||||
|
||||
if (file){
|
||||
output_file_append(system, models, file, value, true);
|
||||
output_file_append(system, models, file, value);
|
||||
i32 pos = 0;
|
||||
if (!set_to_start){
|
||||
pos = buffer_size(&file->state.buffer);
|
||||
|
@ -445,6 +380,19 @@ COMMAND_DECL(null){
|
|||
AllowLocal(command);
|
||||
}
|
||||
|
||||
internal void
|
||||
view_undo_redo(System_Functions *system, Models *models, View *view, Edit_Stack *stack, Edit_Type expected_type){
|
||||
Editing_File *file = view->transient.file_data.file;
|
||||
Assert(file != 0);
|
||||
Assert(view->transient.edit_pos != 0);
|
||||
if (stack->edit_count > 0){
|
||||
Edit_Step step = stack->edits[stack->edit_count - 1];
|
||||
Assert(step.type == expected_type);
|
||||
edit_historical(system, models, file, view, stack,
|
||||
step, hist_normal);
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND_DECL(undo){
|
||||
USE_MODELS(models);
|
||||
REQ_OPEN_VIEW(view);
|
||||
|
@ -526,7 +474,7 @@ COMMAND_DECL(reopen){
|
|||
++vptr_count;
|
||||
}
|
||||
|
||||
file_close(system, general, file);
|
||||
file_free(system, general, file);
|
||||
init_normal_file(system, models, file, buffer, size);
|
||||
|
||||
for (i32 i = 0; i < vptr_count; ++i){
|
||||
|
@ -564,17 +512,6 @@ COMMAND_DECL(save){
|
|||
}
|
||||
}
|
||||
|
||||
COMMAND_DECL(change_active_panel){
|
||||
USE_MODELS(models);
|
||||
USE_PANEL(panel);
|
||||
|
||||
panel = panel->next;
|
||||
if (panel == &models->layout.used_sentinel){
|
||||
panel = panel->next;
|
||||
}
|
||||
models->layout.active_panel = (i32)(panel - models->layout.panels);
|
||||
}
|
||||
|
||||
COMMAND_DECL(interactive_switch_buffer){
|
||||
USE_MODELS(models);
|
||||
USE_VIEW(view);
|
||||
|
@ -992,11 +929,6 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){
|
|||
|
||||
#include "4ed_api_implementation.cpp"
|
||||
|
||||
struct Command_In{
|
||||
Command_Data *cmd;
|
||||
Command_Binding bind;
|
||||
};
|
||||
|
||||
internal void
|
||||
command_caller(Coroutine_Head *coroutine){
|
||||
Command_In *cmd_in = (Command_In*)coroutine->in;
|
||||
|
@ -1121,34 +1053,9 @@ app_hardcode_default_style(Models *models){
|
|||
/////////////////
|
||||
models->styles.count = (i32)(style - styles);
|
||||
models->styles.max = ArrayCount(models->styles.styles);
|
||||
style_copy(main_style(models), models->styles.styles + 1);
|
||||
style_copy(&models->styles.styles[0], models->styles.styles + 1);
|
||||
}
|
||||
|
||||
enum Command_Line_Action{
|
||||
CLAct_Nothing,
|
||||
CLAct_Ignore,
|
||||
CLAct_UserFile,
|
||||
CLAct_CustomDLL,
|
||||
CLAct_InitialFilePosition,
|
||||
CLAct_WindowSize,
|
||||
CLAct_WindowMaximize,
|
||||
CLAct_WindowPosition,
|
||||
CLAct_WindowFullscreen,
|
||||
CLAct_FontSize,
|
||||
CLAct_FontUseHinting,
|
||||
CLAct_LogStdout,
|
||||
CLAct_LogFile,
|
||||
CLAct_TestInput,
|
||||
CLAct_RecordInput,
|
||||
//
|
||||
CLAct_COUNT,
|
||||
};
|
||||
|
||||
enum Command_Line_Mode{
|
||||
CLMode_App,
|
||||
CLMode_Custom
|
||||
};
|
||||
|
||||
internal void
|
||||
init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings, i32 argc, char **argv){
|
||||
char *arg = 0;
|
||||
|
@ -1498,12 +1405,6 @@ App_Init_Sig(app_init){
|
|||
|
||||
General_Memory *general = &models->mem.general;
|
||||
|
||||
struct File_Init{
|
||||
String name;
|
||||
Editing_File **ptr;
|
||||
b32 read_only;
|
||||
};
|
||||
|
||||
File_Init init_files[] = {
|
||||
{ make_lit_string("*messages*"), &models->message_buffer, true , },
|
||||
{ make_lit_string("*scratch*"), &models->scratch_buffer, false, }
|
||||
|
@ -1686,8 +1587,9 @@ App_Step_Sig(app_step){
|
|||
Editing_File *file = working_set_contains_canon(working_set, canon.name);
|
||||
if (file != 0){
|
||||
if (file->state.ignore_behind_os == 0){
|
||||
|
||||
file_mark_behind_os(file);
|
||||
if (!file->settings.unimportant){
|
||||
|
||||
}
|
||||
}
|
||||
else if (file->state.ignore_behind_os == 1){
|
||||
file->state.ignore_behind_os = 2;
|
||||
|
@ -1847,7 +1749,7 @@ App_Step_Sig(app_step){
|
|||
if (system->cli_update_step(cli, dest, max, &amount)){
|
||||
if (file != 0){
|
||||
amount = eol_in_place_convert_in(dest, amount);
|
||||
output_file_append(system, models, file, make_string(dest, amount), proc_ptr->cursor_at_end);
|
||||
output_file_append(system, models, file, make_string(dest, amount));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1857,12 +1759,14 @@ App_Step_Sig(app_step){
|
|||
String str = make_fixed_width_string(str_space);
|
||||
append(&str, make_lit_string("exited with code "));
|
||||
append_int_to_str(&str, cli->exit);
|
||||
output_file_append(system, models, file, str, proc_ptr->cursor_at_end);
|
||||
output_file_append(system, models, file, str);
|
||||
}
|
||||
procs_to_free[proc_free_count++] = proc_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(allen): proc_ptr->cursor_at_end
|
||||
|
||||
for (i32 i = proc_free_count - 1; i >= 0; --i){
|
||||
cli_list_free_proc(list, procs_to_free[i]);
|
||||
}
|
||||
|
@ -2008,15 +1912,6 @@ App_Step_Sig(app_step){
|
|||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
// HACK(allen): This can be simplified a lot more.
|
||||
enum{
|
||||
Event_Keyboard,
|
||||
Event_Mouse,
|
||||
};
|
||||
struct Coroutine_Event{
|
||||
u32 type;
|
||||
u32 key_i;
|
||||
};
|
||||
|
||||
Coroutine_Event *events = push_array(part, Coroutine_Event, 32);
|
||||
u32 event_count = 0;
|
||||
|
||||
|
@ -2518,7 +2413,7 @@ App_Step_Sig(app_step){
|
|||
i32_Rect inner = panel->inner;
|
||||
|
||||
View *view = panel->view;
|
||||
Style *style = main_style(models);
|
||||
Style *style = &models->styles.styles[0];
|
||||
|
||||
b32 active = (panel == active_panel);
|
||||
u32 back_color = style->main.back_color;
|
||||
|
|
|
@ -320,7 +320,7 @@ DOC_SEE(Command_Line_Interface_Flag)
|
|||
|
||||
// NOTE(allen): If we have an output file, prepare it for child proc output.
|
||||
if (file != 0){
|
||||
file_clear(system, models, file);
|
||||
edit_clear(system, models, file);
|
||||
file->settings.unimportant = true;
|
||||
}
|
||||
|
||||
|
@ -337,7 +337,7 @@ DOC_SEE(Command_Line_Interface_Flag)
|
|||
View *vptr = imp_get_view(cmd, view);
|
||||
if (vptr != 0){
|
||||
view_set_file(system, vptr, file, models);
|
||||
view_show_file(vptr, models);
|
||||
view_show_file(vptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -700,8 +700,8 @@ DOC_SEE(4coder_Buffer_Positioning_System)
|
|||
if (0 <= start && start <= end && end <= size){
|
||||
result = true;
|
||||
|
||||
file_replace_range(cmd->system, cmd->models,
|
||||
file, start, end, str, len);
|
||||
edit_single(cmd->system, cmd->models,
|
||||
file, start, end, str, len);
|
||||
}
|
||||
fill_buffer_summary(buffer, file, cmd);
|
||||
}
|
||||
|
@ -772,7 +772,7 @@ DOC_SEE(Buffer_Batch_Edit_Type)
|
|||
|
||||
Edit_Spec spec = file_compute_edit(mem, file, edits, str, str_len, inverse_edits, inv_str, inv_str_max, edit_count, type);
|
||||
|
||||
file_do_batch_edit(system, models, file, spec, hist_normal, type);
|
||||
edit_batch(system, models, file, spec, hist_normal, type);
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
@ -904,18 +904,65 @@ DOC_RETURN(returns non-zero on success)
|
|||
if (file){
|
||||
result = 1;
|
||||
switch (setting){
|
||||
case BufferSetting_Lex: *value_out = file->settings.tokens_exist; break;
|
||||
case BufferSetting_LexWithoutStrings: *value_out = file->settings.tokens_without_strings; break;
|
||||
case BufferSetting_ParserContext: *value_out = file->settings.parse_context_id; break;
|
||||
case BufferSetting_WrapLine: *value_out = !file->settings.unwrapped_lines; break;
|
||||
case BufferSetting_WrapPosition: *value_out = file->settings.display_width; break;
|
||||
case BufferSetting_MinimumBaseWrapPosition: *value_out = file->settings.minimum_base_display_width; break;
|
||||
case BufferSetting_MapID: *value_out = file->settings.base_map_id; break;
|
||||
case BufferSetting_Eol: *value_out = file->settings.dos_write_mode; break;
|
||||
case BufferSetting_Unimportant: *value_out = file->settings.unimportant; break;
|
||||
case BufferSetting_ReadOnly: *value_out = file->settings.read_only; break;
|
||||
case BufferSetting_VirtualWhitespace: *value_out = file->settings.virtual_white; break;
|
||||
default: result = 0; break;
|
||||
case BufferSetting_Lex:
|
||||
{
|
||||
*value_out = file->settings.tokens_exist;
|
||||
}break;
|
||||
|
||||
case BufferSetting_LexWithoutStrings:
|
||||
{
|
||||
*value_out = file->settings.tokens_without_strings;
|
||||
}break;
|
||||
|
||||
case BufferSetting_ParserContext:
|
||||
{
|
||||
*value_out = file->settings.parse_context_id;
|
||||
}break;
|
||||
|
||||
case BufferSetting_WrapLine:
|
||||
{
|
||||
*value_out = !file->settings.unwrapped_lines;
|
||||
}break;
|
||||
|
||||
case BufferSetting_WrapPosition:
|
||||
{
|
||||
*value_out = file->settings.display_width;
|
||||
}break;
|
||||
|
||||
case BufferSetting_MinimumBaseWrapPosition:
|
||||
{
|
||||
*value_out = file->settings.minimum_base_display_width;
|
||||
}break;
|
||||
|
||||
case BufferSetting_MapID:
|
||||
{
|
||||
*value_out = file->settings.base_map_id;
|
||||
}break;
|
||||
|
||||
case BufferSetting_Eol:
|
||||
{
|
||||
*value_out = file->settings.dos_write_mode;
|
||||
}break;
|
||||
|
||||
case BufferSetting_Unimportant:
|
||||
{
|
||||
*value_out = file->settings.unimportant;
|
||||
}break;
|
||||
|
||||
case BufferSetting_ReadOnly:
|
||||
{
|
||||
*value_out = file->settings.read_only;
|
||||
}break;
|
||||
|
||||
case BufferSetting_VirtualWhitespace:
|
||||
{
|
||||
*value_out = file->settings.virtual_white;
|
||||
}break;
|
||||
|
||||
default:
|
||||
{
|
||||
result = 0;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1015,7 +1062,8 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
if (new_value != file->settings.display_width){
|
||||
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
|
||||
file->settings.display_width = new_value;
|
||||
file_measure_wraps_and_fix_cursor(system, models, file, font);
|
||||
file_measure_wraps(system, &models->mem, file, font);
|
||||
adjust_views_looking_at_files_to_new_cursor(system, models, file);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -1028,7 +1076,8 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
if (new_value != file->settings.minimum_base_display_width){
|
||||
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
|
||||
file->settings.minimum_base_display_width = new_value;
|
||||
file_measure_wraps_and_fix_cursor(system, models, file, font);
|
||||
file_measure_wraps(system, &models->mem, file, font);
|
||||
adjust_views_looking_at_files_to_new_cursor(system, models, file);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -1117,8 +1166,8 @@ DOC_SEE(Buffer_Setting_ID)
|
|||
|
||||
file_allocate_character_starts_as_needed(&models->mem.general, file);
|
||||
buffer_measure_character_starts(system, font, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
file_measure_wraps(system, models, file, font);
|
||||
file_update_cursor_positions(system, models, file);
|
||||
file_measure_wraps(system, &models->mem, file, font);
|
||||
adjust_views_looking_at_files_to_new_cursor(system, models, file);
|
||||
}
|
||||
}break;
|
||||
|
||||
|
@ -1358,7 +1407,7 @@ DOC_SEE(Buffer_Save_Flag)
|
|||
if (file != 0){
|
||||
b32 skip_save = false;
|
||||
if (!(flags & BufferSave_IgnoreDirtyFlag)){
|
||||
if (file_get_sync(file) == DirtyState_UpToDate){
|
||||
if (file->state.dirty == DirtyState_UpToDate){
|
||||
skip_save = true;
|
||||
}
|
||||
}
|
||||
|
@ -2032,7 +2081,7 @@ DOC_SEE(Set_Buffer_Flag)
|
|||
if (file != vptr->transient.file_data.file){
|
||||
view_set_file(system, vptr, file, models);
|
||||
if (!(flags & SetBuffer_KeepOriginalGUI)){
|
||||
view_show_file(vptr, models);
|
||||
view_show_file(vptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2254,7 +2303,7 @@ DOC(This call changes 4coder's color pallet to one of the built in themes.)
|
|||
Style *s = styles->styles;
|
||||
for (i32 i = 0; i < count; ++i, ++s){
|
||||
if (match_ss(s->name, theme_name)){
|
||||
style_copy(main_style(cmd->models), s);
|
||||
style_copy(&styles->styles[0], s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2571,15 +2620,11 @@ DOC(For each struct in the array, the slot in the main color pallet specified by
|
|||
DOC_SEE(Theme_Color)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
Style *style = main_style(cmd->models);
|
||||
|
||||
int_color *color = 0;
|
||||
i32 i = 0;
|
||||
Style *style = &cmd->models->styles.styles[0];
|
||||
Theme_Color *theme_color = colors;
|
||||
|
||||
for (i = 0; i < count; ++i, ++theme_color){
|
||||
color = style_index_by_tag(&style->main, theme_color->tag);
|
||||
if (color){
|
||||
for (i32 i = 0; i < count; ++i, ++theme_color){
|
||||
int_color *color = style_index_by_tag(&style->main, theme_color->tag);
|
||||
if (color != 0){
|
||||
*color = theme_color->color | 0xFF000000;
|
||||
}
|
||||
}
|
||||
|
@ -2594,15 +2639,11 @@ DOC(For each struct in the array, the color field of the struct is filled with t
|
|||
DOC_SEE(Theme_Color)
|
||||
*/{
|
||||
Command_Data *cmd = (Command_Data*)app->cmd_context;
|
||||
Style *style = main_style(cmd->models);
|
||||
|
||||
u32 *color = 0;
|
||||
i32 i = 0;
|
||||
Style *style = &cmd->models->styles.styles[0];
|
||||
Theme_Color *theme_color = colors;
|
||||
|
||||
for (i = 0; i < count; ++i, ++theme_color){
|
||||
color = style_index_by_tag(&style->main, theme_color->tag);
|
||||
if (color){
|
||||
for (i32 i = 0; i < count; ++i, ++theme_color){
|
||||
u32 *color = style_index_by_tag(&style->main, theme_color->tag);
|
||||
if (color != 0){
|
||||
theme_color->color = *color | 0xFF000000;
|
||||
}
|
||||
else{
|
||||
|
|
120
4ed_app_models.h
120
4ed_app_models.h
|
@ -9,6 +9,9 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_APP_MODELS_H)
|
||||
#define FRED_APP_MODELS_H
|
||||
|
||||
struct App_Settings{
|
||||
char *init_files[8];
|
||||
i32 init_files_count;
|
||||
|
@ -110,7 +113,120 @@ struct Models{
|
|||
i32 recorded_event_max;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
enum App_State{
|
||||
APP_STATE_EDIT,
|
||||
APP_STATE_RESIZING,
|
||||
// never below this
|
||||
APP_STATE_COUNT
|
||||
};
|
||||
|
||||
struct App_State_Resizing{
|
||||
Panel_Divider *divider;
|
||||
};
|
||||
|
||||
struct Command_Data{
|
||||
Models *models;
|
||||
struct App_Vars *vars;
|
||||
System_Functions *system;
|
||||
Live_Views *live_set;
|
||||
|
||||
i32 screen_width;
|
||||
i32 screen_height;
|
||||
|
||||
Key_Event_Data key;
|
||||
};
|
||||
|
||||
enum Input_Types{
|
||||
Input_AnyKey,
|
||||
Input_Esc,
|
||||
Input_MouseMove,
|
||||
Input_MouseLeftButton,
|
||||
Input_MouseRightButton,
|
||||
Input_MouseWheel,
|
||||
Input_Count
|
||||
};
|
||||
|
||||
struct Consumption_Record{
|
||||
b32 consumed;
|
||||
char consumer[32];
|
||||
};
|
||||
|
||||
struct Available_Input{
|
||||
Key_Input_Data *keys;
|
||||
Mouse_State *mouse;
|
||||
Consumption_Record records[Input_Count];
|
||||
};
|
||||
|
||||
struct App_Vars{
|
||||
Models models;
|
||||
|
||||
CLI_List cli_processes;
|
||||
|
||||
App_State state;
|
||||
App_State_Resizing resizing;
|
||||
|
||||
Command_Data command_data;
|
||||
|
||||
Available_Input available_input;
|
||||
};
|
||||
|
||||
enum Coroutine_Type{
|
||||
Co_View,
|
||||
Co_Command
|
||||
};
|
||||
struct App_Coroutine_State{
|
||||
void *co;
|
||||
i32 type;
|
||||
};
|
||||
|
||||
struct Command_In{
|
||||
Command_Data *cmd;
|
||||
Command_Binding bind;
|
||||
};
|
||||
|
||||
struct File_Init{
|
||||
String name;
|
||||
Editing_File **ptr;
|
||||
b32 read_only;
|
||||
};
|
||||
|
||||
enum{
|
||||
Event_Keyboard,
|
||||
Event_Mouse,
|
||||
};
|
||||
struct Coroutine_Event{
|
||||
u32 type;
|
||||
u32 key_i;
|
||||
};
|
||||
|
||||
enum Command_Line_Action{
|
||||
CLAct_Nothing,
|
||||
CLAct_Ignore,
|
||||
CLAct_UserFile,
|
||||
CLAct_CustomDLL,
|
||||
CLAct_InitialFilePosition,
|
||||
CLAct_WindowSize,
|
||||
CLAct_WindowMaximize,
|
||||
CLAct_WindowPosition,
|
||||
CLAct_WindowFullscreen,
|
||||
CLAct_FontSize,
|
||||
CLAct_FontUseHinting,
|
||||
CLAct_LogStdout,
|
||||
CLAct_LogFile,
|
||||
CLAct_TestInput,
|
||||
CLAct_RecordInput,
|
||||
//
|
||||
CLAct_COUNT,
|
||||
};
|
||||
|
||||
enum Command_Line_Mode{
|
||||
CLMode_App,
|
||||
CLMode_Custom
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -44,37 +44,41 @@
|
|||
|
||||
#include "4ed_linked_node_macros.h"
|
||||
#include "4ed_log.h"
|
||||
#include "4ed_gui.h"
|
||||
|
||||
#include "4ed_buffer_model.h"
|
||||
#include "4ed_translation.h"
|
||||
#include "4ed_command.h"
|
||||
#include "4ed_buffer.h"
|
||||
#include "4ed_undo.h"
|
||||
#include "4ed_file.h"
|
||||
#include "4ed_code_wrap.h"
|
||||
|
||||
#include "4ed_working_set.h"
|
||||
#include "4ed_style.h"
|
||||
#include "4ed_hot_directory.h"
|
||||
#include "4ed_parse_context.h"
|
||||
#include "4ed_cli.h"
|
||||
#include "4ed_gui.h"
|
||||
#include "4ed_layout.h"
|
||||
#include "4ed_view.h"
|
||||
#include "4ed_app_models.h"
|
||||
|
||||
#include "4ed_font.cpp"
|
||||
|
||||
//check
|
||||
#include "4ed_translation.cpp"
|
||||
#include "4ed_render_target.cpp"
|
||||
#include "4ed_render_fill.cpp"
|
||||
#include "4ed_render_format.cpp"
|
||||
#include "4ed_command.cpp"
|
||||
//check
|
||||
#include "4ed_buffer.cpp"
|
||||
//check
|
||||
#include "4ed_undo.cpp"
|
||||
#include "4ed_file.cpp"
|
||||
#include "4ed_code_wrap.cpp"
|
||||
#include "4ed_working_set.cpp"
|
||||
//check
|
||||
#include "4ed_hot_directory.cpp"
|
||||
#include "4ed_parse_contexts.cpp"
|
||||
#include "4ed_parse_context.cpp"
|
||||
#include "4ed_file_lex.cpp"
|
||||
#include "4ed_cli.cpp"
|
||||
//check
|
||||
#include "4ed_gui.cpp"
|
||||
#include "4ed_layout.cpp"
|
||||
#include "4ed_app_models.h"
|
||||
#include "4ed_view.cpp"
|
||||
#include "4ed.cpp"
|
||||
|
||||
|
|
17
4ed_cli.cpp
17
4ed_cli.cpp
|
@ -9,21 +9,6 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_CLI_CPP)
|
||||
#define FRED_CLI_CPP
|
||||
|
||||
struct CLI_Process{
|
||||
CLI_Handles cli;
|
||||
Editing_File *out_file;
|
||||
b32 cursor_at_end;
|
||||
};
|
||||
|
||||
struct CLI_List{
|
||||
CLI_Process *procs;
|
||||
u32 count;
|
||||
u32 max;
|
||||
};
|
||||
|
||||
inline CLI_List
|
||||
make_cli_list(Partition *part, u32 max){
|
||||
CLI_List list = {0};
|
||||
|
@ -63,7 +48,5 @@ cli_list_has_space(CLI_List *list){
|
|||
return(has_space);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* CLI handling code.
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_CLI_H)
|
||||
#define FRED_CLI_H
|
||||
|
||||
struct CLI_Process{
|
||||
CLI_Handles cli;
|
||||
Editing_File *out_file;
|
||||
b32 cursor_at_end;
|
||||
};
|
||||
|
||||
struct CLI_List{
|
||||
CLI_Process *procs;
|
||||
u32 count;
|
||||
u32 max;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -0,0 +1,938 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* Code wrapping logic
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
internal void
|
||||
wrap_state_init(System_Functions *system, Code_Wrap_State *state, Editing_File *file, Font_Pointers font){
|
||||
state->token_array = file->state.token_array;
|
||||
state->token_ptr = state->token_array.tokens;
|
||||
state->end_token = state->token_ptr + state->token_array.count;
|
||||
|
||||
state->line_starts = file->state.buffer.line_starts;
|
||||
state->line_count = file->state.buffer.line_count;
|
||||
state->next_line_start = state->line_starts[1];
|
||||
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
i32 size = buffer_size(buffer);
|
||||
buffer_stringify_loop(&state->stream, buffer, 0, size);
|
||||
state->size = size;
|
||||
state->i = 0;
|
||||
|
||||
state->font = font;
|
||||
|
||||
state->tab_indent_amount = font_get_glyph_advance(system, font.settings, font.metrics, font.pages, '\t');
|
||||
state->byte_advance = font.metrics->byte_advance;
|
||||
|
||||
state->tran = null_buffer_translating_state;
|
||||
}
|
||||
|
||||
internal void
|
||||
wrap_state_set_top(Code_Wrap_State *state, f32 line_shift){
|
||||
if (state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top] > line_shift){
|
||||
state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top] = line_shift;
|
||||
}
|
||||
}
|
||||
|
||||
internal Code_Wrap_Step
|
||||
wrap_state_consume_token(System_Functions *system, Font_Pointers font, Code_Wrap_State *state, i32 fixed_end_point){
|
||||
Code_Wrap_Step result = {0};
|
||||
i32 i = state->i;
|
||||
|
||||
result.position_start = i;
|
||||
|
||||
Cpp_Token token = {0};
|
||||
|
||||
token.start = state->size;
|
||||
if (state->token_ptr < state->end_token){
|
||||
token = *state->token_ptr;
|
||||
}
|
||||
|
||||
if (state->consume_newline){
|
||||
++i;
|
||||
state->x = 0;
|
||||
state->consume_newline = 0;
|
||||
}
|
||||
|
||||
|
||||
if (state->in_pp_body){
|
||||
if (!(token.flags & CPP_TFLAG_PP_BODY)){
|
||||
state->in_pp_body = false;
|
||||
state->wrap_x = state->plane_wrap_x;
|
||||
}
|
||||
}
|
||||
|
||||
if (!state->in_pp_body){
|
||||
if (token.flags & CPP_TFLAG_PP_DIRECTIVE){
|
||||
state->in_pp_body = true;
|
||||
state->plane_wrap_x = state->wrap_x;
|
||||
state->wrap_x = null_wrap_x;
|
||||
}
|
||||
}
|
||||
|
||||
b32 skipping_whitespace = false;
|
||||
if (i >= state->next_line_start){
|
||||
state->x = state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top];
|
||||
state->x = state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top];
|
||||
skipping_whitespace = true;
|
||||
}
|
||||
|
||||
// TODO(allen): exponential search this shit!
|
||||
for (;i >= state->next_line_start;){
|
||||
state->next_line_start = state->size;
|
||||
if (state->line_index < state->line_count){
|
||||
++state->line_index;
|
||||
if (state->line_index + 1 < state->line_count){
|
||||
state->next_line_start = state->line_starts[state->line_index + 1];
|
||||
}
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i32 line_start = state->size;
|
||||
if (state->line_index < 0){
|
||||
line_start = 0;
|
||||
}
|
||||
else if (state->line_index < state->line_count){
|
||||
line_start = state->line_starts[state->line_index];
|
||||
}
|
||||
b32 still_looping = 0;
|
||||
i32 end = token.start + token.size;
|
||||
if (fixed_end_point >= 0 && end > fixed_end_point){
|
||||
end = fixed_end_point;
|
||||
}
|
||||
|
||||
i = clamp_bottom(line_start, i);
|
||||
if (i == line_start){
|
||||
skipping_whitespace = true;
|
||||
}
|
||||
|
||||
b32 recorded_start_x = false;
|
||||
do{
|
||||
for (; i < state->stream.end; ++i){
|
||||
if (!(i < end)){
|
||||
goto doublebreak;
|
||||
}
|
||||
|
||||
u8 ch = (u8)state->stream.data[i];
|
||||
translating_fully_process_byte(system, font, &state->tran, ch, i, state->size, &state->emits);
|
||||
|
||||
for (TRANSLATION_EMIT_LOOP(state->J, state->emits)){
|
||||
TRANSLATION_GET_STEP(state->step, state->behavior, state->J, state->emits);
|
||||
|
||||
if (state->behavior.do_newline){
|
||||
state->consume_newline = 1;
|
||||
goto doublebreak;
|
||||
}
|
||||
else if(state->behavior.do_number_advance || state->behavior.do_codepoint_advance){
|
||||
u32 n = state->step.value;
|
||||
f32 adv = 0;
|
||||
if (state->behavior.do_codepoint_advance){
|
||||
adv = font_get_glyph_advance(system, state->font.settings, state->font.metrics, state->font.pages, n);
|
||||
|
||||
if (n != ' ' && n != '\t'){
|
||||
skipping_whitespace = false;
|
||||
}
|
||||
}
|
||||
else{
|
||||
adv = state->byte_advance;
|
||||
skipping_whitespace = false;
|
||||
}
|
||||
|
||||
if (!skipping_whitespace){
|
||||
if (!recorded_start_x){
|
||||
result.start_x = state->x;
|
||||
recorded_start_x = true;
|
||||
}
|
||||
state->x += adv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = buffer_stringify_next(&state->stream);
|
||||
}while(still_looping);
|
||||
doublebreak:;
|
||||
|
||||
state->i = i;
|
||||
|
||||
b32 consume_token = false;
|
||||
if (state->token_ptr < state->end_token && i >= token.start + token.size){
|
||||
consume_token = true;
|
||||
}
|
||||
|
||||
result.this_token = state->token_ptr;
|
||||
if (consume_token){
|
||||
Assert(state->token_ptr < state->end_token);
|
||||
switch (state->token_ptr->type){
|
||||
case CPP_TOKEN_BRACE_OPEN:
|
||||
{
|
||||
state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top] += state->tab_indent_amount;
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
{
|
||||
state->wrap_x.paren_nesting[state->wrap_x.paren_safe_top] -= state->tab_indent_amount;
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_OPEN:
|
||||
case CPP_TOKEN_BRACKET_OPEN:
|
||||
{
|
||||
++state->wrap_x.paren_top;
|
||||
|
||||
i32 top = state->wrap_x.paren_top;
|
||||
if (top >= ArrayCount(state->wrap_x.paren_nesting)){
|
||||
top = ArrayCount(state->wrap_x.paren_nesting) - 1;
|
||||
}
|
||||
state->wrap_x.paren_safe_top = top;
|
||||
|
||||
state->wrap_x.paren_nesting[top] = state->x;
|
||||
}break;
|
||||
|
||||
case CPP_TOKEN_PARENTHESE_CLOSE:
|
||||
case CPP_TOKEN_BRACKET_CLOSE:
|
||||
{
|
||||
--state->wrap_x.paren_top;
|
||||
|
||||
if (state->wrap_x.paren_top < 0){
|
||||
state->wrap_x.paren_top = 0;
|
||||
}
|
||||
|
||||
i32 top = state->wrap_x.paren_top;
|
||||
if (top >= ArrayCount(state->wrap_x.paren_nesting)){
|
||||
top = ArrayCount(state->wrap_x.paren_nesting) - 1;
|
||||
}
|
||||
state->wrap_x.paren_safe_top = top;
|
||||
}break;
|
||||
}
|
||||
|
||||
++state->token_ptr;
|
||||
if (state->token_ptr > state->end_token){
|
||||
state->token_ptr = state->end_token;
|
||||
}
|
||||
}
|
||||
|
||||
result.position_end = state->i;
|
||||
result.final_x = state->x;
|
||||
|
||||
if (!recorded_start_x){
|
||||
result.start_x = state->x;
|
||||
recorded_start_x = true;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal i32
|
||||
stickieness_guess(Cpp_Token_Type type, Cpp_Token_Type other_type, u16 flags, u16 other_flags, b32 on_left){
|
||||
i32 guess = 0;
|
||||
|
||||
b32 is_words = 0, other_is_words = 0;
|
||||
if (type == CPP_TOKEN_IDENTIFIER || (type >= CPP_TOKEN_KEY_TYPE && type <= CPP_TOKEN_KEY_OTHER)){
|
||||
is_words = 1;
|
||||
}
|
||||
if (other_type == CPP_TOKEN_IDENTIFIER || (other_type >= CPP_TOKEN_KEY_TYPE && other_type <= CPP_TOKEN_KEY_OTHER)){
|
||||
other_is_words = 1;
|
||||
}
|
||||
|
||||
b32 is_operator = 0, other_is_operator = 0;
|
||||
if (flags & CPP_TFLAG_IS_OPERATOR){
|
||||
is_operator = 1;
|
||||
}
|
||||
if (other_flags & CPP_TFLAG_IS_OPERATOR){
|
||||
other_is_operator = 1;
|
||||
}
|
||||
|
||||
i32 operator_side_bias = 70*(!on_left);
|
||||
|
||||
if (is_words && other_is_words){
|
||||
guess = 200;
|
||||
}
|
||||
else if (type == CPP_TOKEN_PARENTHESE_OPEN){
|
||||
if (on_left){
|
||||
guess = 100;
|
||||
}
|
||||
else{
|
||||
if (other_is_words){
|
||||
guess = 100;
|
||||
}
|
||||
else{
|
||||
guess = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == CPP_TOKEN_SEMICOLON){
|
||||
if (on_left){
|
||||
guess = 0;
|
||||
}
|
||||
else{
|
||||
guess = 1000;
|
||||
}
|
||||
}
|
||||
else if (type == CPP_TOKEN_COMMA){
|
||||
guess = 20;
|
||||
}
|
||||
else if (type == CPP_TOKEN_COLON ||
|
||||
type == CPP_TOKEN_PARENTHESE_CLOSE ||
|
||||
type == CPP_TOKEN_BRACKET_OPEN ||
|
||||
type == CPP_TOKEN_BRACKET_CLOSE){
|
||||
if (on_left){
|
||||
guess = 20;
|
||||
if (other_is_words){
|
||||
guess = 100;
|
||||
}
|
||||
}
|
||||
else{
|
||||
guess = 100;
|
||||
}
|
||||
}
|
||||
else if (type == CPP_PP_DEFINED){
|
||||
if (on_left){
|
||||
guess = 100;
|
||||
}
|
||||
else{
|
||||
guess = 0;
|
||||
}
|
||||
}
|
||||
else if (type == CPP_TOKEN_SCOPE){
|
||||
guess = 90;
|
||||
}
|
||||
else if (type == CPP_TOKEN_MINUS){
|
||||
if (on_left){
|
||||
guess = 80;
|
||||
}
|
||||
else{
|
||||
guess = 60;
|
||||
}
|
||||
}
|
||||
else if (type == CPP_TOKEN_DOT ||
|
||||
type == CPP_TOKEN_ARROW){
|
||||
guess = 200;
|
||||
}
|
||||
else if (type == CPP_TOKEN_NOT ||
|
||||
type == CPP_TOKEN_TILDE){
|
||||
if (on_left){
|
||||
guess = 80;
|
||||
}
|
||||
else{
|
||||
guess = 20;
|
||||
}
|
||||
}
|
||||
else if (type == CPP_TOKEN_INCREMENT ||
|
||||
type == CPP_TOKEN_DECREMENT ||
|
||||
type == CPP_TOKEN_STAR ||
|
||||
type == CPP_TOKEN_AMPERSAND ||
|
||||
(type >= CPP_TOKEN_POSTINC &&
|
||||
type <= CPP_TOKEN_DELETE_ARRAY)){
|
||||
guess = 80;
|
||||
if (!on_left && other_is_operator){
|
||||
guess = 20;
|
||||
}
|
||||
}
|
||||
else if (type >= CPP_TOKEN_MUL && type <= CPP_TOKEN_MOD){
|
||||
guess = 70;
|
||||
}
|
||||
else if (type == CPP_TOKEN_PLUS){
|
||||
guess = 60 + operator_side_bias;
|
||||
}
|
||||
else if (type >= CPP_TOKEN_LSHIFT && type <= CPP_TOKEN_RSHIFT){
|
||||
guess = 50;
|
||||
}
|
||||
else if (type >= CPP_TOKEN_LESS && type <= CPP_TOKEN_NOTEQ){
|
||||
guess = 40 + operator_side_bias;
|
||||
}
|
||||
else if (type >= CPP_TOKEN_BIT_XOR && type <= CPP_TOKEN_BIT_OR){
|
||||
guess = 40;
|
||||
}
|
||||
else if (type >= CPP_TOKEN_AND && type <= CPP_TOKEN_OR){
|
||||
guess = 30 + operator_side_bias;
|
||||
}
|
||||
else if (type >= CPP_TOKEN_TERNARY_QMARK && type <= CPP_TOKEN_COLON){
|
||||
guess = 20 + operator_side_bias;
|
||||
}
|
||||
else if (type == CPP_TOKEN_THROW){
|
||||
if (on_left){
|
||||
guess = 100;
|
||||
}
|
||||
else{
|
||||
guess = 0;
|
||||
}
|
||||
}
|
||||
else if (type >= CPP_TOKEN_EQ && type <= CPP_TOKEN_XOREQ){
|
||||
guess = 15 + operator_side_bias;
|
||||
}
|
||||
|
||||
return(guess);
|
||||
}
|
||||
|
||||
internal Wrap_Current_Shift
|
||||
get_current_shift(Code_Wrap_State *wrap_state, i32 next_line_start){
|
||||
Wrap_Current_Shift result = {0};
|
||||
|
||||
result.shift = wrap_state->wrap_x.paren_nesting[wrap_state->wrap_x.paren_safe_top];
|
||||
|
||||
Cpp_Token next_token = {0};
|
||||
if (wrap_state->token_ptr < wrap_state->end_token){
|
||||
next_token = *wrap_state->token_ptr;
|
||||
}
|
||||
|
||||
if (wrap_state->token_ptr > wrap_state->token_array.tokens){
|
||||
Cpp_Token prev_token = *(wrap_state->token_ptr-1);
|
||||
|
||||
if (wrap_state->wrap_x.paren_safe_top != 0 && prev_token.type == CPP_TOKEN_PARENTHESE_OPEN){
|
||||
result.shift = wrap_state->wrap_x.paren_nesting[wrap_state->wrap_x.paren_safe_top-1] + wrap_state->tab_indent_amount;
|
||||
result.adjust_top_to_this = 1;
|
||||
}
|
||||
|
||||
f32 statement_continuation_indent = 0.f;
|
||||
if (result.shift != 0.f && wrap_state->wrap_x.paren_safe_top == 0){
|
||||
if (!(prev_token.flags & (CPP_TFLAG_PP_DIRECTIVE|CPP_TFLAG_PP_BODY))){
|
||||
switch (prev_token.type){
|
||||
case CPP_TOKEN_BRACKET_OPEN:
|
||||
case CPP_TOKEN_BRACE_OPEN:
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
case CPP_TOKEN_SEMICOLON:
|
||||
case CPP_TOKEN_COLON:
|
||||
case CPP_TOKEN_COMMA:
|
||||
case CPP_TOKEN_COMMENT: break;
|
||||
default: statement_continuation_indent += wrap_state->tab_indent_amount; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (next_token.type){
|
||||
case CPP_TOKEN_BRACE_CLOSE: case CPP_TOKEN_BRACE_OPEN: break;
|
||||
default: result.shift += statement_continuation_indent; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (next_token.start < next_line_start){
|
||||
if (next_token.flags & CPP_TFLAG_PP_DIRECTIVE){
|
||||
result.shift = 0;
|
||||
}
|
||||
else{
|
||||
switch (next_token.type){
|
||||
case CPP_TOKEN_BRACE_CLOSE:
|
||||
{
|
||||
if (wrap_state->wrap_x.paren_safe_top == 0){
|
||||
result.shift -= wrap_state->tab_indent_amount;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.shift = clamp_bottom(0.f, result.shift);
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *file, Font_Pointers font){
|
||||
PRFL_FUNC_GROUP();
|
||||
|
||||
General_Memory *general = &mem->general;
|
||||
Partition *part = &mem->part;
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
file_allocate_wraps_as_needed(general, file);
|
||||
file_allocate_indents_as_needed(general, file, file->state.buffer.line_count);
|
||||
file_allocate_wrap_positions_as_needed(general, file, file->state.buffer.line_count);
|
||||
|
||||
Buffer_Measure_Wrap_Params params;
|
||||
params.buffer = &file->state.buffer;
|
||||
params.wrap_line_index = file->state.wrap_line_index;
|
||||
params.system = system;
|
||||
params.font = font;
|
||||
params.virtual_white = file->settings.virtual_white;
|
||||
|
||||
f32 width = (f32)file->settings.display_width;
|
||||
f32 minimum_base_width = (f32)file->settings.minimum_base_display_width;
|
||||
|
||||
i32 size = buffer_size(params.buffer);
|
||||
|
||||
Buffer_Measure_Wrap_State state = {0};
|
||||
Buffer_Layout_Stop stop = {0};
|
||||
|
||||
f32 edge_tolerance = 50.f;
|
||||
edge_tolerance = clamp_top(edge_tolerance, 50.f);
|
||||
|
||||
f32 current_line_shift = 0.f;
|
||||
b32 do_wrap = 0;
|
||||
i32 wrap_unit_end = 0;
|
||||
|
||||
i32 wrap_position_index = 0;
|
||||
file->state.wrap_positions[wrap_position_index++] = 0;
|
||||
|
||||
Code_Wrap_State wrap_state = {0};
|
||||
|
||||
b32 use_tokens = false;
|
||||
|
||||
Wrap_Indent_Pair *wrap_indent_marks = 0;
|
||||
Potential_Wrap_Indent_Pair *potential_marks = 0;
|
||||
i32 max_wrap_indent_mark = 0;
|
||||
|
||||
if (params.virtual_white && file->state.tokens_complete && !file->state.still_lexing){
|
||||
wrap_state_init(system, &wrap_state, file, font);
|
||||
use_tokens = true;
|
||||
|
||||
potential_marks = push_array(part, Potential_Wrap_Indent_Pair, floor32(width));
|
||||
|
||||
max_wrap_indent_mark = partition_remaining(part)/sizeof(Wrap_Indent_Pair);
|
||||
wrap_indent_marks = push_array(part, Wrap_Indent_Pair, max_wrap_indent_mark);
|
||||
}
|
||||
|
||||
i32 real_count = 0;
|
||||
i32 potential_count = 0;
|
||||
i32 stage = 0;
|
||||
|
||||
do{
|
||||
stop = buffer_measure_wrap_y(&state, params, current_line_shift, do_wrap, wrap_unit_end);
|
||||
|
||||
switch (stop.status){
|
||||
case BLStatus_NeedWrapDetermination:
|
||||
{
|
||||
if (use_tokens){
|
||||
if (stage == 0){
|
||||
do_wrap = 0;
|
||||
wrap_unit_end = wrap_indent_marks[stage+1].wrap_position;
|
||||
++stage;
|
||||
}
|
||||
else{
|
||||
do_wrap = 1;
|
||||
wrap_unit_end = wrap_indent_marks[stage+1].wrap_position;
|
||||
file_allocate_wrap_positions_as_needed(general, file, wrap_position_index);
|
||||
file->state.wrap_positions[wrap_position_index++] = stop.pos;
|
||||
}
|
||||
}
|
||||
else{
|
||||
Translation_State tran = {0};
|
||||
Translation_Emits emits = {0};
|
||||
Gap_Buffer_Stream stream = {0};
|
||||
|
||||
i32 word_stage = 0;
|
||||
i32 i = stop.pos;
|
||||
f32 x = stop.x;
|
||||
f32 self_x = 0;
|
||||
i32 wrap_end_result = size;
|
||||
if (buffer_stringify_loop(&stream, params.buffer, i, size)){
|
||||
b32 still_looping = false;
|
||||
do{
|
||||
for (; i < stream.end; ++i){
|
||||
{
|
||||
u8 ch = stream.data[i];
|
||||
translating_fully_process_byte(system, font, &tran, ch, i, size, &emits);
|
||||
}
|
||||
|
||||
for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){
|
||||
TRANSLATION_DECL_GET_STEP(step, behavior, J, emits);
|
||||
|
||||
u32 codepoint = step.value;
|
||||
switch (word_stage){
|
||||
case 0:
|
||||
{
|
||||
if (codepoint_is_whitespace(codepoint)){
|
||||
word_stage = 1;
|
||||
}
|
||||
else{
|
||||
f32 adv = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, codepoint);
|
||||
|
||||
x += adv;
|
||||
self_x += adv;
|
||||
if (self_x > width){
|
||||
wrap_end_result = step.i;
|
||||
goto doublebreak;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (!codepoint_is_whitespace(codepoint)){
|
||||
wrap_end_result = step.i;
|
||||
goto doublebreak;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = buffer_stringify_next(&stream);
|
||||
}while(still_looping);
|
||||
}
|
||||
|
||||
doublebreak:;
|
||||
wrap_unit_end = wrap_end_result;
|
||||
if (x > width){
|
||||
do_wrap = 1;
|
||||
file_allocate_wrap_positions_as_needed(general, file, wrap_position_index);
|
||||
file->state.wrap_positions[wrap_position_index++] = stop.pos;
|
||||
}
|
||||
else{
|
||||
do_wrap = 0;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case BLStatus_NeedWrapLineShift:
|
||||
case BLStatus_NeedLineShift:
|
||||
{
|
||||
f32 current_width = width;
|
||||
|
||||
if (use_tokens){
|
||||
Code_Wrap_State original_wrap_state = wrap_state;
|
||||
i32 next_line_start = buffer_size(params.buffer);
|
||||
if (stop.line_index+1 < params.buffer->line_count){
|
||||
next_line_start = params.buffer->line_starts[stop.line_index+1];
|
||||
}
|
||||
|
||||
f32 base_adjusted_width = wrap_state.wrap_x.base_x + minimum_base_width;
|
||||
|
||||
if (minimum_base_width != 0 && current_width < base_adjusted_width){
|
||||
current_width = base_adjusted_width;
|
||||
}
|
||||
|
||||
if (stop.status == BLStatus_NeedLineShift){
|
||||
real_count = 0;
|
||||
potential_count = 0;
|
||||
stage = 0;
|
||||
|
||||
Wrap_Current_Shift current_shift = get_current_shift(&wrap_state, next_line_start);
|
||||
|
||||
if (current_shift.adjust_top_to_this){
|
||||
wrap_state_set_top(&wrap_state, current_shift.shift);
|
||||
}
|
||||
|
||||
wrap_indent_marks[real_count].wrap_position = 0;
|
||||
wrap_indent_marks[real_count].line_shift =current_shift.shift;
|
||||
++real_count;
|
||||
|
||||
wrap_state.wrap_x.base_x = wrap_state.wrap_x.paren_nesting[0];
|
||||
|
||||
for (; wrap_state.token_ptr < wrap_state.end_token; ){
|
||||
Code_Wrap_Step step = {0};
|
||||
b32 emit_comment_position = false;
|
||||
b32 first_word = true;
|
||||
|
||||
if (wrap_state.token_ptr->type == CPP_TOKEN_COMMENT || wrap_state.token_ptr->type == CPP_TOKEN_STRING_CONSTANT){
|
||||
i32 i = wrap_state.token_ptr->start;
|
||||
i32 end_i = i + wrap_state.token_ptr->size;
|
||||
|
||||
if (i < wrap_state.i){
|
||||
i = wrap_state.i;
|
||||
}
|
||||
|
||||
if (end_i > wrap_state.next_line_start){
|
||||
end_i = wrap_state.next_line_start;
|
||||
}
|
||||
|
||||
f32 x = wrap_state.x;
|
||||
|
||||
step.position_start = i;
|
||||
step.start_x = x;
|
||||
step.this_token = wrap_state.token_ptr;
|
||||
|
||||
Gap_Buffer_Stream stream = {0};
|
||||
Translation_State tran = {0};
|
||||
Translation_Emits emits = {0};
|
||||
|
||||
Potential_Wrap_Indent_Pair potential_wrap = {0};
|
||||
potential_wrap.wrap_position = i;
|
||||
potential_wrap.line_shift = x;
|
||||
potential_wrap.wrappable_score = 5;
|
||||
potential_wrap.wrap_x = x;
|
||||
potential_wrap.adjust_top_to_this = 0;
|
||||
|
||||
if (buffer_stringify_loop(&stream, params.buffer, i, end_i)){
|
||||
b32 still_looping = true;
|
||||
|
||||
while(still_looping){
|
||||
for (; i < stream.end; ++i){
|
||||
{
|
||||
u8 ch = stream.data[i];
|
||||
translating_fully_process_byte(system, font, &tran, ch, i, end_i, &emits);
|
||||
}
|
||||
|
||||
for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){
|
||||
TRANSLATION_DECL_GET_STEP(buffer_step, behav, J, emits);
|
||||
if (!codepoint_is_whitespace(buffer_step.value)){
|
||||
i = buffer_step.i;
|
||||
goto doublebreak_stage_vspace;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = buffer_stringify_next(&stream);
|
||||
}
|
||||
doublebreak_stage_vspace:;
|
||||
|
||||
do{
|
||||
i32 pos_end_i = end_i;
|
||||
while (still_looping){
|
||||
for (; i < stream.end; ++i){
|
||||
{
|
||||
u8 ch = stream.data[i];
|
||||
translating_fully_process_byte(system, font, &tran, ch, i, end_i, &emits);
|
||||
}
|
||||
|
||||
for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){
|
||||
TRANSLATION_DECL_GET_STEP(buffer_step, behav, J, emits);
|
||||
if (codepoint_is_whitespace(buffer_step.value)){
|
||||
pos_end_i = buffer_step.i;
|
||||
goto doublebreak_stage1;
|
||||
}
|
||||
|
||||
f32 adv = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, buffer_step.value);
|
||||
x += adv;
|
||||
|
||||
if (!first_word && x > current_width){
|
||||
pos_end_i = buffer_step.i;
|
||||
emit_comment_position = true;
|
||||
goto doublebreak_stage1;
|
||||
}
|
||||
}
|
||||
}
|
||||
still_looping = buffer_stringify_next(&stream);
|
||||
}
|
||||
doublebreak_stage1:;
|
||||
first_word = 0;
|
||||
|
||||
if (emit_comment_position){
|
||||
step.position_end = pos_end_i;
|
||||
step.final_x = x;
|
||||
goto finished_comment_split;
|
||||
}
|
||||
|
||||
while(still_looping){
|
||||
for (; i < stream.end; ++i){
|
||||
{
|
||||
u8 ch = stream.data[i];
|
||||
translating_fully_process_byte(system, font, &tran, ch, i, end_i, &emits);
|
||||
}
|
||||
|
||||
for (TRANSLATION_DECL_EMIT_LOOP(J, emits)){
|
||||
TRANSLATION_DECL_GET_STEP(buffer_step, behav, J, emits);
|
||||
|
||||
if (!codepoint_is_whitespace(buffer_step.value)){
|
||||
pos_end_i = buffer_step.i;
|
||||
goto doublebreak_stage2;
|
||||
}
|
||||
|
||||
f32 adv = font_get_glyph_advance(params.system, params.font.settings, params.font.metrics, params.font.pages, buffer_step.value);
|
||||
x += adv;
|
||||
}
|
||||
}
|
||||
still_looping = buffer_stringify_next(&stream);
|
||||
}
|
||||
doublebreak_stage2:;
|
||||
|
||||
potential_wrap.wrap_position = pos_end_i;
|
||||
potential_wrap.wrap_x = x;
|
||||
}while(still_looping);
|
||||
}
|
||||
|
||||
finished_comment_split:;
|
||||
if (emit_comment_position){
|
||||
potential_marks[potential_count] = potential_wrap;
|
||||
++potential_count;
|
||||
}
|
||||
}
|
||||
|
||||
if (!emit_comment_position){
|
||||
step = wrap_state_consume_token(system, font, &wrap_state, next_line_start);
|
||||
}
|
||||
|
||||
b32 need_to_choose_a_wrap = false;
|
||||
if (step.final_x > current_width){
|
||||
need_to_choose_a_wrap = true;
|
||||
}
|
||||
|
||||
current_shift = get_current_shift(&wrap_state, next_line_start);
|
||||
|
||||
b32 next_token_is_on_line = false;
|
||||
if (wrap_state.token_ptr < wrap_state.end_token){
|
||||
if (wrap_state.token_ptr->start < next_line_start){
|
||||
next_token_is_on_line = true;
|
||||
}
|
||||
}
|
||||
|
||||
i32 next_wrap_position = step.position_end;
|
||||
f32 wrap_x = step.final_x;
|
||||
if (next_token_is_on_line){
|
||||
if (wrap_state.token_ptr < wrap_state.end_token){
|
||||
i32 pos_i = wrap_state.token_ptr->start;
|
||||
if (pos_i > step.position_start && next_wrap_position < pos_i){
|
||||
next_wrap_position = pos_i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!need_to_choose_a_wrap){
|
||||
i32 wrappable_score = 1;
|
||||
|
||||
Cpp_Token *this_token = step.this_token;
|
||||
Cpp_Token *next_token = 0;
|
||||
if (wrap_state.token_ptr < wrap_state.end_token){
|
||||
next_token = wrap_state.token_ptr;
|
||||
}
|
||||
|
||||
Cpp_Token_Type this_type = this_token->type;
|
||||
Cpp_Token_Type next_type = CPP_TOKEN_JUNK;
|
||||
|
||||
u16 this_flags = this_token->flags;
|
||||
u16 next_flags = 0;
|
||||
|
||||
if (this_token == next_token || !next_token_is_on_line){
|
||||
next_token = 0;
|
||||
}
|
||||
|
||||
if (next_token){
|
||||
next_type = next_token->type;
|
||||
next_flags = next_token->flags;
|
||||
}
|
||||
|
||||
i32 this_stickieness = stickieness_guess(this_type, next_type, this_flags, next_flags, 1);
|
||||
|
||||
i32 next_stickieness = 0;
|
||||
if (next_token){
|
||||
next_stickieness = stickieness_guess(next_type, this_type, next_flags, this_flags, 0);
|
||||
}
|
||||
|
||||
i32 general_stickieness = this_stickieness;
|
||||
if (general_stickieness < next_stickieness){
|
||||
general_stickieness = next_stickieness;
|
||||
}
|
||||
|
||||
if (wrap_state.wrap_x.paren_top != 0 && this_type == CPP_TOKEN_COMMA){
|
||||
general_stickieness = 0;
|
||||
}
|
||||
|
||||
wrappable_score = 64*50;
|
||||
wrappable_score += 101 - general_stickieness - wrap_state.wrap_x.paren_safe_top*80;
|
||||
|
||||
potential_marks[potential_count].wrap_position = next_wrap_position;
|
||||
potential_marks[potential_count].line_shift = current_shift.shift;
|
||||
potential_marks[potential_count].wrappable_score = wrappable_score;
|
||||
potential_marks[potential_count].wrap_x = wrap_x;
|
||||
potential_marks[potential_count].adjust_top_to_this = current_shift.adjust_top_to_this;
|
||||
++potential_count;
|
||||
}
|
||||
|
||||
if (need_to_choose_a_wrap){
|
||||
if (potential_count == 0){
|
||||
wrap_indent_marks[real_count].wrap_position = next_wrap_position;
|
||||
wrap_indent_marks[real_count].line_shift = current_shift.shift;
|
||||
++real_count;
|
||||
}
|
||||
else{
|
||||
i32 i = 0, best_i = 0;
|
||||
i32 best_score = -1;
|
||||
f32 best_x_shift = 0;
|
||||
|
||||
f32 x_gain_threshold = 18.f;
|
||||
|
||||
for (; i < potential_count; ++i){
|
||||
i32 this_score = potential_marks[i].wrappable_score;
|
||||
f32 x_shift = potential_marks[i].wrap_x - potential_marks[i].line_shift;
|
||||
|
||||
f32 x_shift_adjusted = x_shift - x_gain_threshold;
|
||||
f32 x_left_over = step.final_x - x_shift;
|
||||
|
||||
if (x_shift_adjusted < 0){
|
||||
this_score = 0;
|
||||
}
|
||||
else if (x_left_over <= x_gain_threshold){
|
||||
this_score = 1;
|
||||
}
|
||||
|
||||
if (this_score > best_score){
|
||||
best_score = this_score;
|
||||
best_x_shift = x_shift;
|
||||
best_i = i;
|
||||
}
|
||||
else if (this_score == best_score && x_shift > best_x_shift){
|
||||
best_x_shift = x_shift;
|
||||
best_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
i32 wrap_position = potential_marks[best_i].wrap_position;
|
||||
f32 line_shift = potential_marks[best_i].line_shift;
|
||||
b32 adjust_top_to_this = potential_marks[best_i].adjust_top_to_this;
|
||||
wrap_indent_marks[real_count].wrap_position = wrap_position;
|
||||
wrap_indent_marks[real_count].line_shift = line_shift;
|
||||
++real_count;
|
||||
potential_count = 0;
|
||||
|
||||
wrap_state = original_wrap_state;
|
||||
for (;;){
|
||||
step = wrap_state_consume_token(system, font, &wrap_state, wrap_position);
|
||||
if (step.position_end >= wrap_position){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wrap_state.x = line_shift;
|
||||
wrap_state.i = wrap_position;
|
||||
if (adjust_top_to_this){
|
||||
wrap_state_set_top(&wrap_state, line_shift);
|
||||
}
|
||||
|
||||
original_wrap_state = wrap_state;
|
||||
}
|
||||
}
|
||||
|
||||
if (step.position_end >= next_line_start-1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wrap_indent_marks[real_count].wrap_position = next_line_start;
|
||||
wrap_indent_marks[real_count].line_shift = 0;
|
||||
++real_count;
|
||||
|
||||
for (i32 l = 0; wrap_state.i < next_line_start && l < 3; ++l){
|
||||
wrap_state_consume_token(system, font, &wrap_state, next_line_start);
|
||||
}
|
||||
}
|
||||
|
||||
current_line_shift = wrap_indent_marks[stage].line_shift;
|
||||
|
||||
if (stage > 0){
|
||||
++stage;
|
||||
}
|
||||
|
||||
current_line_shift = clamp_bottom(0.f, current_line_shift);
|
||||
}
|
||||
else{
|
||||
current_line_shift = 0.f;
|
||||
}
|
||||
|
||||
current_line_shift = clamp_top(current_line_shift, current_width - edge_tolerance);
|
||||
|
||||
if (stop.wrap_line_index >= file->state.line_indent_max){
|
||||
file_allocate_indents_as_needed(general, file, stop.wrap_line_index);
|
||||
}
|
||||
|
||||
file->state.line_indents[stop.wrap_line_index] = current_line_shift;
|
||||
file->state.wrap_line_count = stop.wrap_line_index;
|
||||
}break;
|
||||
}
|
||||
}while(stop.status != BLStatus_Finished);
|
||||
|
||||
++file->state.wrap_line_count;
|
||||
|
||||
file_allocate_wrap_positions_as_needed(general, file, wrap_position_index);
|
||||
file->state.wrap_positions[wrap_position_index++] = size;
|
||||
file->state.wrap_position_count = wrap_position_index;
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* Code wrapping logic
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_CODE_WRAP_H)
|
||||
#define FRED_CODE_WRAP_H
|
||||
|
||||
struct Code_Wrap_X{
|
||||
f32 base_x;
|
||||
f32 paren_nesting[32];
|
||||
i32 paren_safe_top;
|
||||
i32 paren_top;
|
||||
};
|
||||
global Code_Wrap_X null_wrap_x = {0};
|
||||
|
||||
struct Code_Wrap_State{
|
||||
Cpp_Token_Array token_array;
|
||||
Cpp_Token *token_ptr;
|
||||
Cpp_Token *end_token;
|
||||
|
||||
Code_Wrap_X wrap_x;
|
||||
|
||||
b32 in_pp_body;
|
||||
Code_Wrap_X plane_wrap_x;
|
||||
|
||||
i32 *line_starts;
|
||||
i32 line_count;
|
||||
i32 line_index;
|
||||
i32 next_line_start;
|
||||
|
||||
f32 x;
|
||||
b32 consume_newline;
|
||||
|
||||
Gap_Buffer_Stream stream;
|
||||
i32 size;
|
||||
i32 i;
|
||||
|
||||
Font_Pointers font;
|
||||
f32 tab_indent_amount;
|
||||
f32 byte_advance;
|
||||
|
||||
Translation_State tran;
|
||||
Translation_Emits emits;
|
||||
u32 J;
|
||||
Buffer_Model_Step step;
|
||||
Buffer_Model_Behavior behavior;
|
||||
};
|
||||
|
||||
struct Code_Wrap_Step{
|
||||
i32 position_start;
|
||||
i32 position_end;
|
||||
|
||||
f32 start_x;
|
||||
f32 final_x;
|
||||
|
||||
Cpp_Token *this_token;
|
||||
};
|
||||
|
||||
struct Wrap_Current_Shift{
|
||||
f32 shift;
|
||||
b32 adjust_top_to_this;
|
||||
};
|
||||
|
||||
internal void
|
||||
file_measure_wraps(System_Functions *system, Mem_Options *mem, Editing_File *file, Font_Pointers font);
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -3,47 +3,12 @@
|
|||
*
|
||||
* 19.08.2015
|
||||
*
|
||||
* Command management functions for 4coder
|
||||
* Command management functions
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#define Command_Function_Sig(name) \
|
||||
void (name)(System_Functions *system, struct Command_Data *command, struct Command_Binding binding)
|
||||
|
||||
typedef Command_Function_Sig(Command_Function);
|
||||
|
||||
struct Command_Binding{
|
||||
Command_Function *function;
|
||||
union{
|
||||
Custom_Command_Function *custom;
|
||||
u64 custom_id;
|
||||
};
|
||||
u64 hash;
|
||||
};
|
||||
static Command_Binding null_command_binding = {0};
|
||||
|
||||
struct Command_Map{
|
||||
i32 parent;
|
||||
Command_Binding vanilla_keyboard_default[1 << MDFR_INDEX_BINDABLE_COUNT];
|
||||
Command_Binding *commands;
|
||||
i32 count, max;
|
||||
void *real_beginning;
|
||||
};
|
||||
|
||||
struct Mapping{
|
||||
void *memory;
|
||||
|
||||
Command_Map map_top;
|
||||
Command_Map map_file;
|
||||
Command_Map map_ui;
|
||||
|
||||
i32 *map_id_table;
|
||||
Command_Map *user_maps;
|
||||
i32 user_map_count;
|
||||
};
|
||||
|
||||
internal i32
|
||||
get_or_add_map_index(Mapping *mapping, i32 mapid){
|
||||
i32 user_map_count = mapping->user_map_count;
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2015
|
||||
*
|
||||
* Command representation structures
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_COMMAND_H)
|
||||
#define FRED_COMMAND_H
|
||||
|
||||
#define Command_Function_Sig(name) \
|
||||
void (name)(System_Functions *system, struct Command_Data *command, struct Command_Binding binding)
|
||||
|
||||
typedef Command_Function_Sig(Command_Function);
|
||||
|
||||
struct Command_Binding{
|
||||
Command_Function *function;
|
||||
union{
|
||||
Custom_Command_Function *custom;
|
||||
u64 custom_id;
|
||||
};
|
||||
u64 hash;
|
||||
};
|
||||
|
||||
struct Command_Map{
|
||||
i32 parent;
|
||||
Command_Binding vanilla_keyboard_default[1 << MDFR_INDEX_BINDABLE_COUNT];
|
||||
Command_Binding *commands;
|
||||
i32 count;
|
||||
i32 max;
|
||||
void *real_beginning;
|
||||
};
|
||||
|
||||
struct Mapping{
|
||||
void *memory;
|
||||
|
||||
Command_Map map_top;
|
||||
Command_Map map_file;
|
||||
Command_Map map_ui;
|
||||
|
||||
i32 *map_id_table;
|
||||
Command_Map *user_maps;
|
||||
i32 user_map_count;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
533
4ed_file.cpp
533
4ed_file.cpp
|
@ -9,32 +9,6 @@
|
|||
|
||||
// TOP
|
||||
|
||||
//
|
||||
// Edit Position Basics
|
||||
//
|
||||
|
||||
internal void
|
||||
edit_pos_set_cursor(File_Edit_Positions *edit_pos, Full_Cursor cursor, b32 set_preferred_x, b32 unwrapped_lines){
|
||||
edit_pos->cursor = cursor;
|
||||
if (set_preferred_x){
|
||||
edit_pos->preferred_x = cursor.wrapped_x;
|
||||
if (unwrapped_lines){
|
||||
edit_pos->preferred_x = cursor.unwrapped_x;
|
||||
}
|
||||
}
|
||||
edit_pos->last_set_type = EditPos_CursorSet;
|
||||
}
|
||||
|
||||
internal void
|
||||
edit_pos_set_scroll(File_Edit_Positions *edit_pos, GUI_Scroll_Vars scroll){
|
||||
edit_pos->scroll = scroll;
|
||||
edit_pos->last_set_type = EditPos_ScrollSet;
|
||||
}
|
||||
|
||||
//
|
||||
// Editing_File
|
||||
//
|
||||
|
||||
inline Buffer_Slot_ID
|
||||
to_file_id(i32 id){
|
||||
Buffer_Slot_ID result;
|
||||
|
@ -42,9 +16,7 @@ to_file_id(i32 id){
|
|||
return(result);
|
||||
}
|
||||
|
||||
//
|
||||
// Handling a file's Marker Arrays
|
||||
//
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
init_file_markers_state(Editing_File_Markers *markers){
|
||||
|
@ -149,9 +121,25 @@ markers_free(General_Memory *general, Editing_File *file, void *handle){
|
|||
return(result);
|
||||
}
|
||||
|
||||
//
|
||||
// Manipulating a file's Edit_Pos array
|
||||
//
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
edit_pos_set_cursor(File_Edit_Positions *edit_pos, Full_Cursor cursor, b32 set_preferred_x, b32 unwrapped_lines){
|
||||
edit_pos->cursor = cursor;
|
||||
if (set_preferred_x){
|
||||
edit_pos->preferred_x = cursor.wrapped_x;
|
||||
if (unwrapped_lines){
|
||||
edit_pos->preferred_x = cursor.unwrapped_x;
|
||||
}
|
||||
}
|
||||
edit_pos->last_set_type = EditPos_CursorSet;
|
||||
}
|
||||
|
||||
internal void
|
||||
edit_pos_set_scroll(File_Edit_Positions *edit_pos, GUI_Scroll_Vars scroll){
|
||||
edit_pos->scroll = scroll;
|
||||
edit_pos->last_set_type = EditPos_ScrollSet;
|
||||
}
|
||||
|
||||
internal i32
|
||||
edit_pos_get_index(Editing_File *file, File_Edit_Positions *edit_pos){
|
||||
|
@ -251,78 +239,32 @@ edit_pos_get_new(Editing_File *file, i32 index){
|
|||
return(result);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Cursor Seeking
|
||||
//
|
||||
|
||||
inline Partial_Cursor
|
||||
file_compute_cursor_from_pos(Editing_File *file, i32 pos){
|
||||
Partial_Cursor result = buffer_partial_from_pos(&file->state.buffer, pos);
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline Partial_Cursor
|
||||
file_compute_cursor_from_line_character(Editing_File *file, i32 line, i32 character){
|
||||
Partial_Cursor result = buffer_partial_from_line_character(&file->state.buffer, line, character);
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline b32
|
||||
file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek, Partial_Cursor *cursor){
|
||||
b32 result = true;
|
||||
switch (seek.type){
|
||||
case buffer_seek_pos:
|
||||
{
|
||||
*cursor = file_compute_cursor_from_pos(file, seek.pos);
|
||||
}break;
|
||||
|
||||
case buffer_seek_line_char:
|
||||
{
|
||||
*cursor = file_compute_cursor_from_line_character(file, seek.line, seek.character);
|
||||
}break;
|
||||
|
||||
default:
|
||||
{
|
||||
result = false;
|
||||
}break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Dirty Flags
|
||||
//
|
||||
////////////////////////////////
|
||||
|
||||
inline b32
|
||||
buffer_needs_save(Editing_File *file){
|
||||
b32 result = 0;
|
||||
if (!file->settings.unimportant){
|
||||
if (file->state.dirty == DirtyState_UnsavedChanges){
|
||||
result = 1;
|
||||
}
|
||||
b32 result = false;
|
||||
if (file->state.dirty == DirtyState_UnsavedChanges){
|
||||
result = true;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline b32
|
||||
buffer_can_save(Editing_File *file){
|
||||
b32 result = 0;
|
||||
if (!file->settings.unimportant){
|
||||
if (file->state.dirty == DirtyState_UnsavedChanges ||
|
||||
file->state.dirty == DirtyState_UnloadedChanges){
|
||||
result = 1;
|
||||
}
|
||||
b32 result = false;
|
||||
if (file->state.dirty == DirtyState_UnsavedChanges ||
|
||||
file->state.dirty == DirtyState_UnloadedChanges){
|
||||
result = true;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline b32
|
||||
file_is_ready(Editing_File *file){
|
||||
b32 result = 0;
|
||||
if (file && file->is_loading == 0){
|
||||
result = 1;
|
||||
b32 result = false;
|
||||
if (file != 0 && file->is_loading == 0){
|
||||
result = true;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
@ -335,44 +277,409 @@ file_set_to_loading(Editing_File *file){
|
|||
}
|
||||
|
||||
inline void
|
||||
file_mark_clean(Editing_File *file){
|
||||
if (file->settings.unimportant){
|
||||
file->state.dirty = DirtyState_UpToDate;
|
||||
file_set_dirty_flag(Editing_File *file, Dirty_State state){
|
||||
if (!file->settings.unimportant){
|
||||
file->state.dirty = state;
|
||||
}
|
||||
else{
|
||||
if (file->state.dirty != DirtyState_UnloadedChanges){
|
||||
file->state.dirty = DirtyState_UpToDate;
|
||||
file->state.dirty = DirtyState_UpToDate;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal b32
|
||||
save_file_to_name(System_Functions *system, Models *models, Editing_File *file, char *filename){
|
||||
b32 result = false;
|
||||
b32 using_actual_filename = false;
|
||||
|
||||
if (filename == 0){
|
||||
terminate_with_null(&file->canon.name);
|
||||
filename = file->canon.name.str;
|
||||
using_actual_filename = true;
|
||||
}
|
||||
|
||||
if (filename != 0){
|
||||
Mem_Options *mem = &models->mem;
|
||||
if (models->hook_save_file){
|
||||
models->hook_save_file(&models->app_links, file->id.id);
|
||||
}
|
||||
|
||||
i32 max = 0, size = 0;
|
||||
b32 dos_write_mode = file->settings.dos_write_mode;
|
||||
char *data = 0;
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
|
||||
if (dos_write_mode){
|
||||
max = buffer_size(buffer) + buffer->line_count + 1;
|
||||
}
|
||||
else{
|
||||
max = buffer_size(buffer);
|
||||
}
|
||||
|
||||
b32 used_general = 0;
|
||||
Temp_Memory temp = begin_temp_memory(&mem->part);
|
||||
char empty = 0;
|
||||
if (max == 0){
|
||||
data = ∅
|
||||
}
|
||||
else{
|
||||
data = (char*)push_array(&mem->part, char, max);
|
||||
if (!data){
|
||||
used_general = 1;
|
||||
data = (char*)general_memory_allocate(&mem->general, max);
|
||||
}
|
||||
}
|
||||
Assert(data != 0);
|
||||
|
||||
if (dos_write_mode){
|
||||
size = buffer_convert_out(buffer, data, max);
|
||||
}
|
||||
else{
|
||||
size = max;
|
||||
buffer_stringify(buffer, 0, size, data);
|
||||
}
|
||||
|
||||
if (!using_actual_filename && file->canon.name.str != 0){
|
||||
char space[512];
|
||||
u32 length = str_size(filename);
|
||||
system->get_canonical(filename, length, space, sizeof(space));
|
||||
|
||||
char *source_path = file->canon.name.str;
|
||||
if (match(space, source_path)){
|
||||
using_actual_filename = true;
|
||||
}
|
||||
}
|
||||
|
||||
result = system->save_file(filename, data, size);
|
||||
|
||||
if (result && using_actual_filename){
|
||||
file->state.ignore_behind_os = 1;
|
||||
}
|
||||
|
||||
file_set_dirty_flag(file, DirtyState_UpToDate);
|
||||
|
||||
if (used_general){
|
||||
general_memory_free(&mem->general, data);
|
||||
}
|
||||
end_temp_memory(temp);
|
||||
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline b32
|
||||
save_file(System_Functions *system, Models *models, Editing_File *file){
|
||||
b32 result = save_file_to_name(system, models, file, 0);
|
||||
return(result);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
inline b32
|
||||
file_compute_partial_cursor(Editing_File *file, Buffer_Seek seek, Partial_Cursor *cursor){
|
||||
b32 result = true;
|
||||
switch (seek.type){
|
||||
case buffer_seek_pos:
|
||||
{
|
||||
*cursor = buffer_partial_from_pos(&file->state.buffer, seek.pos);
|
||||
}break;
|
||||
|
||||
case buffer_seek_line_char:
|
||||
{
|
||||
*cursor = buffer_partial_from_line_character(&file->state.buffer, seek.line, seek.character);
|
||||
}break;
|
||||
|
||||
default:
|
||||
{
|
||||
result = false;
|
||||
}break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal Full_Cursor
|
||||
file_compute_cursor(System_Functions *system, Editing_File *file, Buffer_Seek seek, b32 return_hint){
|
||||
Font_Pointers font = system->font.get_pointers_by_id(file->settings.font_id);
|
||||
Assert(font.valid);
|
||||
|
||||
Full_Cursor result = {0};
|
||||
|
||||
Buffer_Cursor_Seek_Params params;
|
||||
params.buffer = &file->state.buffer;
|
||||
params.seek = seek;
|
||||
params.system = system;
|
||||
params.font = font;
|
||||
params.wrap_line_index = file->state.wrap_line_index;
|
||||
params.character_starts = file->state.character_starts;
|
||||
params.virtual_white = file->settings.virtual_white;
|
||||
params.return_hint = return_hint;
|
||||
params.cursor_out = &result;
|
||||
|
||||
Buffer_Cursor_Seek_State state = {0};
|
||||
Buffer_Layout_Stop stop = {0};
|
||||
|
||||
i32 size = buffer_size(params.buffer);
|
||||
|
||||
f32 line_shift = 0.f;
|
||||
b32 do_wrap = 0;
|
||||
i32 wrap_unit_end = 0;
|
||||
|
||||
b32 first_wrap_determination = 1;
|
||||
i32 wrap_array_index = 0;
|
||||
|
||||
do{
|
||||
stop = buffer_cursor_seek(&state, params, line_shift, do_wrap, wrap_unit_end);
|
||||
switch (stop.status){
|
||||
case BLStatus_NeedWrapDetermination:
|
||||
{
|
||||
if (stop.pos >= size){
|
||||
do_wrap = 0;
|
||||
wrap_unit_end = max_i32;
|
||||
}
|
||||
else{
|
||||
if (first_wrap_determination){
|
||||
wrap_array_index = binary_search(file->state.wrap_positions, stop.pos, 0, file->state.wrap_position_count);
|
||||
++wrap_array_index;
|
||||
if (file->state.wrap_positions[wrap_array_index] == stop.pos){
|
||||
do_wrap = 1;
|
||||
wrap_unit_end = file->state.wrap_positions[wrap_array_index];
|
||||
}
|
||||
else{
|
||||
do_wrap = 0;
|
||||
wrap_unit_end = file->state.wrap_positions[wrap_array_index];
|
||||
}
|
||||
first_wrap_determination = 0;
|
||||
}
|
||||
else{
|
||||
Assert(stop.pos == wrap_unit_end);
|
||||
do_wrap = 1;
|
||||
++wrap_array_index;
|
||||
wrap_unit_end = file->state.wrap_positions[wrap_array_index];
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case BLStatus_NeedWrapLineShift:
|
||||
case BLStatus_NeedLineShift:
|
||||
{
|
||||
line_shift = file->state.line_indents[stop.wrap_line_index];
|
||||
}break;
|
||||
}
|
||||
}while(stop.status != BLStatus_Finished);
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal i32
|
||||
file_grow_starts_as_needed(General_Memory *general, Gap_Buffer *buffer, i32 additional_lines){
|
||||
b32 result = GROW_NOT_NEEDED;
|
||||
i32 max = buffer->line_max;
|
||||
i32 count = buffer->line_count;
|
||||
i32 target_lines = count + additional_lines;
|
||||
|
||||
if (target_lines > max || max == 0){
|
||||
max = l_round_up_i32(target_lines + max, KB(1));
|
||||
|
||||
i32 *new_lines = (i32*)general_memory_reallocate(general, buffer->line_starts, sizeof(i32)*count, sizeof(f32)*max);
|
||||
|
||||
if (new_lines){
|
||||
result = GROW_SUCCESS;
|
||||
buffer->line_max = max;
|
||||
buffer->line_starts = new_lines;
|
||||
}
|
||||
else{
|
||||
result = GROW_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
file_measure_starts(General_Memory *general, Gap_Buffer *buffer){
|
||||
PRFL_FUNC_GROUP();
|
||||
|
||||
if (buffer->line_starts == 0){
|
||||
i32 max = buffer->line_max = KB(1);
|
||||
buffer->line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32));
|
||||
Assert(buffer->line_starts != 0);
|
||||
}
|
||||
|
||||
Buffer_Measure_Starts state = {0};
|
||||
for (;buffer_measure_starts(&state, buffer);){
|
||||
i32 count = state.count;
|
||||
i32 max = ((buffer->line_max + 1) << 1);
|
||||
i32 *new_lines = (i32*)general_memory_reallocate(general, buffer->line_starts, sizeof(i32)*count, sizeof(i32)*max);
|
||||
Assert(new_lines);
|
||||
buffer->line_starts = new_lines;
|
||||
buffer->line_max = max;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
file_allocate_metadata_as_needed(General_Memory *general, Gap_Buffer *buffer, void **mem, i32 *mem_max_count, i32 count, i32 item_size){
|
||||
if (*mem == 0){
|
||||
i32 max = l_round_up_i32(((count + 1)*2), KB(1));
|
||||
*mem = general_memory_allocate(general, max*item_size);
|
||||
*mem_max_count = max;
|
||||
Assert(*mem != 0);
|
||||
}
|
||||
else if (*mem_max_count < count){
|
||||
i32 old_max = *mem_max_count;
|
||||
i32 max = l_round_up_i32(((count + 1)*2), KB(1));
|
||||
void *new_mem = general_memory_reallocate(general, *mem, item_size*old_max, item_size*max);
|
||||
*mem = new_mem;
|
||||
*mem_max_count = max;
|
||||
Assert(*mem != 0);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
file_mark_dirty(Editing_File *file){
|
||||
if (file->settings.unimportant){
|
||||
file->state.dirty = DirtyState_UpToDate;
|
||||
}
|
||||
else{
|
||||
if (file->state.dirty != DirtyState_UnloadedChanges){
|
||||
file->state.dirty = DirtyState_UnsavedChanges;
|
||||
}
|
||||
}
|
||||
file_allocate_character_starts_as_needed(General_Memory *general, Editing_File *file){
|
||||
file_allocate_metadata_as_needed(general, &file->state.buffer, (void**)&file->state.character_starts, &file->state. character_start_max, file->state.buffer.line_count, sizeof(i32));
|
||||
}
|
||||
|
||||
internal void
|
||||
file_allocate_indents_as_needed(General_Memory *general, Editing_File *file, i32 min_last_index){
|
||||
i32 min_amount = min_last_index + 1;
|
||||
file_allocate_metadata_as_needed(general, &file->state.buffer, (void**)&file->state.line_indents, &file->state.line_indent_max, min_amount, sizeof(f32));
|
||||
}
|
||||
|
||||
inline void
|
||||
file_mark_behind_os(Editing_File *file){
|
||||
if (file->settings.unimportant){
|
||||
file->state.dirty = DirtyState_UpToDate;
|
||||
}
|
||||
else{
|
||||
file->state.dirty = DirtyState_UnloadedChanges;
|
||||
}
|
||||
file_allocate_wraps_as_needed(General_Memory *general, Editing_File *file){
|
||||
file_allocate_metadata_as_needed(general, &file->state.buffer, (void**)&file->state.wrap_line_index, &file->state.wrap_max, file->state.buffer.line_count, sizeof(f32));
|
||||
}
|
||||
|
||||
inline Dirty_State
|
||||
file_get_sync(Editing_File *file){
|
||||
return (file->state.dirty);
|
||||
inline void
|
||||
file_allocate_wrap_positions_as_needed(General_Memory *general, Editing_File *file, i32 min_last_index){
|
||||
i32 min_amount = min_last_index + 1;
|
||||
file_allocate_metadata_as_needed(general, &file->state.buffer, (void**)&file->state.wrap_positions, &file->state.wrap_position_max, min_amount, sizeof(f32));
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal void
|
||||
file_create_from_string(System_Functions *system, Models *models, Editing_File *file, String val, u32 flags){
|
||||
PRFL_FUNC_GROUP();
|
||||
|
||||
General_Memory *general = &models->mem.general;
|
||||
Partition *part = &models->mem.part;
|
||||
Open_File_Hook_Function *hook_open_file = models->hook_open_file;
|
||||
Application_Links *app_links = &models->app_links;
|
||||
|
||||
memset(&file->state, 0, sizeof(file->state));
|
||||
Gap_Buffer_Init init = buffer_begin_init(&file->state.buffer, val.str, val.size);
|
||||
for (; buffer_init_need_more(&init); ){
|
||||
i32 page_size = buffer_init_page_size(&init);
|
||||
page_size = l_round_up_i32(page_size, KB(4));
|
||||
if (page_size < KB(4)){
|
||||
page_size = KB(4);
|
||||
}
|
||||
void *data = general_memory_allocate(general, page_size);
|
||||
buffer_init_provide_page(&init, data, page_size);
|
||||
}
|
||||
|
||||
i32 scratch_size = partition_remaining(part);
|
||||
Assert(scratch_size > 0);
|
||||
b32 init_success = buffer_end_init(&init, part->base + part->pos, scratch_size);
|
||||
AllowLocal(init_success); Assert(init_success);
|
||||
|
||||
if (buffer_size(&file->state.buffer) < val.size){
|
||||
file->settings.dos_write_mode = 1;
|
||||
}
|
||||
file_set_dirty_flag(file, DirtyState_UpToDate);
|
||||
|
||||
Face_ID font_id = models->global_font_id;
|
||||
file->settings.font_id = font_id;
|
||||
Font_Pointers font = system->font.get_pointers_by_id(font_id);
|
||||
Assert(font.valid);
|
||||
|
||||
{
|
||||
file_measure_starts(general, &file->state.buffer);
|
||||
|
||||
file_allocate_character_starts_as_needed(general, file);
|
||||
buffer_measure_character_starts(system, font, &file->state.buffer, file->state.character_starts, 0, file->settings.virtual_white);
|
||||
|
||||
file_measure_wraps(system, &models->mem, file, font);
|
||||
//adjust_views_looking_at_files_to_new_cursor(system, models, file);
|
||||
}
|
||||
|
||||
file->settings.read_only = ((flags & FileCreateFlag_ReadOnly) != 0);
|
||||
if (!file->settings.read_only){
|
||||
// TODO(allen): Redo undo system (if you don't mind the pun)
|
||||
i32 request_size = KB(64);
|
||||
file->state.undo.undo.max = request_size;
|
||||
file->state.undo.undo.strings = (u8*)general_memory_allocate(general, request_size);
|
||||
file->state.undo.undo.edit_max = request_size / sizeof(Edit_Step);
|
||||
file->state.undo.undo.edits = (Edit_Step*)general_memory_allocate(general, request_size);
|
||||
|
||||
file->state.undo.redo.max = request_size;
|
||||
file->state.undo.redo.strings = (u8*)general_memory_allocate(general, request_size);
|
||||
file->state.undo.redo.edit_max = request_size / sizeof(Edit_Step);
|
||||
file->state.undo.redo.edits = (Edit_Step*)general_memory_allocate(general, request_size);
|
||||
|
||||
file->state.undo.history.max = request_size;
|
||||
file->state.undo.history.strings = (u8*)general_memory_allocate(general, request_size);
|
||||
file->state.undo.history.edit_max = request_size / sizeof(Edit_Step);
|
||||
file->state.undo.history.edits = (Edit_Step*)general_memory_allocate(general, request_size);
|
||||
|
||||
file->state.undo.children.max = request_size;
|
||||
file->state.undo.children.strings = (u8*)general_memory_allocate(general, request_size);
|
||||
file->state.undo.children.edit_max = request_size / sizeof(Buffer_Edit);
|
||||
file->state.undo.children.edits = (Buffer_Edit*)general_memory_allocate(general, request_size);
|
||||
|
||||
file->state.undo.history_block_count = 1;
|
||||
file->state.undo.history_head_block = 0;
|
||||
file->state.undo.current_block_normal = 1;
|
||||
}
|
||||
|
||||
if (hook_open_file != 0){
|
||||
hook_open_file(app_links, file->id.id);
|
||||
}
|
||||
file->settings.is_initialized = true;
|
||||
}
|
||||
|
||||
internal void
|
||||
file_free(System_Functions *system, General_Memory *general, Editing_File *file){
|
||||
if (file->state.still_lexing){
|
||||
system->cancel_job(BACKGROUND_THREADS, file->state.lex_job);
|
||||
if (file->state.swap_array.tokens){
|
||||
general_memory_free(general, file->state.swap_array.tokens);
|
||||
file->state.swap_array.tokens = 0;
|
||||
}
|
||||
}
|
||||
if (file->state.token_array.tokens){
|
||||
general_memory_free(general, file->state.token_array.tokens);
|
||||
}
|
||||
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
if (buffer->data){
|
||||
general_memory_free(general, buffer->data);
|
||||
general_memory_free(general, buffer->line_starts);
|
||||
}
|
||||
|
||||
general_memory_free(general, file->state.wrap_line_index);
|
||||
general_memory_free(general, file->state.character_starts);
|
||||
general_memory_free(general, file->state.line_indents);
|
||||
|
||||
if (file->state.undo.undo.edits){
|
||||
general_memory_free(general, file->state.undo.undo.strings);
|
||||
general_memory_free(general, file->state.undo.undo.edits);
|
||||
|
||||
general_memory_free(general, file->state.undo.redo.strings);
|
||||
general_memory_free(general, file->state.undo.redo.edits);
|
||||
|
||||
general_memory_free(general, file->state.undo.history.strings);
|
||||
general_memory_free(general, file->state.undo.history.edits);
|
||||
|
||||
general_memory_free(general, file->state.undo.children.strings);
|
||||
general_memory_free(general, file->state.undo.children.edits);
|
||||
}
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -72,11 +72,6 @@ struct Editing_File_Settings{
|
|||
u8 pad[1];
|
||||
};
|
||||
|
||||
struct Editing_Hacks{
|
||||
b32 suppression_mode;
|
||||
b32 needs_wraps_and_fix_cursor;
|
||||
};
|
||||
|
||||
struct Editing_File_State{
|
||||
Gap_Buffer buffer;
|
||||
|
||||
|
@ -111,8 +106,6 @@ struct Editing_File_State{
|
|||
File_Edit_Positions edit_pos_space[16];
|
||||
File_Edit_Positions *edit_poss[16];
|
||||
i32 edit_poss_count;
|
||||
|
||||
Editing_Hacks hacks;
|
||||
};
|
||||
|
||||
struct Editing_File_Name{
|
||||
|
|
|
@ -0,0 +1,511 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 19.08.2018
|
||||
*
|
||||
* Ways of calling lexer for the text in Editing_File
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
internal
|
||||
Job_Callback_Sig(job_full_lex){
|
||||
Editing_File *file = (Editing_File*)data[0];
|
||||
General_Memory *general = (General_Memory*)data[1];
|
||||
Models *models = (Models*)data[2];
|
||||
|
||||
Parse_Context parse_context = parse_context_get(&models->parse_context_memory, file->settings.parse_context_id, memory->data, memory->size);
|
||||
if (!parse_context.valid){
|
||||
return;
|
||||
}
|
||||
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
i32 text_size = buffer_size(buffer);
|
||||
|
||||
u32 aligned_buffer_size = (text_size + 3)&(~3);
|
||||
|
||||
for (;memory->size < aligned_buffer_size + parse_context.memory_size;){
|
||||
void *old_base = memory->data;
|
||||
system->grow_thread_memory(memory);
|
||||
parse_context_rebase(&parse_context, old_base, memory->data);
|
||||
}
|
||||
|
||||
u8 *data_ptr = (u8*)memory->data;
|
||||
umem data_size = memory->size;
|
||||
data_ptr += parse_context.memory_size;
|
||||
data_size -= parse_context.memory_size;
|
||||
|
||||
Cpp_Token_Array tokens = {0};
|
||||
tokens.tokens = (Cpp_Token*)(data_ptr);
|
||||
tokens.max_count = (u32)(data_size / sizeof(Cpp_Token));
|
||||
tokens.count = 0;
|
||||
|
||||
b32 still_lexing = true;
|
||||
|
||||
Cpp_Lex_Data lex = cpp_lex_data_init(file->settings.tokens_without_strings, parse_context.kw_table, parse_context.pp_table);
|
||||
|
||||
// TODO(allen): deduplicate this against relex
|
||||
char *chunks[3];
|
||||
i32 chunk_sizes[3];
|
||||
chunks[0] = buffer->data;
|
||||
chunk_sizes[0] = buffer->size1;
|
||||
chunks[1] = buffer->data + buffer->size1 + buffer->gap_size;
|
||||
chunk_sizes[1] = buffer->size2;
|
||||
chunks[2] = 0;
|
||||
chunk_sizes[2] = 0;
|
||||
|
||||
i32 chunk_index = 0;
|
||||
|
||||
do{
|
||||
char *chunk = chunks[chunk_index];
|
||||
i32 chunk_size = chunk_sizes[chunk_index];
|
||||
|
||||
i32 result =
|
||||
cpp_lex_step(&lex, chunk, chunk_size, text_size, &tokens, 2048);
|
||||
|
||||
switch (result){
|
||||
case LexResult_NeedChunk:
|
||||
{
|
||||
++chunk_index;
|
||||
Assert(chunk_index < ArrayCount(chunks));
|
||||
}break;
|
||||
|
||||
case LexResult_NeedTokenMemory:
|
||||
{
|
||||
if (system->check_cancel(thread)){
|
||||
return;
|
||||
}
|
||||
|
||||
void *old_base = memory->data;
|
||||
system->grow_thread_memory(memory);
|
||||
cpp_rebase_tables(&lex, old_base, memory->data);
|
||||
|
||||
data_ptr = (u8*)memory->data;
|
||||
data_size = memory->size;
|
||||
data_ptr += parse_context.memory_size;
|
||||
data_size -= parse_context.memory_size;
|
||||
tokens.tokens = (Cpp_Token*)(data_ptr);
|
||||
tokens.max_count = (u32)(data_size / sizeof(Cpp_Token));
|
||||
}break;
|
||||
|
||||
case LexResult_HitTokenLimit:
|
||||
{
|
||||
if (system->check_cancel(thread)){
|
||||
return;
|
||||
}
|
||||
}break;
|
||||
|
||||
case LexResult_Finished:
|
||||
{
|
||||
still_lexing = false;
|
||||
}break;
|
||||
}
|
||||
}while(still_lexing);
|
||||
|
||||
i32 new_max = l_round_up_i32(tokens.count+1, KB(1));
|
||||
|
||||
system->acquire_lock(FRAME_LOCK);
|
||||
{
|
||||
Assert(file->state.swap_array.tokens == 0);
|
||||
file->state.swap_array.tokens = (Cpp_Token*)general_memory_allocate(general, new_max*sizeof(Cpp_Token));
|
||||
}
|
||||
system->release_lock(FRAME_LOCK);
|
||||
|
||||
u8 *dest = (u8*)file->state.swap_array.tokens;
|
||||
u8 *src = (u8*)tokens.tokens;
|
||||
|
||||
memcpy(dest, src, tokens.count*sizeof(Cpp_Token));
|
||||
|
||||
system->acquire_lock(FRAME_LOCK);
|
||||
{
|
||||
Cpp_Token_Array *file_token_array = &file->state.token_array;
|
||||
file_token_array->count = tokens.count;
|
||||
file_token_array->max_count = new_max;
|
||||
if (file_token_array->tokens){
|
||||
general_memory_free(general, file_token_array->tokens);
|
||||
}
|
||||
file_token_array->tokens = file->state.swap_array.tokens;
|
||||
file->state.swap_array.tokens = 0;
|
||||
}
|
||||
system->release_lock(FRAME_LOCK);
|
||||
|
||||
// NOTE(allen): These are outside the locked section because I don't
|
||||
// think getting these out of order will cause critical bugs, and I
|
||||
// want to minimize what's done in locked sections.
|
||||
file->state.tokens_complete = true;
|
||||
file->state.still_lexing = false;
|
||||
}
|
||||
|
||||
internal void
|
||||
file_kill_tokens(System_Functions *system, General_Memory *general, Editing_File *file){
|
||||
file->settings.tokens_exist = 0;
|
||||
if (file->state.still_lexing){
|
||||
system->cancel_job(BACKGROUND_THREADS, file->state.lex_job);
|
||||
if (file->state.swap_array.tokens){
|
||||
general_memory_free(general, file->state.swap_array.tokens);
|
||||
file->state.swap_array.tokens = 0;
|
||||
}
|
||||
}
|
||||
if (file->state.token_array.tokens){
|
||||
general_memory_free(general, file->state.token_array.tokens);
|
||||
}
|
||||
file->state.tokens_complete = 0;
|
||||
file->state.token_array = null_cpp_token_array;
|
||||
}
|
||||
|
||||
internal void
|
||||
file_first_lex_parallel(System_Functions *system, Models *models, Editing_File *file){
|
||||
General_Memory *general = &models->mem.general;
|
||||
file->settings.tokens_exist = true;
|
||||
|
||||
if (file->is_loading == 0 && file->state.still_lexing == 0){
|
||||
Assert(file->state.token_array.tokens == 0);
|
||||
|
||||
file->state.tokens_complete = false;
|
||||
file->state.still_lexing = true;
|
||||
|
||||
Job_Data job;
|
||||
job.callback = job_full_lex;
|
||||
job.data[0] = file;
|
||||
job.data[1] = general;
|
||||
job.data[2] = models;
|
||||
file->state.lex_job = system->post_job(BACKGROUND_THREADS, job);
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
file_first_lex_serial(Models *models, Editing_File *file){
|
||||
Mem_Options *mem = &models->mem;
|
||||
Partition *part = &mem->part;
|
||||
General_Memory *general = &mem->general;
|
||||
file->settings.tokens_exist = true;
|
||||
|
||||
Assert(!file->state.still_lexing);
|
||||
|
||||
if (file->is_loading == 0){
|
||||
Assert(file->state.token_array.tokens == 0);
|
||||
|
||||
{
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
|
||||
Parse_Context parse_context = parse_context_get(&models->parse_context_memory, file->settings.parse_context_id, partition_current(part), partition_remaining(part));
|
||||
Assert(parse_context.valid);
|
||||
push_block(part, (i32)parse_context.memory_size);
|
||||
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
i32 text_size = buffer_size(buffer);
|
||||
|
||||
i32 mem_size = partition_remaining(part);
|
||||
|
||||
Cpp_Token_Array new_tokens;
|
||||
new_tokens.max_count = mem_size/sizeof(Cpp_Token);
|
||||
new_tokens.count = 0;
|
||||
new_tokens.tokens = push_array(part, Cpp_Token, new_tokens.max_count);
|
||||
|
||||
b32 still_lexing = true;
|
||||
|
||||
Cpp_Lex_Data lex = cpp_lex_data_init(file->settings.tokens_without_strings, parse_context.kw_table, parse_context.pp_table);
|
||||
|
||||
// TODO(allen): deduplicate this against relex
|
||||
char *chunks[3];
|
||||
i32 chunk_sizes[3];
|
||||
chunks[0] = buffer->data;
|
||||
chunk_sizes[0] = buffer->size1;
|
||||
chunks[1] = buffer->data + buffer->size1 + buffer->gap_size;
|
||||
chunk_sizes[1] = buffer->size2;
|
||||
chunks[2] = 0;
|
||||
chunk_sizes[2] = 0;
|
||||
|
||||
i32 chunk_index = 0;
|
||||
|
||||
Cpp_Token_Array *swap_array = &file->state.swap_array;
|
||||
|
||||
do{
|
||||
char *chunk = chunks[chunk_index];
|
||||
i32 chunk_size = chunk_sizes[chunk_index];
|
||||
|
||||
i32 result = cpp_lex_step(&lex, chunk, chunk_size, text_size, &new_tokens, NO_OUT_LIMIT);
|
||||
|
||||
switch (result){
|
||||
case LexResult_NeedChunk:
|
||||
{
|
||||
++chunk_index;
|
||||
Assert(chunk_index < ArrayCount(chunks));
|
||||
}break;
|
||||
|
||||
case LexResult_Finished:
|
||||
case LexResult_NeedTokenMemory:
|
||||
{
|
||||
u32 new_max = l_round_up_u32(swap_array->count + new_tokens.count + 1, KB(1));
|
||||
u32 new_mem_max = new_max*sizeof(Cpp_Token);
|
||||
u32 old_mem_count = swap_array->count*sizeof(Cpp_Token);
|
||||
if (swap_array->tokens == 0){
|
||||
swap_array->tokens = (Cpp_Token*)general_memory_allocate(general, new_mem_max);
|
||||
}
|
||||
else{
|
||||
swap_array->tokens = (Cpp_Token*)
|
||||
general_memory_reallocate(general, swap_array->tokens, old_mem_count, new_mem_max);
|
||||
}
|
||||
swap_array->max_count = new_max;
|
||||
|
||||
Assert(swap_array->count + new_tokens.count <= swap_array->max_count);
|
||||
memcpy(swap_array->tokens + swap_array->count, new_tokens.tokens, new_tokens.count*sizeof(Cpp_Token));
|
||||
swap_array->count += new_tokens.count;
|
||||
new_tokens.count = 0;
|
||||
|
||||
if (result == LexResult_Finished){
|
||||
still_lexing = false;
|
||||
}
|
||||
}break;
|
||||
|
||||
case LexResult_HitTokenLimit: InvalidCodePath;
|
||||
}
|
||||
} while (still_lexing);
|
||||
|
||||
Cpp_Token_Array *token_array = &file->state.token_array;
|
||||
token_array->count = swap_array->count;
|
||||
token_array->max_count = swap_array->max_count;
|
||||
if (token_array->tokens != 0){
|
||||
general_memory_free(general, token_array->tokens);
|
||||
}
|
||||
token_array->tokens = swap_array->tokens;
|
||||
|
||||
swap_array->tokens = 0;
|
||||
swap_array->count = 0;
|
||||
swap_array->max_count = 0;
|
||||
|
||||
file->state.tokens_complete = true;
|
||||
file->state.still_lexing = false;
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
file->state.tokens_complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal b32
|
||||
file_relex_parallel(System_Functions *system, Models *models, Editing_File *file, i32 start_i, i32 end_i, i32 shift_amount){
|
||||
Mem_Options *mem = &models->mem;
|
||||
General_Memory *general = &mem->general;
|
||||
Partition *part = &mem->part;
|
||||
|
||||
if (file->state.token_array.tokens == 0){
|
||||
file_first_lex_parallel(system, models, file);
|
||||
return(false);
|
||||
}
|
||||
|
||||
b32 result = true;
|
||||
b32 inline_lex = !file->state.still_lexing;
|
||||
if (inline_lex){
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
i32 extra_tolerance = 100;
|
||||
|
||||
Cpp_Token_Array *array = &file->state.token_array;
|
||||
Cpp_Relex_Range relex_range = cpp_get_relex_range(array, start_i, end_i);
|
||||
|
||||
i32 relex_space_size =
|
||||
relex_range.end_token_index - relex_range.start_token_index + extra_tolerance;
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
Parse_Context parse_context = parse_context_get(&models->parse_context_memory, file->settings.parse_context_id, partition_current(part), partition_remaining(part));
|
||||
Assert(parse_context.valid);
|
||||
push_block(part, (i32)parse_context.memory_size);
|
||||
|
||||
Cpp_Token_Array relex_array;
|
||||
relex_array.count = 0;
|
||||
relex_array.max_count = relex_space_size;
|
||||
relex_array.tokens = push_array(part, Cpp_Token, relex_array.max_count);
|
||||
|
||||
i32 size = buffer_size(buffer);
|
||||
|
||||
Cpp_Relex_Data state = cpp_relex_init(array, start_i, end_i, shift_amount, file->settings.tokens_without_strings, parse_context.kw_table, parse_context.pp_table);
|
||||
|
||||
char *chunks[3];
|
||||
i32 chunk_sizes[3];
|
||||
|
||||
chunks[0] = buffer->data;
|
||||
chunk_sizes[0] = buffer->size1;
|
||||
|
||||
chunks[1] = buffer->data + buffer->size1 + buffer->gap_size;
|
||||
chunk_sizes[1] = buffer->size2;
|
||||
|
||||
chunks[2] = 0;
|
||||
chunk_sizes[2] = 0;
|
||||
|
||||
i32 chunk_index = 0;
|
||||
char *chunk = chunks[chunk_index];
|
||||
i32 chunk_size = chunk_sizes[chunk_index];
|
||||
|
||||
while (!cpp_relex_is_start_chunk(&state, chunk, chunk_size)){
|
||||
++chunk_index;
|
||||
Assert(chunk_index < ArrayCount(chunks));
|
||||
chunk = chunks[chunk_index];
|
||||
chunk_size = chunk_sizes[chunk_index];
|
||||
}
|
||||
|
||||
for(;;){
|
||||
Cpp_Lex_Result lex_result =
|
||||
cpp_relex_step(&state, chunk, chunk_size, size, array, &relex_array);
|
||||
|
||||
switch (lex_result){
|
||||
case LexResult_NeedChunk:
|
||||
{
|
||||
++chunk_index;
|
||||
Assert(chunk_index < ArrayCount(chunks));
|
||||
chunk = chunks[chunk_index];
|
||||
chunk_size = chunk_sizes[chunk_index];
|
||||
}break;
|
||||
|
||||
case LexResult_NeedTokenMemory:
|
||||
{
|
||||
inline_lex = false;
|
||||
}goto doublebreak;
|
||||
|
||||
case LexResult_Finished: goto doublebreak;
|
||||
}
|
||||
}
|
||||
doublebreak:;
|
||||
|
||||
if (inline_lex){
|
||||
i32 new_count = cpp_relex_get_new_count(&state, array->count, &relex_array);
|
||||
if (new_count > array->max_count){
|
||||
i32 new_max = l_round_up_i32(new_count, KB(1));
|
||||
void *memory = general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token));
|
||||
array->tokens = (Cpp_Token*)memory;
|
||||
array->max_count = new_max;
|
||||
}
|
||||
|
||||
cpp_relex_complete(&state, array, &relex_array);
|
||||
}
|
||||
else{
|
||||
cpp_relex_abort(&state, array);
|
||||
}
|
||||
|
||||
end_temp_memory(temp);
|
||||
}
|
||||
|
||||
if (!inline_lex){
|
||||
Cpp_Token_Array *array = &file->state.token_array;
|
||||
Cpp_Get_Token_Result get_token_result = cpp_get_token(*array, end_i);
|
||||
i32 end_token_i = get_token_result.token_index;
|
||||
|
||||
if (end_token_i < 0){
|
||||
end_token_i = 0;
|
||||
}
|
||||
else if (end_i > array->tokens[end_token_i].start){
|
||||
++end_token_i;
|
||||
}
|
||||
|
||||
cpp_shift_token_starts(array, end_token_i, shift_amount);
|
||||
--end_token_i;
|
||||
if (end_token_i >= 0){
|
||||
Cpp_Token *token = array->tokens + end_token_i;
|
||||
if (token->start < end_i && token->start + token->size > end_i){
|
||||
token->size += shift_amount;
|
||||
}
|
||||
}
|
||||
|
||||
file->state.still_lexing = true;
|
||||
|
||||
Job_Data job;
|
||||
job.callback = job_full_lex;
|
||||
job.data[0] = file;
|
||||
job.data[1] = general;
|
||||
job.data[2] = models;
|
||||
file->state.lex_job = system->post_job(BACKGROUND_THREADS, job);
|
||||
result = false;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal b32
|
||||
file_relex_serial(Models *models, Editing_File *file, i32 start_i, i32 end_i, i32 shift_amount){
|
||||
Mem_Options *mem = &models->mem;
|
||||
General_Memory *general = &mem->general;
|
||||
Partition *part = &mem->part;
|
||||
|
||||
if (file->state.token_array.tokens == 0){
|
||||
file_first_lex_serial(models, file);
|
||||
return(1);
|
||||
}
|
||||
|
||||
Assert(!file->state.still_lexing);
|
||||
|
||||
Gap_Buffer *buffer = &file->state.buffer;
|
||||
Cpp_Token_Array *array = &file->state.token_array;
|
||||
|
||||
Temp_Memory temp = begin_temp_memory(part);
|
||||
Parse_Context parse_context = parse_context_get(&models->parse_context_memory, file->settings.parse_context_id, partition_current(part), partition_remaining(part));
|
||||
Assert(parse_context.valid);
|
||||
push_block(part, (i32)parse_context.memory_size);
|
||||
|
||||
Cpp_Token_Array relex_array;
|
||||
relex_array.count = 0;
|
||||
relex_array.max_count = partition_remaining(part) / sizeof(Cpp_Token);
|
||||
relex_array.tokens = push_array(part, Cpp_Token, relex_array.max_count);
|
||||
|
||||
i32 size = buffer_size(buffer);
|
||||
|
||||
Cpp_Relex_Data state = cpp_relex_init(array, start_i, end_i, shift_amount, file->settings.tokens_without_strings, parse_context.kw_table, parse_context.pp_table);
|
||||
|
||||
char *chunks[3];
|
||||
i32 chunk_sizes[3];
|
||||
|
||||
chunks[0] = buffer->data;
|
||||
chunk_sizes[0] = buffer->size1;
|
||||
|
||||
chunks[1] = buffer->data + buffer->size1 + buffer->gap_size;
|
||||
chunk_sizes[1] = buffer->size2;
|
||||
|
||||
chunks[2] = 0;
|
||||
chunk_sizes[2] = 0;
|
||||
|
||||
i32 chunk_index = 0;
|
||||
char *chunk = chunks[chunk_index];
|
||||
i32 chunk_size = chunk_sizes[chunk_index];
|
||||
|
||||
while (!cpp_relex_is_start_chunk(&state, chunk, chunk_size)){
|
||||
++chunk_index;
|
||||
Assert(chunk_index < ArrayCount(chunks));
|
||||
chunk = chunks[chunk_index];
|
||||
chunk_size = chunk_sizes[chunk_index];
|
||||
}
|
||||
|
||||
for(;;){
|
||||
Cpp_Lex_Result lex_result = cpp_relex_step(&state, chunk, chunk_size, size, array, &relex_array);
|
||||
|
||||
switch (lex_result){
|
||||
case LexResult_NeedChunk:
|
||||
{
|
||||
++chunk_index;
|
||||
Assert(chunk_index < ArrayCount(chunks));
|
||||
chunk = chunks[chunk_index];
|
||||
chunk_size = chunk_sizes[chunk_index];
|
||||
}break;
|
||||
|
||||
case LexResult_NeedTokenMemory: InvalidCodePath;
|
||||
|
||||
case LexResult_Finished: goto doublebreak;
|
||||
}
|
||||
}
|
||||
doublebreak:;
|
||||
|
||||
i32 new_count = cpp_relex_get_new_count(&state, array->count, &relex_array);
|
||||
if (new_count > array->max_count){
|
||||
i32 new_max = l_round_up_i32(new_count, KB(1));
|
||||
array->tokens = (Cpp_Token*)general_memory_reallocate(general, array->tokens, array->count*sizeof(Cpp_Token), new_max*sizeof(Cpp_Token));
|
||||
array->max_count = new_max;
|
||||
}
|
||||
|
||||
cpp_relex_complete(&state, array, &relex_array);
|
||||
|
||||
end_temp_memory(temp);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -3,71 +3,12 @@
|
|||
*
|
||||
* 19.08.2015
|
||||
*
|
||||
* Panel layout and general view functions for 4coder
|
||||
* Panel layout functions
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
struct Panel_Divider{
|
||||
Panel_Divider *next;
|
||||
i32 parent;
|
||||
i32 which_child;
|
||||
i32 child1, child2;
|
||||
b32 v_divider;
|
||||
f32 pos;
|
||||
};
|
||||
|
||||
struct Screen_Region{
|
||||
i32_Rect full;
|
||||
i32_Rect inner;
|
||||
i32 l_margin, r_margin;
|
||||
i32 t_margin, b_margin;
|
||||
};
|
||||
|
||||
struct Panel{
|
||||
Panel *next;
|
||||
Panel *prev;
|
||||
|
||||
struct View *view;
|
||||
i32 parent;
|
||||
i32 which_child;
|
||||
|
||||
union{
|
||||
struct{
|
||||
i32_Rect full;
|
||||
i32_Rect inner;
|
||||
i32_Rect prev_inner;
|
||||
i32 l_margin, r_margin;
|
||||
i32 t_margin, b_margin;
|
||||
};
|
||||
Screen_Region screen_region;
|
||||
};
|
||||
};
|
||||
|
||||
struct Editing_Layout{
|
||||
Panel *panels;
|
||||
Panel free_sentinel;
|
||||
Panel used_sentinel;
|
||||
Panel_Divider *dividers;
|
||||
Panel_Divider *free_divider;
|
||||
i32 panel_count, panel_max_count;
|
||||
i32 root;
|
||||
i32 active_panel;
|
||||
i32 full_width, full_height;
|
||||
b32 panel_state_dirty;
|
||||
};
|
||||
|
||||
struct Divider_And_ID{
|
||||
Panel_Divider* divider;
|
||||
i32 id;
|
||||
};
|
||||
|
||||
struct Panel_And_ID{
|
||||
Panel* panel;
|
||||
i32 id;
|
||||
};
|
||||
|
||||
internal void
|
||||
panel_init(Panel *panel){
|
||||
panel->view = 0;
|
||||
|
@ -89,9 +30,9 @@ panel_divider_zero(){
|
|||
|
||||
internal Divider_And_ID
|
||||
layout_alloc_divider(Editing_Layout *layout){
|
||||
Divider_And_ID result;
|
||||
|
||||
Assert(layout->free_divider);
|
||||
|
||||
Divider_And_ID result;
|
||||
result.divider = layout->free_divider;
|
||||
layout->free_divider = result.divider->next;
|
||||
|
||||
|
@ -109,12 +50,10 @@ layout_alloc_divider(Editing_Layout *layout){
|
|||
|
||||
internal Divider_And_ID
|
||||
layout_get_divider(Editing_Layout *layout, i32 id){
|
||||
Divider_And_ID result;
|
||||
|
||||
Assert(id >= 0 && id < layout->panel_max_count-1);
|
||||
Divider_And_ID result;
|
||||
result.id = id;
|
||||
result.divider = layout->dividers + id;
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* Panel layout structures
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_LAYOUT_H)
|
||||
#define FRED_LAYOUT_H
|
||||
|
||||
struct Panel_Divider{
|
||||
Panel_Divider *next;
|
||||
i32 parent;
|
||||
i32 which_child;
|
||||
i32 child1, child2;
|
||||
b32 v_divider;
|
||||
f32 pos;
|
||||
};
|
||||
|
||||
struct Screen_Region{
|
||||
i32_Rect full;
|
||||
i32_Rect inner;
|
||||
i32 l_margin, r_margin;
|
||||
i32 t_margin, b_margin;
|
||||
};
|
||||
|
||||
struct Panel{
|
||||
Panel *next;
|
||||
Panel *prev;
|
||||
|
||||
struct View *view;
|
||||
i32 parent;
|
||||
i32 which_child;
|
||||
|
||||
union{
|
||||
struct{
|
||||
i32_Rect full;
|
||||
i32_Rect inner;
|
||||
i32_Rect prev_inner;
|
||||
i32 l_margin, r_margin;
|
||||
i32 t_margin, b_margin;
|
||||
};
|
||||
Screen_Region screen_region;
|
||||
};
|
||||
};
|
||||
|
||||
struct Editing_Layout{
|
||||
Panel *panels;
|
||||
Panel free_sentinel;
|
||||
Panel used_sentinel;
|
||||
Panel_Divider *dividers;
|
||||
Panel_Divider *free_divider;
|
||||
i32 panel_count, panel_max_count;
|
||||
i32 root;
|
||||
i32 active_panel;
|
||||
i32 full_width, full_height;
|
||||
b32 panel_state_dirty;
|
||||
};
|
||||
|
||||
struct Divider_And_ID{
|
||||
Panel_Divider* divider;
|
||||
i32 id;
|
||||
};
|
||||
|
||||
struct Panel_And_ID{
|
||||
Panel* panel;
|
||||
i32 id;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -3,36 +3,12 @@
|
|||
*
|
||||
* 19.05.2017
|
||||
*
|
||||
* Parse contexts allocation and locking.
|
||||
* Parse contexts allocation and locking
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
struct Stored_Parse_Context{
|
||||
umem memsize;
|
||||
u64 *kw_keywords;
|
||||
u64 *pp_keywords;
|
||||
u32 kw_max;
|
||||
u32 pp_max;
|
||||
};
|
||||
|
||||
struct Stored_Parse_Context_Slot{
|
||||
union{
|
||||
Stored_Parse_Context_Slot *next;
|
||||
Stored_Parse_Context *context;
|
||||
};
|
||||
b32 freed;
|
||||
};
|
||||
|
||||
struct Parse_Context_Memory{
|
||||
Stored_Parse_Context_Slot *parse_context_array;
|
||||
u32 parse_context_counter;
|
||||
u32 parse_context_max;
|
||||
|
||||
Stored_Parse_Context_Slot free_sentinel;
|
||||
};
|
||||
|
||||
internal void
|
||||
parse_context_init_memory(Parse_Context_Memory *parse_mem, void *mem, umem memsize){
|
||||
sll_init_sentinel(&parse_mem->free_sentinel);
|
||||
|
@ -133,13 +109,6 @@ parse_context_add_default(Parse_Context_Memory *parse_mem, General_Memory *gener
|
|||
return(result);
|
||||
}
|
||||
|
||||
struct Parse_Context{
|
||||
b32 valid;
|
||||
Cpp_Keyword_Table kw_table;
|
||||
Cpp_Keyword_Table pp_table;
|
||||
umem memory_size;
|
||||
};
|
||||
|
||||
internal Parse_Context
|
||||
parse_context_get(Parse_Context_Memory *parse_mem, Parse_Context_ID id, void *mem, umem memsize){
|
||||
Parse_Context result = {0};
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* Parse context structures
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_PARSE_CONTEXT_H)
|
||||
#define FRED_PARSE_CONTEXT_H
|
||||
|
||||
struct Stored_Parse_Context{
|
||||
umem memsize;
|
||||
u64 *kw_keywords;
|
||||
u64 *pp_keywords;
|
||||
u32 kw_max;
|
||||
u32 pp_max;
|
||||
};
|
||||
|
||||
struct Stored_Parse_Context_Slot{
|
||||
union{
|
||||
Stored_Parse_Context_Slot *next;
|
||||
Stored_Parse_Context *context;
|
||||
};
|
||||
b32 freed;
|
||||
};
|
||||
|
||||
struct Parse_Context_Memory{
|
||||
Stored_Parse_Context_Slot *parse_context_array;
|
||||
u32 parse_context_counter;
|
||||
u32 parse_context_max;
|
||||
|
||||
Stored_Parse_Context_Slot free_sentinel;
|
||||
};
|
||||
|
||||
struct Parse_Context{
|
||||
b32 valid;
|
||||
Cpp_Keyword_Table kw_table;
|
||||
Cpp_Keyword_Table pp_table;
|
||||
umem memory_size;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_RENDER_FORMAT_H)
|
||||
#define FRED_RENDER_FORMAT_H
|
||||
|
||||
enum Render_Command_Type{
|
||||
RenCom_Rectangle,
|
||||
RenCom_Outline,
|
||||
|
@ -57,5 +60,7 @@ struct Render_Pseudo_Command_Free_Texture{
|
|||
Render_Free_Texture free_texture_node;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
||||
|
|
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* Undo
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
internal void
|
||||
undo_stack_grow_string(General_Memory *general, Edit_Stack *stack, i32 extra_size){
|
||||
i32 old_max = stack->max;
|
||||
u8 *old_str = stack->strings;
|
||||
i32 new_max = old_max*2 + extra_size;
|
||||
u8 *new_str = (u8*)general_memory_reallocate(general, old_str, old_max, new_max);
|
||||
stack->strings = new_str;
|
||||
stack->max = new_max;
|
||||
}
|
||||
|
||||
internal void
|
||||
undo_stack_grow_edits(General_Memory *general, Edit_Stack *stack){
|
||||
i32 old_max = stack->edit_max;
|
||||
Edit_Step *old_eds = stack->edits;
|
||||
i32 new_max = old_max*2 + 2;
|
||||
Edit_Step *new_eds = (Edit_Step*)general_memory_reallocate(general, old_eds, old_max*sizeof(Edit_Step), new_max*sizeof(Edit_Step));
|
||||
stack->edits = new_eds;
|
||||
stack->edit_max = new_max;
|
||||
}
|
||||
|
||||
internal void
|
||||
child_stack_grow_string(General_Memory *general, Small_Edit_Stack *stack, i32 extra_size){
|
||||
i32 old_max = stack->max;
|
||||
u8 *old_str = stack->strings;
|
||||
i32 new_max = old_max*2 + extra_size;
|
||||
u8 *new_str = (u8*)general_memory_reallocate(general, old_str, old_max, new_max);
|
||||
stack->strings = new_str;
|
||||
stack->max = new_max;
|
||||
}
|
||||
|
||||
internal void
|
||||
child_stack_grow_edits(General_Memory *general, Small_Edit_Stack *stack, i32 amount){
|
||||
i32 old_max = stack->edit_max;
|
||||
Buffer_Edit *old_eds = stack->edits;
|
||||
i32 new_max = old_max*2 + amount;
|
||||
Buffer_Edit *new_eds = (Buffer_Edit*)general_memory_reallocate(general, old_eds, old_max*sizeof(Buffer_Edit), new_max*sizeof(Buffer_Edit));
|
||||
stack->edits = new_eds;
|
||||
stack->edit_max = new_max;
|
||||
}
|
||||
|
||||
internal i32
|
||||
undo_children_push(General_Memory *general, Small_Edit_Stack *children, Buffer_Edit *edits, i32 edit_count, u8 *strings, i32 string_size){
|
||||
i32 result = children->edit_count;
|
||||
if (children->edit_count + edit_count > children->edit_max){
|
||||
child_stack_grow_edits(general, children, edit_count);
|
||||
}
|
||||
|
||||
if (children->size + string_size > children->max){
|
||||
child_stack_grow_string(general, children, string_size);
|
||||
}
|
||||
|
||||
memcpy(children->edits + children->edit_count, edits, edit_count*sizeof(Buffer_Edit));
|
||||
memcpy(children->strings + children->size, strings, string_size);
|
||||
|
||||
Buffer_Edit *edit = children->edits + children->edit_count;
|
||||
i32 start_pos = children->size;
|
||||
for (i32 i = 0; i < edit_count; ++i, ++edit){
|
||||
edit->str_start += start_pos;
|
||||
}
|
||||
|
||||
children->edit_count += edit_count;
|
||||
children->size += string_size;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal Edit_Step*
|
||||
file_post_undo(General_Memory *general, Editing_File *file, Edit_Step step, b32 do_merge, b32 can_merge){
|
||||
if (step.type == ED_NORMAL){
|
||||
file->state.undo.redo.size = 0;
|
||||
file->state.undo.redo.edit_count = 0;
|
||||
}
|
||||
|
||||
Edit_Stack *undo = &file->state.undo.undo;
|
||||
Edit_Step *result = 0;
|
||||
|
||||
if (step.child_count == 0){
|
||||
if (step.edit.end - step.edit.start + undo->size > undo->max){
|
||||
undo_stack_grow_string(general, undo, step.edit.end - step.edit.start);
|
||||
}
|
||||
|
||||
Buffer_Edit inv;
|
||||
buffer_invert_edit(&file->state.buffer, step.edit, &inv, (char*)undo->strings, &undo->size, undo->max);
|
||||
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.edit = inv;
|
||||
inv_step.can_merge = (b8)can_merge;
|
||||
inv_step.type = ED_UNDO;
|
||||
|
||||
b32 did_merge = 0;
|
||||
if (do_merge && undo->edit_count > 0){
|
||||
Edit_Step prev = undo->edits[undo->edit_count-1];
|
||||
if (prev.can_merge && inv_step.edit.len == 0 && prev.edit.len == 0){
|
||||
if (prev.edit.end == inv_step.edit.start){
|
||||
did_merge = 1;
|
||||
inv_step.edit.start = prev.edit.start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (did_merge){
|
||||
result = undo->edits + (undo->edit_count-1);
|
||||
*result = inv_step;
|
||||
}
|
||||
else{
|
||||
if (undo->edit_count == undo->edit_max){
|
||||
undo_stack_grow_edits(general, undo);
|
||||
}
|
||||
|
||||
result = undo->edits + (undo->edit_count++);
|
||||
*result = inv_step;
|
||||
}
|
||||
}
|
||||
else{
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.type = ED_UNDO;
|
||||
inv_step.first_child = step.inverse_first_child;
|
||||
inv_step.inverse_first_child = step.first_child;
|
||||
inv_step.special_type = step.special_type;
|
||||
inv_step.child_count = step.inverse_child_count;
|
||||
inv_step.inverse_child_count = step.child_count;
|
||||
|
||||
if (undo->edit_count == undo->edit_max){
|
||||
undo_stack_grow_edits(general, undo);
|
||||
}
|
||||
result = undo->edits + (undo->edit_count++);
|
||||
*result = inv_step;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void
|
||||
undo_stack_pop(Edit_Stack *stack){
|
||||
if (stack->edit_count > 0){
|
||||
Edit_Step *edit = stack->edits + (--stack->edit_count);
|
||||
if (edit->child_count == 0){
|
||||
stack->size -= edit->edit.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
file_post_redo(General_Memory *general, Editing_File *file, Edit_Step step){
|
||||
Edit_Stack *redo = &file->state.undo.redo;
|
||||
|
||||
if (step.child_count == 0){
|
||||
if (step.edit.end - step.edit.start + redo->size > redo->max){
|
||||
undo_stack_grow_string(general, redo, step.edit.end - step.edit.start);
|
||||
}
|
||||
|
||||
Buffer_Edit inv;
|
||||
buffer_invert_edit(&file->state.buffer, step.edit, &inv, (char*)redo->strings, &redo->size, redo->max);
|
||||
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.edit = inv;
|
||||
inv_step.type = ED_REDO;
|
||||
|
||||
if (redo->edit_count == redo->edit_max){
|
||||
undo_stack_grow_edits(general, redo);
|
||||
}
|
||||
redo->edits[redo->edit_count++] = inv_step;
|
||||
}
|
||||
else{
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.type = ED_REDO;
|
||||
inv_step.first_child = step.inverse_first_child;
|
||||
inv_step.inverse_first_child = step.first_child;
|
||||
inv_step.special_type = step.special_type;
|
||||
inv_step.child_count = step.inverse_child_count;
|
||||
inv_step.inverse_child_count = step.child_count;
|
||||
|
||||
if (redo->edit_count == redo->edit_max){
|
||||
undo_stack_grow_edits(general, redo);
|
||||
}
|
||||
redo->edits[redo->edit_count++] = inv_step;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
file_post_history_block(Editing_File *file, i32 pos){
|
||||
Assert(file->state.undo.history_head_block < pos);
|
||||
Assert(pos < file->state.undo.history.edit_count);
|
||||
|
||||
Edit_Step *history = file->state.undo.history.edits;
|
||||
Edit_Step *step = history + file->state.undo.history_head_block;
|
||||
step->next_block = pos;
|
||||
step = history + pos;
|
||||
step->prev_block = file->state.undo.history_head_block;
|
||||
file->state.undo.history_head_block = pos;
|
||||
++file->state.undo.history_block_count;
|
||||
}
|
||||
|
||||
inline void
|
||||
file_unpost_history_block(Editing_File *file){
|
||||
Assert(file->state.undo.history_block_count > 1);
|
||||
--file->state.undo.history_block_count;
|
||||
Edit_Step *old_head = file->state.undo.history.edits + file->state.undo.history_head_block;
|
||||
file->state.undo.history_head_block = old_head->prev_block;
|
||||
}
|
||||
|
||||
internal Edit_Step*
|
||||
file_post_history(General_Memory *general, Editing_File *file, Edit_Step step, b32 do_merge, b32 can_merge){
|
||||
Edit_Stack *history = &file->state.undo.history;
|
||||
Edit_Step *result = 0;
|
||||
|
||||
local_persist Edit_Type reverse_types[4];
|
||||
if (reverse_types[ED_UNDO] == 0){
|
||||
reverse_types[ED_NORMAL] = ED_REVERSE_NORMAL;
|
||||
reverse_types[ED_REVERSE_NORMAL] = ED_NORMAL;
|
||||
reverse_types[ED_UNDO] = ED_REDO;
|
||||
reverse_types[ED_REDO] = ED_UNDO;
|
||||
}
|
||||
|
||||
if (step.child_count == 0){
|
||||
if (step.edit.end - step.edit.start + history->size > history->max){
|
||||
undo_stack_grow_string(general, history, step.edit.end - step.edit.start);
|
||||
}
|
||||
|
||||
Buffer_Edit inv;
|
||||
buffer_invert_edit(&file->state.buffer, step.edit, &inv,
|
||||
(char*)history->strings, &history->size, history->max);
|
||||
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.edit = inv;
|
||||
inv_step.can_merge = (b8)can_merge;
|
||||
inv_step.type = reverse_types[step.type];
|
||||
|
||||
b32 did_merge = 0;
|
||||
if (do_merge && history->edit_count > 0){
|
||||
Edit_Step prev = history->edits[history->edit_count-1];
|
||||
if (prev.can_merge && inv_step.edit.len == 0 && prev.edit.len == 0){
|
||||
if (prev.edit.end == inv_step.edit.start){
|
||||
did_merge = 1;
|
||||
inv_step.edit.start = prev.edit.start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (did_merge){
|
||||
result = history->edits + (history->edit_count-1);
|
||||
}
|
||||
else{
|
||||
if (history->edit_count == history->edit_max){
|
||||
undo_stack_grow_edits(general, history);
|
||||
}
|
||||
result = history->edits + (history->edit_count++);
|
||||
}
|
||||
|
||||
*result = inv_step;
|
||||
}
|
||||
else{
|
||||
Edit_Step inv_step = {};
|
||||
inv_step.type = reverse_types[step.type];
|
||||
inv_step.first_child = step.inverse_first_child;
|
||||
inv_step.inverse_first_child = step.first_child;
|
||||
inv_step.special_type = step.special_type;
|
||||
inv_step.inverse_child_count = step.child_count;
|
||||
inv_step.child_count = step.inverse_child_count;
|
||||
|
||||
if (history->edit_count == history->edit_max){
|
||||
undo_stack_grow_edits(general, history);
|
||||
}
|
||||
result = history->edits + (history->edit_count++);
|
||||
*result = inv_step;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str, History_Mode history_mode){
|
||||
if (!file->state.undo.undo.edits) return;
|
||||
General_Memory *general = &mem->general;
|
||||
|
||||
b32 can_merge = 0, do_merge = 0;
|
||||
switch (step.type){
|
||||
case ED_NORMAL:
|
||||
{
|
||||
if (step.edit.len == 1 && str && char_is_alpha_numeric(*str)){
|
||||
can_merge = 1;
|
||||
}
|
||||
if (step.edit.len == 1 && str && (can_merge || char_is_whitespace(*str))){
|
||||
do_merge = 1;
|
||||
}
|
||||
|
||||
if (history_mode != hist_forward){
|
||||
file_post_history(general, file, step, do_merge, can_merge);
|
||||
}
|
||||
|
||||
file_post_undo(general, file, step, do_merge, can_merge);
|
||||
}break;
|
||||
|
||||
case ED_REVERSE_NORMAL:
|
||||
{
|
||||
if (history_mode != hist_forward){
|
||||
file_post_history(general, file, step, do_merge, can_merge);
|
||||
}
|
||||
|
||||
undo_stack_pop(&file->state.undo.undo);
|
||||
|
||||
b32 restore_redos = 0;
|
||||
Edit_Step *redo_end = 0;
|
||||
|
||||
if (history_mode == hist_backward && file->state.undo.edit_history_cursor > 0){
|
||||
restore_redos = 1;
|
||||
redo_end = file->state.undo.history.edits + (file->state.undo.edit_history_cursor - 1);
|
||||
}
|
||||
else if (history_mode == hist_forward && file->state.undo.history.edit_count > 0){
|
||||
restore_redos = 1;
|
||||
redo_end = file->state.undo.history.edits + (file->state.undo.history.edit_count - 1);
|
||||
}
|
||||
|
||||
if (restore_redos){
|
||||
Edit_Step *redo_start = redo_end;
|
||||
i32 steps_of_redo = 0;
|
||||
i32 strings_of_redo = 0;
|
||||
{
|
||||
i32 undo_count = 0;
|
||||
while (redo_start->type == ED_REDO || redo_start->type == ED_UNDO){
|
||||
if (redo_start->type == ED_REDO){
|
||||
if (undo_count > 0){
|
||||
--undo_count;
|
||||
}
|
||||
else{
|
||||
++steps_of_redo;
|
||||
strings_of_redo += redo_start->edit.len;
|
||||
}
|
||||
}
|
||||
else{
|
||||
++undo_count;
|
||||
}
|
||||
--redo_start;
|
||||
}
|
||||
}
|
||||
|
||||
if (redo_start < redo_end){
|
||||
++redo_start;
|
||||
++redo_end;
|
||||
|
||||
if (file->state.undo.redo.edit_count + steps_of_redo > file->state.undo.redo.edit_max)
|
||||
undo_stack_grow_edits(general, &file->state.undo.redo);
|
||||
|
||||
if (file->state.undo.redo.size + strings_of_redo > file->state.undo.redo.max)
|
||||
undo_stack_grow_string(general, &file->state.undo.redo, strings_of_redo);
|
||||
|
||||
u8 *str_src = file->state.undo.history.strings + redo_end->edit.str_start;
|
||||
u8 *str_dest_base = file->state.undo.redo.strings;
|
||||
i32 str_redo_pos = file->state.undo.redo.size + strings_of_redo;
|
||||
|
||||
Edit_Step *edit_src = redo_end;
|
||||
Edit_Step *edit_dest = file->state.undo.redo.edits + file->state.undo.redo.edit_count + steps_of_redo;
|
||||
|
||||
{
|
||||
i32 undo_count = 0;
|
||||
for (i32 i = 0; i < steps_of_redo;){
|
||||
--edit_src;
|
||||
str_src -= edit_src->edit.len;
|
||||
if (edit_src->type == ED_REDO){
|
||||
if (undo_count > 0){
|
||||
--undo_count;
|
||||
}
|
||||
else{
|
||||
++i;
|
||||
|
||||
--edit_dest;
|
||||
*edit_dest = *edit_src;
|
||||
|
||||
str_redo_pos -= edit_dest->edit.len;
|
||||
edit_dest->edit.str_start = str_redo_pos;
|
||||
|
||||
memcpy(str_dest_base + str_redo_pos, str_src, edit_dest->edit.len);
|
||||
}
|
||||
}
|
||||
else{
|
||||
++undo_count;
|
||||
}
|
||||
}
|
||||
Assert(undo_count == 0);
|
||||
}
|
||||
|
||||
file->state.undo.redo.size += strings_of_redo;
|
||||
file->state.undo.redo.edit_count += steps_of_redo;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
|
||||
case ED_UNDO:
|
||||
{
|
||||
if (history_mode != hist_forward){
|
||||
file_post_history(general, file, step, do_merge, can_merge);
|
||||
}
|
||||
file_post_redo(general, file, step);
|
||||
undo_stack_pop(&file->state.undo.undo);
|
||||
}break;
|
||||
|
||||
case ED_REDO:
|
||||
{
|
||||
if (step.edit.len == 1 && str && char_is_alpha_numeric(*str)) can_merge = 1;
|
||||
if (step.edit.len == 1 && str && (can_merge || char_is_whitespace(*str))) do_merge = 1;
|
||||
|
||||
if (history_mode != hist_forward){
|
||||
file_post_history(general, file, step, do_merge, can_merge);
|
||||
}
|
||||
|
||||
file_post_undo(general, file, step, do_merge, can_merge);
|
||||
undo_stack_pop(&file->state.undo.redo);
|
||||
}break;
|
||||
}
|
||||
|
||||
if (history_mode != hist_forward){
|
||||
if (step.type == ED_UNDO || step.type == ED_REDO){
|
||||
if (file->state.undo.current_block_normal){
|
||||
file_post_history_block(file, file->state.undo.history.edit_count - 1);
|
||||
file->state.undo.current_block_normal = 0;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (!file->state.undo.current_block_normal){
|
||||
file_post_history_block(file, file->state.undo.history.edit_count - 1);
|
||||
file->state.undo.current_block_normal = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (file->state.undo.history_head_block == file->state.undo.history.edit_count){
|
||||
file_unpost_history_block(file);
|
||||
file->state.undo.current_block_normal = !file->state.undo.current_block_normal;
|
||||
}
|
||||
}
|
||||
|
||||
if (history_mode == hist_normal){
|
||||
file->state.undo.edit_history_cursor = file->state.undo.history.edit_count;
|
||||
}
|
||||
}
|
||||
|
||||
// BOTTOM
|
||||
|
2546
4ed_view.cpp
2546
4ed_view.cpp
File diff suppressed because it is too large
Load Diff
56
4ed_view.h
56
4ed_view.h
|
@ -171,57 +171,6 @@ enum{
|
|||
GROW_SUCCESS,
|
||||
};
|
||||
|
||||
struct Code_Wrap_X{
|
||||
f32 base_x;
|
||||
f32 paren_nesting[32];
|
||||
i32 paren_safe_top;
|
||||
i32 paren_top;
|
||||
};
|
||||
global Code_Wrap_X null_wrap_x = {0};
|
||||
|
||||
struct Code_Wrap_State{
|
||||
Cpp_Token_Array token_array;
|
||||
Cpp_Token *token_ptr;
|
||||
Cpp_Token *end_token;
|
||||
|
||||
Code_Wrap_X wrap_x;
|
||||
|
||||
b32 in_pp_body;
|
||||
Code_Wrap_X plane_wrap_x;
|
||||
|
||||
i32 *line_starts;
|
||||
i32 line_count;
|
||||
i32 line_index;
|
||||
i32 next_line_start;
|
||||
|
||||
f32 x;
|
||||
b32 consume_newline;
|
||||
|
||||
Gap_Buffer_Stream stream;
|
||||
i32 size;
|
||||
i32 i;
|
||||
|
||||
Font_Pointers font;
|
||||
f32 tab_indent_amount;
|
||||
f32 byte_advance;
|
||||
|
||||
Translation_State tran;
|
||||
Translation_Emits emits;
|
||||
u32 J;
|
||||
Buffer_Model_Step step;
|
||||
Buffer_Model_Behavior behavior;
|
||||
};
|
||||
|
||||
struct Code_Wrap_Step{
|
||||
i32 position_start;
|
||||
i32 position_end;
|
||||
|
||||
f32 start_x;
|
||||
f32 final_x;
|
||||
|
||||
Cpp_Token *this_token;
|
||||
};
|
||||
|
||||
struct Wrap_Indent_Pair{
|
||||
i32 wrap_position;
|
||||
f32 line_shift;
|
||||
|
@ -237,11 +186,6 @@ struct Potential_Wrap_Indent_Pair{
|
|||
b32 adjust_top_to_this;
|
||||
};
|
||||
|
||||
struct Wrap_Current_Shift{
|
||||
f32 shift;
|
||||
b32 adjust_top_to_this;
|
||||
};
|
||||
|
||||
struct Shift_Information{
|
||||
i32 start, end, amount;
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* 03.01.2017
|
||||
*
|
||||
* Working_Set data structure for 4coder
|
||||
* Working_Set data structure
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -13,58 +13,6 @@
|
|||
// Working_Set of files
|
||||
//
|
||||
|
||||
struct Non_File_Table_Entry{
|
||||
String name;
|
||||
Buffer_Slot_ID id;
|
||||
};
|
||||
|
||||
struct File_Array{
|
||||
Editing_File *files;
|
||||
i32 size;
|
||||
};
|
||||
|
||||
struct Working_Set{
|
||||
File_Array *file_arrays;
|
||||
i32 file_count, file_max;
|
||||
i16 array_count, array_max;
|
||||
|
||||
File_Node free_sentinel;
|
||||
File_Node used_sentinel;
|
||||
|
||||
Table canon_table;
|
||||
Table name_table;
|
||||
|
||||
String clipboards[64];
|
||||
i32 clipboard_size, clipboard_max_size;
|
||||
i32 clipboard_current, clipboard_rolling;
|
||||
|
||||
//u64 unique_file_counter;
|
||||
|
||||
File_Node *sync_check_iter;
|
||||
|
||||
i32 default_display_width;
|
||||
i32 default_minimum_base_display_width;
|
||||
};
|
||||
|
||||
struct File_Name_Entry{
|
||||
String name;
|
||||
Buffer_Slot_ID id;
|
||||
};
|
||||
|
||||
|
||||
internal i32
|
||||
tbl_name_compare(void *a, void *b, void *arg){
|
||||
String *fa = (String*)a;
|
||||
File_Name_Entry *fb = (File_Name_Entry*)b;
|
||||
|
||||
i32 result = 1;
|
||||
if (match_ss(*fa, fb->name)){
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
internal void
|
||||
working_set_extend_memory(Working_Set *working_set, Editing_File *new_space, i16 number_of_files){
|
||||
Assert(working_set->array_count < working_set->array_max);
|
||||
|
@ -161,7 +109,7 @@ inline Editing_File*
|
|||
working_set_get_active_file(Working_Set *working_set, Buffer_Slot_ID id){
|
||||
Editing_File *result = 0;
|
||||
result = working_set_index(working_set, id);
|
||||
if (result && result->is_dummy){
|
||||
if (result != 0 && result->is_dummy){
|
||||
result = 0;
|
||||
}
|
||||
return(result);
|
||||
|
@ -169,8 +117,7 @@ working_set_get_active_file(Working_Set *working_set, Buffer_Slot_ID id){
|
|||
|
||||
inline Editing_File*
|
||||
working_set_get_active_file(Working_Set *working_set, i32 id){
|
||||
Editing_File *result;
|
||||
result = working_set_get_active_file(working_set, to_file_id(id));
|
||||
Editing_File *result= working_set_get_active_file(working_set, to_file_id(id));
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Mr. 4th Dimention - Allen Webster
|
||||
*
|
||||
* 24.03.2018
|
||||
*
|
||||
* Working_Set data structure
|
||||
*
|
||||
*/
|
||||
|
||||
// TOP
|
||||
|
||||
#if !defined(FRED_WORKING_SET_H)
|
||||
#define FRED_WORKING_SET_H
|
||||
|
||||
struct Non_File_Table_Entry{
|
||||
String name;
|
||||
Buffer_Slot_ID id;
|
||||
};
|
||||
|
||||
struct File_Array{
|
||||
Editing_File *files;
|
||||
i32 size;
|
||||
};
|
||||
|
||||
struct Working_Set{
|
||||
File_Array *file_arrays;
|
||||
i32 file_count, file_max;
|
||||
i16 array_count, array_max;
|
||||
|
||||
File_Node free_sentinel;
|
||||
File_Node used_sentinel;
|
||||
|
||||
Table canon_table;
|
||||
Table name_table;
|
||||
|
||||
// TODO(allen): WTF?
|
||||
String clipboards[64];
|
||||
i32 clipboard_size, clipboard_max_size;
|
||||
i32 clipboard_current, clipboard_rolling;
|
||||
|
||||
//u64 unique_file_counter;
|
||||
|
||||
File_Node *sync_check_iter;
|
||||
|
||||
i32 default_display_width;
|
||||
i32 default_minimum_base_display_width;
|
||||
};
|
||||
|
||||
struct File_Name_Entry{
|
||||
String name;
|
||||
Buffer_Slot_ID id;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// BOTTOM
|
||||
|
Loading…
Reference in New Issue