diff --git a/4coder_default_include.cpp b/4coder_default_include.cpp index a6728866..7f408843 100644 --- a/4coder_default_include.cpp +++ b/4coder_default_include.cpp @@ -1654,6 +1654,7 @@ isearch(Application_Links *app, int start_reversed){ int reverse = start_reversed; int pos = view.cursor.pos; int start_pos = pos; + int first_pos = pos; Range match = make_range(pos, pos); char bar_string_space[256]; @@ -1756,7 +1757,7 @@ isearch(Application_Links *app, int start_reversed){ } app->view_set_highlight(app, &view, 0, 0, false); if (in.abort){ - app->view_set_cursor(app, &view, seek_pos(start_pos), true); + app->view_set_cursor(app, &view, seek_pos(first_pos), true); return; } diff --git a/4coder_table.cpp b/4coder_table.cpp index 0a7ec22a..2748deb2 100644 --- a/4coder_table.cpp +++ b/4coder_table.cpp @@ -170,15 +170,12 @@ table_rehash(Table *src, Table *dst, void *arg, Hash_Function *hash_func, Compar static uint32_t tbl_string_hash(void *item, void *arg){ String *string = (String*)item; - char *str; - int32_t i,len; + char *str = string->str; + int32_t i = 0, len = string->size; uint32_t x = 5381; char c; (void)arg; - str = string->str; - len = string->size; - i = 0; while (i < len){ c = str[i++]; x = ((x << 5) + x) + c; diff --git a/4ed_file.cpp b/4ed_file.cpp index 202d2564..462faa18 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -188,6 +188,7 @@ struct Editing_File{ Editing_File_Name name; Buffer_Slot_ID id; u64 unique_buffer_id; + Unique_Hash file_index; }; struct Non_File_Table_Entry{ @@ -208,7 +209,8 @@ struct Working_Set{ File_Node free_sentinel; File_Node used_sentinel; - Table table; + Table uhash_table; + Table name_table; String clipboards[64]; i32 clipboard_size, clipboard_max_size; @@ -219,42 +221,6 @@ struct Working_Set{ File_Node *sync_check_iter; }; -struct File_Entry{ - String short_name; - String long_name; - Buffer_Slot_ID id; -}; - -struct File_Entry_Comparison{ - File_Entry entry; - Unique_Hash hash; - b32 use_hash; -}; - -internal i32 -tbl_file_compare(void *a, void *b, void *arg){ - File_Entry_Comparison *fa = (File_Entry_Comparison*)a; - File_Entry *fb = (File_Entry*)b; - System_Functions *system = (System_Functions*)arg; - Unique_Hash uhash; - i32 result = 1; - b32 success; - - if (fa->use_hash){ - uhash = system->file_unique_hash(fb->long_name, &success); - if (success && uhash_equal(uhash, fa->hash)){ - result = 0; - } - } - else{ - if (match(fa->entry.short_name, fb->short_name)){ - result = 0; - } - } - - return(result); -} - // // File_Edit_Positions stuff // @@ -382,6 +348,48 @@ edit_pos_get_new(Editing_File *file, i32 index){ // Working_Set stuff // +struct File_Uhash_Entry{ + Unique_Hash hash; + Buffer_Slot_ID id; +}; + +struct File_Name_Entry{ + String name; + Buffer_Slot_ID id; +}; + +internal u32 +tbl_uhash_hash(void *item, void *arg){ + Unique_Hash *hash = (Unique_Hash*)item; + return(hash->d[0] ^ (hash->d[1] << 24)); +} + +internal i32 +tbl_uhash_compare(void *a, void *b, void *arg){ + Unique_Hash *fa = (Unique_Hash*)a; + File_Uhash_Entry *fb = (File_Uhash_Entry*)b; + + i32 result = 1; + if (uhash_equal(fb->hash, *fa)){ + result = 0; + } + + return(result); +} + +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(*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){ Buffer_Slot_ID id; @@ -434,7 +442,7 @@ working_set_alloc(Working_Set *working_set){ ++working_set->file_count; } - return result; + return(result); } internal Editing_File* @@ -472,7 +480,7 @@ working_set_free_file(Working_Set *working_set, Editing_File *file){ inline Editing_File* working_set_index(Working_Set *working_set, Buffer_Slot_ID id){ Editing_File *result = 0; - File_Array *array; + File_Array *array = 0; if (id.part[1] >= 0 && id.part[1] < working_set->array_count){ array = working_set->file_arrays + id.part[1]; @@ -486,8 +494,7 @@ working_set_index(Working_Set *working_set, Buffer_Slot_ID id){ inline Editing_File* working_set_index(Working_Set *working_set, i32 id){ - Editing_File *result; - result = working_set_index(working_set, to_file_id(id)); + Editing_File *result = working_set_index(working_set, to_file_id(id)); return(result); } @@ -510,45 +517,54 @@ working_set_get_active_file(Working_Set *working_set, i32 id){ internal void working_set_init(Working_Set *working_set, Partition *partition, General_Memory *general){ - Editing_File *files, *null_file; - void *mem; - i32 mem_size, table_size; - - i32 item_size = sizeof(File_Entry); i16 init_count = 16; i16 array_init_count = 256; dll_init_sentinel(&working_set->free_sentinel); dll_init_sentinel(&working_set->used_sentinel); - + working_set->array_max = array_init_count; working_set->file_arrays = push_array(partition, File_Array, array_init_count); - - files = push_array(partition, Editing_File, init_count); + + Editing_File *files = push_array(partition, Editing_File, init_count); working_set_extend_memory(working_set, files, init_count); - - null_file = working_set_index(working_set, 0); - dll_remove(&null_file->node); - null_file->is_dummy = 1; - ++working_set->file_count; - - table_size = working_set->file_max; - mem_size = table_required_mem_size(table_size, item_size); - mem = general_memory_allocate(general, mem_size); - memset(mem, 0, mem_size); - table_init_memory(&working_set->table, mem, table_size, item_size); + + // NOTE(allen): init null file + { + Editing_File *null_file = working_set_index(working_set, 0); + dll_remove(&null_file->node); + null_file->is_dummy = 1; + ++working_set->file_count; + } + + // NOTE(allen): init uhash table + { + i32 item_size = sizeof(File_Uhash_Entry); + i32 table_size = working_set->file_max; + i32 mem_size = table_required_mem_size(table_size, item_size); + void *mem = general_memory_allocate(general, mem_size); + memset(mem, 0, mem_size); + table_init_memory(&working_set->uhash_table, mem, table_size, item_size); + } + + // NOTE(allen): init name table + { + i32 item_size = sizeof(File_Name_Entry); + i32 table_size = working_set->file_max; + i32 mem_size = table_required_mem_size(table_size, item_size); + void *mem = general_memory_allocate(general, mem_size); + memset(mem, 0, mem_size); + table_init_memory(&working_set->name_table, mem, table_size, item_size); + } } inline void working_set__grow_if_needed(Table *table, General_Memory *general, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){ - Table btable; - i32 new_max, mem_size; - void *mem; - if (table_at_capacity(table)){ - new_max = table->max * 2; - mem_size = table_required_mem_size(new_max, table->item_size); - mem = general_memory_allocate(general, mem_size); + Table btable = {0}; + i32 new_max = table->max * 2; + i32 mem_size = table_required_mem_size(new_max, table->item_size); + void *mem = general_memory_allocate(general, mem_size); table_init_memory(&btable, mem, new_max, table->item_size); table_clear(&btable); table_rehash(table, &btable, 0, hash_func, comp_func); @@ -557,6 +573,80 @@ working_set__grow_if_needed(Table *table, General_Memory *general, void *arg, Ha } } +internal Editing_File* +working_set_uhash_contains(Working_Set *working_set, Unique_Hash index){ + Editing_File *result = 0; + + File_Uhash_Entry *entry = (File_Uhash_Entry*) + table_find_item(&working_set->uhash_table, &index, 0, tbl_uhash_hash, tbl_uhash_compare); + if (entry){ + result = working_set_index(working_set, entry->id); + } + + return(result); +} + +internal Editing_File* +working_set_uhash_contains(System_Functions *system, Working_Set *working_set, String name){ + Editing_File *file = 0; + Unique_Hash index = {0}; + if (system->get_file_index(name.str, &index)){ + if (!uhash_equal(index, uhash_zero())){ + file = working_set_uhash_contains(working_set, index); + } + } + return(file); +} + +internal void +working_set_uhash_add(General_Memory *general, Working_Set *working_set, + Editing_File *file, Unique_Hash hash){ + working_set__grow_if_needed(&working_set->uhash_table, general, + 0, tbl_uhash_hash, tbl_uhash_compare); + + File_Uhash_Entry entry; + entry.hash = hash; + entry.id = file->id; + table_add(&working_set->uhash_table, &entry, 0, tbl_uhash_hash, tbl_uhash_compare); +} + +internal void +working_set_uhash_remove(Working_Set *working_set, Unique_Hash hash){ + table_remove_match(&working_set->uhash_table, &hash, 0, tbl_uhash_hash, tbl_uhash_compare); +} + +internal Editing_File* +working_set_name_contains(Working_Set *working_set, String name){ + Editing_File *result = 0; + + File_Name_Entry *entry = (File_Name_Entry*) + table_find_item(&working_set->name_table, &name, 0, tbl_string_hash, tbl_string_compare); + if (entry){ + result = working_set_index(working_set, entry->id); + } + + return(result); +} + +internal void +working_set_name_add(General_Memory *general, Working_Set *working_set, + Editing_File *file, String name){ + working_set__grow_if_needed(&working_set->name_table, general, + 0, tbl_string_hash, tbl_string_compare); + + File_Name_Entry entry; + entry.name = name; + entry.id = file->id; + table_add(&working_set->name_table, &entry, 0, tbl_string_hash, tbl_string_compare); +} + +internal void +working_set_name_remove(Working_Set *working_set, String name){ + table_remove_match(&working_set->name_table, &name, 0, tbl_string_hash, tbl_string_compare); +} + + +#if 0 inline void working_set__entry_comp(System_Functions *system, String filename, File_Entry_Comparison *out){ out->entry.long_name = filename; @@ -572,7 +662,6 @@ working_set_contains(System_Functions *system, Working_Set *working_set, String working_set__entry_comp(system, filename, &entry_comp); entry = (File_Entry*)table_find_item(&working_set->table, &entry_comp, system, tbl_string_hash, tbl_file_compare); - if (entry){ result = working_set_index(working_set, entry->id); } @@ -602,6 +691,7 @@ working_set_remove(System_Functions *system, Working_Set *working_set, String fi system->file_untrack(filename); } } +#endif // TODO(allen): Pick better first options. internal Editing_File* @@ -609,6 +699,7 @@ working_set_lookup_file(Working_Set *working_set, String string){ Editing_File *file = 0; { + // TODO(allen): use the name table for this File_Node *node, *used_nodes; used_nodes = &working_set->used_sentinel; for (dll_items(node, used_nodes)){ @@ -800,5 +891,130 @@ file_get_sync(Editing_File *file){ return (file->state.sync); } +internal void +editing_file_name_init(Editing_File_Name *name){ + name->live_name = make_fixed_width_string(name->live_name_); + name->source_path = make_fixed_width_string(name->source_path_); + name->extension = make_fixed_width_string(name->extension_); +} + +internal void +buffer_get_new_name(Working_Set *working_set, Editing_File_Name *name, String filename){ + Assert(name->live_name.str != 0); + + copy_checked(&name->source_path, filename); + copy(&name->live_name, front_of_directory(filename)); + + if (name->source_path.size == name->live_name.size){ + name->extension.size = 0; + } + else{ + String ext = file_extension(filename); + copy(&name->extension, ext); + } + + { + i32 original_len = name->live_name.size; + i32 file_x = 0; + b32 hit_conflict = 1; + while (hit_conflict){ + hit_conflict = 0; + + File_Node *used_nodes = &working_set->used_sentinel, *node; + for (dll_items(node, used_nodes)){ + Editing_File *file_ptr = (Editing_File*)node; + if (file_is_ready(file_ptr)){ + if (match(name->live_name, file_ptr->name.live_name)){ + ++file_x; + hit_conflict = 1; + break; + } + } + } + + if (hit_conflict){ + name->live_name.size = original_len; + append(&name->live_name, " <"); + append_int_to_str(&name->live_name, file_x); + append(&name->live_name, ">"); + } + } + } +} + +inline void +buffer_get_new_name(Working_Set *working_set, Editing_File_Name *name, char *filename){ + String f = make_string_slowly(filename); + buffer_get_new_name(working_set, name, f); +} + +internal void +buffer_bind_file(System_Functions *system, General_Memory *general, Working_Set *working_set, + Editing_File *file, Unique_Hash index){ + Assert(file->name.live_name.size == 0 && + file->name.source_path.size == 0 && + file->name.extension.size == 0); + Assert(uhash_equal(file->file_index, uhash_zero())); + Assert(!uhash_equal(index, uhash_zero())); + + working_set_uhash_add(general, working_set, file, index); + file->file_index = index; +} + +internal void +buffer_bind_file(System_Functions *system, General_Memory *general, Working_Set *working_set, + Editing_File *file, char *filename, u32 flags){ + Assert(file->name.live_name.size == 0 && + file->name.source_path.size == 0 && + file->name.extension.size == 0); + Assert(uhash_equal(file->file_index, uhash_zero())); + + Unique_Hash index = system->track_file(filename, flags); + if (!uhash_equal(index, uhash_zero())){ + working_set_uhash_add(general, working_set, file, index); + file->file_index = index; + } +} + +internal void +buffer_unbind_file(System_Functions *system, Working_Set *working_set, Editing_File *file){ + Assert(file->name.live_name.size == 0 && + file->name.source_path.size == 0 && + file->name.extension.size == 0); + Assert(!uhash_equal(file->file_index, uhash_zero())); + + system->untrack_file(file->file_index); + working_set_uhash_remove(working_set, file->file_index); + file->file_index = uhash_zero(); +} + +internal void +buffer_bind_name(General_Memory *general, Working_Set *working_set, + Editing_File *file, char *filename){ + Assert(file->name.live_name.size == 0 && + file->name.source_path.size == 0 && + file->name.extension.size == 0); + + Editing_File_Name new_name; + editing_file_name_init(&new_name); + buffer_get_new_name(working_set, &new_name, filename); + + editing_file_name_init(&file->name); + copy(&file->name.live_name, new_name.live_name); + copy(&file->name.source_path, new_name.source_path); + copy(&file->name.extension, new_name.extension); + + working_set_name_add(general, working_set, file, file->name.live_name); +} + +internal void +buffer_unbind_name(Working_Set *working_set, Editing_File *file){ + Assert(file->name.live_name.size != 0); + working_set_name_remove(working_set, file->name.live_name); + file->name.live_name.size = 0; + file->name.source_path.size = 0; + file->name.extension.size = 0; +} + // BOTTOM diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index ca2bd632..bc23b202 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -780,71 +780,6 @@ starts_new_line(u8 character){ return (character == '\n'); } -inline void -file_init_strings(Editing_File *file){ - file->name.source_path = make_fixed_width_string(file->name.source_path_); - file->name.live_name = make_fixed_width_string(file->name.live_name_); - file->name.extension = make_fixed_width_string(file->name.extension_); -} - -internal void -file_set_name(Working_Set *working_set, Editing_File *file, String filename){ - String ext; - - Assert(file->name.live_name.str != 0); - - copy_checked(&file->name.source_path, filename); - - copy(&file->name.live_name, front_of_directory(filename)); - - if (file->name.source_path.size == file->name.live_name.size){ - file->name.extension.size = 0; - } - else{ - ext = file_extension(filename); - copy(&file->name.extension, ext); - } - - { - File_Node *node, *used_nodes; - Editing_File *file_ptr; - i32 file_x, original_len; - b32 hit_conflict; - - used_nodes = &working_set->used_sentinel; - original_len = file->name.live_name.size; - hit_conflict = 1; - file_x = 0; - while (hit_conflict){ - hit_conflict = 0; - for (dll_items(node, used_nodes)){ - file_ptr = (Editing_File*)node; - if (file_ptr != file && file_is_ready(file_ptr)){ - if (match(file->name.live_name, file_ptr->name.live_name)){ - ++file_x; - hit_conflict = 1; - break; - } - } - } - - if (hit_conflict){ - file->name.live_name.size = original_len; - append(&file->name.live_name, " <"); - append_int_to_str(&file->name.live_name, file_x); - append(&file->name.live_name, ">"); - } - } - } -} - -inline void -file_set_name(Working_Set *working_set, Editing_File *file, char *filename){ - String f = make_string_slowly(filename); - file_set_name(working_set, file, f); -} - - #if 0 inline void file_synchronize_times(System_Functions *system, Editing_File *file, char *filename){ @@ -860,61 +795,80 @@ file_synchronize_times(System_Functions *system, Editing_File *file, char *filen inline void file_synchronize_times(System_Functions *system, Editing_File *file){ - file->state.last_sync = system->now_time_stamp(); + system->now_file_time(&file->state.last_sync); file->state.sync = SYNC_GOOD; } internal b32 -file_save(System_Functions *system, Mem_Options *mem, Editing_File *file, char *filename){ +file_save(System_Functions *system, Mem_Options *mem, Editing_File *file){ b32 result = 0; - i32 max = 0, size = 0; - b32 dos_write_mode = file->settings.dos_write_mode; - char *data = 0; - Buffer_Type *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 (!uhash_equal(file->file_index, uhash_zero())){ + i32 max = 0, size = 0; + b32 dos_write_mode = file->settings.dos_write_mode; + char *data = 0; + Buffer_Type *buffer = &file->state.buffer; - if (!data){ - used_general = 1; - data = (char*)general_memory_allocate(&mem->general, max); + if (dos_write_mode){ + max = buffer_size(buffer) + buffer->line_count + 1; } - } - Assert(data); - - if (dos_write_mode){ - size = buffer_convert_out(buffer, data, max); - } - else{ - size = max; - buffer_stringify(buffer, 0, size, data); + 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); + + if (dos_write_mode){ + size = buffer_convert_out(buffer, data, max); + } + else{ + size = max; + buffer_stringify(buffer, 0, size, data); + } + + result = system->save_file(file->file_index, data, size); + + file_mark_clean(file); + + if (used_general){ + general_memory_free(&mem->general, data); + } + end_temp_memory(temp); + + file_synchronize_times(system, file); } - result = system->file_save(filename, data, size); - - file_mark_clean(file); - - if (used_general){ - general_memory_free(&mem->general, data); + return(result); +} + +internal b32 +buffer_link_to_new_file(System_Functions *system, General_Memory *general, Working_Set *working_set, + Editing_File *file, char *filename){ + b32 result = 0; + Unique_Hash index = system->track_file(filename, TrackFileFlag_ExistingOrNew); + if (!uhash_equal(index, uhash_zero())){ + buffer_unbind_name(working_set, file); + if (!uhash_equal(file->file_index, uhash_zero())){ + buffer_unbind_file(system, working_set, file); + } + buffer_bind_file(system, general, working_set, file, filename, TrackFileFlag_ExistingOrNew); + buffer_bind_name(general, working_set, file, filename); + result = 1; } - end_temp_memory(temp); - - file_synchronize_times(system, file); - return(result); } @@ -922,12 +876,11 @@ inline b32 file_save_and_set_names(System_Functions *system, Mem_Options *mem, Working_Set *working_set, Editing_File *file, char *filename){ - b32 result = 0; - result = file_save(system, mem, file, filename); + b32 result = buffer_link_to_new_file(system, &mem->general, working_set, file, filename); if (result){ - file_set_name(working_set, file, filename); + result = file_save(system, mem, file); } - return result; + return(result); } enum{ @@ -1054,7 +1007,6 @@ file_create_from_string(System_Functions *system, Models *models, String val, b8 read_only = 0){ Font_Set *font_set = models->font_set; - Working_Set *working_set = &models->working_set; General_Memory *general = &models->mem.general; Partition *part = &models->mem.part; Buffer_Init_Type init; @@ -1074,16 +1026,12 @@ file_create_from_string(System_Functions *system, Models *models, Assert(scratch_size > 0); b32 init_success = buffer_end_init(&init, part->base + part->pos, scratch_size); - AllowLocal(init_success); - Assert(init_success); + AllowLocal(init_success); Assert(init_success); if (buffer_size(&file->state.buffer) < val.size){ file->settings.dos_write_mode = 1; } - file_init_strings(file); - file_set_name(working_set, file, (char*)name); - file_synchronize_times(system, file); i16 font_id = models->global_font.font_id; @@ -1129,15 +1077,6 @@ file_create_from_string(System_Functions *system, Models *models, file->settings.is_initialized = 1; } -#undef TEST_TIME_MAX - -internal b32 -file_create_empty(System_Functions *system, - Models *models, Editing_File *file, char *filename){ - file_create_from_string(system, models, file, filename, string_zero()); - return (1); -} - internal b32 file_create_read_only(System_Functions *system, Models *models, Editing_File *file, char *filename){ @@ -3232,7 +3171,6 @@ view_show_file(View *view){ } } - internal String make_string_terminated(Partition *part, char *str, i32 len){ char *space = (char*)push_array(part, char, len + 1); @@ -3243,68 +3181,9 @@ make_string_terminated(Partition *part, char *str, i32 len){ return(string); } -internal void -view_save_file(System_Functions *system, Models *models, - Editing_File *file, View *view, String filename, b32 save_as){ - Mem_Options *mem = &models->mem; - Working_Set *working_set = &models->working_set; - - Temp_Memory temp = begin_temp_memory(&mem->part); - - String filename_string = - make_string_terminated(&mem->part, filename.str, filename.size); - - if (!file){ - if (view){ - file = view->file_data.file; - } - else{ - file = working_set_lookup_file(working_set, filename_string); - } - } - - if (file && (file_get_sync(file) != SYNC_GOOD || save_as)){ - if (file_save(system, mem, file, filename_string.str)){ - if (save_as){ - file_set_name(working_set, file, filename_string.str); - } - } - } - - end_temp_memory(temp); -} - -internal void -view_new_file(System_Functions *system, Models *models, - View *view, String string){ - Working_Set *working_set = &models->working_set; - General_Memory *general = &models->mem.general; - - Editing_File *file = working_set_alloc_always(working_set, general); - file_create_empty(system, models, file, string.str); - working_set_add(system, working_set, file, general); - - view_set_file(view, file, models); - view_show_file(view); - view->map = get_map(models, file->settings.base_map_id); - - Open_File_Hook_Function *new_file_fnc = models->hook_new_file; - if (new_file_fnc){ - new_file_fnc(&models->app_links, file->id.id); - } - file->settings.is_initialized = 1; - -#if BUFFER_EXPERIMENT_SCALPEL <= 0 - if (file->settings.tokens_exist && file->state.token_stack.tokens == 0){ - file_first_lex_parallel(system, general, file); - } -#endif -} - internal void init_normal_file(System_Functions *system, Models *models, Editing_File *file, char *buffer, i32 size){ - General_Memory *general = &models->mem.general; String val = make_string(buffer, size); @@ -3322,77 +3201,106 @@ init_normal_file(System_Functions *system, Models *models, Editing_File *file, } internal void -view_open_file(System_Functions *system, Models *models, - View *view, String filename){ +view_interactive_open_file(System_Functions *system, Models *models, View *view, String filename){ Working_Set *working_set = &models->working_set; - General_Memory *general = &models->mem.general; - Partition *part = &models->mem.part; + Editing_File *file = 0; + Unique_Hash index = {0}; - Editing_File *file = working_set_contains(system, working_set, filename); - - if (file == 0){ - File_Loading loading = system->file_load_begin(filename.str); - - if (loading.exists){ - b32 in_general_mem = 0; - Temp_Memory temp = begin_temp_memory(part); - char *buffer = push_array(part, char, loading.size); - - // TODO(allen): How will we get temporary space for large - // buffers? The main partition isn't always big enough - // but getting a general block this large and copying it - // then freeing it is *super* dumb! - if (buffer == 0){ - buffer = (char*)general_memory_allocate(general, loading.size); - if (buffer != 0){ - in_general_mem = 1; - } - } - - if (system->file_load_end(loading, buffer)){ + if (terminate_with_null(&filename)){ + if (system->get_file_index(filename.str, &index)){ + file = working_set_uhash_contains(working_set, index); + } + else{ + index = system->track_file(filename.str, TrackFileFlag_ExistingOrFail); + if (!uhash_equal(index, uhash_zero())){ + Mem_Options *mem = &models->mem; + General_Memory *general = &mem->general; + file = working_set_alloc_always(working_set, general); - if (file){ - file_init_strings(file); - file_set_name(working_set, file, filename.str); - working_set_add(system, working_set, file, general); - - init_normal_file(system, models, file, - buffer, loading.size); + + buffer_bind_file(system, general, working_set, file, index); + buffer_bind_name(general, working_set, file, filename.str); + + i32 size = system->file_size(index); + Partition *part = &mem->part; + char *buffer = 0; + b32 gen_buffer = 0; + Temp_Memory temp = begin_temp_memory(part); + + buffer = push_array(part, char, size); + + if (buffer == 0){ + buffer = (char*)general_memory_allocate(general, size); + Assert(buffer); + gen_buffer = 1; } + + system->load_file(index, buffer, size); + + init_normal_file(system, models, file, buffer, size); + + if (gen_buffer){ + general_memory_free(general, buffer); + } + + end_temp_memory(temp); } - - if (in_general_mem){ - general_memory_free(general, buffer); - } - - end_temp_memory(temp); } } if (file){ - if (view){ - view_set_file(view, file, models); - view_show_file(view); - } + view_set_file(view, file, models); } } internal void -kill_file(System_Functions *system, Models *models, - Editing_File *file, String string){ +view_interactive_save_as(System_Functions *system, Models *models, Editing_File *file, String filename){ + if (terminate_with_null(&filename)){ + file_save_and_set_names(system, &models->mem, &models->working_set, file, filename.str); + } +} + +internal void +view_interactive_new_file(System_Functions *system, Models *models, View *view, String filename){ Working_Set *working_set = &models->working_set; + Editing_File *file = 0; + Unique_Hash index = {0}; - if (!file && string.str){ - file = working_set_lookup_file(working_set, string); - if (!file){ - file = working_set_contains(system, working_set, string); + if (terminate_with_null(&filename)){ + if (system->get_file_index(filename.str, &index)){ + file = working_set_uhash_contains(working_set, index); + file_clear(system, models, file); + } + else{ + index = system->track_file(filename.str, TrackFileFlag_NewAlways); + if (!uhash_equal(index, uhash_zero())){ + Mem_Options *mem = &models->mem; + General_Memory *general = &mem->general; + + file = working_set_alloc_always(working_set, general); + + buffer_bind_file(system, general, working_set, file, index); + buffer_bind_name(general, working_set, file, filename.str); + + init_normal_file(system, models, file, 0, 0); + } } } + if (file){ + view_set_file(view, file, models); + } +} + +internal void +kill_file(System_Functions *system, Models *models, Editing_File *file){ + Working_Set *working_set = &models->working_set; + if (file && !file->settings.never_kill){ - working_set_remove(system, working_set, file->name.source_path); + buffer_unbind_name(working_set, file); + buffer_unbind_file(system, working_set, file); file_close(system, &models->mem.general, file); - working_set_free_file(&models->working_set, file); + working_set_free_file(working_set, file); File_Node *used = &models->working_set.used_sentinel; File_Node *node = used->next; @@ -3412,25 +3320,29 @@ kill_file(System_Functions *system, Models *models, } } -internal b32 -try_kill_file(System_Functions *system, Models *models, - Editing_File *file, View *view, String string){ - - b32 kill_dialogue = false; - Working_Set *working_set = &models->working_set; - - if (!file && string.str){ - file = working_set_lookup_file(working_set, string); - if (!file){ - file = working_set_contains(system, working_set, string); - } +internal void +kill_file_by_name(System_Functions *system, Models *models, String name){ + Editing_File *file = working_set_name_contains(&models->working_set, name); + if (file){ + kill_file(system, models, file); } +} + +internal void +save_file_by_name(System_Functions *system, Models *models, String name){ + Editing_File *file = working_set_name_contains(&models->working_set, name); + if (file){ + file_save(system, &models->mem, file); + } +} + +internal b32 +interactive_try_kill_file(System_Functions *system, Models *models, View *view, String name){ + b32 kill_dialogue = false; + Editing_File *file = working_set_name_contains(&models->working_set, name); if (file && !file->settings.never_kill){ if (buffer_needs_save(file)){ - if (view == 0){ - view = models->layout.panels[models->layout.active_panel].view; - } view_show_interactive(system, view, IAct_Sure_To_Kill, IInt_Sure_To_Kill, make_lit_string("Are you sure?")); @@ -3438,7 +3350,7 @@ try_kill_file(System_Functions *system, Models *models, kill_dialogue = true; } else{ - kill_file(system, models, file, string_zero()); + kill_file(system, models, file); } } @@ -3448,37 +3360,28 @@ try_kill_file(System_Functions *system, Models *models, internal void interactive_view_complete(System_Functions *system, View *view, String dest, i32 user_action){ Models *models = view->persistent.models; - //Editing_File *old_file = view->file_data.file; switch (view->action){ case IAct_Open: - view_open_file(system, models, view, dest); - //touch_file(&models->working_set, old_file); + view_interactive_open_file(system, models, view, dest); view_show_file(view); break; case IAct_Save_As: - view_save_file(system, models, 0, view, dest, 1); + view_interactive_save_as(system, models, view->file_data.file, dest); view_show_file(view); break; case IAct_New: if (dest.size > 0 && !char_is_slash(dest.str[dest.size-1])){ - view_new_file(system, models, view, dest); + view_interactive_new_file(system, models, view, dest); view_show_file(view); - }break; + } + break; case IAct_Switch: { - //touch_file(&models->working_set, old_file); - - Editing_File *file = 0; - String string = dest; - - file = working_set_lookup_file(&models->working_set, string); - if (!file){ - file = working_set_contains(system, &models->working_set, string); - } + Editing_File *file = working_set_name_contains(&models->working_set, dest); if (file){ view_set_file(view, file, models); } @@ -3487,7 +3390,7 @@ interactive_view_complete(System_Functions *system, View *view, String dest, i32 break; case IAct_Kill: - if (!try_kill_file(system, models, 0, 0, dest)){ + if (!interactive_try_kill_file(system, models, view, dest)){ view_show_file(view); } break; @@ -3511,7 +3414,7 @@ interactive_view_complete(System_Functions *system, View *view, String dest, i32 case IAct_Sure_To_Kill: switch (user_action){ case 0: - kill_file(system, models, 0, dest); + kill_file_by_name(system, models, dest); view_show_file(view); break; @@ -3520,8 +3423,8 @@ interactive_view_complete(System_Functions *system, View *view, String dest, i32 break; case 2: - view_save_file(system, models, 0, 0, dest, 0); - kill_file(system, models, 0, dest); + save_file_by_name(system, models, dest); + kill_file_by_name(system, models, dest); view_show_file(view); break; } @@ -3746,7 +3649,7 @@ get_exhaustive_info(System_Functions *system, Working_Set *working_set, Exhausti loop->full_path.size = loop->r; append(&loop->full_path, result.info->filename); terminate_with_null(&loop->full_path); - file = working_set_contains(system, working_set, loop->full_path); + file = working_set_uhash_contains(system, working_set, loop->full_path); String filename = make_string(result.info->filename, result.info->filename_len, result.info->filename_len+1); @@ -4715,7 +4618,8 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su // Time Watcher { string.size = 0; - u64 time = system->now_time_stamp(); + u64 time = 0; + system->now_file_time(&time); append(&string, "last redraw: "); append_u64_to_str(&string, time);