diff --git a/4coder_custom.cpp b/4coder_custom.cpp index 986af21e..49d504e6 100644 --- a/4coder_custom.cpp +++ b/4coder_custom.cpp @@ -236,7 +236,7 @@ extern "C" GET_BINDING_DATA(get_bindings){ bind(context, codes->down, MDFR_ALT, cmdid_stop_rewind_fastforward); bind(context, 'h', MDFR_CTRL, cmdid_history_backward); bind(context, 'H', MDFR_CTRL, cmdid_history_forward); - bind(context, 'd', MDFR_CTRL, cmdid_delete_chunk); + bind(context, 'd', MDFR_CTRL, cmdid_delete_range); bind(context, 'l', MDFR_CTRL, cmdid_toggle_line_wrap); bind(context, 'L', MDFR_CTRL, cmdid_toggle_endline_mode); bind(context, 'u', MDFR_CTRL, cmdid_to_uppercase); diff --git a/4coder_custom.h b/4coder_custom.h index 833a6109..bf56a768 100644 --- a/4coder_custom.h +++ b/4coder_custom.h @@ -69,7 +69,7 @@ enum Command_ID{ cmdid_cut, cmdid_paste, cmdid_paste_next, - cmdid_delete_chunk, + cmdid_delete_range, cmdid_timeline_scrub, cmdid_undo, cmdid_redo, diff --git a/4ed.cpp b/4ed.cpp index 3a6707ca..9a8015f0 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -135,6 +135,8 @@ globalvar Application_Links app_links; #define REQ_VIEW(n) View *n = command->view; if (!n) return #define REQ_FILE_VIEW(n) File_View *n = view_to_file_view(command->view); if (!n) return +#define REQ_OPEN_FILE_VIEW(n) File_View *n = view_to_file_view(command->view); if (!n || n->locked) return +#define REQ_FILE_HISTORY(n,v) Editing_File *n = (v)->file; if (!n || !buffer_good(&n->buffer) || n->is_dummy || !n->undo.undo.edits) return #define REQ_FILE(n,v) Editing_File *n = (v)->file; if (!n || !buffer_good(&n->buffer) || n->is_dummy) return #define REQ_COLOR_VIEW(n) Color_View *n = view_to_color_view(command->view); if (!n) return #define REQ_DBG_VIEW(n) Debug_View *n = view_to_debug_view(command->view); if (!n) return @@ -206,7 +208,7 @@ COMMAND_DECL(null){ COMMAND_DECL(write_character){ ProfileMomentFunction(); - REQ_FILE_VIEW(view); + REQ_OPEN_FILE_VIEW(view); REQ_FILE(file, view); USE_LAYOUT(layout); USE_MEM(mem); @@ -223,7 +225,7 @@ COMMAND_DECL(write_character){ view_replace_range(mem, view, layout, pos, pos, (u8*)string.str, string.size, next_cursor_pos); view_cursor_move(view, next_cursor_pos); if (view->mark >= pos) view->mark += string.size; - view->file->cursor_pos = view->cursor.pos; + file->cursor_pos = view->cursor.pos; } COMMAND_DECL(seek_whitespace_right){ @@ -233,7 +235,6 @@ COMMAND_DECL(seek_whitespace_right){ REQ_FILE(file, view); i32 pos = buffer_seek_whitespace_right(&file->buffer, view->cursor.pos); - view_cursor_move(view, pos); #endif } @@ -245,7 +246,6 @@ COMMAND_DECL(seek_whitespace_left){ REQ_FILE(file, view); i32 pos = buffer_seek_whitespace_left(&file->buffer, view->cursor.pos); - view_cursor_move(view, pos); #endif } @@ -356,7 +356,7 @@ COMMAND_DECL(seek_white_or_token_left){ } COMMAND_DECL(seek_alphanumeric_right){ -#if BUFFER_EXPERIMENT_SCALPEL <= 1 +#if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -367,7 +367,7 @@ COMMAND_DECL(seek_alphanumeric_right){ } COMMAND_DECL(seek_alphanumeric_left){ -#if BUFFER_EXPERIMENT_SCALPEL <= 1 +#if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -378,7 +378,7 @@ COMMAND_DECL(seek_alphanumeric_left){ } COMMAND_DECL(seek_alphanumeric_or_camel_right){ -#if BUFFER_EXPERIMENT_SCALPEL <= 1 +#if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -390,7 +390,7 @@ COMMAND_DECL(seek_alphanumeric_or_camel_right){ } COMMAND_DECL(seek_alphanumeric_or_camel_left){ -#if BUFFER_EXPERIMENT_SCALPEL <= 1 +#if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); REQ_FILE_VIEW(view); REQ_FILE(file, view); @@ -404,7 +404,7 @@ COMMAND_DECL(seek_alphanumeric_or_camel_left){ COMMAND_DECL(search){ ProfileMomentFunction(); REQ_FILE_VIEW(view); - REQ_FILE(file, view); + REQ_FILE(fixed, view); USE_VARS(vars); view_set_widget(view, FWIDG_SEARCH); @@ -416,7 +416,7 @@ COMMAND_DECL(search){ COMMAND_DECL(rsearch){ ProfileMomentFunction(); REQ_FILE_VIEW(view); - REQ_FILE(file, view); + REQ_FILE(fixed, view); USE_VARS(vars); view_set_widget(view, FWIDG_SEARCH); @@ -428,7 +428,7 @@ COMMAND_DECL(rsearch){ COMMAND_DECL(goto_line){ ProfileMomentFunction(); REQ_FILE_VIEW(view); - REQ_FILE(file, view); + REQ_FILE(fixed, view); USE_VARS(vars); view_set_widget(view, FWIDG_GOTO_LINE); @@ -460,7 +460,7 @@ COMMAND_DECL(copy){ COMMAND_DECL(cut){ ProfileMomentFunction(); - REQ_FILE_VIEW(view); + REQ_OPEN_FILE_VIEW(view); REQ_FILE(file, view); USE_WORKING_SET(working_set); USE_LAYOUT(layout); @@ -481,7 +481,7 @@ COMMAND_DECL(cut){ COMMAND_DECL(paste){ ProfileMomentFunction(); - REQ_FILE_VIEW(view); + REQ_OPEN_FILE_VIEW(view); REQ_FILE(file, view); USE_WORKING_SET(working_set); USE_LAYOUT(layout); @@ -516,7 +516,7 @@ COMMAND_DECL(paste){ COMMAND_DECL(paste_next){ ProfileMomentFunction(); - REQ_FILE_VIEW(view); + REQ_OPEN_FILE_VIEW(view); REQ_FILE(file, view); USE_WORKING_SET(working_set); USE_LAYOUT(layout); @@ -552,9 +552,9 @@ COMMAND_DECL(paste_next){ } } -COMMAND_DECL(delete_chunk){ +COMMAND_DECL(delete_range){ ProfileMomentFunction(); - REQ_FILE_VIEW(view); + REQ_OPEN_FILE_VIEW(view); REQ_FILE(file, view); USE_LAYOUT(layout); USE_MEM(mem); @@ -572,7 +572,7 @@ COMMAND_DECL(delete_chunk){ COMMAND_DECL(timeline_scrub){ ProfileMomentFunction(); REQ_FILE_VIEW(view); - REQ_FILE(file, view); + REQ_FILE_HISTORY(file, view); view_set_widget(view, FWIDG_TIMELINES); view->widget.timeline.undo_line = 1; @@ -582,6 +582,7 @@ COMMAND_DECL(timeline_scrub){ COMMAND_DECL(undo){ ProfileMomentFunction(); REQ_FILE_VIEW(view); + REQ_FILE_HISTORY(file, view); USE_LAYOUT(layout); USE_MEM(mem); @@ -591,6 +592,7 @@ COMMAND_DECL(undo){ COMMAND_DECL(redo){ ProfileMomentFunction(); REQ_FILE_VIEW(view); + REQ_FILE_HISTORY(file, view); USE_LAYOUT(layout); USE_MEM(mem); @@ -600,6 +602,7 @@ COMMAND_DECL(redo){ COMMAND_DECL(increase_rewind_speed){ ProfileMomentFunction(); REQ_FILE_VIEW(view); + REQ_FILE_HISTORY(file, view); i32 rewind_speed = ROUND32(view->rewind_speed * 4.f); if (rewind_speed > 1) rewind_speed >>= 1; @@ -613,6 +616,7 @@ COMMAND_DECL(increase_rewind_speed){ COMMAND_DECL(increase_fastforward_speed){ ProfileMomentFunction(); REQ_FILE_VIEW(view); + REQ_FILE_HISTORY(file, view); i32 neg_rewind_speed = -ROUND32(view->rewind_speed * 4.f); if (neg_rewind_speed > 1) neg_rewind_speed >>= 1; @@ -626,6 +630,7 @@ COMMAND_DECL(increase_fastforward_speed){ COMMAND_DECL(stop_rewind_fastforward){ ProfileMomentFunction(); REQ_FILE_VIEW(view); + REQ_FILE_HISTORY(file, view); view->rewind_speed = 0; } @@ -633,7 +638,7 @@ COMMAND_DECL(stop_rewind_fastforward){ COMMAND_DECL(history_backward){ ProfileMomentFunction(); REQ_FILE_VIEW(view); - REQ_FILE(file, view); + REQ_FILE_HISTORY(file, view); USE_LAYOUT(layout); USE_MEM(mem); @@ -643,7 +648,7 @@ COMMAND_DECL(history_backward){ COMMAND_DECL(history_forward){ ProfileMomentFunction(); REQ_FILE_VIEW(view); - REQ_FILE(file, view); + REQ_FILE_HISTORY(file, view); USE_LAYOUT(layout); USE_MEM(mem); @@ -698,7 +703,7 @@ app_open_file(App_Vars *vars, General_Memory *general, Panel *panel, view_replace_major(new_view, panel, live_set); - File_View *file_view = file_view_init(new_view, &vars->delay, &vars->layout); + File_View *file_view = file_view_init(new_view, &vars->layout); result = file_view; View *old_view = command_data->view; @@ -830,7 +835,7 @@ COMMAND_DECL(save){ String *file_path = &file->source_path; if (file_path->size > 0){ - file_save(&mem->part, file, (u8*)file_path->str); + file_save(&mem->part, file, file_path->str); } } @@ -1219,7 +1224,6 @@ COMMAND_DECL(move_left){ i32 pos = view->cursor.pos; if (pos > 0) --pos; - view_cursor_move(view, pos); } @@ -1231,13 +1235,12 @@ COMMAND_DECL(move_right){ i32 size = buffer_size(&file->buffer); i32 pos = view->cursor.pos; if (pos < size) ++pos; - view_cursor_move(view, pos); } COMMAND_DECL(delete){ ProfileMomentFunction(); - REQ_FILE_VIEW(view); + REQ_OPEN_FILE_VIEW(view); REQ_FILE(file, view); USE_LAYOUT(layout); USE_MEM(mem); @@ -1261,7 +1264,7 @@ COMMAND_DECL(delete){ COMMAND_DECL(backspace){ ProfileMomentFunction(); - REQ_FILE_VIEW(view); + REQ_OPEN_FILE_VIEW(view); REQ_FILE(file, view); USE_LAYOUT(layout); USE_MEM(mem); @@ -1292,7 +1295,7 @@ COMMAND_DECL(move_up){ real32 px = view->preferred_x; if (cy >= 0){ view->cursor = view_compute_cursor_from_xy(view, px, cy); - view->file->cursor_pos = view->cursor.pos; + file->cursor_pos = view->cursor.pos; } } @@ -1304,7 +1307,7 @@ COMMAND_DECL(move_down){ real32 cy = view_get_cursor_y(view)+view->style->font->height; real32 px = view->preferred_x; view->cursor = view_compute_cursor_from_xy(view, px, cy); - view->file->cursor_pos = view->cursor.pos; + file->cursor_pos = view->cursor.pos; } COMMAND_DECL(seek_end_of_line){ @@ -1539,27 +1542,47 @@ COMMAND_DECL(build){ USE_LIVE_SET(live_set); USE_PANEL(panel); + char *buffer_name = "*cli process*"; + char *path = "..\\misc"; + char *script = "test"; + if (vars->cli_processes.count < vars->cli_processes.max){ - Get_File_Result file = working_set_get_available_file(working_set); - if (file.file){ - file_create_empty(&mem->general, file.file, (u8*)"*cli process*", style->font); - table_add(&working_set->table, file.file->source_path, file.index); + Editing_File *file = working_set_contains(working_set, make_string_slowly(buffer_name)); + i32 index; + + if (!file){ + Get_File_Result get_file = working_set_get_available_file(working_set); + file = get_file.file; + index = get_file.index; + } + else{ + i32 proc_count = vars->cli_processes.count; + for (i32 i = 0; i < proc_count; ++i){ + if (vars->cli_processes.procs[i].out_file == file){ + vars->cli_processes.procs[i].out_file = 0; + } + } + index = (int)(file - vars->working_set.files); + } + + if (file){ + file_create_super_locked(&mem->general, file, (u8*)buffer_name, style->font); + table_add(&working_set->table, file->live_name, index); View *new_view = live_set_alloc_view(live_set, mem); view_replace_major(new_view, panel, live_set); - File_View *file_view = file_view_init(new_view, &vars->delay, &vars->layout); - view_set_file(file_view, file.file, style, + File_View *file_view = file_view_init(new_view, &vars->layout); + view_set_file(file_view, file, style, vars->hooks[hook_open_file], command, app_links); - file.file->tokens_exist = 0; - new_view->map = app_get_map(vars, file.file->base_map_id); + new_view->map = app_get_map(vars, file->base_map_id); i32 i = vars->cli_processes.count++; CLI_Process *proc = vars->cli_processes.procs + i; - if (!system_cli_call("..\\misc", "build_all_test", &proc->cli)){ + if (!system_cli_call(path, script, &proc->cli)){ --vars->cli_processes.count; } - proc->out_file = file.file; + proc->out_file = file; } else{ // TODO(allen): feedback message - no available file @@ -1608,25 +1631,6 @@ extern "C"{ if (function) function(cmd, binding); update_command_data(cmd->vars, cmd); -#if 0 - App_Vars *vars = cmd->vars; - Command_Data command_data; - command_data.vars = vars; - command_data.mem = &vars->mem; - command_data.working_set = &vars->working_set; - command_data.layout = &vars->layout; - command_data.panel = command_data.layout->panels + command_data.layout->active_panel; - command_data.view = command_data.panel->view; - command_data.live_set = &vars->live_set; - command_data.style = &vars->style; - command_data.delay = &vars->delay; - command_data.screen_width = cmd->screen_width; - command_data.screen_height = cmd->screen_height; - command_data.key = cmd->key; - command_data.part = cmd->part; - - *cmd = command_data; -#endif } PUSH_PARAMETER_SIG(external_push_parameter){ @@ -1755,7 +1759,7 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co map_add(commands, codes->down, MDFR_ALT, command_stop_rewind_fastforward); map_add(commands, 'h', MDFR_CTRL, command_history_backward); map_add(commands, 'H', MDFR_CTRL, command_history_forward); - map_add(commands, 'd', MDFR_CTRL, command_delete_chunk); + map_add(commands, 'd', MDFR_CTRL, command_delete_range); map_add(commands, 'l', MDFR_CTRL, command_toggle_line_wrap); map_add(commands, '?', MDFR_CTRL, command_toggle_show_whitespace); map_add(commands, '|', MDFR_CTRL, command_toggle_tokens); @@ -1830,7 +1834,7 @@ setup_command_table(){ SET(cut); SET(paste); SET(paste_next); - SET(delete_chunk); + SET(delete_range); SET(timeline_scrub); SET(undo); SET(redo); @@ -1998,7 +2002,6 @@ app_hardcode_styles(App_Vars *vars){ style->main.paste_color = 0xFFDDEE00; style->main.undo_color = 0xFF00DDEE; - style->main.next_undo_color = 0xFF006E77; style->main.highlight_junk_color = 0xff3a0000; style->main.highlight_white_color = 0xff003a3a; @@ -2086,7 +2089,6 @@ app_hardcode_styles(App_Vars *vars){ style->main.paste_color = 0xFFDDEE00; style->main.undo_color = 0xFF00DDEE; - style->main.next_undo_color = 0xFF006E77; style->main.highlight_junk_color = 0xff3a0000; style->main.highlight_white_color = 0xFF151F2A; @@ -2127,7 +2129,6 @@ app_hardcode_styles(App_Vars *vars){ style->main.paste_color = 0xFF900090; style->main.undo_color = 0xFF606090; - style->main.next_undo_color = 0xFF404070; style->main.highlight_junk_color = 0xff3a0000; style->main.highlight_white_color = 0xff003a3a; @@ -2168,7 +2169,6 @@ app_hardcode_styles(App_Vars *vars){ style->main.paste_color = 0xFF00B8B8; style->main.undo_color = 0xFFB800B8; - style->main.next_undo_color = 0xFF5C005C; style->main.highlight_junk_color = 0xFFFF7878; style->main.highlight_white_color = 0xFFBCBCBC; @@ -2592,7 +2592,7 @@ app_step(Thread_Context *thread, Key_Codes *codes, } // NOTE(allen): update child processes - { + if (time_step){ Temp_Memory temp = begin_temp_memory(&vars->mem.part); u32 max = Kbytes(32); char *dest = push_array(&vars->mem.part, char, max); @@ -2610,7 +2610,7 @@ app_step(Thread_Context *thread, Key_Codes *codes, amount = eol_in_place_convert_in(dest, amount); Edit_Spec spec = {}; spec.step.type = ED_NORMAL; - spec.step.edit.start = buffer_size(&out_file->buffer); + spec.step.edit.start = buffer_size(&out_file->buffer); spec.step.edit.end = spec.step.edit.start; spec.step.edit.len = amount; spec.step.pre_pos = new_cursor; @@ -2622,11 +2622,22 @@ app_step(Thread_Context *thread, Key_Codes *codes, new_cursor = spec.step.post_pos; } } - + if (system_cli_end_update(&proc->cli)){ *proc = vars->cli_processes.procs[--count]; --i; } + + Panel *panel = vars->layout.panels; + i32 panel_count = vars->layout.panel_count; + for (i32 i = 0; i < panel_count; ++i, ++panel){ + View *view = panel->view; + if (view && view->is_minor) view = view->major; + File_View *fview = view_to_file_view(view); + if (fview){ + view_cursor_move(fview, new_cursor); + } + } } vars->cli_processes.count = count; @@ -3043,7 +3054,7 @@ app_step(Thread_Context *thread, Key_Codes *codes, if (fview){ Editing_File *file = fview->file; if (file && !file->is_dummy){ - file_save_and_set_names(&vars->mem.part, file, (u8*)string->str); + file_save_and_set_names(&vars->mem.part, file, string->str); } } }break; @@ -3051,8 +3062,8 @@ app_step(Thread_Context *thread, Key_Codes *codes, case DACT_SAVE: { Editing_File *file = working_set_lookup_file(working_set, *string); - if (file && !file->is_dummy){ - file_save(&vars->mem.part, file, (u8*)file->source_path.str); + if (!file->is_dummy){ + file_save(&vars->mem.part, file, file->source_path.str); } }break; @@ -3065,7 +3076,7 @@ app_step(Thread_Context *thread, Key_Codes *codes, View *new_view = live_set_alloc_view(live_set, mem); view_replace_major(new_view, panel, live_set); - File_View *file_view = file_view_init(new_view, &vars->delay, &vars->layout); + File_View *file_view = file_view_init(new_view, &vars->layout); command_data.view = (View*)file_view; view_set_file(file_view, file.file, style, vars->hooks[hook_open_file], &command_data, app_links); @@ -3082,10 +3093,12 @@ app_step(Thread_Context *thread, Key_Codes *codes, View *new_view = live_set_alloc_view(live_set, mem); view_replace_major(new_view, panel, live_set); - File_View *file_view = file_view_init(new_view, &vars->delay, &vars->layout); + File_View *file_view = file_view_init(new_view, &vars->layout); command_data.view = (View*)file_view; + view_set_file(file_view, file, style, vars->hooks[hook_open_file], &command_data, app_links); + new_view->map = app_get_map(vars, file->base_map_id); } }break; @@ -3095,7 +3108,7 @@ app_step(Thread_Context *thread, Key_Codes *codes, Editing_File *file = working_set_lookup_file(working_set, *string); if (file){ table_remove(&working_set->table, file->source_path); - kill_buffer(general, file, live_set, &vars->layout); + kill_file(general, file, live_set, &vars->layout); } }break; @@ -3108,7 +3121,7 @@ app_step(Thread_Context *thread, Key_Codes *codes, case SYNC_GOOD: { table_remove(&working_set->table, file->source_path); - kill_buffer(general, file, live_set, &vars->layout); + kill_file(general, file, live_set, &vars->layout); view_remove_minor(panel, live_set); }break; @@ -3186,7 +3199,7 @@ app_step(Thread_Context *thread, Key_Codes *codes, Editing_File *file = vars->working_set.files; for (i32 i = vars->working_set.file_index_count; i > 0; --i, ++file){ if (buffer_good(&file->buffer) && !file->is_dummy){ - file_measure_widths(&vars->mem.general, file, vars->style.font); + file_measure_widths(&vars->mem.general, &file->buffer, vars->style.font); } } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index ad089218..2eca2df5 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -84,28 +84,28 @@ struct Undo_Data{ struct Editing_File{ Buffer_Type buffer; - - Undo_Data undo; - Font *font; i32 cursor_pos; b32 is_dummy; + char live_name_[256]; + String live_name; + + i32 base_map_id; char source_path_[256]; - char live_name_[256]; char extension_[16]; String source_path; - String live_name; String extension; + Undo_Data undo; + b32 super_locked; + Cpp_Token_Stack token_stack; b32 tokens_complete; b32 tokens_exist; b32 still_lexing; u32 lex_job; - - i32 base_map_id; i32 dos_write_mode; u64 last_4ed_write_time; @@ -116,7 +116,7 @@ struct Editing_File{ struct File_Table_Entry{ String name; u32 hash; - i32 index; + i32 id; }; struct File_Table{ @@ -136,15 +136,15 @@ get_file_hash(String name){ return x; } -internal bool32 -table_add(File_Table *table, String name, i32 index){ +internal b32 +table_add(File_Table *table, String name, i32 id){ Assert(table->count * 3 < table->max * 2); File_Table_Entry entry, e; i32 i; entry.name = name; - entry.index = index; + entry.id = id; entry.hash = get_file_hash(name); i = entry.hash % table->max; while ((e = table->table[i]).name.str){ @@ -178,18 +178,18 @@ table_find_pos(File_Table *table, String name, i32 *index){ return 0; } -inline bool32 -table_find(File_Table *table, String name, i32 *index){ +inline b32 +table_find(File_Table *table, String name, i32 *id){ i32 pos; - bool32 r = table_find_pos(table, name, &pos); - if (r) *index = table->table[pos].index; + b32 r = table_find_pos(table, name, &pos); + if (r) *id = table->table[pos].id; return r; } -inline bool32 +inline b32 table_remove(File_Table *table, String name){ i32 pos; - bool32 r = table_find_pos(table, name, &pos); + b32 r = table_find_pos(table, name, &pos); if (r){ table->table[pos].name.str = 0; --table->count; @@ -1021,23 +1021,37 @@ struct File_View_Widget{ } timeline; }; +enum Link_Type{ + link_result, + link_related, + link_error, + link_warning, + // never below this + link_type_count +}; + +struct Hyper_Link{ + char *file_name; + i32 line_number; + i32 start, end; + Link_Type link_type; +}; + struct File_View{ View view_base; - - Delay *delay; - Editing_Layout *layout; - + Editing_File *file; Style *style; + Editing_Layout *layout; i32 font_advance; i32 font_height; - + Full_Cursor cursor; i32 mark; - real32 scroll_y, target_y, vel_y; - real32 scroll_x, target_x, vel_x; - real32 preferred_x; + f32 scroll_y, target_y, vel_y; + f32 scroll_x, target_x, vel_x; + f32 preferred_x; Full_Cursor scroll_y_cursor; union{ Incremental_Search isearch; @@ -1048,19 +1062,23 @@ struct File_View{ Full_Cursor temp_highlight; i32 temp_highlight_end_pos; - bool32 show_temp_highlight; + b32 show_temp_highlight; File_View_Mode mode, next_mode; File_View_Widget widget; - real32 rewind_amount, rewind_speed; + f32 rewind_amount, rewind_speed; i32 rewind_max, scrub_max; - bool32 unwrapped_lines; - bool32 show_whitespace; + b32 unwrapped_lines; + b32 show_whitespace; + b32 locked; i32 line_count, line_max; - real32 *line_wrap_y; + f32 *line_wrap_y; Text_Effect paste_effect; + + Hyper_Link *links; + i32 link_count, link_max; }; inline File_View* @@ -1099,14 +1117,19 @@ file_init_strings(Editing_File *file){ } inline void -file_set_name(Editing_File *file, u8 *filename){ - String f, ext; - f = make_string_slowly((char*)filename); - copy_checked(&file->source_path, f); +file_set_name(Editing_File *file, char *filename){ file->live_name = make_fixed_width_string(file->live_name_); - get_front_of_directory(&file->live_name, f); - ext = file_extension(f); - copy(&file->extension, ext); + if (filename[0] == '*'){ + copy(&file->live_name, filename); + } + else{ + String f, ext; + f = make_string_slowly(filename); + copy_checked(&file->source_path, f); + get_front_of_directory(&file->live_name, f); + ext = file_extension(f); + copy(&file->extension, ext); + } } inline void @@ -1119,32 +1142,32 @@ file_synchronize_times(Editing_File *file, u8 *filename){ } } -internal bool32 -file_save(Partition *part, Editing_File *file, u8 *filename){ - bool32 result = 0; -#if BUFFER_EXPERIMENT_SCALPEL <= 1 +internal b32 +file_save(Partition *part, Editing_File *file, char *filename){ + b32 result = 0; +#if BUFFER_EXPERIMENT_SCALPEL <= 2 Temp_Memory temp = begin_temp_memory(part); i32 max = partition_remaining(part); if (file->dos_write_mode){ char *data = push_array(part, char, max); i32 size = buffer_convert_out(&file->buffer, data, max); - result = system_save_file(filename, data, size); + result = system_save_file((u8*)filename, data, size); } else{ char *data = push_array(part, char, max); i32 size = buffer_size(&file->buffer); Assert(size <= max); buffer_stringify(&file->buffer, 0, size, data); - result = system_save_file(filename, data, size); + result = system_save_file((u8*)filename, data, size); } end_temp_memory(temp); - file_synchronize_times(file, filename); + file_synchronize_times(file, (u8*)filename); #endif return result; } inline bool32 -file_save_and_set_names(Partition *part, Editing_File *file, u8 *filename){ +file_save_and_set_names(Partition *part, Editing_File *file, char *filename){ bool32 result = 0; if (file_save(part, file, filename)){ result = 1; @@ -1153,16 +1176,6 @@ file_save_and_set_names(Partition *part, Editing_File *file, u8 *filename){ return result; } -inline i32 -file_count_newlines(Editing_File *file, i32 start, i32 end){ -#if BUFFER_EXPERIMENT_SCALPEL <= 2 - i32 count = buffer_count_newlines(&file->buffer, start, end); -#else - i32 count = 0; -#endif - return count; -} - enum File_Bubble_Type{ BUBBLE_BUFFER = 1, BUBBLE_STARTS, @@ -1181,20 +1194,20 @@ enum File_Bubble_Type{ #define GROW_SUCCESS 2 internal i32 -file_grow_starts_as_needed(General_Memory *general, Editing_File *file, i32 additional_lines){ +file_grow_starts_as_needed(General_Memory *general, Buffer_Type *buffer, i32 additional_lines){ bool32 result = GROW_NOT_NEEDED; #if BUFFER_EXPERIMENT_SCALPEL <= 2 - i32 max = file->buffer.line_max; - i32 count = file->buffer.line_count; + i32 max = buffer->line_max; + i32 count = buffer->line_count; i32 target_lines = count + additional_lines; if (target_lines > max || max == 0){ max = LargeRoundUp(target_lines + max, Kbytes(1)); i32 *new_lines = (i32*) - general_memory_reallocate(general, file->buffer.line_starts, + general_memory_reallocate(general, buffer->line_starts, sizeof(i32)*count, sizeof(i32)*max, BUBBLE_STARTS); if (new_lines){ - file->buffer.line_starts = new_lines; - file->buffer.line_max = max; + buffer->line_starts = new_lines; + buffer->line_max = max; result = GROW_SUCCESS; } else{ @@ -1206,47 +1219,45 @@ file_grow_starts_as_needed(General_Memory *general, Editing_File *file, i32 addi } internal void -file_measure_starts(General_Memory *general, Editing_File *file){ +file_measure_starts(General_Memory *general, Buffer_Type *buffer){ #if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); - if (!file->buffer.line_starts){ - i32 max = file->buffer.line_max = Kbytes(1); - file->buffer.line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32), BUBBLE_STARTS); - TentativeAssert(file->buffer.line_starts); + if (!buffer->line_starts){ + i32 max = buffer->line_max = Kbytes(1); + buffer->line_starts = (i32*)general_memory_allocate(general, max*sizeof(i32), BUBBLE_STARTS); + TentativeAssert(buffer->line_starts); // TODO(allen): when unable to allocate? } Buffer_Measure_Starts state = {}; - while (buffer_measure_starts(&state, &file->buffer)){ - i32 max = file->buffer.line_max; + while (buffer_measure_starts(&state, buffer)){ + i32 max = buffer->line_max; i32 count = state.count; i32 target_lines = count + 1; max = (target_lines << 1); i32 *new_lines = (i32*) - general_memory_reallocate(general, file->buffer.line_starts, + general_memory_reallocate(general, buffer->line_starts, sizeof(i32)*count, sizeof(i32)*max, BUBBLE_STARTS); // TODO(allen): when unable to grow? TentativeAssert(new_lines); - file->buffer.line_starts = new_lines; - file->buffer.line_max = max; + buffer->line_starts = new_lines; + buffer->line_max = max; } - file->buffer.line_count = state.count; + buffer->line_count = state.count; #endif } internal void -file_remeasure_starts(General_Memory *general, Editing_File *file, +file_remeasure_starts(General_Memory *general, Buffer_Type *buffer, i32 line_start, i32 line_end, i32 line_shift, i32 character_shift){ #if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); - - Assert(file->buffer.line_starts); - file_grow_starts_as_needed(general, file, line_shift); - - buffer_remeasure_starts(&file->buffer, line_start, line_end, line_shift, character_shift); + Assert(buffer->line_starts); + file_grow_starts_as_needed(general, buffer, line_shift); + buffer_remeasure_starts(buffer, line_start, line_end, line_shift, character_shift); #endif } @@ -1264,47 +1275,44 @@ get_opaque_font_advance(Font *font){ } internal void -file_grow_widths_as_needed(General_Memory *general, Editing_File *file){ +file_grow_widths_as_needed(General_Memory *general, Buffer_Type *buffer){ #if BUFFER_EXPERIMENT_SCALPEL <= 2 - i32 line_count = file->buffer.line_count; - if (line_count > file->buffer.widths_max || file->buffer.widths_max == 0){ + i32 line_count = buffer->line_count; + if (line_count > buffer->widths_max || buffer->widths_max == 0){ i32 new_max = LargeRoundUp(line_count, Kbytes(1)); if (new_max < Kbytes(1)) new_max = Kbytes(1); - if (file->buffer.line_widths){ - file->buffer.line_widths = (f32*) - general_memory_reallocate(general, file->buffer.line_widths, - sizeof(f32)*file->buffer.widths_count, sizeof(f32)*new_max, BUBBLE_WIDTHS); + if (buffer->line_widths){ + buffer->line_widths = (f32*) + general_memory_reallocate(general, buffer->line_widths, + sizeof(f32)*buffer->widths_count, sizeof(f32)*new_max, BUBBLE_WIDTHS); } else{ - file->buffer.line_widths = (f32*) + buffer->line_widths = (f32*) general_memory_allocate(general, sizeof(f32)*new_max, BUBBLE_WIDTHS); } - file->buffer.widths_max = new_max; + buffer->widths_max = new_max; } #endif } internal void -file_measure_widths(General_Memory *general, Editing_File *file, Font *font){ +file_measure_widths(General_Memory *general, Buffer_Type *buffer, Font *font){ #if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); - - file_grow_widths_as_needed(general, file); + file_grow_widths_as_needed(general, buffer); Opaque_Font_Advance opad = get_opaque_font_advance(font); - buffer_measure_widths(&file->buffer, opad.data, opad.stride); + buffer_measure_widths(buffer, opad.data, opad.stride); #endif } internal void -file_remeasure_widths(General_Memory *general, Editing_File *file, Font *font, +file_remeasure_widths(General_Memory *general, Buffer_Type *buffer, Font *font, i32 line_start, i32 line_end, i32 line_shift){ #if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); - - file_grow_widths_as_needed(general, file); + file_grow_widths_as_needed(general, buffer); Opaque_Font_Advance opad = get_opaque_font_advance(font); - buffer_remeasure_widths(&file->buffer, opad.data, opad.stride, - line_start, line_end, line_shift); + buffer_remeasure_widths(buffer, opad.data, opad.stride, line_start, line_end, line_shift); #endif } @@ -1325,15 +1333,15 @@ view_compute_lowest_line(File_View *view){ lowest_line = last_line; } else{ - real32 wrap_y = view->line_wrap_y[last_line]; - Editing_File *file = view->file; - Assert(!file->is_dummy); Style *style = view->style; Font *font = style->font; + real32 wrap_y = view->line_wrap_y[last_line]; lowest_line = FLOOR32(wrap_y / font->height); - - real32 width = file->buffer.line_widths[last_line]; - real32 max_width = view_compute_width(view); + f32 max_width = view_compute_width(view); + + Editing_File *file = view->file; + Assert(!file->is_dummy); + f32 width = file->buffer.line_widths[last_line]; i32 line_span = view_wrapped_line_span(width, max_width); lowest_line += line_span - 1; } @@ -1346,8 +1354,10 @@ internal void view_measure_wraps(General_Memory *general, File_View *view){ #if BUFFER_EXPERIMENT_SCALPEL <= 2 ProfileMomentFunction(); - Editing_File *file = view->file; - i32 line_count = file->buffer.line_count; + Buffer_Type *buffer; + + buffer = &view->file->buffer; + i32 line_count = buffer->line_count; if (view->line_max < line_count){ i32 max = view->line_max = LargeRoundUp(line_count, Kbytes(1)); @@ -1364,7 +1374,7 @@ view_measure_wraps(General_Memory *general, File_View *view){ Font *font = view->style->font; real32 line_height = (real32)font->height; real32 max_width = view_compute_width(view); - buffer_measure_wrap_y(&file->buffer, view->line_wrap_y, line_height, max_width); + buffer_measure_wrap_y(buffer, view->line_wrap_y, line_height, max_width); view->line_count = line_count; #endif @@ -1378,7 +1388,7 @@ alloc_for_buffer(void *context, int *size){ } internal void -file_create_from_string(General_Memory *general, Editing_File *file, u8 *filename, Font *font, String val){ +file_create_from_string(General_Memory *general, Editing_File *file, u8 *filename, Font *font, String val, b32 super_locked = 0){ *file = {}; #if BUFFER_EXPERIMENT_SCALPEL <= 2 Buffer_Init_Type init = buffer_begin_init(&file->buffer, val.str, val.size); @@ -1393,40 +1403,44 @@ file_create_from_string(General_Memory *general, Editing_File *file, u8 *filenam Assert(init_success); #endif - file_synchronize_times(file, filename); file_init_strings(file); - file_set_name(file, filename); + file_set_name(file, (char*)filename); file->base_map_id = mapid_file; - - file_measure_starts(general, file); - file_measure_widths(general, file, font); file->font = font; + + file_synchronize_times(file, filename); + + file_measure_starts(general, &file->buffer); + file_measure_widths(general, &file->buffer, font); - i32 request_size = Kbytes(64); - file->undo.undo.max = request_size; - file->undo.undo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); - file->undo.undo.edit_max = request_size / sizeof(Edit_Step); - file->undo.undo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); + file->super_locked = super_locked; + if (!super_locked){ + i32 request_size = Kbytes(64); + file->undo.undo.max = request_size; + file->undo.undo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + file->undo.undo.edit_max = request_size / sizeof(Edit_Step); + file->undo.undo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); - file->undo.redo.max = request_size; - file->undo.redo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); - file->undo.redo.edit_max = request_size / sizeof(Edit_Step); - file->undo.redo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); + file->undo.redo.max = request_size; + file->undo.redo.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + file->undo.redo.edit_max = request_size / sizeof(Edit_Step); + file->undo.redo.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); - file->undo.history.max = request_size; - file->undo.history.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); - file->undo.history.edit_max = request_size / sizeof(Edit_Step); - file->undo.history.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); + file->undo.history.max = request_size; + file->undo.history.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + file->undo.history.edit_max = request_size / sizeof(Edit_Step); + file->undo.history.edits = (Edit_Step*)general_memory_allocate(general, request_size, BUBBLE_UNDO); - file->undo.children.max = request_size; - file->undo.children.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); - file->undo.children.edit_max = request_size / sizeof(Buffer_Edit); - file->undo.children.edits = (Buffer_Edit*)general_memory_allocate(general, request_size, BUBBLE_UNDO); + file->undo.children.max = request_size; + file->undo.children.strings = (u8*)general_memory_allocate(general, request_size, BUBBLE_UNDO_STRING); + file->undo.children.edit_max = request_size / sizeof(Buffer_Edit); + file->undo.children.edits = (Buffer_Edit*)general_memory_allocate(general, request_size, BUBBLE_UNDO); - file->undo.history_block_count = 1; - file->undo.history_head_block = 0; - file->undo.current_block_normal = 1; + file->undo.history_block_count = 1; + file->undo.history_head_block = 0; + file->undo.current_block_normal = 1; + } } internal bool32 @@ -1444,13 +1458,19 @@ file_create(General_Memory *general, Editing_File *file, u8 *filename, Font *fon return result; } -internal bool32 +internal b32 file_create_empty(General_Memory *general, Editing_File *file, u8 *filename, Font *font){ - bool32 result = 1; - + b32 result = 1; String empty_str = {}; file_create_from_string(general, file, filename, font, empty_str); - + return result; +} + +internal b32 +file_create_super_locked(General_Memory *general, Editing_File *file, u8 *filename, Font *font){ + b32 result = 1; + String empty_str = {}; + file_create_from_string(general, file, filename, font, empty_str, 1); return result; } @@ -1487,25 +1507,31 @@ file_close(General_Memory *general, Editing_File *file){ if (file->token_stack.tokens){ general_memory_free(general, file->token_stack.tokens); } + #if BUFFER_EXPERIMENT_SCALPEL <= 1 - general_memory_free(general, file->buffer.data); - general_memory_free(general, file->buffer.line_starts); - general_memory_free(general, file->buffer.line_widths); + Buffer_Type *buffer = &file->buffer; + if (buffer->data){ + general_memory_free(general, buffer->data); + general_memory_free(general, buffer->line_starts); + general_memory_free(general, buffer->line_widths); + } #elif BUFFER_EXPERIMENT_SCALPEL == 2 // TODO #endif + + if (file->undo.undo.edits){ + general_memory_free(general, file->undo.undo.strings); + general_memory_free(general, file->undo.undo.edits); - general_memory_free(general, file->undo.undo.strings); - general_memory_free(general, file->undo.undo.edits); + general_memory_free(general, file->undo.redo.strings); + general_memory_free(general, file->undo.redo.edits); - general_memory_free(general, file->undo.redo.strings); - general_memory_free(general, file->undo.redo.edits); - - general_memory_free(general, file->undo.history.strings); - general_memory_free(general, file->undo.history.edits); + general_memory_free(general, file->undo.history.strings); + general_memory_free(general, file->undo.history.edits); + } } -internal void +inline void file_get_dummy(Editing_File *file){ *file = {}; file->is_dummy = 1; @@ -2101,9 +2127,9 @@ view_set_file(File_View *view, Editing_File *file, Style *style, Custom_Command_Function *open_hook, void *cmd_context, Application_Links app){ Panel *panel = view->view_base.panel; view->file = file; + view->locked = file->super_locked; General_Memory *general = &view->view_base.mem->general; - AllowLocal(general); Font *font = style->font; view->style = style; view->font_advance = font->advance; @@ -2114,25 +2140,25 @@ view_set_file(File_View *view, Editing_File *file, Style *style, view->cursor = {}; view->cursor = view_compute_cursor_from_pos(view, file->cursor_pos); - real32 cursor_x, cursor_y; - real32 w, h; - real32 target_x, target_y; + f32 cursor_x, cursor_y; + f32 w, h; + f32 target_x, target_y; cursor_x = view_get_cursor_x(view); cursor_y = view_get_cursor_y(view); - w = (real32)(panel->inner.x1 - panel->inner.x0); - h = (real32)(panel->inner.y1 - panel->inner.y0); + w = (f32)(panel->inner.x1 - panel->inner.x0); + h = (f32)(panel->inner.y1 - panel->inner.y0); target_x = 0; if (cursor_x < target_x){ - target_x = (real32)Max(0, cursor_x - w*.5f); + target_x = (f32)Max(0, cursor_x - w*.5f); } else if (cursor_x >= target_x + w){ - target_x = (real32)(cursor_x - w*.5f); + target_x = (f32)(cursor_x - w*.5f); } - target_y = (real32)FLOOR32(cursor_y - h*.5f); + target_y = (f32)FLOOR32(cursor_y - h*.5f); if (target_y < 0) target_y = 0; view->target_x = target_x; @@ -2257,6 +2283,7 @@ enum History_Mode{ internal void file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step step, u8 *str, History_Mode history_mode){ + if (!file->undo.undo.edits) return; #if BUFFER_EXPERIMENT_SCALPEL <= 1 General_Memory *general = &mem->general; @@ -2443,30 +2470,28 @@ inline void file_pre_edit_maintenance(Editing_File *file){ if (file->still_lexing) system_cancel_job(BACKGROUND_THREADS, file->lex_job); - file->last_4ed_edit_time = system_get_now(); } internal void file_do_single_edit(Mem_Options *mem, Editing_File *file, Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){ - Assert(file); ProfileMomentFunction(); // NOTE(allen): fixing stuff beforewards???? file_update_history_before_edit(mem, file, spec.step, spec.str, history_mode); file_pre_edit_maintenance(file); -#if BUFFER_EXPERIMENT_SCALPEL <= 1 // NOTE(allen): actual text replacement +#if BUFFER_EXPERIMENT_SCALPEL <= 2 + i32 shift_amount = 0; General_Memory *general = &mem->general; + char *str = (char*)spec.str; i32 start = spec.step.edit.start; i32 end = spec.step.edit.end; - char *str = (char*)spec.str; i32 str_len = spec.step.edit.len; - i32 shift_amount = 0; i32 request_amount = 0; while (buffer_replace_range(&file->buffer, start, end, str, str_len, &shift_amount, &request_amount)){ void *new_data = 0; @@ -2476,22 +2501,20 @@ file_do_single_edit(Mem_Options *mem, Editing_File *file, void *old_data = buffer_edit_provide_memory(&file->buffer, new_data, request_amount); if (old_data) general_memory_free(general, old_data); } - -#if BUFFER_EXPERIMENT_SCALPEL <= 0 - // NOTE(allen): fixing stuff afterwards - if (file->tokens_exist) - file_relex_parallel(mem, file, start, end, shift_amount); + +#if BUFFER_EXPERIMENT_SCALPEL == 2 + buffer_mugab_check(&file->buffer); #endif i32 line_start = buffer_get_line_index(&file->buffer, start); i32 line_end = buffer_get_line_index(&file->buffer, end); i32 replaced_line_count = line_end - line_start; - i32 new_line_count = file_count_newlines(file, start, start+str_len); + i32 new_line_count = buffer_count_newlines(&file->buffer, start, start+str_len); i32 line_shift = new_line_count - replaced_line_count; - file_remeasure_starts(general, file, line_start, line_end, line_shift, shift_amount); - file_remeasure_widths(general, file, file->font, line_start, line_end, line_shift); - + file_remeasure_starts(general, &file->buffer, line_start, line_end, line_shift, shift_amount); + file_remeasure_widths(general, &file->buffer, file->font, line_start, line_end, line_shift); + i32 panel_count = layout->panel_count; Panel *current_panel = layout->panels; for (i32 i = 0; i < panel_count; ++i, ++current_panel){ @@ -2500,7 +2523,15 @@ file_do_single_edit(Mem_Options *mem, Editing_File *file, view_measure_wraps(general, current_view); } } +#endif + +#if BUFFER_EXPERIMENT_SCALPEL <= 0 + // NOTE(allen): fixing stuff afterwards + if (file->tokens_exist) + file_relex_parallel(mem, file, start, end, shift_amount); +#endif +#if BUFFER_EXPERIMENT_SCALPEL <= 1 Temp_Memory cursor_temp = begin_temp_memory(&mem->part); i32 cursor_max = layout->panel_max_count * 2; Cursor_With_Index *cursors = push_array(&mem->part, Cursor_With_Index, cursor_max); @@ -2541,6 +2572,7 @@ file_do_single_edit(Mem_Options *mem, Editing_File *file, internal void view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file, Editing_Layout *layout, Edit_Spec spec, History_Mode history_mode){ + if (view->locked) return; #if BUFFER_EXPERIMENT_SCALPEL <= 1 Assert(file); ProfileMomentFunction(); @@ -2652,6 +2684,7 @@ view_do_white_batch_edit(Mem_Options *mem, File_View *view, Editing_File *file, inline void view_replace_range(Mem_Options *mem, File_View *view, Editing_Layout *layout, i32 start, i32 end, u8 *str, i32 len, i32 next_cursor){ + if (view->locked) return; Edit_Spec spec = {}; spec.step.type = ED_NORMAL; spec.step.edit.start = start; @@ -2663,7 +2696,7 @@ view_replace_range(Mem_Options *mem, File_View *view, Editing_Layout *layout, file_do_single_edit(mem, view->file, layout, spec, hist_normal); } -internal void +inline void view_post_paste_effect(File_View *view, i32 ticks, i32 start, i32 size, u32 color){ view->paste_effect.start = start; view->paste_effect.end = start + size; @@ -2675,6 +2708,7 @@ view_post_paste_effect(File_View *view, i32 ticks, i32 start, i32 size, u32 colo internal void view_undo_redo(Mem_Options *mem, Editing_Layout *layout, File_View *view, Editing_File *file, Edit_Stack *stack, Edit_Type expected_type){ + if (view->locked) return; if (file && stack->edit_count > 0){ Edit_Step step = stack->edits[stack->edit_count-1]; @@ -2717,9 +2751,11 @@ view_redo(Mem_Options *mem, Editing_Layout *layout, File_View *view){ internal void view_history_step(Mem_Options *mem, Editing_Layout *layout, File_View *view, History_Mode history_mode){ + if (view->locked) return; Assert(history_mode != hist_normal); Editing_File *file = view->file; + bool32 do_history_step = 0; Edit_Step step = {}; if (history_mode == hist_backward){ @@ -2768,7 +2804,7 @@ view_history_step(Mem_Options *mem, Editing_Layout *layout, File_View *view, His } } -// TODO(allen): should these still be view operations? +// TODO(allen): write these as streamed operations internal i32 view_find_end_of_line(File_View *view, i32 pos){ #if BUFFER_EXPERIMENT_SCALPEL <= 0 @@ -2871,9 +2907,11 @@ working_set_clipboard_roll_down(Working_Set *working){ inline Editing_File* working_set_contains(Working_Set *working, String filename){ Editing_File *result = 0; - i32 index; - if (table_find(&working->table, filename, &index)){ - result = working->files + index; + i32 id; + if (table_find(&working->table, filename, &id)){ + if (id < working->file_max_count){ + result = working->files + id; + } } return result; } @@ -2894,7 +2932,7 @@ working_set_lookup_file(Working_Set *working_set, String string){ } if (file_i == end) file = 0; } - + return file; } @@ -3194,6 +3232,44 @@ view_auto_tab_tokens(Mem_Options *mem, File_View *view, Editing_Layout *layout, #endif } +struct Get_Link_Result{ + b32 in_link; + i32 index; +}; + +internal Get_Link_Result +get_link(Hyper_Link *links, i32 link_count, i32 pos){ + Get_Link_Result result = {}; + // TODO TODO TODO TODO TODO TODO TODO TODO + return result; +} + +internal u32* +style_get_link_color(Style *style, Link_Type type){ + u32 *result; + switch (type){ + case link_result: + result = &style->main.result_link_color; + break; + + case link_related: + result = &style->main.related_link_color; + break; + + case link_error: + result = &style->main.error_link_color; + break; + + case link_warning: + result = &style->main.warning_link_color; + break; + + default: + result = &style->main.default_color; + } + return result; +} + internal u32* style_get_color(Style *style, Cpp_Token token){ u32 *result; @@ -3503,16 +3579,16 @@ step_file_view(Thread_Context *thread, View *view_, i32_Rect rect, Style *style = view->style; Font *font = style->font; - real32 line_height = (real32)font->height; - real32 cursor_y = view_get_cursor_y(view); - real32 target_y = view->target_y; - real32 max_y = view_compute_height(view) - line_height*2; + f32 line_height = (f32)font->height; + f32 cursor_y = view_get_cursor_y(view); + f32 target_y = view->target_y; + f32 max_y = view_compute_height(view) - line_height*2; i32 lowest_line = view_compute_lowest_line(view); - real32 max_target_y = view_compute_max_target_y(lowest_line, font->height, max_y); - real32 delta_y = 3.f*line_height; - real32 extra_top = 0.f; + f32 max_target_y = view_compute_max_target_y(lowest_line, font->height, max_y); + f32 delta_y = 3.f*line_height; + f32 extra_top = 0.f; extra_top += view_widget_height(view, font); - real32 taken_top_space = line_height + extra_top; + f32 taken_top_space = line_height + extra_top; if (user_input->mouse.my < rect.y0 + taken_top_space){ view_->mouse_cursor_type = APP_MOUSE_CURSOR_ARROW; @@ -3595,7 +3671,7 @@ step_file_view(Thread_Context *thread, View *view_, i32_Rect rect, if (!is_active) view_set_widget(view, FWIDG_NONE); // NOTE(allen): framely undo stuff - { + if (file){ i32 scrub_max = view->scrub_max; i32 undo_count, redo_count, total_count; undo_count = file->undo.undo.edit_count; @@ -3740,12 +3816,27 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act i32 max_x = rect.x1 - rect.x0; i32 max_y = rect.y1 - rect.y0 + font->height; - Assert(file && buffer_good(&file->buffer) && !file->is_dummy); + Assert(file && !file->is_dummy && buffer_good(&file->buffer)); Opaque_Font_Advance opad = get_opaque_font_advance(font); - b32 tokens_use = file->tokens_complete && (file->token_stack.count > 0); - Cpp_Token_Stack token_stack = file->token_stack; - + b32 tokens_use = 0; + Cpp_Token_Stack token_stack = {}; + if (file){ + tokens_use = file->tokens_complete && (file->token_stack.count > 0); + token_stack = file->token_stack; + } + + b32 links_use = 0; + Hyper_Link *links = 0; + i32 link_count = 0; + if (view->links){ + if (view->link_count > 0){ + links_use = 1; + links = view->links; + link_count = view->link_count; + } + } + Partition *part = &view_->mem->part; Temp_Memory temp = begin_temp_memory(part); @@ -3775,17 +3866,38 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act } i32 token_i = 0; + i32 link_i = 0; u32 main_color = style->main.default_color; + u32 link_color = 0; if (tokens_use){ Cpp_Get_Token_Result result = cpp_get_token(&token_stack, items->index); main_color = *style_get_color(style, token_stack.tokens[result.token_index]); token_i = result.token_index + 1; } + if (links_use){ + Get_Link_Result result = get_link(links, link_count, items->index); + if (result.in_link){ + link_color = *style_get_link_color(style, links[result.index].link_type); + } + link_i = result.index; + } u32 mark_color = style->main.mark_color; Buffer_Render_Item *item = items; i32 prev_ind = -1; - u32 highlight_color = 0; AllowLocal(highlight_color); + u32 highlight_color = 0; + + u32 chunk_highlights[] = { + 0x22FF0000, + 0x22FFFF00, + 0x2200FF00, + 0x2200FFFF, + 0x220000FF, + 0x22FF00FF + }; + + i32 current_chunk = item->chunk_i; + u32 chunk_highlight = chunk_highlights[current_chunk % ArrayCount(chunk_highlights)]; for (i32 i = 0; i < count; ++i, ++item){ i32 ind = item->index; if (tokens_use && ind != prev_ind){ @@ -3810,11 +3922,22 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act } u32 char_color = main_color; + if (item->chunk_i > current_chunk){ + current_chunk = item->chunk_i; + chunk_highlight = chunk_highlights[current_chunk % ArrayCount(chunk_highlights)]; + } + if (cursor_begin <= ind && ind < cursor_end && (ind != prev_ind || cursor_begin < ind)){ if (is_active) draw_rectangle(target, f32R(item->x0, item->y0, item->x1, item->y1), cursor_color); else draw_rectangle_outline(target, f32R(item->x0, item->y0, item->x1, item->y1), cursor_color); char_color = at_cursor_color; } + else if (highlight_color){ + draw_rectangle(target, f32R(item->x0, item->y0, item->x1, item->y1), highlight_color); + } + else if (chunk_highlight){ + draw_rectangle(target, f32R(item->x0, item->y0, item->x1, item->y1), chunk_highlight); + } u32 fade_color = 0xFFFF00FF; f32 fade_amount = 0.f; @@ -3859,6 +3982,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act switch (view->widget.type){ case FWIDG_TIMELINES: { + Assert(file); if (view->widget.timeline.undo_line){ do_button(1, &state, &layout, "- Undo", 1); @@ -3925,18 +4049,20 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act intbar_draw_string(target, &bar, line_number, base_color); - switch (buffer_get_sync(file)){ - case SYNC_BEHIND_OS: - { - persist String out_of_sync = make_lit_string(" BEHIND OS"); - intbar_draw_string(target, &bar, out_of_sync, bar.style.pop2_color); - }break; + if (file){ + switch (buffer_get_sync(file)){ + case SYNC_BEHIND_OS: + { + persist String out_of_sync = make_lit_string(" BEHIND OS"); + intbar_draw_string(target, &bar, out_of_sync, bar.style.pop2_color); + }break; - case SYNC_UNSAVED: - { - persist String out_of_sync = make_lit_string(" *"); - intbar_draw_string(target, &bar, out_of_sync, bar.style.pop2_color); - }break; + case SYNC_UNSAVED: + { + persist String out_of_sync = make_lit_string(" *"); + intbar_draw_string(target, &bar, out_of_sync, bar.style.pop2_color); + }break; + } } } @@ -3944,7 +4070,7 @@ draw_file_view(Thread_Context *thread, View *view_, i32_Rect rect, bool32 is_act } internal void -kill_buffer(General_Memory *general, Editing_File *file, Live_Views *live_set, Editing_Layout *layout){ +kill_file(General_Memory *general, Editing_File *file, Live_Views *live_set, Editing_Layout *layout){ i32 panel_count = layout->panel_count; Panel *panels = layout->panels, *panel; panel = panels; @@ -3963,7 +4089,6 @@ kill_buffer(General_Memory *general, Editing_File *file, Live_Views *live_set, E } ++panel; } - file_close(general, file); file_get_dummy(file); } @@ -4098,9 +4223,11 @@ HANDLE_COMMAND_SIG(handle_command_file_view){ } inline void -free_file_view(View *view_){ - File_View *view = (File_View*)view_; - general_memory_free(&view_->mem->general, view->line_wrap_y); +free_file_view(View *view){ + File_View *fview = (File_View*)view; + general_memory_free(&view->mem->general, fview->line_wrap_y); + if (fview->links) + general_memory_free(&view->mem->general, fview->links); } internal @@ -4129,13 +4256,12 @@ DO_VIEW_SIG(do_file_view){ } internal File_View* -file_view_init(View *view, Delay *delay, Editing_Layout *layout){ +file_view_init(View *view, Editing_Layout *layout){ view->type = VIEW_TYPE_FILE; view->do_view = do_file_view; view->handle_command = handle_command_file_view; File_View *result = (File_View*)view; - result->delay = delay; result->layout = layout; result->rewind_max = 4; result->scrub_max = 1; diff --git a/4ed_style.cpp b/4ed_style.cpp index 0f818a59..8097f94c 100644 --- a/4ed_style.cpp +++ b/4ed_style.cpp @@ -143,7 +143,10 @@ struct Style_Main_Data{ u32 highlight_white_color; u32 paste_color; u32 undo_color; - u32 next_undo_color; + u32 result_link_color; + u32 related_link_color; + u32 error_link_color; + u32 warning_link_color; Interactive_Style file_info_style; }; @@ -186,6 +189,10 @@ enum Style_Color_Tag{ STAG_PASTE_COLOR, STAG_UNDO_COLOR, STAG_NEXT_UNDO_COLOR, + STAG_RESULT_LINK_COLOR, + STAG_RELATED_LINK_COLOR, + STAG_ERROR_LINK_COLOR, + STAG_WARNING_LINK_COLOR, // never below this STAG_COUNT }; @@ -350,7 +357,6 @@ style_form_convert(Style_File_Format_v4 *o, Style_File_Format_v3 *i){ o->main.highlight_white_color = i->main.highlight_white_color; o->main.paste_color = i->main.paste_color; o->main.undo_color = i->main.paste_color ^ 0x00FFFFFF; - o->main.next_undo_color = i->main.paste_color ^ 0x00FFFFFF; o->main.file_info_style = i->main.file_info_style; o->main.file_info_style.bar_active_color = i->main.file_info_style.bar_color; } @@ -395,7 +401,11 @@ style_index_by_tag(Style *s, u32 tag){ case STAG_PASTE_COLOR: result = &s->main.paste_color; break; case STAG_UNDO_COLOR: result = &s->main.undo_color; break; - case STAG_NEXT_UNDO_COLOR: result = &s->main.next_undo_color; break; + + case STAG_RESULT_LINK_COLOR: result = &s->main.result_link_color; break; + case STAG_RELATED_LINK_COLOR: result = &s->main.related_link_color; break; + case STAG_ERROR_LINK_COLOR: result = &s->main.error_link_color; break; + case STAG_WARNING_LINK_COLOR: result = &s->main.warning_link_color; break; } return result; } diff --git a/buffer/4coder_buffer_abstract.cpp b/buffer/4coder_buffer_abstract.cpp index aa38cc86..2e92ea39 100644 --- a/buffer/4coder_buffer_abstract.cpp +++ b/buffer/4coder_buffer_abstract.cpp @@ -131,7 +131,7 @@ buffer_seek_whitespace_up(Buffer_Type *buffer, int pos){ int no_hard; size = buffer_size(buffer); - loop = buffer_backify_loop(buffer, pos, 1); + loop = buffer_backify_loop(buffer, pos-1, 1); for (;buffer_backify_good(&loop); buffer_backify_next(&loop)){ @@ -245,18 +245,22 @@ buffer_seek_alphanumeric_right(Buffer_Type *buffer, int pos){ buffer_stringify_next(&loop)){ end = loop.size + loop.absolute_pos; data = loop.data - loop.absolute_pos; - for (; pos < end && is_alphanumeric_true(data[pos]); ++pos); - if (!is_alphanumeric_true(data[pos])) break; + for (; pos < end; ++pos){ + if (!is_alphanumeric_true(data[pos])) goto buffer_seek_alphanumeric_right_mid; + } } +buffer_seek_alphanumeric_right_mid: for (;buffer_stringify_good(&loop); buffer_stringify_next(&loop)){ end = loop.size + loop.absolute_pos; data = loop.data - loop.absolute_pos; - for (; pos < end && !is_alphanumeric_true(data[pos]); ++pos); - if (is_alphanumeric_true(data[pos])) break; + for (; pos < end; ++pos){ + if (is_alphanumeric_true(data[pos])) goto buffer_seek_alphanumeric_right_end; + } } +buffer_seek_alphanumeric_right_end: return(pos); } @@ -276,16 +280,19 @@ buffer_seek_alphanumeric_left(Buffer_Type *buffer, int pos){ buffer_backify_next(&loop)){ end = loop.absolute_pos; data = loop.data - end; - for (; pos >= end && !is_alphanumeric_true(data[pos]); --pos); - if (is_alphanumeric_true(data[pos])) break; + for (; pos >= end; --pos){ + if (is_alphanumeric_true(data[pos])) goto buffer_seek_alphanumeric_left_mid; + } } +buffer_seek_alphanumeric_left_mid: for (;buffer_backify_good(&loop); buffer_backify_next(&loop)){ end = loop.absolute_pos; data = loop.data - end; - for (; pos >= end && is_alphanumeric_true(data[pos]); --pos); - if (!is_alphanumeric_true(data[pos])) break; + for (; pos >= end; --pos){ + if (!is_alphanumeric_true(data[pos])) goto buffer_seek_alphanumeric_left_end; + } } ++pos; @@ -294,6 +301,7 @@ buffer_seek_alphanumeric_left(Buffer_Type *buffer, int pos){ pos = 0; } +buffer_seek_alphanumeric_left_end: return(pos); } @@ -1069,6 +1077,9 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it switch (ch){ case '\n': write_render_item_inline(item, i, ' ', x, y, advance_data, stride, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = loop.chunk_i*2 + ((loop.pos >= buffer->gaps[loop.chunk_i].size1)?1:0); +#endif ++item_i; ++item; @@ -1078,11 +1089,17 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it case 0: ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = loop.chunk_i*2 + ((loop.pos >= buffer->gaps[loop.chunk_i].size1)?1:0); +#endif ++item_i; ++item; x += ch_width; ch_width = write_render_item_inline(item, i, '0', x, y, advance_data, stride, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = loop.chunk_i*2 + ((loop.pos >= buffer->gaps[loop.chunk_i].size1)?1:0); +#endif ++item_i; ++item; x += ch_width; @@ -1090,11 +1107,17 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it case '\r': ch_width = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = loop.chunk_i*2 + ((loop.pos >= buffer->gaps[loop.chunk_i].size1)?1:0); +#endif ++item_i; ++item; x += ch_width; ch_width = write_render_item_inline(item, i, 'r', x, y, advance_data, stride, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = loop.chunk_i*2 + ((loop.pos >= buffer->gaps[loop.chunk_i].size1)?1:0); +#endif ++item_i; ++item; x += ch_width; @@ -1102,10 +1125,16 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it case '\t': ch_width_sub = write_render_item_inline(item, i, '\\', x, y, advance_data, stride, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = loop.chunk_i*2 + ((loop.pos >= buffer->gaps[loop.chunk_i].size1)?1:0); +#endif ++item_i; ++item; write_render_item_inline(item, i, 't', x + ch_width_sub, y, advance_data, stride, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = loop.chunk_i*2 + ((loop.pos >= buffer->gaps[loop.chunk_i].size1)?1:0); +#endif ++item_i; ++item; x += ch_width; @@ -1113,9 +1142,13 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it default: write_render_item(item, i, ch, x, y, ch_width, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = loop.chunk_i*2 + ((loop.pos >= buffer->gaps[loop.chunk_i].size1)?1:0); +#endif ++item_i; ++item; x += ch_width; + break; } if (y > height + shift_y) goto buffer_get_render_data_end; @@ -1127,6 +1160,9 @@ buffer_get_render_data_end: ch = 0; ch_width = measure_character(advance_data, stride, ' '); write_render_item(item, size, ch, x, y, ch_width, font_height); +#if BUFFER_EXPERIMENT_SCALPEL == 2 + item->chunk_i = -1; +#endif ++item_i; ++item; x += ch_width; diff --git a/buffer/4coder_gap_buffer.cpp b/buffer/4coder_gap_buffer.cpp index 58d49f58..654399c5 100644 --- a/buffer/4coder_gap_buffer.cpp +++ b/buffer/4coder_gap_buffer.cpp @@ -110,25 +110,6 @@ buffer_end_init(Gap_Buffer_Init *init){ return(result); } -internal_4tech void* -buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, int new_max){ - void *result; - int new_gap_size; - - assert_4tech(new_max >= buffer_size(buffer)); - - result = buffer->data; - new_gap_size = new_max - buffer_size(buffer); - memcpy_4tech(new_data, buffer->data, buffer->size1); - memcpy_4tech((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); - - buffer->data = (char*)new_data; - buffer->gap_size = new_gap_size; - buffer->max = new_max; - - return(result); -} - typedef struct{ Gap_Buffer *buffer; char *data, *base; @@ -334,5 +315,24 @@ buffer_batch_edit_step(Buffer_Batch_State *state, Gap_Buffer *buffer, Buffer_Edi return(result); } +internal_4tech void* +buffer_edit_provide_memory(Gap_Buffer *buffer, void *new_data, int new_max){ + void *result; + int new_gap_size; + + assert_4tech(new_max >= buffer_size(buffer)); + + result = buffer->data; + new_gap_size = new_max - buffer_size(buffer); + memcpy_4tech(new_data, buffer->data, buffer->size1); + memcpy_4tech((char*)new_data + buffer->size1 + new_gap_size, buffer->data + buffer->size1 + buffer->gap_size, buffer->size2); + + buffer->data = (char*)new_data; + buffer->gap_size = new_gap_size; + buffer->max = new_max; + + return(result); +} + // BOTTOM diff --git a/buffer/4coder_golden_array.cpp b/buffer/4coder_golden_array.cpp index 6d893f7f..2e7592eb 100644 --- a/buffer/4coder_golden_array.cpp +++ b/buffer/4coder_golden_array.cpp @@ -92,20 +92,6 @@ buffer_end_init(Buffer_Init *init){ return(result); } -internal_4tech void* -buffer_edit_provide_memory(Buffer *buffer, void *new_data, int new_max){ - void *result; - - assert_4tech(new_max >= buffer->size); - - result = buffer->data; - memcpy_4tech(new_data, buffer->data, buffer->size); - buffer->data = (char*)new_data; - buffer->max = new_max; - - return(result); -} - typedef struct{ Buffer *buffer; char *data, *end; @@ -226,5 +212,19 @@ buffer_batch_edit_step(Buffer_Batch_State *state, Buffer *buffer, Buffer_Edit *s return(result); } +internal_4tech void* +buffer_edit_provide_memory(Buffer *buffer, void *new_data, int new_max){ + void *result; + + assert_4tech(new_max >= buffer->size); + + result = buffer->data; + memcpy_4tech(new_data, buffer->data, buffer->size); + buffer->data = (char*)new_data; + buffer->max = new_max; + + return(result); +} + // BOTTOM diff --git a/buffer/4coder_multi_gap_buffer.cpp b/buffer/4coder_multi_gap_buffer.cpp index 62abc9b7..25ad00d1 100644 --- a/buffer/4coder_multi_gap_buffer.cpp +++ b/buffer/4coder_multi_gap_buffer.cpp @@ -28,6 +28,7 @@ typedef struct{ typedef struct{ Fixed_Width_Gap_Buffer *gaps; int chunk_count; + int chunk_alloced; int chunk_max; int size; @@ -37,6 +38,9 @@ typedef struct{ int widths_count; int line_max; int widths_max; + + int grow_gaps; + int edit_stage; } Multi_Gap_Buffer; inline_4tech int @@ -59,9 +63,9 @@ typedef struct{ int size; int chunk_i; int chunk_count; + int chunk_alloc; } Multi_Gap_Buffer_Init; - internal_4tech Multi_Gap_Buffer_Init buffer_begin_init(Multi_Gap_Buffer *buffer, char *data, int size){ Multi_Gap_Buffer_Init init; @@ -69,7 +73,9 @@ buffer_begin_init(Multi_Gap_Buffer *buffer, char *data, int size){ init.data = data; init.size = size; init.chunk_i = 0; - init.chunk_count = div_ceil_4tech(size, fixed_width_buffer_half_size); + init.chunk_alloc = div_ceil_4tech(size, fixed_width_buffer_half_size); + init.chunk_count = init.chunk_alloc; + if (init.chunk_alloc < 4) init.chunk_alloc = 4; return(init); } @@ -77,7 +83,7 @@ internal_4tech int buffer_init_need_more(Multi_Gap_Buffer_Init *init){ int result; result = 1; - if (init->buffer->gaps && init->chunk_i == init->chunk_count) + if (init->buffer->gaps && init->chunk_i == init->chunk_alloc) result = 0; return(result); } @@ -88,7 +94,7 @@ buffer_init_page_size(Multi_Gap_Buffer_Init *init){ int result; buffer = init->buffer; if (buffer->gaps) result = fixed_width_buffer_size; - else result = init->chunk_count * 2 * sizeof(*buffer->gaps); + else result = init->chunk_alloc * 2 * sizeof(*buffer->gaps); return(result); } @@ -123,12 +129,14 @@ buffer_end_init(Multi_Gap_Buffer_Init *init){ if (buffer->gaps){ if (buffer->chunk_max >= div_ceil_4tech(init->size, fixed_width_buffer_half_size)){ buffer->chunk_count = init->chunk_count; + if (buffer->chunk_count == 0) buffer->chunk_count = 1; + buffer->chunk_alloced = init->chunk_alloc; result = 1; data = init->data; total_size = init->size; gap = buffer->gaps; - count = init->chunk_count; + count = buffer->chunk_count; size = fixed_width_buffer_half_size; pos = 0; start_pos = 0; @@ -151,7 +159,7 @@ buffer_end_init(Multi_Gap_Buffer_Init *init){ gap->size2 = size2; gap->gap_size = fixed_width_buffer_size - size1 - size2; memmove_4tech(gap->data + size1 + gap->gap_size, gap->data + size1, size2); - + gap->start_pos = start_pos; start_pos += size1 + size2; } @@ -171,25 +179,24 @@ internal_4tech int buffer_find_chunk(Multi_Gap_Buffer *buffer, int pos){ Fixed_Width_Gap_Buffer *gaps; int start, end, m, this_pos; - - if (pos == buffer_size(buffer)){ - m = buffer->chunk_count; - } - else{ - gaps = buffer->gaps; - start = 0; - end = buffer->chunk_count; - for(;;){ - m = (start + end) / 2; - this_pos = gaps[m].start_pos; - if (this_pos < pos) start = m; - else if (this_pos > pos) end = m; - else break; - if (start+1 == end){ - m = start; break; - } - assert_4tech(start < end); + + gaps = buffer->gaps; + start = 0; + end = buffer->chunk_count; + for(;;){ + m = (start + end) / 2; + this_pos = gaps[m].start_pos; + if (this_pos < pos) start = m; + else if (this_pos > pos) end = m; + else{ + --m; + if (m < 0) m = 0; + break; } + if (start+1 == end){ + m = start; break; + } + assert_4tech(start < end); } return(m); @@ -222,7 +229,7 @@ buffer_stringify_loop(Multi_Gap_Buffer *buffer, int start, int end){ gap = result.gaps + result.chunk_end; end -= gap->start_pos; - if (end < gap->size1) result.end = end; + if (end <= gap->size1) result.end = end; else result.end = end + gap->gap_size; gap = result.gaps + result.chunk_i; @@ -272,6 +279,10 @@ buffer_stringify_next(Multi_Gap_Buffer_Stringify_Loop *loop){ loop->pos = 0; loop->absolute_pos = gap->start_pos; temp_end = gap->size1; + if (gap->size1 == 0){ + loop->pos = gap->gap_size; + temp_end = fixed_width_buffer_size; + } } if (loop->chunk_i == loop->chunk_end && temp_end > loop->end) temp_end = loop->end; loop->size = temp_end - loop->pos; @@ -301,7 +312,7 @@ buffer_backify_loop(Multi_Gap_Buffer *buffer, int start, int end){ result.buffer = buffer; result.gaps = buffer->gaps; - result.chunk_i = buffer_find_chunk(buffer, start); + result.chunk_i = buffer_find_chunk(buffer, start-1); result.chunk_end = buffer_find_chunk(buffer, end); gap = result.gaps + result.chunk_end; @@ -369,12 +380,20 @@ buffer_backify_next(Multi_Gap_Buffer_Backify_Loop *loop){ internal_4tech int buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, int len, int *shift_amount_out, int *request_amount){ - Fixed_Width_Gap_Buffer *gaps, *gap; + Fixed_Width_Gap_Buffer *gaps, *gap, *dgap; + char *data; + int move_size; int gap_start, gap_end; int result; int size; int local_end; int shift_amount; + int required_empty_buffers; + int supplanted_gaps; + int dpos; + int head_size, middle_size, tail_size; + int mem_pos, local_start_pos; + debug_4tech(int osize); size = buffer_size(buffer); assert_4tech(0 <= start); @@ -386,35 +405,58 @@ buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, in gaps = buffer->gaps; gap_start = buffer_find_chunk(buffer, start); gap_end = buffer_find_chunk(buffer, end); - - gap = gaps + gap_start; - if (gap_start < gap_end){ - memmove_4tech(gap + 1, gaps + gap_end, sizeof(*gaps)*(buffer->chunk_count - gap_end)); - buffer->chunk_count -= (gap_end - gap_start + 1); - ++gap; - - local_end = end - gap->start_pos; - - if (gap->size1 >= local_end){ - gap->size2 -= (local_end - gap->size1); - gap->size1 = 0; + + if (buffer->edit_stage == 0){ + buffer->size += *shift_amount_out; + for (gap = gaps + gap_end + 1; + gap < gaps + buffer->chunk_count; + ++gap){ + gap->start_pos += *shift_amount_out; } - else{ - memmove_4tech(gap->data, gap->data + local_end, gap->size1 - local_end); - gap->size1 -= local_end; - } - - --gap; + buffer->edit_stage = 1; + } + + gap = gaps + gap_start; + if (buffer->edit_stage == 1){ + if (gap_start < gap_end && gap_start+1 < buffer->chunk_count){ + supplanted_gaps = gap_end - gap_start + 1; + if (buffer->chunk_max - buffer->chunk_alloced >= supplanted_gaps){ + ++gap; + memcpy_4tech(gaps + buffer->chunk_alloced, gap, sizeof(*gaps)*supplanted_gaps); + memmove_4tech(gap, gaps + gap_end, sizeof(*gaps)*(buffer->chunk_alloced - gap_start - 1)); + buffer->chunk_count -= (gap_end - gap_start + 1); + + local_end = end - gap->start_pos; + + if (gap->size1 >= local_end){ + gap->size2 -= (local_end - gap->size1); + gap->size1 = 0; + } + else{ + memmove_4tech(gap->data, gap->data + local_end, gap->size1 - local_end); + gap->size1 -= local_end; + } + + --gap; + } + else{ + buffer->grow_gaps = 1; + *request_amount = round_up_4tech(sizeof(*gaps)*(supplanted_gaps+buffer->chunk_max*2), 4<<10); + result = 1; + goto mugab_replace_range_end; + } + } + buffer->edit_stage = 2; } - if (end > gap->size1 + gap->size2) end = gap->size1 + gap->size2; shift_amount = (len - (end - start)); + start -= gap->start_pos; + end -= gap->start_pos; + if (end > gap->size1 + gap->size2) end = gap->size1 + gap->size2; if (shift_amount + gap->size1 + gap->size2 <= fixed_width_buffer_size){ - start -= gap->start_pos; - end -= gap->start_pos; - data = gap->data; + debug_4tech(osize = gap->size1 + gap->size2); if (end < gap->size1){ move_size = gap->size1 - end; memmove_4tech(data + gap->size1 + gap->gap_size - move_size, data + end, move_size); @@ -429,20 +471,206 @@ buffer_replace_range(Multi_Gap_Buffer *buffer, int start, int end, char *str, in } memcpy_4tech(data + start, str, len); - gap->size2 = size - end; + gap->size2 = fixed_width_buffer_size - (end + gap->gap_size); gap->size1 = start + len; gap->gap_size -= shift_amount; - assert_4tech(gap->size1 + gap->size2 == size + shift_amount); - assert_4tech(gap->size1 + gap->gap_size + gap->size2 == gap->max); + assert_4tech(gap->size1 + gap->size2 == osize + shift_amount); + assert_4tech(gap->size1 + gap->gap_size + gap->size2 == fixed_width_buffer_size); result = 0; + buffer->edit_stage = 0; + + if (gap_start < gap_end){ + ++gap; + gap->start_pos += shift_amount; + } } else{ - div_ceil_4tech(shift_amount, fixed_width_buffer_half_size); - result = 1; + required_empty_buffers = div_ceil_4tech(shift_amount, fixed_width_buffer_half_size); + if (buffer->chunk_alloced - buffer->chunk_count >= required_empty_buffers){ + if (buffer->chunk_max - buffer->chunk_alloced >= required_empty_buffers){ + memcpy_4tech(gaps + buffer->chunk_alloced, gaps + buffer->chunk_count, sizeof(*gaps)*required_empty_buffers); + memmove_4tech(gap + required_empty_buffers + 1, gap + 1, sizeof(*gaps)*(buffer->chunk_count - gap_start - 1)); + memcpy_4tech(gap + 1, gaps + buffer->chunk_alloced, sizeof(*gaps)*required_empty_buffers); + + data = gap->data; + if (end < gap->size1){ + move_size = gap->size1 - end; + memmove_4tech(data + gap->size1 + gap->gap_size - move_size, data + end, move_size); + gap->size1 -= move_size + (end - start); + gap->size2 += move_size; + } + else if (start > gap->size1){ + move_size = start - gap->size1; + memmove_4tech(data + gap->size1, data + gap->size1 + gap->gap_size, move_size); + gap->size1 += move_size; + gap->size2 -= move_size + (end - start); + } + else{ + if (end > gap->size1){ + gap->size2 -= (end - gap->size1); + } + gap->size1 = start; + } + + if (gap->size1 > fixed_width_buffer_half_size){ + move_size = gap->size1 - fixed_width_buffer_half_size; + memmove_4tech(data + gap->size1 + gap->gap_size - move_size, data + end, move_size); + gap->size1 -= move_size + (end - start); + gap->size2 += move_size; + } + else if (gap->size2 > fixed_width_buffer_half_size){ + move_size = gap->size2 - fixed_width_buffer_half_size; + memmove_4tech(data + gap->size1, data + gap->size1 + gap->gap_size, move_size); + gap->size1 += move_size; + gap->size2 -= move_size + (end - start); + } + + dgap = gap + required_empty_buffers; + dpos = gap->size1 + gap->gap_size; + memcpy_4tech(dgap->data + dpos, data + dpos, gap->size2); + dgap->size2 = gap->size2; + gap->size2 = 0; + + middle_size = div_ceil_4tech(len, (required_empty_buffers * 2)); + + head_size = middle_size; + tail_size = middle_size; + + if (head_size + gap->size1 + 256 > fixed_width_buffer_size){ + head_size = fixed_width_buffer_size - gap->size1 - 256; + if (head_size < 0) head_size = 0; + } + + if (tail_size + dgap->size2 + 256 > fixed_width_buffer_size){ + tail_size = fixed_width_buffer_size - dgap->size2 - 256; + if (tail_size < 0) tail_size = 0; + } + + if (required_empty_buffers-1 > 0) + middle_size = div_ceil_4tech(len - head_size - tail_size, (required_empty_buffers-1)*2); + else + middle_size = 0; + + mem_pos = 0; + if (head_size > len - mem_pos) head_size = len - mem_pos; + + gap->size2 = head_size; + gap->gap_size = fixed_width_buffer_size - gap->size1 - gap->size2; + memcpy_4tech(gap->data + fixed_width_buffer_size - head_size, str + mem_pos, head_size); + mem_pos += head_size; + local_start_pos = gap->start_pos + gap->size1 + gap->size2; + + ++gap; + for (;gap < dgap; ++gap){ + gap->start_pos = local_start_pos; + + if (middle_size > len - mem_pos) middle_size = len - mem_pos; + gap->size1 = middle_size; + memcpy_4tech(gap->data, str + mem_pos, middle_size); + mem_pos += middle_size; + + if (middle_size > len - mem_pos) middle_size = len - mem_pos; + gap->size2 = middle_size; + memcpy_4tech(gap->data + fixed_width_buffer_size - middle_size, str + mem_pos, middle_size); + mem_pos += middle_size; + + gap->gap_size = fixed_width_buffer_size - (gap->size1 + gap->size2); + local_start_pos += gap->size1 + gap->size2; + ++gap; + } + + if (tail_size > len - mem_pos) tail_size = len - mem_pos; + gap->start_pos = local_start_pos; + gap->size1 = tail_size; + gap->gap_size = fixed_width_buffer_size - gap->size1 - gap->size2; + memcpy_4tech(gap->data, str + mem_pos, tail_size); + mem_pos += tail_size; + assert_4tech(mem_pos == len); + + buffer->chunk_count += required_empty_buffers; + + result = 0; + buffer->edit_stage = 0; + } + else{ + buffer->grow_gaps = 1; + *request_amount = round_up_4tech(sizeof(*gaps)*(required_empty_buffers+buffer->chunk_max*2), 4<<10); + result = 1; + goto mugab_replace_range_end; + } + } + else{ + if (buffer->chunk_alloced < buffer->chunk_max){ + *request_amount = fixed_width_buffer_size; + result = 1; + } + else{ + buffer->grow_gaps = 1; + *request_amount = round_up_4tech(sizeof(*gaps)*(1+buffer->chunk_max*2), 4<<10); + result = 1; + } + } + } + +mugab_replace_range_end: + return(result); +} + +internal_4tech void* +buffer_edit_provide_memory(Multi_Gap_Buffer *buffer, void *new_data, int size){ + void *result; + Fixed_Width_Gap_Buffer *gap; + + if (buffer->grow_gaps){ + assert_4tech(size >= buffer->chunk_max*sizeof(*buffer->gaps)); + + result = buffer->gaps; + memcpy_4tech(new_data, buffer->gaps, buffer->chunk_alloced*sizeof(*buffer->gaps)); + buffer->gaps = (Fixed_Width_Gap_Buffer*)new_data; + buffer->chunk_max = size / sizeof(*buffer->gaps); + buffer->grow_gaps = 0; } + else{ + assert_4tech(buffer->chunk_max > buffer->chunk_alloced); + assert_4tech(size >= fixed_width_buffer_size); + + gap = &buffer->gaps[buffer->chunk_alloced++]; + *gap = {}; + gap->data = (char*)new_data; + result = 0; + } + + return(result); +} + +internal_4tech int +buffer_mugab_check(Multi_Gap_Buffer *buffer){ + Fixed_Width_Gap_Buffer *gap; + int result; + int total_size; + int i, count; + + assert_4tech(buffer->chunk_count <= buffer->chunk_alloced); + assert_4tech(buffer->chunk_alloced <= buffer->chunk_max); + + count = buffer->chunk_count; + + total_size = 0; + gap = buffer->gaps; + for (i = 0; i < count; ++i, ++gap){ + assert_4tech(gap->size1 + gap->size2 + gap->gap_size == fixed_width_buffer_size); + assert_4tech(gap->start_pos == total_size); + total_size += gap->size1 + gap->size2; + } + assert_4tech(total_size == buffer->size); + + assert_4tech(buffer->edit_stage == 0); + assert_4tech(buffer->grow_gaps == 0); + + result = 1; return(result); } diff --git a/buffer/4coder_shared.cpp b/buffer/4coder_shared.cpp index b103d464..bb8e0019 100644 --- a/buffer/4coder_shared.cpp +++ b/buffer/4coder_shared.cpp @@ -157,6 +157,8 @@ typedef struct{ int glyphid; float x0, y0; float x1, y1; + + int chunk_i; } Buffer_Render_Item; inline_4tech void diff --git a/win32_4ed.cpp b/win32_4ed.cpp index 01f488e1..2eb405d6 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -58,7 +58,7 @@ #define FPS 30 #define FRAME_TIME (1000000 / FPS) -#define BUFFER_EXPERIMENT_SCALPEL 0 +#define BUFFER_EXPERIMENT_SCALPEL 1 #include "4ed_meta.h"