From 6e9bcb4e369ded7b884db770f3e63e838cffb671 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Wed, 24 Aug 2016 19:01:33 -0400 Subject: [PATCH] file tracking appears to be integrated fully --- 4ed.cpp | 85 ++++++------- 4ed_api_implementation.cpp | 67 ++++++----- 4ed_file.cpp | 4 +- 4ed_file_view.cpp | 75 ++++++++---- 4ed_system.h | 6 +- build_all.bat | 2 +- filetrack/4tech_file_track.h | 20 +++ filetrack/4tech_file_track_win32.c | 187 ++++++++++++++++++++++++----- win32_4ed.cpp | 98 +++++++++++---- 9 files changed, 394 insertions(+), 150 deletions(-) diff --git a/4ed.cpp b/4ed.cpp index 16dd347a..0f72ea73 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -338,38 +338,42 @@ COMMAND_DECL(reopen){ if (match(file->name.source_path, file->name.live_name)) return; - File_Loading loading = system->file_load_begin(file->name.source_path.str); + Unique_Hash index = file->file_index; - if (loading.exists){ + if (!uhash_equal(index, uhash_zero())){ + i32 size = system->file_size(index); + Partition *part = &models->mem.part; Temp_Memory temp = begin_temp_memory(part); - char *buffer = push_array(part, char, loading.size); + char *buffer = push_array(part, char, size); - if (system->file_load_end(loading, buffer)){ - General_Memory *general = &models->mem.general; - - File_Edit_Positions edit_poss[16]; - View *vptrs[16]; - i32 vptr_count = 0; - for (View_Iter iter = file_view_iter_init(&models->layout, file, 0); - file_view_iter_good(iter); - iter = file_view_iter_next(iter)){ - vptrs[vptr_count] = iter.view; - edit_poss[vptr_count] = *iter.view->edit_pos; - iter.view->edit_pos = 0; - ++vptr_count; - } - - file_close(system, general, file); - init_normal_file(system, models, file, buffer, loading.size); - - for (i32 i = 0; - i < vptr_count; - ++i){ - view_set_file(vptrs[i], file, models); - *vptrs[i]->edit_pos = edit_poss[i]; - view_set_cursor(vptrs[i], edit_poss[i].cursor, - true, view->file_data.unwrapped_lines); + if (buffer){ + if (system->load_file(index, buffer, size)){ + General_Memory *general = &models->mem.general; + + File_Edit_Positions edit_poss[16]; + View *vptrs[16]; + i32 vptr_count = 0; + for (View_Iter iter = file_view_iter_init(&models->layout, file, 0); + file_view_iter_good(iter); + iter = file_view_iter_next(iter)){ + vptrs[vptr_count] = iter.view; + edit_poss[vptr_count] = *iter.view->edit_pos; + iter.view->edit_pos = 0; + ++vptr_count; + } + + file_close(system, general, file); + init_normal_file(system, models, file, buffer, size); + + for (i32 i = 0; + i < vptr_count; + ++i){ + view_set_file(vptrs[i], file, models); + *vptrs[i]->edit_pos = edit_poss[i]; + view_set_cursor(vptrs[i], edit_poss[i].cursor, + true, view->file_data.unwrapped_lines); + } } } @@ -382,9 +386,8 @@ COMMAND_DECL(save){ USE_VIEW(view); REQ_FILE(file, view); - if (!file->is_dummy && file_is_ready(file)){ - String name = file->name.source_path; - view_save_file(system, models, file, 0, name, 0); + if (!file->is_dummy && file_is_ready(file) && buffer_needs_save(file)){ + save_file(system, &models->mem, file); } } @@ -429,7 +432,7 @@ COMMAND_DECL(kill_buffer){ USE_VIEW(view); REQ_FILE(file, view); - try_kill_file(system, models, file, view, string_zero()); + interactive_try_kill_file(system, models, view, file); } COMMAND_DECL(toggle_line_wrap){ @@ -1673,6 +1676,7 @@ App_Step_Sig(app_step){ dest->size = eol_convert_in(dest->str, clipboard.str, clipboard.size); } +#if 0 // NOTE(allen): check files are up to date if (!input->first_step){ Panel *panel = 0, *used_panels = &models->layout.used_sentinel; @@ -1720,6 +1724,7 @@ App_Step_Sig(app_step){ else{ models->working_set.sync_check_iter = &models->working_set.used_sentinel; } +#endif // NOTE(allen): reorganizing panels on screen { @@ -1934,8 +1939,8 @@ App_Step_Sig(app_step){ { Editing_File *file = working_set_alloc_always(&models->working_set, general); - file_create_read_only(system, models, file, "*messages*"); - working_set_add(system, &models->working_set, file, general); + buffer_bind_name(general, &models->working_set, file, "*messages*"); + init_read_only_file(system, models, file); file->settings.never_kill = 1; file->settings.unimportant = 1; file->settings.unwrapped_lines = 1; @@ -1945,8 +1950,8 @@ App_Step_Sig(app_step){ { Editing_File *file = working_set_alloc_always(&models->working_set, general); - file_create_empty(system, models, file, "*scratch*"); - working_set_add(system, &models->working_set, file, general); + buffer_bind_name(general, &models->working_set, file, "*scratch*"); + init_normal_file(system, models, file, 0, 0); file->settings.never_kill = 1; file->settings.unimportant = 1; file->settings.unwrapped_lines = 1; @@ -1958,13 +1963,11 @@ App_Step_Sig(app_step){ models->hooks[hook_start](&models->app_links); } - i32 i; - String filename; + i32 i = 0; Panel *panel = models->layout.used_sentinel.next; - for (i = 0; - i < models->settings.init_files_count; + for (; i < models->settings.init_files_count; ++i, panel = panel->next){ - filename = make_string_slowly(models->settings.init_files[i]); + String filename = make_string_slowly(models->settings.init_files[i]); if (i < models->layout.panel_count){ view_open_file(system, models, panel->view, filename); diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index d9e958a7..599e83f5 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -85,17 +85,14 @@ fill_view_summary(View_Summary *view, View *vptr, Command_Data *cmd){ internal Editing_File* get_file_from_identifier(System_Functions *system, Working_Set *working_set, Buffer_Identifier buffer){ - i32 buffer_id = buffer.id; - i32 buffer_name_len = buffer.name_len; - char *buffer_name = buffer.name; - Editing_File *file = 0; - if (buffer_id){ - file = working_set_get_active_file(working_set, buffer_id); + if (buffer.id){ + file = working_set_get_active_file(working_set, buffer.id); } - else if (buffer_name){ - file = working_set_contains(system, working_set, make_string(buffer_name, buffer_name_len)); + else if (buffer.name){ + String name = make_string(buffer.name, buffer.name_len); + file = working_set_name_contains(working_set, name); } return(file); @@ -248,8 +245,10 @@ DOC_SEE(Command_Line_Input_Flag) result = false; goto done; } - file_create_read_only(system, models, file, buffer.name); - working_set_add(system, working_set, file, general); + + String name = make_string_terminated(part, buffer.name, buffer.name_len); + buffer_bind_name(general, working_set, file, name.str); + init_read_only_file(system, models, file); } if (file){ @@ -527,7 +526,8 @@ DOC_SEE(Access_Flag) Editing_File *file; Working_Set *working_set = &cmd->models->working_set; - file = working_set_contains(cmd->system, working_set, make_string(name, len)); + String str = make_string(name, len); + file = working_set_name_contains(working_set, str); if (file && !file->is_dummy){ fill_buffer_summary(&buffer, file, working_set); if (!access_test(buffer.lock_flags, access)){ @@ -985,42 +985,43 @@ DOC_SEE(Buffer_Create_Flag) Temp_Memory temp = begin_temp_memory(part); if (filename != 0){ String filename_string = make_string_terminated(part, filename, filename_len); - Editing_File *file = working_set_contains(system, working_set, filename_string); + Editing_File *file = working_set_uhash_contains(system, working_set, filename_string.str); if (file == 0){ - File_Loading loading = {0}; - b32 do_new_file = false; + Unique_Hash index = {0}; + if (flags & BufferCreate_AlwaysNew){ do_new_file = true; } else{ - loading = system->file_load_begin(filename_string.str); - if (!loading.exists){ + index = system->track_file(filename_string.str, TrackFileFlag_ExistingOrFail); + if (uhash_equal(index, uhash_zero())){ do_new_file = true; } } if (!do_new_file){ + Assert(!uhash_equal(index, uhash_zero())); + + i32 size = system->file_size(index); b32 in_general_mem = false; - char *buffer = push_array(part, char, loading.size); + char *buffer = push_array(part, char, size); if (buffer == 0){ - buffer = (char*)general_memory_allocate(general, loading.size); + buffer = (char*)general_memory_allocate(general, size); if (buffer != 0){ in_general_mem = true; } } - if (system->file_load_end(loading, buffer)){ + if (system->load_file(index, buffer, size)){ file = working_set_alloc_always(working_set, general); if (file){ - file_init_strings(file); - file_set_name(working_set, file, filename_string); - 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_string.str); + init_normal_file(system, models, file, buffer, size); fill_buffer_summary(&result, file, cmd); } } @@ -1033,9 +1034,7 @@ DOC_SEE(Buffer_Create_Flag) else{ file = working_set_alloc_always(working_set, general); if (file){ - file_init_strings(file); - file_set_name(working_set, file, filename_string); - working_set_add(system, working_set, file, general); + buffer_bind_name(general, working_set, file, filename_string.str); init_normal_file(system, models, file, 0, 0); fill_buffer_summary(&result, file, cmd); } @@ -1066,8 +1065,12 @@ DOC_RETURN(This call returns non-zero on success.) Editing_File *file = imp_get_file(cmd, buffer); if (file){ result = true; - String name = make_string(filename, filename_len); - view_save_file(system, models, file, 0, name, false); + + Partition *part = &models->mem.part; + Temp_Memory temp = begin_temp_memory(part); + String name = make_string_terminated(part, filename, filename_len); + save_file_to_name(system, &models->mem, file, name.str); + end_temp_memory(temp); } return(result); @@ -1099,12 +1102,12 @@ DOC_SEE(Buffer_Identifier) if (file){ if (flags & BufferKill_AlwaysKill){ result = true; - kill_file(system, models, file, string_zero()); + kill_file(system, models, file); } else{ - if (vptr == 0){ + if (vptr){ result = true; - try_kill_file(system, models, file, vptr, string_zero()); + interactive_try_kill_file(system, models, vptr, file); } else{ app->print_message(app, literal("CUSTOM WARNING: the buffer is dirty and no view was specified for a dialogue.")); diff --git a/4ed_file.cpp b/4ed_file.cpp index 462faa18..b18db0f3 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -587,10 +587,10 @@ working_set_uhash_contains(Working_Set *working_set, Unique_Hash index){ } internal Editing_File* -working_set_uhash_contains(System_Functions *system, Working_Set *working_set, String name){ +working_set_uhash_contains(System_Functions *system, Working_Set *working_set, char *name){ Editing_File *file = 0; Unique_Hash index = {0}; - if (system->get_file_index(name.str, &index)){ + if (system->get_file_index(name, &index)){ if (!uhash_equal(index, uhash_zero())){ file = working_set_uhash_contains(working_set, index); } diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index bc23b202..4a5acfc1 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -800,7 +800,7 @@ file_synchronize_times(System_Functions *system, Editing_File *file){ } internal b32 -file_save(System_Functions *system, Mem_Options *mem, Editing_File *file){ +save_file_to_name(System_Functions *system, Mem_Options *mem, Editing_File *file, char *filename){ b32 result = 0; if (!uhash_equal(file->file_index, uhash_zero())){ @@ -840,7 +840,12 @@ file_save(System_Functions *system, Mem_Options *mem, Editing_File *file){ buffer_stringify(buffer, 0, size, data); } - result = system->save_file(file->file_index, data, size); + if (filename){ + result = system->save_file_by_name(filename, data, size); + } + else{ + result = system->save_file(file->file_index, data, size); + } file_mark_clean(file); @@ -855,6 +860,12 @@ file_save(System_Functions *system, Mem_Options *mem, Editing_File *file){ return(result); } +inline b32 +save_file(System_Functions *system, Mem_Options *mem, Editing_File *file){ + b32 result = save_file_to_name(system, mem, file, 0); + return(result); +} + internal b32 buffer_link_to_new_file(System_Functions *system, General_Memory *general, Working_Set *working_set, Editing_File *file, char *filename){ @@ -878,7 +889,7 @@ file_save_and_set_names(System_Functions *system, Mem_Options *mem, char *filename){ b32 result = buffer_link_to_new_file(system, &mem->general, working_set, file, filename); if (result){ - result = file_save(system, mem, file); + result = save_file(system, mem, file); } return(result); } @@ -1003,8 +1014,7 @@ view_measure_wraps(General_Memory *general, View *view){ internal void file_create_from_string(System_Functions *system, Models *models, - Editing_File *file, char *name, - String val, b8 read_only = 0){ + Editing_File *file, String val, b8 read_only = 0){ Font_Set *font_set = models->font_set; General_Memory *general = &models->mem.general; @@ -1077,13 +1087,6 @@ file_create_from_string(System_Functions *system, Models *models, file->settings.is_initialized = 1; } -internal b32 -file_create_read_only(System_Functions *system, - Models *models, Editing_File *file, char *filename){ - file_create_from_string(system, models, file, filename, string_zero(), 1); - return (1); -} - internal void file_close(System_Functions *system, General_Memory *general, Editing_File *file){ if (file->state.still_lexing){ @@ -3187,7 +3190,7 @@ init_normal_file(System_Functions *system, Models *models, Editing_File *file, General_Memory *general = &models->mem.general; String val = make_string(buffer, size); - file_create_from_string(system, models, file, file->name.source_path.str, val); + file_create_from_string(system, models, file, val); if (file->settings.tokens_exist && file->state.token_stack.tokens == 0){ file_first_lex_parallel(system, general, file); @@ -3201,7 +3204,26 @@ init_normal_file(System_Functions *system, Models *models, Editing_File *file, } internal void -view_interactive_open_file(System_Functions *system, Models *models, View *view, String filename){ +init_read_only_file(System_Functions *system, Models *models, Editing_File *file){ + General_Memory *general = &models->mem.general; + + String val = string_zero(); + file_create_from_string(system, models, file, val, 1); + + if (file->settings.tokens_exist && file->state.token_stack.tokens == 0){ + file_first_lex_parallel(system, general, file); + } + + for (View_Iter iter = file_view_iter_init(&models->layout, file, 0); + file_view_iter_good(iter); + iter = file_view_iter_next(iter)){ + view_measure_wraps(general, iter.view); + } +} + + +internal void +view_open_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}; @@ -3332,16 +3354,15 @@ 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); + save_file(system, &models->mem, file); } } internal b32 -interactive_try_kill_file(System_Functions *system, Models *models, View *view, String name){ +interactive_try_kill_file(System_Functions *system, Models *models, View *view, Editing_File *file){ b32 kill_dialogue = false; - Editing_File *file = working_set_name_contains(&models->working_set, name); - if (file && !file->settings.never_kill){ + if (!file->settings.never_kill){ if (buffer_needs_save(file)){ view_show_interactive(system, view, IAct_Sure_To_Kill, IInt_Sure_To_Kill, @@ -3357,13 +3378,25 @@ interactive_try_kill_file(System_Functions *system, Models *models, View *view, return(kill_dialogue); } +internal b32 +interactive_try_kill_file_by_name(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){ + kill_dialogue = interactive_try_kill_file(system, models, view, file); + } + + return(kill_dialogue); +} + internal void interactive_view_complete(System_Functions *system, View *view, String dest, i32 user_action){ Models *models = view->persistent.models; switch (view->action){ case IAct_Open: - view_interactive_open_file(system, models, view, dest); + view_open_file(system, models, view, dest); view_show_file(view); break; @@ -3390,7 +3423,7 @@ interactive_view_complete(System_Functions *system, View *view, String dest, i32 break; case IAct_Kill: - if (!interactive_try_kill_file(system, models, view, dest)){ + if (!interactive_try_kill_file_by_name(system, models, view, dest)){ view_show_file(view); } break; @@ -3649,7 +3682,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_uhash_contains(system, working_set, loop->full_path); + file = working_set_uhash_contains(system, working_set, loop->full_path.str); String filename = make_string(result.info->filename, result.info->filename_len, result.info->filename_len+1); diff --git a/4ed_system.h b/4ed_system.h index 022300cd..606338b6 100644 --- a/4ed_system.h +++ b/4ed_system.h @@ -73,6 +73,9 @@ typedef Sys_Load_File_Sig(System_Load_File); #define Sys_Save_File_Sig(name) i32 name(Unique_Hash index, char *buffer, i32 size) typedef Sys_Save_File_Sig(System_Save_File); +#define Sys_Save_File_By_Name_Sig(name) i32 name(char *filename, char *buffer, i32 size) +typedef Sys_Save_File_By_Name_Sig(System_Save_File_By_Name); + #define Sys_Post_Clipboard_Sig(name) void name(String str) typedef Sys_Post_Clipboard_Sig(System_Post_Clipboard); @@ -225,7 +228,7 @@ typedef INTERNAL_Sys_Debug_Message_Sig(INTERNAL_System_Debug_Message); struct System_Functions{ - // files (tracked api): 10 + // files (tracked api): 11 System_Set_File_List *set_file_list; System_Track_File *track_file; System_Untrack_File *untrack_file; @@ -236,6 +239,7 @@ struct System_Functions{ System_File_Size *file_size; System_Load_File *load_file; System_Save_File *save_file; + System_Save_File_By_Name *save_file_by_name; // 4coder_custom.h: 7 Memory_Allocate_Function *memory_allocate; diff --git a/build_all.bat b/build_all.bat index 6b7c1cf4..cb12e157 100644 --- a/build_all.bat +++ b/build_all.bat @@ -32,7 +32,7 @@ REM call "%CODE_DIR%\buildsuper.bat" ..\4vim\4coder_chronal.cpp if %ERRORLEVEL% neq 0 (set FirstError=1) set EXPORTS=/EXPORT:app_get_functions -cl %OPTS% %INCLUDES% %DEFINES% %CODE_DIR%\4ed_app_target.cpp %* /Fe4ed_app /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS% +REM cl %OPTS% %INCLUDES% %DEFINES% %CODE_DIR%\4ed_app_target.cpp %* /Fe4ed_app /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS% if %ERRORLEVEL% neq 0 (set FirstError=1) cl %OPTS% %INCLUDES% %DEFINES% %CODE_DIR%\win32_4ed.cpp %LIBS% %ICON% %* /Fe4ed /link /NODEFAULTLIB:library diff --git a/filetrack/4tech_file_track.h b/filetrack/4tech_file_track.h index 38427aee..37d2bc30 100644 --- a/filetrack/4tech_file_track.h +++ b/filetrack/4tech_file_track.h @@ -34,6 +34,10 @@ typedef struct{ uint8_t opaque[128]; } File_Track_System; +typedef struct{ + uint8_t opaque[16]; +} File_Temp_Handle; + typedef struct{ uint32_t id[4]; } File_Index; @@ -63,6 +67,18 @@ init_track_system(File_Track_System *system, File_Track_Result begin_tracking_file(File_Track_System *system, char *name, File_Index *index, File_Time *time); +File_Track_Result +begin_tracking_new_file(File_Track_System *system, char *name, File_Index *index, File_Time *time); + +File_Track_Result +get_file_temp_handle(char *name, File_Temp_Handle *handle); + +File_Track_Result +begin_tracking_from_handle(File_Track_System *system, char *name, File_Temp_Handle handle, File_Index *index, File_Time *time); + +File_Track_Result +finish_with_temp_handle(File_Temp_Handle handle); + File_Track_Result get_tracked_file_index(File_Track_System *system, char *name, File_Index *index); @@ -97,6 +113,10 @@ File_Track_Result rewrite_tracked_file(File_Track_System *system, File_Index index, void *data, int32_t size, File_Time *time); +File_Track_Result +rewrite_arbitrary_file(File_Track_System *system, char *filename, + void *data, int32_t size, File_Time *time); + File_Track_Result shut_down_track_system(File_Track_System *system); diff --git a/filetrack/4tech_file_track_win32.c b/filetrack/4tech_file_track_win32.c index c86c3762..f6f57ea0 100644 --- a/filetrack/4tech_file_track_win32.c +++ b/filetrack/4tech_file_track_win32.c @@ -452,29 +452,10 @@ internal_free_slot(File_Track_Tables *tables, File_Track_Entry *entry){ } File_Track_Result -begin_tracking_file(File_Track_System *system, - char *name, - File_Index *index, - File_Time *time){ +internal_track_file(File_Track_Vars *vars, File_Track_Tables *tables, + char *name, HANDLE file, File_Index *index, File_Time *time){ + File_Track_Result result = FileTrack_Good; - File_Track_Vars *vars = to_vars_(system); - - EnterCriticalSection(&vars->table_lock); - - File_Track_Tables *tables = to_tables(vars); - - // TODO(allen): Try multiple ways to open the - // file and get as many privledges as possible. - // Expand the API to be capable of reporting - // what privledges are available on a file. - HANDLE file = CreateFile( - name, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - 0); if (file != INVALID_HANDLE_VALUE){ char dir_name[1024]; @@ -607,20 +588,114 @@ begin_tracking_file(File_Track_System *system, else{ result = FileTrack_FileSystemError; } - - if (result != FileTrack_Good){ - CloseHandle(file); - } } else{ result = FileTrack_FileNotFound; } + return(result); +} + +HANDLE +open_file_best_privledges(char *name, DWORD open_disposition){ + + // TODO(allen): Try multiple ways to open the + // file and get as many privledges as possible. + // Expand the API to be capable of reporting + // what privledges are available on a file. + HANDLE file = CreateFile( + name, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + open_disposition, + FILE_ATTRIBUTE_NORMAL, + 0); + + return(file); +} + +File_Track_Result +begin_tracking_file(File_Track_System *system, + char *name, + File_Index *index, + File_Time *time){ + File_Track_Result result = FileTrack_Good; + File_Track_Vars *vars = to_vars_(system); + + EnterCriticalSection(&vars->table_lock); + { + File_Track_Tables *tables = to_tables(vars); + HANDLE file = open_file_best_privledges(name, OPEN_EXISTING); + result = internal_track_file(vars, tables, name, file, index, time); + if (file != INVALID_HANDLE_VALUE && result != FileTrack_Good){ + CloseHandle(file); + } + } LeaveCriticalSection(&vars->table_lock); return(result); } +File_Track_Result +begin_tracking_new_file(File_Track_System *system, char *name, File_Index *index, File_Time *time){ + File_Track_Result result = FileTrack_Good; + File_Track_Vars *vars = to_vars_(system); + + EnterCriticalSection(&vars->table_lock); + { + File_Track_Tables *tables = to_tables(vars); + HANDLE file = open_file_best_privledges(name, CREATE_ALWAYS); + result = internal_track_file(vars, tables, name, file, index, time); + if (file != INVALID_HANDLE_VALUE && result != FileTrack_Good){ + CloseHandle(file); + } + } + LeaveCriticalSection(&vars->table_lock); + + return(result); +} + +File_Track_Result +get_file_temp_handle(char *name, File_Temp_Handle *handle){ + File_Track_Result result = FileTrack_FileNotFound; + + HANDLE h = open_file_best_privledges(name, OPEN_EXISTING); + if (h != INVALID_HANDLE_VALUE){ + *(HANDLE*)handle = h; + result = FileTrack_Good; + } + + return(result); +} + +File_Track_Result +begin_tracking_from_handle(File_Track_System *system, char *name, File_Temp_Handle handle, + File_Index *index, File_Time *time){ + File_Track_Result result = FileTrack_Good; + File_Track_Vars *vars = to_vars_(system); + + EnterCriticalSection(&vars->table_lock); + { + File_Track_Tables *tables = to_tables(vars); + HANDLE file = *(HANDLE*)(&handle); + result = internal_track_file(vars, tables, name, file, index, time); + } + LeaveCriticalSection(&vars->table_lock); + + return(result); +} + +File_Track_Result +finish_with_temp_handle(File_Temp_Handle handle){ + File_Track_Result result = FileTrack_Good; + + HANDLE file = *(HANDLE*)(&handle); + CloseHandle(file); + + return(result); +} + File_Track_Result internal_get_tracked_file_index(File_Track_Tables *tables, char *name, @@ -628,6 +703,7 @@ internal_get_tracked_file_index(File_Track_Tables *tables, File_Track_Entry **entry){ File_Track_Result result = FileTrack_Good; + // TODO(allen): Can I open this file with no permissions? HANDLE file = CreateFile( name, GENERIC_READ | GENERIC_WRITE, @@ -640,11 +716,7 @@ internal_get_tracked_file_index(File_Track_Tables *tables, if (file != INVALID_HANDLE_VALUE){ BY_HANDLE_FILE_INFORMATION info = {0}; if (GetFileInformationByHandle(file, &info)){ - File_Index hash; - hash.id[0] = info.nFileIndexLow; - hash.id[1] = info.nFileIndexHigh; - hash.id[2] = info.dwVolumeSerialNumber; - hash.id[3] = 0; + File_Index hash = internal_get_file_index(info); File_Lookup_Result lookup = tracking_system_lookup_entry(tables, hash); if (!entry_is_available(lookup.entry)){ @@ -1051,6 +1123,59 @@ rewrite_tracked_file(File_Track_System *system, File_Index index, return(result); } +File_Track_Result +rewrite_arbitrary_file(File_Track_System *system, char *filename, + void *data, int32_t size, File_Time *time){ + File_Track_Result result = FileTrack_Good; + + HANDLE file = CreateFile( + filename, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0); + + if (file != INVALID_HANDLE_VALUE){ + File_Track_Vars *vars = to_vars_(system); + EnterCriticalSection(&vars->table_lock); + { + File_Track_Tables *tables = to_tables(vars); + BY_HANDLE_FILE_INFORMATION info = {0}; + if (GetFileInformationByHandle(file, &info)){ + DWORD written = 0; + + File_Index index = internal_get_file_index(info); + File_Lookup_Result lookup = tracking_system_lookup_entry(tables, index); + if (!entry_is_available(lookup.entry)){ + lookup.entry->skip_change = 1; + } + + WriteFile(file, data, size, &written, 0); + + FILETIME file_time; + SYSTEMTIME system_time; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + SetFileTime(lookup.entry->file, 0, 0, &file_time); + } + else{ + result = FileTrack_FileSystemError; + } + } + LeaveCriticalSection(&vars->table_lock); + + CloseHandle(file); + } + else{ + result = FileTrack_FileNotFound; + } + + return(result); +} + File_Track_Result shut_down_track_system(File_Track_System *system){ File_Track_Result result = FileTrack_Good; diff --git a/win32_4ed.cpp b/win32_4ed.cpp index a50b05af..1cccf6c0 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -192,11 +192,13 @@ struct Win32_Vars{ b32 first; i32 running_cli; + File_Track_System track; void *track_table; u32 track_table_size; u32 track_node_size; + #if FRED_INTERNAL CRITICAL_SECTION DEBUG_sysmem_lock; Sys_Bubble internal_bubble; @@ -1035,6 +1037,40 @@ to_findex(Unique_Hash index){ return(r); } +internal b32 +handle_track_out_of_memory(i32 val, Unique_Hash *index, File_Index get_index){ + b32 result = 0; + + switch (val){ + case FileTrack_OutOfTableMemory: + { + u32 new_table_size = win32vars.track_table_size*2; + void *new_table = system_get_memory(new_table_size); + move_track_system(&win32vars.track, new_table, new_table_size); + system_free_memory(win32vars.track_table); + win32vars.track_table_size = new_table_size; + win32vars.track_table = new_table; + }break; + + case FileTrack_OutOfListenerMemory: + { + win32vars.track_node_size *= 2; + void *node_expansion = system_get_memory(win32vars.track_node_size); + expand_track_system_listeners(&win32vars.track, node_expansion, win32vars.track_node_size); + }break; + + case FileTrack_Good: + { + *index = to_uhash(get_index); + result = 1; + }break; + + default: result = 1; break; + } + + return(result); +} + internal Sys_Track_File_Sig(system_track_file){ Unique_Hash index = {0}; @@ -1044,64 +1080,72 @@ Sys_Track_File_Sig(system_track_file){ { File_Index get_index = {0}; File_Time time = 0; - i32 result = begin_tracking_file(&win32vars.track, filename, &get_index, &time); - if (result == FileTrack_Good){ - index = to_uhash(get_index); + for (;;){ + i32 result = begin_tracking_file(&win32vars.track, filename, &get_index, &time); + if (handle_track_out_of_memory(result, &index, get_index)){ + goto track_end; + } } }break; - // TODO(allen): provide the functions used here in the file track system case TrackFileFlag_NewOrFail: { -#if 0 File_Index get_index = {0}; File_Time time = 0; File_Temp_Handle handle = {0}; i32 result = get_file_temp_handle(filename, &handle); if (result == FileTrack_FileNotFound){ - result = begin_tracking_new_file(&win32vars.track, filename, &get_index, &time); - if (result == FileTrack_Good){ - index = to_uhash(get_index); + for (;;){ + result = begin_tracking_new_file(&win32vars.track, filename, &get_index, &time); + if (handle_track_out_of_memory(result, &index, get_index)){ + goto track_end; + } } } else{ finish_with_temp_handle(handle); } -#endif }break; case TrackFileFlag_NewAlways: { -#if 0 File_Index get_index = {0}; File_Time time = 0; - result = begin_tracking_new_file(&win32vars.track, filename, &get_index, &time); - if (result == FileTrack_Good){ - index = to_uhash(get_index); + for (;;){ + i32 result = begin_tracking_new_file(&win32vars.track, filename, &get_index, &time); + if (handle_track_out_of_memory(result, &index, get_index)){ + goto track_end; + } } -#endif }break; case TrackFileFlag_ExistingOrNew: { -#if 0 File_Index get_index = {0}; File_Time time = 0; File_Temp_Handle handle = {0}; i32 result = get_file_temp_handle(filename, &handle); if (result == FileTrack_FileNotFound){ - result = begin_tracking_new_file(&win32vars.track, filename, &get_index, &time); + for (;;){ + result = begin_tracking_new_file(&win32vars.track, filename, &get_index, &time); + if (handle_track_out_of_memory(result, &index, get_index)){ + goto track_end; + } + } } else{ - result = begin_tracking_from_handle(&win32vars.track, filename, handle, , &get_index, &time); + for (;;){ + result = begin_tracking_from_handle(&win32vars.track, filename, handle, &get_index, &time); + if (handle_track_out_of_memory(result, &index, get_index)){ + goto track_end; + } + } } - if (result == FileTrack_Good){ - index = to_uhash(get_index); - } -#endif }break; } + track_end:; + return(index); } @@ -1191,6 +1235,17 @@ Sys_Save_File_Sig(system_save_file){ return(result); } +internal +Sys_Save_File_By_Name_Sig(system_save_file_by_name){ + i32 result = 0; + File_Time time = 0; + i32 track_result = rewrite_arbitrary_file(&win32vars.track, filename, buffer, size, &time); + if (track_result == FileTrack_Good){ + result = 1; + } + return(result); +} + b32 Win32DirectoryExists(char *path){ DWORD attrib = GetFileAttributesA(path); return (attrib != INVALID_FILE_ATTRIBUTES && @@ -1550,6 +1605,7 @@ Win32LoadSystemCode(){ win32vars.system.file_size = system_file_size; win32vars.system.load_file = system_load_file; win32vars.system.save_file = system_save_file; + win32vars.system.save_file_by_name = system_save_file_by_name; win32vars.system.memory_allocate = Memory_Allocate; win32vars.system.file_exists = File_Exists;