file tracker version 2 fully integrated
							parent
							
								
									426b8d5576
								
							
						
					
					
						commit
						fc76531ca1
					
				
							
								
								
									
										82
									
								
								4ed.cpp
								
								
								
								
							
							
						
						
									
										82
									
								
								4ed.cpp
								
								
								
								
							|  | @ -338,46 +338,50 @@ COMMAND_DECL(reopen){ | |||
|      | ||||
|     if (match(file->name.source_path, file->name.live_name)) return; | ||||
|      | ||||
|     Unique_Hash index = file->file_index; | ||||
|      | ||||
|     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, size); | ||||
|          | ||||
|         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); | ||||
|     if (file->canon.name.size != 0){ | ||||
|         Plat_Handle handle; | ||||
|         if (system->load_handle(file->canon.name.str, &handle)){ | ||||
|              | ||||
|             i32 size = system->load_size(handle); | ||||
|              | ||||
|             Partition *part = &models->mem.part; | ||||
|             Temp_Memory temp = begin_temp_memory(part); | ||||
|             char *buffer = push_array(part, char, size); | ||||
|              | ||||
|             if (buffer){ | ||||
|                 if (system->load_file(handle, 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); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             end_temp_memory(temp); | ||||
|              | ||||
|             system->load_close(handle); | ||||
|         } | ||||
|          | ||||
|         end_temp_memory(temp); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -1939,7 +1943,7 @@ App_Step_Sig(app_step){ | |||
|          | ||||
|         { | ||||
|             Editing_File *file = working_set_alloc_always(&models->working_set, general); | ||||
|             buffer_bind_name(general, &models->working_set, file, "*messages*"); | ||||
|             buffer_bind_name(general, &models->working_set, file, make_lit_string("*messages*")); | ||||
|             init_read_only_file(system, models, file); | ||||
|             file->settings.never_kill = 1; | ||||
|             file->settings.unimportant = 1; | ||||
|  | @ -1950,7 +1954,7 @@ App_Step_Sig(app_step){ | |||
|          | ||||
|         { | ||||
|             Editing_File *file = working_set_alloc_always(&models->working_set, general); | ||||
|             buffer_bind_name(general, &models->working_set, file, "*scratch*"); | ||||
|             buffer_bind_name(general, &models->working_set, file, make_lit_string("*scratch*")); | ||||
|             init_normal_file(system, models, file, 0, 0); | ||||
|             file->settings.never_kill = 1; | ||||
|             file->settings.unimportant = 1; | ||||
|  |  | |||
|  | @ -247,7 +247,7 @@ DOC_SEE(Command_Line_Input_Flag) | |||
|             } | ||||
|              | ||||
|             String name = make_string_terminated(part, buffer.name, buffer.name_len); | ||||
|             buffer_bind_name(general, working_set, file, name.str); | ||||
|             buffer_bind_name(general, working_set, file, name); | ||||
|             init_read_only_file(system, models, file); | ||||
|         } | ||||
|          | ||||
|  | @ -982,67 +982,71 @@ DOC_SEE(Buffer_Create_Flag) | |||
|      | ||||
|     Buffer_Summary result = {0}; | ||||
|      | ||||
|     String fname = make_string(filename, filename_len); | ||||
|      | ||||
|     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_uhash_contains(system, working_set, filename_string.str); | ||||
|         Editing_File_Canon_Name canon; | ||||
|          | ||||
|         if (file == 0){ | ||||
|             b32 do_new_file = false; | ||||
|         if (get_canon_name(system, &canon, fname)){ | ||||
|             Editing_File *file = working_set_canon_contains(working_set, canon.name); | ||||
|              | ||||
|             Unique_Hash index = {0}; | ||||
|              | ||||
|             if (flags & BufferCreate_AlwaysNew){ | ||||
|                 do_new_file = true; | ||||
|             } | ||||
|             else{ | ||||
|                 index = system->track_file(filename_string.str, TrackFileFlag_ExistingOrFail); | ||||
|                 if (uhash_equal(index, uhash_zero())){ | ||||
|             if (file == 0){ | ||||
|                 b32 do_new_file = false; | ||||
|                  | ||||
|                 Plat_Handle handle = {0}; | ||||
|                  | ||||
|                 if (flags & BufferCreate_AlwaysNew){ | ||||
|                     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, size); | ||||
|                  | ||||
|                 if (buffer == 0){ | ||||
|                     buffer = (char*)general_memory_allocate(general, size); | ||||
|                     if (buffer != 0){ | ||||
|                         in_general_mem = true; | ||||
|                 else{ | ||||
|                     if (!system->load_handle(canon.name.str, &handle)){ | ||||
|                         do_new_file = true; | ||||
|                     } | ||||
|                 } | ||||
|                  | ||||
|                 if (system->load_file(index, buffer, size)){ | ||||
|                 if (!do_new_file){ | ||||
|                     Assert(!handle_equal(handle, handle_zero())); | ||||
|                      | ||||
|                     i32 size = system->load_size(handle); | ||||
|                     b32 in_general_mem = false; | ||||
|                     char *buffer = push_array(part, char, size); | ||||
|                      | ||||
|                     if (buffer == 0){ | ||||
|                         buffer = (char*)general_memory_allocate(general, size); | ||||
|                         Assert(buffer != 0); | ||||
|                         in_general_mem = true; | ||||
|                     } | ||||
|                      | ||||
|                     if (system->load_file(handle, buffer, size)){ | ||||
|                         file = working_set_alloc_always(working_set, general); | ||||
|                         if (file){ | ||||
|                             buffer_bind_file(general, working_set, file, canon.name); | ||||
|                             buffer_bind_name(general, working_set, file, fname); | ||||
|                             init_normal_file(system, models, file, buffer, size); | ||||
|                             fill_buffer_summary(&result, file, cmd); | ||||
|                         } | ||||
|                     } | ||||
|                      | ||||
|                     if (in_general_mem){ | ||||
|                         general_memory_free(general, buffer); | ||||
|                     } | ||||
|                      | ||||
|                     system->load_close(handle); | ||||
|                 } | ||||
|                 else{ | ||||
|                     file = working_set_alloc_always(working_set, general); | ||||
|                     if (file){ | ||||
|                         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); | ||||
|                         buffer_bind_name(general, working_set, file, fname); | ||||
|                         init_normal_file(system, models, file, 0, 0); | ||||
|                         fill_buffer_summary(&result, file, cmd); | ||||
|                     } | ||||
|                 } | ||||
|                  | ||||
|                 if (in_general_mem){ | ||||
|                     general_memory_free(general, buffer); | ||||
|                 } | ||||
|                  | ||||
|             } | ||||
|             else{ | ||||
|                 file = working_set_alloc_always(working_set, general); | ||||
|                 if (file){ | ||||
|                     buffer_bind_name(general, working_set, file, filename_string.str); | ||||
|                     init_normal_file(system, models, file, 0, 0); | ||||
|                     fill_buffer_summary(&result, file, cmd); | ||||
|                 } | ||||
|                 fill_buffer_summary(&result, file, cmd); | ||||
|             } | ||||
|         } | ||||
|         else{ | ||||
|             fill_buffer_summary(&result, file, cmd); | ||||
|         } | ||||
|     } | ||||
|     end_temp_memory(temp); | ||||
|      | ||||
|  |  | |||
							
								
								
									
										239
									
								
								4ed_file.cpp
								
								
								
								
							
							
						
						
									
										239
									
								
								4ed_file.cpp
								
								
								
								
							|  | @ -144,7 +144,6 @@ struct Editing_File_State{ | |||
|     Text_Effect paste_effect; | ||||
|      | ||||
|     File_Sync_State sync; | ||||
|     u64 last_sync; | ||||
|      | ||||
|     File_Edit_Positions edit_pos_space[16]; | ||||
|     File_Edit_Positions *edit_poss[16]; | ||||
|  | @ -160,6 +159,11 @@ struct Editing_File_Name{ | |||
|     String extension; | ||||
| }; | ||||
| 
 | ||||
| struct Editing_File_Canon_Name{ | ||||
|     char name_[256]; | ||||
|     String name; | ||||
| }; | ||||
| 
 | ||||
| struct File_Node{ | ||||
|     File_Node *next, *prev; | ||||
| }; | ||||
|  | @ -186,9 +190,9 @@ struct Editing_File{ | |||
|         Editing_File_State state; | ||||
|     }; | ||||
|     Editing_File_Name name; | ||||
|     Editing_File_Canon_Name canon; | ||||
|     Buffer_Slot_ID id; | ||||
|     u64 unique_buffer_id; | ||||
|     Unique_Hash file_index; | ||||
| }; | ||||
| 
 | ||||
| struct Non_File_Table_Entry{ | ||||
|  | @ -209,7 +213,7 @@ struct Working_Set{ | |||
| 	File_Node free_sentinel; | ||||
|     File_Node used_sentinel; | ||||
|      | ||||
|     Table uhash_table; | ||||
|     Table canon_table; | ||||
|     Table name_table; | ||||
|      | ||||
| 	String clipboards[64]; | ||||
|  | @ -348,35 +352,11 @@ 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; | ||||
|  | @ -537,14 +517,14 @@ working_set_init(Working_Set *working_set, Partition *partition, General_Memory | |||
|         ++working_set->file_count; | ||||
|     } | ||||
|      | ||||
|     // NOTE(allen): init uhash table
 | ||||
|     // NOTE(allen): init canon table
 | ||||
|     { | ||||
|         i32 item_size = sizeof(File_Uhash_Entry); | ||||
|         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->uhash_table, mem, table_size, item_size); | ||||
|         table_init_memory(&working_set->canon_table, mem, table_size, item_size); | ||||
|     } | ||||
|      | ||||
|     // NOTE(allen): init name table
 | ||||
|  | @ -574,53 +554,11 @@ 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, char *name){ | ||||
|     Editing_File *file = 0; | ||||
|     Unique_Hash index = {0}; | ||||
|     if (system->get_file_index(name, &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){ | ||||
| working_set_contains_basic(Working_Set *working_set, Table *table, 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); | ||||
|         table_find_item(table, &name, 0, tbl_string_hash, tbl_string_compare); | ||||
|     if (entry){ | ||||
|         result = working_set_index(working_set, entry->id); | ||||
|     } | ||||
|  | @ -628,71 +566,63 @@ working_set_name_contains(Working_Set *working_set, String name){ | |||
|     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, | ||||
| internal b32 | ||||
| working_set_add_basic(General_Memory *general, Working_Set *working_set, Table *table, | ||||
|                       Editing_File *file, String name){ | ||||
|     working_set__grow_if_needed(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); | ||||
|     b32 result = (table_add(table, &entry, 0, tbl_string_hash, tbl_string_compare) == 0); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| working_set_remove_basic(Working_Set *working_set, Table *table, String name){ | ||||
|     table_remove_match(table, &name, 0, tbl_string_hash, tbl_string_compare); | ||||
| } | ||||
| 
 | ||||
| internal Editing_File* | ||||
| working_set_canon_contains(Working_Set *working_set, String name){ | ||||
|     Editing_File *result = | ||||
|         working_set_contains_basic(working_set, &working_set->canon_table, name); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal b32 | ||||
| working_set_canon_add(General_Memory *general, Working_Set *working_set, | ||||
|                      Editing_File *file, String name){ | ||||
|     b32 result = working_set_add_basic(general, working_set, &working_set->canon_table, file, name); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| working_set_canon_remove(Working_Set *working_set, String name){ | ||||
|     working_set_remove_basic(working_set, &working_set->canon_table, name); | ||||
| } | ||||
| 
 | ||||
| internal Editing_File* | ||||
| working_set_name_contains(Working_Set *working_set, String name){ | ||||
|     Editing_File *result = | ||||
|         working_set_contains_basic(working_set, &working_set->name_table, name); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal b32 | ||||
| working_set_name_add(General_Memory *general, Working_Set *working_set, | ||||
|                      Editing_File *file, String name){ | ||||
|     b32 result = working_set_add_basic(general, working_set, &working_set->name_table, file, name); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|     working_set_remove_basic(working_set, &working_set->name_table, name); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| inline void | ||||
| working_set__entry_comp(System_Functions *system, String filename, File_Entry_Comparison *out){ | ||||
|     out->entry.long_name = filename; | ||||
|     out->entry.short_name = front_of_directory(filename); | ||||
|     out->hash = system->file_unique_hash(filename, &out->use_hash); | ||||
| } | ||||
| 
 | ||||
| inline Editing_File* | ||||
| working_set_contains(System_Functions *system, Working_Set *working_set, String filename){ | ||||
|     File_Entry_Comparison entry_comp = {0}; | ||||
|     File_Entry *entry = 0; | ||||
|     Editing_File *result = 0; | ||||
|     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); | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| working_set_add(System_Functions *system, Working_Set *working_set, Editing_File *file, General_Memory *general){ | ||||
|     File_Entry_Comparison entry_comp; | ||||
|     working_set__grow_if_needed(&working_set->table, general, system, tbl_string_hash, tbl_file_compare); | ||||
|     working_set__entry_comp(system, file->name.source_path, &entry_comp); | ||||
|     entry_comp.entry.id = file->id; | ||||
|     if (table_add(&working_set->table, &entry_comp, system, tbl_string_hash, tbl_file_compare)){ | ||||
|         if (!uhash_equal(entry_comp.hash, uhash_zero())){ | ||||
|             system->file_track(file->name.source_path); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| inline void | ||||
| working_set_remove(System_Functions *system, Working_Set *working_set, String filename){ | ||||
|     File_Entry_Comparison entry_comp; | ||||
|     working_set__entry_comp(system, filename, &entry_comp); | ||||
|     table_remove_match(&working_set->table, &entry_comp, system, tbl_string_hash, tbl_file_compare); | ||||
|     if (!uhash_equal(entry_comp.hash, uhash_zero())){ | ||||
|         system->file_untrack(filename); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| // TODO(allen): Pick better first options.
 | ||||
| internal Editing_File* | ||||
| working_set_lookup_file(Working_Set *working_set, String string){ | ||||
|  | @ -898,6 +828,19 @@ editing_file_name_init(Editing_File_Name *name){ | |||
|     name->extension = make_fixed_width_string(name->extension_); | ||||
| } | ||||
| 
 | ||||
| internal b32 | ||||
| get_canon_name(System_Functions *system, Editing_File_Canon_Name *canon_name, String filename){ | ||||
|     canon_name->name = make_fixed_width_string(canon_name->name_); | ||||
|      | ||||
|     canon_name->name.size = | ||||
|         system->get_canonical(filename.str, filename.size, | ||||
|                               canon_name->name.str, canon_name->name.memory_size); | ||||
|     terminate_with_null(&canon_name->name); | ||||
|      | ||||
|     b32 result = (canon_name->name.size != 0); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| buffer_get_new_name(Working_Set *working_set, Editing_File_Name *name, String filename){ | ||||
|     Assert(name->live_name.str != 0); | ||||
|  | @ -949,48 +892,33 @@ buffer_get_new_name(Working_Set *working_set, Editing_File_Name *name, char *fil | |||
| } | ||||
| 
 | ||||
| internal void | ||||
| buffer_bind_file(System_Functions *system, General_Memory *general, Working_Set *working_set, | ||||
|                  Editing_File *file, Unique_Hash index){ | ||||
| buffer_bind_file(General_Memory *general, Working_Set *working_set, | ||||
|                  Editing_File *file, String canon_filename){ | ||||
|     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())); | ||||
|     Assert(file->canon.name.size == 0); | ||||
|      | ||||
|     working_set_uhash_add(general, working_set, file, index); | ||||
|     file->file_index = index; | ||||
|     file->canon.name = make_fixed_width_string(file->canon.name_); | ||||
|     copy(&file->canon.name, canon_filename); | ||||
|     b32 result = working_set_canon_add(general, working_set, file, file->canon.name); | ||||
|     Assert(result); AllowLocal(result); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| buffer_bind_file(System_Functions *system, General_Memory *general, Working_Set *working_set, | ||||
|                  Editing_File *file, char *filename, u32 flags){ | ||||
| buffer_unbind_file(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())); | ||||
|     Assert(file->canon.name.size != 0); | ||||
|      | ||||
|     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(); | ||||
|     working_set_canon_remove(working_set, file->canon.name); | ||||
|     file->canon.name.size = 0; | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| buffer_bind_name(General_Memory *general, Working_Set *working_set, | ||||
|                  Editing_File *file, char *filename){ | ||||
|                  Editing_File *file, String filename){ | ||||
|     Assert(file->name.live_name.size == 0 && | ||||
|            file->name.source_path.size == 0 && | ||||
|            file->name.extension.size == 0); | ||||
|  | @ -1004,7 +932,8 @@ buffer_bind_name(General_Memory *general, Working_Set *working_set, | |||
|     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); | ||||
|     b32 result = working_set_name_add(general, working_set, file, file->name.live_name); | ||||
|     Assert(result); AllowLocal(result); | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
|  |  | |||
|  | @ -780,22 +780,8 @@ starts_new_line(u8 character){ | |||
|     return (character == '\n'); | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| inline void | ||||
| file_synchronize_times(System_Functions *system, Editing_File *file, char *filename){ | ||||
|     u64 stamp = system->file_time_stamp(filename); | ||||
|     if (stamp > 0){ | ||||
|         file->state.last_4ed_write_time = stamp; | ||||
|         file->state.last_4ed_edit_time = stamp; | ||||
|         file->state.last_sys_write_time = stamp; | ||||
|     } | ||||
|     file->state.sync = buffer_get_sync(file); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| inline void | ||||
| file_synchronize_times(System_Functions *system, Editing_File *file){ | ||||
|     system->now_file_time(&file->state.last_sync); | ||||
|     file->state.sync = SYNC_GOOD; | ||||
| } | ||||
| 
 | ||||
|  | @ -803,7 +789,12 @@ internal b32 | |||
| 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())){ | ||||
|     if (!filename){ | ||||
|         terminate_with_null(&file->canon.name); | ||||
|         filename = file->canon.name.str; | ||||
|     } | ||||
|      | ||||
|     if (filename){ | ||||
|         i32 max = 0, size = 0; | ||||
|         b32 dos_write_mode = file->settings.dos_write_mode; | ||||
|         char *data = 0; | ||||
|  | @ -840,12 +831,7 @@ save_file_to_name(System_Functions *system, Mem_Options *mem, Editing_File *file | |||
|             buffer_stringify(buffer, 0, size, data); | ||||
|         } | ||||
|          | ||||
|         if (filename){ | ||||
|             result = system->save_file_by_name(filename, data, size); | ||||
|         } | ||||
|         else{ | ||||
|             result = system->save_file(file->file_index, data, size); | ||||
|         } | ||||
|         result = system->save_file(filename, data, size); | ||||
|          | ||||
|         file_mark_clean(file); | ||||
|          | ||||
|  | @ -856,7 +842,7 @@ save_file_to_name(System_Functions *system, Mem_Options *mem, Editing_File *file | |||
|          | ||||
|         file_synchronize_times(system, file); | ||||
|     } | ||||
|      | ||||
|          | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
|  | @ -868,25 +854,27 @@ save_file(System_Functions *system, Mem_Options *mem, Editing_File *file){ | |||
| 
 | ||||
| internal b32 | ||||
| buffer_link_to_new_file(System_Functions *system, General_Memory *general, Working_Set *working_set, | ||||
|                         Editing_File *file, char *filename){ | ||||
|                         Editing_File *file, String filename){ | ||||
|     b32 result = 0; | ||||
|     Unique_Hash index = system->track_file(filename, TrackFileFlag_ExistingOrNew); | ||||
|     if (!uhash_equal(index, uhash_zero())){ | ||||
|      | ||||
|     Editing_File_Canon_Name canon_name; | ||||
|     if (get_canon_name(system, &canon_name, filename)){ | ||||
|         buffer_unbind_name(working_set, file); | ||||
|         if (!uhash_equal(file->file_index, uhash_zero())){ | ||||
|             buffer_unbind_file(system, working_set, file); | ||||
|         if (file->canon.name.size != 0){ | ||||
|             buffer_unbind_file(working_set, file); | ||||
|         } | ||||
|         buffer_bind_file(system, general, working_set, file, filename, TrackFileFlag_ExistingOrNew); | ||||
|         buffer_bind_file(general, working_set, file, canon_name.name); | ||||
|         buffer_bind_name(general, working_set, file, filename); | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| inline b32 | ||||
| file_save_and_set_names(System_Functions *system, Mem_Options *mem, | ||||
|                         Working_Set *working_set, Editing_File *file, | ||||
|                         char *filename){ | ||||
|                         String filename){ | ||||
|     b32 result = buffer_link_to_new_file(system, &mem->general, working_set, file, filename); | ||||
|     if (result){ | ||||
|         result = save_file(system, mem, file); | ||||
|  | @ -3226,46 +3214,50 @@ 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}; | ||||
|      | ||||
|     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; | ||||
|         Editing_File_Canon_Name canon_name; | ||||
|         if (get_canon_name(system, &canon_name, filename)){ | ||||
|             file = working_set_canon_contains(working_set, canon_name.name); | ||||
|              | ||||
|             if (!file){ | ||||
|                  | ||||
|                 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); | ||||
|                  | ||||
|                 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; | ||||
|                 Plat_Handle handle; | ||||
|                 if (system->load_handle(canon_name.name.str, &handle)){ | ||||
|                     Mem_Options *mem = &models->mem; | ||||
|                     General_Memory *general = &mem->general; | ||||
|                      | ||||
|                     file = working_set_alloc_always(working_set, general); | ||||
|                      | ||||
|                     buffer_bind_file(general, working_set, file, canon_name.name); | ||||
|                     buffer_bind_name(general, working_set, file, filename); | ||||
|                      | ||||
|                     i32 size = system->load_size(handle); | ||||
|                     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; | ||||
|                     } | ||||
|                      | ||||
|                     if (system->load_file(handle, buffer, size)){ | ||||
|                         init_normal_file(system, models, file, buffer, size); | ||||
|                     } | ||||
|                      | ||||
|                     system->load_close(handle); | ||||
|                      | ||||
|                     if (gen_buffer){ | ||||
|                         general_memory_free(general, buffer); | ||||
|                     } | ||||
|                      | ||||
|                     end_temp_memory(temp); | ||||
|                 } | ||||
|                  | ||||
|                 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); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -3278,7 +3270,7 @@ view_open_file(System_Functions *system, Models *models, View *view, String file | |||
| internal void | ||||
| 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); | ||||
|         file_save_and_set_names(system, &models->mem, &models->working_set, file, filename); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -3286,23 +3278,25 @@ 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 (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())){ | ||||
|         Editing_File_Canon_Name canon_name; | ||||
|          | ||||
|         if (get_canon_name(system, &canon_name, filename)){ | ||||
|              | ||||
|             file = working_set_canon_contains(working_set, canon_name.name); | ||||
|             if (file){ | ||||
|                 file_clear(system, models, file); | ||||
|             } | ||||
|             else{ | ||||
|                  | ||||
|                 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); | ||||
|                 buffer_bind_file(general, working_set, file, canon_name.name); | ||||
|                 buffer_bind_name(general, working_set, file, filename); | ||||
|                  | ||||
|                 init_normal_file(system, models, file, 0, 0); | ||||
|             } | ||||
|  | @ -3320,7 +3314,7 @@ kill_file(System_Functions *system, Models *models, Editing_File *file){ | |||
|      | ||||
|     if (file && !file->settings.never_kill){ | ||||
|         buffer_unbind_name(working_set, file); | ||||
|         buffer_unbind_file(system, working_set, file); | ||||
|         buffer_unbind_file(working_set, file); | ||||
|         file_close(system, &models->mem.general, file); | ||||
|         working_set_free_file(working_set, file); | ||||
|          | ||||
|  | @ -3682,7 +3676,12 @@ 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.str); | ||||
|      | ||||
|     Editing_File_Canon_Name canon_name; | ||||
|      | ||||
|     if (get_canon_name(system, &canon_name, loop->full_path)){ | ||||
|         file = working_set_canon_contains(working_set, canon_name.name); | ||||
|     } | ||||
|      | ||||
|     String filename = make_string(result.info->filename, | ||||
|                                   result.info->filename_len, result.info->filename_len+1); | ||||
|  | @ -4651,8 +4650,7 @@ step_file_view(System_Functions *system, View *view, View *active_view, Input_Su | |||
|                     // Time Watcher
 | ||||
|                     { | ||||
|                         string.size = 0; | ||||
|                         u64 time = 0; | ||||
|                         system->now_file_time(&time); | ||||
|                         u64 time = system->now_time(); | ||||
|                          | ||||
|                         append(&string, "last redraw: "); | ||||
|                         append_u64_to_str(&string, time); | ||||
|  |  | |||
							
								
								
									
										75
									
								
								4ed_system.h
								
								
								
								
							
							
						
						
									
										75
									
								
								4ed_system.h
								
								
								
								
							|  | @ -13,24 +13,14 @@ struct Plat_Handle{ | |||
|     u32 d[4]; | ||||
| }; | ||||
| 
 | ||||
| inline int | ||||
| handle_equal(Plat_Handle a, Plat_Handle b){ | ||||
|     int result = (memcmp(&a, &b, sizeof(a)) == 0); | ||||
| inline Plat_Handle | ||||
| handle_zero(void){ | ||||
|     Plat_Handle result = {0}; | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| struct Unique_Hash{ | ||||
|     u32 d[4]; | ||||
| }; | ||||
| 
 | ||||
| inline Unique_Hash | ||||
| uhash_zero(){ | ||||
|     Unique_Hash r = {0}; | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| inline int | ||||
| uhash_equal(Unique_Hash a, Unique_Hash b){ | ||||
| handle_equal(Plat_Handle a, Plat_Handle b){ | ||||
|     int result = (memcmp(&a, &b, sizeof(a)) == 0); | ||||
|     return(result); | ||||
| } | ||||
|  | @ -39,35 +29,33 @@ uhash_equal(Unique_Hash a, Unique_Hash b){ | |||
| #define Sys_Set_File_List_Sig(name) void name(File_List *file_list, String directory) | ||||
| typedef Sys_Set_File_List_Sig(System_Set_File_List); | ||||
| 
 | ||||
| #define Sys_Add_Listener_Sig(name) Unique_Hash name(char *filename) | ||||
| typedef Sys_Add_Listener_Sig(System_Track_File); | ||||
| #define Sys_Get_Canonical_Sig(name) i32 name(char *filename, i32 len, char *buffer, i32 max) | ||||
| typedef Sys_Get_Canonical_Sig(System_Get_Canonical); | ||||
| 
 | ||||
| #define Sys_Remove_Listener_Sig(name) i32 name(char *filename) | ||||
| typedef Sys_Remove_Listener_Sig(System_Untrack_File); | ||||
| #define Sys_Add_Listener_Sig(name) b32 name(char *filename) | ||||
| typedef Sys_Add_Listener_Sig(System_Add_Listener); | ||||
| 
 | ||||
| #define Sys_Get_File_Index_Sig(name) i32 name(char *filename, Unique_Hash *index) | ||||
| typedef Sys_Get_File_Index_Sig(System_Get_File_Index); | ||||
| #define Sys_Remove_Listener_Sig(name) b32 name(char *filename) | ||||
| typedef Sys_Remove_Listener_Sig(System_Remove_Listener); | ||||
| 
 | ||||
| #define Sys_Get_File_Time_Sig(name) i32 name(Unique_Hash index, u64 *time) | ||||
| typedef Sys_Get_File_Time_Sig(System_Get_File_Time); | ||||
| #define Sys_Load_Handle_Sig(name) b32 name(char *filename, Plat_Handle *handle_out) | ||||
| typedef Sys_Load_Handle_Sig(System_Load_Handle); | ||||
| 
 | ||||
| #define Sys_Now_File_Time_Sig(name) void name(u64 *time) | ||||
| typedef Sys_Now_File_Time_Sig(System_Now_File_Time); | ||||
| #define Sys_Load_Size_Sig(name) u32 name(Plat_Handle handle) | ||||
| typedef Sys_Load_Size_Sig(System_Load_Size); | ||||
| 
 | ||||
| #define Sys_Get_Changed_File_Sig(name) i32 name(Unique_Hash *index) | ||||
| typedef Sys_Get_Changed_File_Sig(System_Get_Changed_File); | ||||
| 
 | ||||
| #define Sys_File_Size_Sig(name) u32 name(Unique_Hash index) | ||||
| typedef Sys_File_Size_Sig(System_File_Size); | ||||
| 
 | ||||
| #define Sys_Load_File_Sig(name) i32 name(Unique_Hash index, char *buffer, i32 size) | ||||
| #define Sys_Load_File_Sig(name) b32 name(Plat_Handle handle, char *buffer, u32 size) | ||||
| typedef Sys_Load_File_Sig(System_Load_File); | ||||
| 
 | ||||
| #define Sys_Save_File_Sig(name) i32 name(Unique_Hash index, char *buffer, i32 size) | ||||
| #define Sys_Load_Close_Sig(name) b32 name(Plat_Handle handle) | ||||
| typedef Sys_Load_Close_Sig(System_Load_Close); | ||||
| 
 | ||||
| #define Sys_Save_File_Sig(name) b32 name(char *filename, char *buffer, u32 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_Now_Time_Sig(name) u64 name() | ||||
| typedef Sys_Now_Time_Sig(System_Now_Time); | ||||
| 
 | ||||
| 
 | ||||
| #define Sys_Post_Clipboard_Sig(name) void name(String str) | ||||
|  | @ -221,18 +209,19 @@ typedef INTERNAL_Sys_Debug_Message_Sig(INTERNAL_System_Debug_Message); | |||
| 
 | ||||
| struct System_Functions{ | ||||
|      | ||||
|     // files (tracked api): 11
 | ||||
|     // files (tracked api): 9
 | ||||
|     System_Set_File_List *set_file_list; | ||||
|     System_Track_File *track_file; | ||||
|     System_Untrack_File *untrack_file; | ||||
|     System_Get_File_Index *get_file_index; | ||||
|     System_Get_File_Time *get_file_time; | ||||
|     System_Now_File_Time *now_file_time; | ||||
|     System_Get_Changed_File *get_changed_file; | ||||
|     System_File_Size *file_size; | ||||
|     System_Get_Canonical *get_canonical; | ||||
|     System_Add_Listener *add_listener; | ||||
|     System_Remove_Listener *remove_listener; | ||||
|     System_Load_Handle *load_handle; | ||||
|     System_Load_Size *load_size; | ||||
|     System_Load_File *load_file; | ||||
|     System_Load_Close *load_close; | ||||
|     System_Save_File *save_file; | ||||
|     System_Save_File_By_Name *save_file_by_name; | ||||
|      | ||||
|     // time: 1
 | ||||
|     System_Now_Time *now_time; | ||||
|      | ||||
|     // 4coder_custom.h: 7
 | ||||
|     Memory_Allocate_Function *memory_allocate; | ||||
|  |  | |||
|  | @ -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 | ||||
| REM cl %OPTS% %INCLUDES% %DEFINES% %CODE_DIR%\4ed_app_target.cpp %* /Fe4ed_app /LD /link /INCREMENTAL:NO /OPT:REF %EXPORTS% | ||||
| 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 | ||||
|  |  | |||
							
								
								
									
										374
									
								
								win32_4ed.cpp
								
								
								
								
							
							
						
						
									
										374
									
								
								win32_4ed.cpp
								
								
								
								
							|  | @ -144,6 +144,11 @@ enum CV_ID{ | |||
|     CV_COUNT | ||||
| }; | ||||
| 
 | ||||
| struct Drive_Strings{ | ||||
|     char *prefix_[26]; | ||||
|     char **prefix; | ||||
| }; | ||||
| 
 | ||||
| struct Win32_Vars{ | ||||
|     System_Functions system; | ||||
|     App_Functions app; | ||||
|  | @ -197,7 +202,7 @@ struct Win32_Vars{ | |||
|     void *track_table; | ||||
|     u32 track_table_size; | ||||
|     u32 track_node_size; | ||||
|      | ||||
|     Drive_Strings dstrings; | ||||
|      | ||||
| #if FRED_INTERNAL | ||||
|     CRITICAL_SECTION DEBUG_sysmem_lock; | ||||
|  | @ -1023,22 +1028,8 @@ Sys_Set_File_List_Sig(system_set_file_list){ | |||
|     } | ||||
| } | ||||
| 
 | ||||
| inline Unique_Hash | ||||
| to_uhash(File_Index index){ | ||||
|     Unique_Hash r; | ||||
|     *(File_Index*)(&r) = index; | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| inline File_Index | ||||
| to_findex(Unique_Hash index){ | ||||
|     File_Index r; | ||||
|     *(Unique_Hash*)(&r) = index; | ||||
|     return(r); | ||||
| } | ||||
| 
 | ||||
| internal b32 | ||||
| handle_track_out_of_memory(i32 val, Unique_Hash *index, File_Index get_index){ | ||||
| handle_track_out_of_memory(i32 val){ | ||||
|     b32 result = 0; | ||||
|      | ||||
|     switch (val){ | ||||
|  | @ -1059,100 +1050,160 @@ handle_track_out_of_memory(i32 val, Unique_Hash *index, File_Index get_index){ | |||
|             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}; | ||||
| internal void | ||||
| set_volume_prefix(Drive_Strings *dstrings, char *vol){ | ||||
|     char c = vol[0]; | ||||
|     if (dstrings->prefix[c]){ | ||||
|         system_free_memory(dstrings->prefix[c]); | ||||
|     } | ||||
|      | ||||
|     switch (flags){ | ||||
|         case TrackFileFlag_ExistingOrFail: | ||||
|         { | ||||
|             File_Index get_index = {0}; | ||||
|             File_Time time = 0; | ||||
|             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; | ||||
|     HANDLE hdir = CreateFile( | ||||
|         vol, | ||||
|         GENERIC_READ, | ||||
|         FILE_SHARE_DELETE|FILE_SHARE_WRITE|FILE_SHARE_READ, | ||||
|         0, | ||||
|         OPEN_EXISTING, | ||||
|         FILE_FLAG_BACKUP_SEMANTICS, | ||||
|         0); | ||||
|      | ||||
|     if (hdir != INVALID_HANDLE_VALUE){ | ||||
|         char *s = 0; | ||||
|         DWORD len = GetFinalPathNameByHandle(hdir, 0, 0, 0); | ||||
|         len = len + 1; | ||||
|         s = (char*)system_get_memory(len); | ||||
|         len = GetFinalPathNameByHandle(hdir, s, len, 0); | ||||
|         s[len] = 0; | ||||
|         if (s[len-1] == '\\') s[len-1] = 0; | ||||
|         dstrings->prefix[c] = s + 4; | ||||
|         CloseHandle(hdir); | ||||
|     } | ||||
|     else{ | ||||
|         dstrings->prefix[c] = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| internal void | ||||
| win32_init_drive_strings(Drive_Strings *dstrings){ | ||||
|     dstrings->prefix = dstrings->prefix_ - 'A'; | ||||
|      | ||||
|     char vol[4] = "A:\\"; | ||||
|     for (char c = 'A'; c <= 'Z'; ++c){ | ||||
|         vol[0] = c; | ||||
|         set_volume_prefix(dstrings, vol); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // NOTE(allen): This does not chase down symbolic links because doing so
 | ||||
| // would require a lot of heavy duty OS calls.  I've decided to give up
 | ||||
| // a little ground on always recognizing files as equivalent in exchange
 | ||||
| // for the ability to handle them very quickly when nothing strange is
 | ||||
| // going on.
 | ||||
| static int32_t | ||||
| win32_canonical_ansi_name(Drive_Strings *dstrings, char *src, i32 len, char *dst, i32 max){ | ||||
|     char *wrt = dst; | ||||
|     char *wrt_stop = dst + max; | ||||
|     char *src_stop = src + len; | ||||
|     char c = 0; | ||||
|     char **prefix_array = dstrings->prefix; | ||||
|     char *prefix = 0; | ||||
|      | ||||
|     if (len >= 2 && max > 0){ | ||||
|         c = src[0]; | ||||
|         if (c >= 'a' && c <= 'z'){ | ||||
|             c -= 'a' - 'A'; | ||||
|         } | ||||
|          | ||||
|         case TrackFileFlag_NewOrFail: | ||||
|         { | ||||
|             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){ | ||||
|                 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; | ||||
|                     } | ||||
|         if (c >= 'A' && c <= 'Z' && src[1] == ':'){ | ||||
|             prefix = prefix_array[c]; | ||||
|             if (prefix){ | ||||
|                 for (;*prefix;){ | ||||
|                     *(wrt++) = *(prefix++); | ||||
|                     if (wrt == wrt_stop) goto fail; | ||||
|                 } | ||||
|             } | ||||
|             else{ | ||||
|                 finish_with_temp_handle(handle); | ||||
|                 *(wrt++) = c; | ||||
|                 if (wrt == wrt_stop) goto fail; | ||||
|                 *(wrt++) = ':'; | ||||
|                 if (wrt == wrt_stop) goto fail; | ||||
|             } | ||||
|         }break; | ||||
|          | ||||
|         case TrackFileFlag_NewAlways: | ||||
|         { | ||||
|             File_Index get_index = {0}; | ||||
|             File_Time time = 0; | ||||
|             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; | ||||
|             src += 2; | ||||
|              | ||||
|             for (; src < src_stop; ++src){ | ||||
|                 c = src[0]; | ||||
|                  | ||||
|                 if (c >= 'A' && c <= 'Z'){ | ||||
|                     c += 'a' - 'A'; | ||||
|                 } | ||||
|             } | ||||
|         }break; | ||||
|          | ||||
|         case TrackFileFlag_ExistingOrNew: | ||||
|         { | ||||
|             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){ | ||||
|                 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; | ||||
|                  | ||||
|                 if (c == '/' || c == '\\'){ | ||||
|                     c = '\\'; | ||||
|                     if (wrt > dst && wrt[-1] == '\\'){ | ||||
|                         continue; | ||||
|                     } | ||||
|                     else if (src[1] == '.'){ | ||||
|                         if (src[2] == '\\' || src[2] == '/'){ | ||||
|                             src += 1; | ||||
|                         } | ||||
|                         else if (src[2] == '.' && (src[3] == '\\' || src[3] == '/')){ | ||||
|                             src += 2; | ||||
|                             while (wrt > dst && wrt[0] != '\\'){ | ||||
|                                 --wrt; | ||||
|                             } | ||||
|                             if (wrt == dst) goto fail; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                  | ||||
|                 *wrt = c; | ||||
|                 ++wrt; | ||||
|                 if (wrt == wrt_stop) goto fail; | ||||
|             } | ||||
|             else{ | ||||
|                 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; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }break; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     track_end:; | ||||
|     if (0){ | ||||
|         fail:; | ||||
|         wrt = dst; | ||||
|     } | ||||
|      | ||||
|     return(index); | ||||
|     int32_t result = (int32_t)(wrt - dst); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Untrack_File_Sig(system_untrack_file){ | ||||
| Sys_Get_Canonical_Sig(system_get_canonical){ | ||||
|     i32 result = win32_canonical_ansi_name(&win32vars.dstrings, filename, len, buffer, max); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Add_Listener_Sig(system_add_listener){ | ||||
|     b32 result = 0; | ||||
|      | ||||
|     for (;;){ | ||||
|         i32 track_result = add_listener(&win32vars.track, filename); | ||||
|         if (handle_track_out_of_memory(track_result)){ | ||||
|             if (track_result == FileTrack_Good){ | ||||
|                 result = 1; | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Remove_Listener_Sig(system_remove_listener){ | ||||
|     i32 result = 0; | ||||
|     i32 track_result = stop_tracking_file(&win32vars.track, to_findex(index)); | ||||
|     i32 track_result = remove_listener(&win32vars.track, filename); | ||||
|     if (track_result == FileTrack_Good){ | ||||
|         result = 1; | ||||
|     } | ||||
|  | @ -1160,64 +1211,64 @@ Sys_Untrack_File_Sig(system_untrack_file){ | |||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Get_File_Index_Sig(system_get_file_index){ | ||||
|     i32 result = 0; | ||||
|     File_Index get_index = {0}; | ||||
|     i32 track_result = get_tracked_file_index(&win32vars.track, filename, &get_index); | ||||
|     if (track_result == FileTrack_Good){ | ||||
|         *index = to_uhash(get_index); | ||||
| Sys_Load_Handle_Sig(system_load_handle){ | ||||
|     b32 result = 0; | ||||
|     HANDLE file = CreateFile(filename, | ||||
|                              GENERIC_READ, | ||||
|                              0, | ||||
|                              0, | ||||
|                              OPEN_EXISTING, | ||||
|                              FILE_ATTRIBUTE_NORMAL, | ||||
|                              0); | ||||
|      | ||||
|     if (file != INVALID_HANDLE_VALUE){ | ||||
|         *(HANDLE*)handle_out = file; | ||||
|         result = 1; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Get_File_Time_Sig(system_get_file_time){ | ||||
|     i32 result = 0; | ||||
|     u64 get_time = 0; | ||||
|     File_Index findex = to_findex(index); | ||||
|     i32 track_result = get_tracked_file_time(&win32vars.track, findex, &get_time); | ||||
|     if (track_result == FileTrack_Good){ | ||||
|         *time = get_time; | ||||
|         result = 1; | ||||
| Sys_Load_Size_Sig(system_load_size){ | ||||
|     u32 result = 0; | ||||
|     HANDLE file = *(HANDLE*)(&handle); | ||||
|      | ||||
|     DWORD hi = 0; | ||||
|     DWORD lo = GetFileSize(file, &hi); | ||||
|      | ||||
|     if (hi == 0){ | ||||
|         result = lo; | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Now_File_Time_Sig(system_now_file_time){ | ||||
|     get_file_time_now(time); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Get_Changed_File_Sig(system_get_changed_file){ | ||||
|     i32 result = 0; | ||||
|     File_Index get_index = {0}; | ||||
|     i32 track_result = get_change_event(&win32vars.track, &get_index); | ||||
|     if (track_result == FileTrack_Good){ | ||||
|         *index = to_uhash(get_index); | ||||
|         result = 1; | ||||
|     } | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_File_Size_Sig(system_file_size){ | ||||
|     u32 size = 0; | ||||
|     File_Index findex = to_findex(index); | ||||
|     i32 track_result = get_tracked_file_size(&win32vars.track, findex, &size); | ||||
|     if (track_result != FileTrack_Good){ | ||||
|         size = 0; | ||||
|     } | ||||
|     return(size); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Load_File_Sig(system_load_file){ | ||||
|     i32 result = 0; | ||||
|     File_Index findex = to_findex(index); | ||||
|     i32 track_result = get_tracked_file_data(&win32vars.track, findex, buffer, size); | ||||
|     if (track_result == FileTrack_Good){ | ||||
|     b32 result = 0; | ||||
|     HANDLE file = *(HANDLE*)(&handle); | ||||
|      | ||||
|     DWORD read_size = 0; | ||||
|      | ||||
|     if (ReadFile(file, | ||||
|                  buffer, | ||||
|                  size, | ||||
|                  &read_size, | ||||
|                  0)){ | ||||
|         if (read_size == size){ | ||||
|             result = 1; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
| internal | ||||
| Sys_Load_Close_Sig(system_load_close){ | ||||
|     b32 result = 0; | ||||
|     HANDLE file = *(HANDLE*)(&handle); | ||||
|     if (CloseHandle(file)){ | ||||
|         result = 1; | ||||
|     } | ||||
|     return(result); | ||||
|  | @ -1225,24 +1276,36 @@ Sys_Load_File_Sig(system_load_file){ | |||
| 
 | ||||
| internal | ||||
| Sys_Save_File_Sig(system_save_file){ | ||||
|     i32 result = 0; | ||||
|     File_Index findex = to_findex(index); | ||||
|     File_Time time = 0; | ||||
|     i32 track_result = rewrite_tracked_file(&win32vars.track, findex, buffer, size, &time); | ||||
|     if (track_result == FileTrack_Good){ | ||||
|     b32 result = 0; | ||||
|     HANDLE file = CreateFile(filename, | ||||
|                              GENERIC_WRITE, | ||||
|                              0, | ||||
|                              0, | ||||
|                              CREATE_NEW, | ||||
|                              FILE_ATTRIBUTE_NORMAL, | ||||
|                              0); | ||||
|      | ||||
|     if (file != INVALID_HANDLE_VALUE){ | ||||
|         DWORD written_total = 0; | ||||
|         DWORD written_size = 0; | ||||
|          | ||||
|         result = 1; | ||||
|          | ||||
|         while (written_total < size){ | ||||
|             if (!WriteFile(file, buffer, size, &written_size, 0)){ | ||||
|                 result = 0; | ||||
|                 break; | ||||
|             } | ||||
|             written_total += written_size; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     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; | ||||
|     } | ||||
| Sys_Now_Time_Sig(system_now_time){ | ||||
|     u64 result = __rdtsc(); | ||||
|     return(result); | ||||
| } | ||||
| 
 | ||||
|  | @ -1596,16 +1659,16 @@ Win32LoadAppCode(){ | |||
| internal void | ||||
| Win32LoadSystemCode(){ | ||||
|     win32vars.system.set_file_list = system_set_file_list; | ||||
|     win32vars.system.track_file = system_track_file; | ||||
|     win32vars.system.untrack_file = system_untrack_file; | ||||
|     win32vars.system.get_file_index = system_get_file_index; | ||||
|     win32vars.system.get_file_time = system_get_file_time; | ||||
|     win32vars.system.now_file_time = system_now_file_time; | ||||
|     win32vars.system.get_changed_file = system_get_changed_file; | ||||
|     win32vars.system.file_size = system_file_size; | ||||
|     win32vars.system.get_canonical = system_get_canonical; | ||||
|     win32vars.system.add_listener = system_add_listener; | ||||
|     win32vars.system.remove_listener = system_remove_listener; | ||||
|     win32vars.system.load_handle = system_load_handle; | ||||
|     win32vars.system.load_size = system_load_size; | ||||
|     win32vars.system.load_file = system_load_file; | ||||
|     win32vars.system.load_close = system_load_close; | ||||
|     win32vars.system.save_file = system_save_file; | ||||
|     win32vars.system.save_file_by_name = system_save_file_by_name; | ||||
|      | ||||
|     win32vars.system.now_time = system_now_time; | ||||
|      | ||||
|     win32vars.system.memory_allocate = Memory_Allocate; | ||||
|     win32vars.system.file_exists = File_Exists; | ||||
|  | @ -2064,7 +2127,6 @@ WinMain(HINSTANCE hInstance, | |||
|      | ||||
|     memset(&win32vars, 0, sizeof(win32vars)); | ||||
|      | ||||
|      | ||||
|     //
 | ||||
|     // Threads and Coroutines
 | ||||
|     //
 | ||||
|  | @ -2127,6 +2189,10 @@ WinMain(HINSTANCE hInstance, | |||
|         win32vars.coroutine_data[i].next = win32vars.coroutine_data + i + 1; | ||||
|     } | ||||
|      | ||||
|     //
 | ||||
|     // Volume Initialization
 | ||||
|     //
 | ||||
|     win32_init_drive_strings(&win32vars.dstrings); | ||||
|      | ||||
|     //
 | ||||
|     // Memory Initialization
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Allen Webster
						Allen Webster