2016-02-21 17:44:23 +00:00
/*
* Mr . 4 th Dimention - Allen Webster
*
2017-01-03 20:05:35 +00:00
* 03.01 .2017
2016-02-21 17:44:23 +00:00
*
2018-03-24 21:43:57 +00:00
* Working_Set data structure
2016-02-21 17:44:23 +00:00
*
*/
// TOP
2018-03-25 06:43:56 +00:00
// TODO(allen): Find a real home for this... string library needs a makeover.
internal String
push_string ( Partition * part , char * str , i32 len ) {
char * space = ( char * ) push_array ( part , char , len + 1 ) ;
memcpy ( space , str , len ) ;
space [ len ] = 0 ;
String string = make_string_cap ( space , len , len + 1 ) ;
return ( string ) ;
}
internal String
push_string ( Partition * part , String str ) {
String res = push_string ( part , str . str , str . size ) ;
return ( res ) ;
}
internal String
push_string ( Partition * part , char * str , i32 len , i32 cap ) {
cap = clamp_bottom ( len + 1 , cap ) ;
char * space = ( char * ) push_array ( part , char , cap ) ;
memcpy ( space , str , len ) ;
space [ len ] = 0 ;
String string = make_string_cap ( space , len , cap ) ;
return ( string ) ;
}
internal String
push_string ( Partition * part , String str , i32 cap ) {
String res = push_string ( part , str . str , str . size , cap ) ;
return ( res ) ;
}
////////////////////////////////
2016-02-21 17:44:23 +00:00
2016-03-08 23:06:27 +00:00
internal void
working_set_extend_memory ( Working_Set * working_set , Editing_File * new_space , i16 number_of_files ) {
Assert ( working_set - > array_count < working_set - > array_max ) ;
2017-03-11 18:53:48 +00:00
i16 high_part = working_set - > array_count + + ;
2016-03-08 23:06:27 +00:00
working_set - > file_arrays [ high_part ] . files = new_space ;
working_set - > file_arrays [ high_part ] . size = number_of_files ;
working_set - > file_max + = number_of_files ;
2018-11-20 08:18:54 +00:00
Buffer_Slot_ID id = { } ;
2016-03-08 23:06:27 +00:00
id . part [ 1 ] = high_part ;
2017-03-11 18:53:48 +00:00
Editing_File * file_ptr = new_space ;
File_Node * free_sentinel = & working_set - > free_sentinel ;
for ( i16 i = 0 ; i < number_of_files ; + + i , + + file_ptr ) {
2016-03-08 23:06:27 +00:00
id . part [ 0 ] = i ;
file_ptr - > id = id ;
dll_insert ( free_sentinel , & file_ptr - > node ) ;
}
}
internal Editing_File *
2018-08-18 08:16:52 +00:00
working_set_alloc_always ( Working_Set * working_set , Heap * heap , Lifetime_Allocator * lifetime_allocator ) {
2016-03-08 23:06:27 +00:00
Editing_File * result = 0 ;
2018-08-12 03:45:09 +00:00
if ( working_set - > file_count = = working_set - > file_max & & working_set - > array_count < working_set - > array_max ) {
i16 new_count = ( i16 ) clamp_top ( working_set - > file_max , max_i16 ) ;
2018-08-18 08:16:52 +00:00
Editing_File * new_chunk = heap_array ( heap , Editing_File , new_count ) ;
2018-08-12 03:45:09 +00:00
working_set_extend_memory ( working_set , new_chunk , new_count ) ;
}
2016-03-08 23:06:27 +00:00
if ( working_set - > file_count < working_set - > file_max ) {
2016-10-27 23:45:41 +00:00
File_Node * node = working_set - > free_sentinel . next ;
2016-03-08 23:06:27 +00:00
Assert ( node ! = & working_set - > free_sentinel ) ;
result = ( Editing_File * ) node ;
dll_remove ( node ) ;
2016-10-27 23:45:41 +00:00
Buffer_Slot_ID id = result - > id ;
2018-03-24 10:06:45 +00:00
memset ( result , 0 , sizeof ( * result ) ) ;
2016-03-08 23:06:27 +00:00
result - > id = id ;
dll_insert ( & working_set - > used_sentinel , node ) ;
2016-09-22 00:01:12 +00:00
result - > settings . display_width = working_set - > default_display_width ;
2016-10-24 23:02:10 +00:00
result - > settings . minimum_base_display_width = working_set - > default_minimum_base_display_width ;
2016-10-27 23:45:41 +00:00
result - > settings . wrap_indicator = WrapIndicator_Show_At_Wrap_Edge ;
2016-03-08 23:06:27 +00:00
+ + working_set - > file_count ;
}
2016-05-19 18:01:36 +00:00
2016-08-24 14:36:29 +00:00
return ( result ) ;
2016-03-08 23:06:27 +00:00
}
inline void
2018-09-14 19:02:02 +00:00
working_set_free_file ( Heap * heap , Working_Set * working_set , Editing_File * file ) {
2016-07-20 16:16:02 +00:00
if ( working_set - > sync_check_iter = = & file - > node ) {
working_set - > sync_check_iter = working_set - > sync_check_iter - > next ;
}
2018-08-12 03:45:09 +00:00
file - > is_dummy = true ;
2016-03-08 23:06:27 +00:00
dll_remove ( & file - > node ) ;
dll_insert ( & working_set - > free_sentinel , & file - > node ) ;
- - working_set - > file_count ;
}
inline Editing_File *
2016-05-19 18:01:36 +00:00
working_set_index ( Working_Set * working_set , Buffer_Slot_ID id ) {
2016-03-08 23:06:27 +00:00
Editing_File * result = 0 ;
2016-08-24 14:36:29 +00:00
File_Array * array = 0 ;
2016-03-08 23:06:27 +00:00
if ( id . part [ 1 ] > = 0 & & id . part [ 1 ] < working_set - > array_count ) {
array = working_set - > file_arrays + id . part [ 1 ] ;
if ( id . part [ 0 ] > = 0 & & id . part [ 0 ] < array - > size ) {
result = array - > files + id . part [ 0 ] ;
}
}
return ( result ) ;
}
inline Editing_File *
working_set_index ( Working_Set * working_set , i32 id ) {
2016-08-24 14:36:29 +00:00
Editing_File * result = working_set_index ( working_set , to_file_id ( id ) ) ;
2016-03-08 23:06:27 +00:00
return ( result ) ;
}
inline Editing_File *
2016-05-19 18:01:36 +00:00
working_set_get_active_file ( Working_Set * working_set , Buffer_Slot_ID id ) {
2016-03-08 23:06:27 +00:00
Editing_File * result = 0 ;
result = working_set_index ( working_set , id ) ;
2018-03-24 21:43:57 +00:00
if ( result ! = 0 & & result - > is_dummy ) {
2016-03-08 23:06:27 +00:00
result = 0 ;
}
return ( result ) ;
}
inline Editing_File *
working_set_get_active_file ( Working_Set * working_set , i32 id ) {
2018-03-24 21:43:57 +00:00
Editing_File * result = working_set_get_active_file ( working_set , to_file_id ( id ) ) ;
2016-03-08 23:06:27 +00:00
return ( result ) ;
}
2016-03-11 03:33:19 +00:00
internal void
2018-08-18 08:16:52 +00:00
working_set_init ( Working_Set * working_set , Partition * partition , Heap * heap ) {
2016-03-24 02:14:44 +00:00
i16 init_count = 16 ;
i16 array_init_count = 256 ;
2016-03-11 03:33:19 +00:00
dll_init_sentinel ( & working_set - > free_sentinel ) ;
dll_init_sentinel ( & working_set - > used_sentinel ) ;
2016-08-24 14:36:29 +00:00
2016-03-15 14:12:06 +00:00
working_set - > array_max = array_init_count ;
working_set - > file_arrays = push_array ( partition , File_Array , array_init_count ) ;
2016-08-24 14:36:29 +00:00
Editing_File * files = push_array ( partition , Editing_File , init_count ) ;
2016-03-11 03:33:19 +00:00
working_set_extend_memory ( working_set , files , init_count ) ;
2016-08-24 14:36:29 +00:00
2017-02-24 02:30:29 +00:00
// TODO(NAME): Unclear that this is still needed. But double check that the buffer id 0 does not start getting used by the next real buffer when this is removed before actually removing it. Buffer id cannot be allowed to be zero on real buffers.
# if 1
2016-08-24 14:36:29 +00:00
// NOTE(allen): init null file
{
Editing_File * null_file = working_set_index ( working_set , 0 ) ;
dll_remove ( & null_file - > node ) ;
null_file - > is_dummy = 1 ;
+ + working_set - > file_count ;
}
2017-02-24 02:30:29 +00:00
# endif
2016-08-24 14:36:29 +00:00
2016-08-26 17:52:35 +00:00
// NOTE(allen): init canon table
2016-08-24 14:36:29 +00:00
{
2016-08-26 17:52:35 +00:00
i32 item_size = sizeof ( File_Name_Entry ) ;
2016-08-24 14:36:29 +00:00
i32 table_size = working_set - > file_max ;
2017-03-23 19:15:33 +00:00
i32 mem_size = table_required_mem_size ( table_size , item_size ) ;
2018-08-18 08:16:52 +00:00
void * mem = heap_allocate ( heap , mem_size ) ;
2016-08-24 14:36:29 +00:00
memset ( mem , 0 , mem_size ) ;
2016-08-26 17:52:35 +00:00
table_init_memory ( & working_set - > canon_table , mem , table_size , item_size ) ;
2016-08-24 14:36:29 +00:00
}
// NOTE(allen): init name table
{
2017-03-23 19:15:33 +00:00
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 ) ;
2018-08-18 08:16:52 +00:00
void * mem = heap_allocate ( heap , mem_size ) ;
2016-08-24 14:36:29 +00:00
memset ( mem , 0 , mem_size ) ;
table_init_memory ( & working_set - > name_table , mem , table_size , item_size ) ;
}
2016-03-11 03:33:19 +00:00
}
2016-03-11 21:54:32 +00:00
inline void
2018-08-18 08:16:52 +00:00
working_set__grow_if_needed ( Table * table , Heap * heap , void * arg , Hash_Function * hash_func , Compare_Function * comp_func ) {
2016-03-15 14:12:06 +00:00
if ( table_at_capacity ( table ) ) {
2018-11-20 08:18:54 +00:00
Table btable = { } ;
2017-03-23 19:15:33 +00:00
i32 new_max = table - > max * 2 ;
i32 mem_size = table_required_mem_size ( new_max , table - > item_size ) ;
2018-08-18 08:16:52 +00:00
void * mem = heap_allocate ( heap , mem_size ) ;
2016-03-15 14:12:06 +00:00
table_init_memory ( & btable , mem , new_max , table - > item_size ) ;
table_clear ( & btable ) ;
table_rehash ( table , & btable , 0 , hash_func , comp_func ) ;
2018-08-18 08:16:52 +00:00
heap_free ( heap , table - > hash_array ) ;
2016-03-15 14:12:06 +00:00
* table = btable ;
}
}
2016-08-24 14:36:29 +00:00
internal Editing_File *
2016-08-26 17:52:35 +00:00
working_set_contains_basic ( Working_Set * working_set , Table * table , String name ) {
2016-08-24 14:36:29 +00:00
Editing_File * result = 0 ;
2016-08-26 17:52:35 +00:00
File_Name_Entry * entry = ( File_Name_Entry * )
table_find_item ( table , & name , 0 , tbl_string_hash , tbl_string_compare ) ;
2016-08-24 14:36:29 +00:00
if ( entry ) {
result = working_set_index ( working_set , entry - > id ) ;
}
return ( result ) ;
}
2016-08-26 17:52:35 +00:00
internal b32
2018-08-18 08:16:52 +00:00
working_set_add_basic ( Heap * heap , Working_Set * working_set , Table * table , Editing_File * file , String name ) {
working_set__grow_if_needed ( table , heap , 0 , tbl_string_hash , tbl_string_compare ) ;
2016-08-24 14:36:29 +00:00
2016-08-26 17:52:35 +00:00
File_Name_Entry entry ;
entry . name = name ;
2016-08-24 14:36:29 +00:00
entry . id = file - > id ;
2016-08-26 17:52:35 +00:00
b32 result = ( table_add ( table , & entry , 0 , tbl_string_hash , tbl_string_compare ) = = 0 ) ;
return ( result ) ;
2016-08-24 14:36:29 +00:00
}
internal void
2016-08-26 17:52:35 +00:00
working_set_remove_basic ( Working_Set * working_set , Table * table , String name ) {
table_remove_match ( table , & name , 0 , tbl_string_hash , tbl_string_compare ) ;
2016-08-24 14:36:29 +00:00
}
internal Editing_File *
2017-11-30 23:25:49 +00:00
working_set_contains_canon ( Working_Set * working_set , String name ) {
Editing_File * result = working_set_contains_basic ( working_set , & working_set - > canon_table , name ) ;
2016-08-24 14:36:29 +00:00
return ( result ) ;
}
2016-08-26 17:52:35 +00:00
internal b32
2018-08-18 08:16:52 +00:00
working_set_canon_add ( Heap * heap , Working_Set * working_set , Editing_File * file , String name ) {
b32 result = working_set_add_basic ( heap , working_set , & working_set - > canon_table , file , name ) ;
2016-08-26 17:52:35 +00:00
return ( result ) ;
2016-08-24 14:36:29 +00:00
}
internal void
2016-08-26 17:52:35 +00:00
working_set_canon_remove ( Working_Set * working_set , String name ) {
working_set_remove_basic ( working_set , & working_set - > canon_table , name ) ;
2016-08-24 14:36:29 +00:00
}
2016-08-26 17:52:35 +00:00
internal Editing_File *
2017-11-30 23:25:49 +00:00
working_set_contains_name ( Working_Set * working_set , String name ) {
Editing_File * result = working_set_contains_basic ( working_set , & working_set - > name_table , name ) ;
2016-08-26 17:52:35 +00:00
return ( result ) ;
2016-03-11 03:33:19 +00:00
}
2016-08-26 17:52:35 +00:00
internal b32
2018-08-18 08:16:52 +00:00
working_set_add_name ( Heap * heap , Working_Set * working_set , Editing_File * file , String name ) {
b32 result = working_set_add_basic ( heap , working_set , & working_set - > name_table , file , name ) ;
2016-03-24 02:14:44 +00:00
return ( result ) ;
2016-03-11 21:54:32 +00:00
}
2016-08-26 17:52:35 +00:00
internal void
2017-11-30 23:25:49 +00:00
working_set_remove_name ( Working_Set * working_set , String name ) {
2016-08-26 17:52:35 +00:00
working_set_remove_basic ( working_set , & working_set - > name_table , name ) ;
2016-03-11 21:54:32 +00:00
}
2016-03-11 03:33:19 +00:00
2016-03-08 23:06:27 +00:00
// TODO(allen): Pick better first options.
internal Editing_File *
working_set_lookup_file ( Working_Set * working_set , String string ) {
Editing_File * file = 0 ;
2018-03-24 10:06:45 +00:00
// TODO(allen): use the name table for this
for ( File_Node * node = working_set - > used_sentinel . next ;
node ! = & working_set - > used_sentinel ;
node = node - > next ) {
Editing_File * nfile = ( Editing_File * ) node ;
if ( string . size = = 0 | | match_ss ( string , nfile - > unique_name . name ) ) {
file = nfile ;
break ;
2016-03-08 23:06:27 +00:00
}
}
2017-01-03 20:05:35 +00:00
2018-03-24 10:06:45 +00:00
if ( file = = 0 ) {
for ( File_Node * node = working_set - > used_sentinel . next ;
2018-05-07 04:44:03 +00:00
node ! = & working_set - > used_sentinel ;
2018-03-24 10:06:45 +00:00
node = node - > next ) {
Editing_File * nfile = ( Editing_File * ) node ;
if ( string . size = = 0 | | has_substr_s ( nfile - > unique_name . name , string ) ) {
file = nfile ;
2016-03-08 23:06:27 +00:00
break ;
}
}
2017-01-03 20:05:35 +00:00
}
2016-03-08 23:06:27 +00:00
2018-03-24 10:06:45 +00:00
return ( file ) ;
2016-03-08 23:06:27 +00:00
}
2016-05-19 16:23:12 +00:00
internal void
touch_file ( Working_Set * working_set , Editing_File * file ) {
2018-03-25 06:43:56 +00:00
Assert ( file ! = 0 ) ;
2018-03-24 10:06:45 +00:00
Assert ( ! file - > is_dummy ) ;
dll_remove ( & file - > node ) ;
dll_insert ( & working_set - > used_sentinel , & file - > node ) ;
2016-05-19 16:23:12 +00:00
}
2016-03-08 23:06:27 +00:00
2018-03-25 06:43:56 +00:00
////////////////////////////////
// TODO(allen): Bring the clipboard fully to the custom side.
internal String *
2018-08-18 08:16:52 +00:00
working_set_next_clipboard_string ( Heap * heap , Working_Set * working , i32 str_size ) {
2018-03-25 06:43:56 +00:00
i32 clipboard_current = working - > clipboard_current ;
if ( working - > clipboard_size = = 0 ) {
clipboard_current = 0 ;
working - > clipboard_size = 1 ;
}
else {
+ + clipboard_current ;
if ( clipboard_current > = working - > clipboard_max_size ) {
clipboard_current = 0 ;
}
else if ( working - > clipboard_size < = clipboard_current ) {
working - > clipboard_size = clipboard_current + 1 ;
}
}
String * result = & working - > clipboards [ clipboard_current ] ;
working - > clipboard_current = clipboard_current ;
working - > clipboard_rolling = clipboard_current ;
if ( result - > str ! = 0 ) {
2018-09-12 19:43:24 +00:00
if ( result - > memory_size < = str_size ) {
heap_free ( heap , result - > str ) ;
char * new_str = ( char * ) heap_allocate ( heap , str_size + 1 ) ;
* result = make_string_cap ( new_str , 0 , str_size + 1 ) ;
}
else {
result - > size = 0 ;
}
2018-03-25 06:43:56 +00:00
}
else {
2018-09-12 19:43:24 +00:00
char * new_str = ( char * ) heap_allocate ( heap , str_size + 1 ) ;
* result = make_string_cap ( new_str , 0 , str_size + 1 ) ;
2018-03-25 06:43:56 +00:00
}
return ( result ) ;
}
internal String *
working_set_clipboard_index ( Working_Set * working , i32 index ) {
String * result = 0 ;
i32 size = working - > clipboard_size ;
i32 current = working - > clipboard_current ;
if ( index > = 0 & & size > 0 ) {
index = index % size ;
index = current + size - index ;
index = index % size ;
result = & working - > clipboards [ index ] ;
}
return ( result ) ;
}
2016-07-20 15:19:54 +00:00
2018-03-25 06:43:56 +00:00
internal String *
working_set_clipboard_head ( Working_Set * working ) {
String * result = 0 ;
if ( working - > clipboard_size > 0 ) {
working - > clipboard_rolling = 0 ;
result = working_set_clipboard_index ( working , working - > clipboard_rolling ) ;
}
return ( result ) ;
}
2016-07-02 22:59:16 +00:00
2018-03-25 06:43:56 +00:00
internal String *
working_set_clipboard_roll_down ( Working_Set * working ) {
String * result = 0 ;
if ( working - > clipboard_size > 0 ) {
i32 clipboard_index = working - > clipboard_rolling ;
+ + clipboard_index ;
working - > clipboard_rolling = clipboard_index ;
result = working_set_clipboard_index ( working , working - > clipboard_rolling ) ;
}
return ( result ) ;
2016-08-24 14:36:29 +00:00
}
2018-03-25 06:43:56 +00:00
////////////////////////////////
2016-08-26 17:52:35 +00:00
internal b32
2018-10-10 04:59:42 +00:00
get_canon_name ( System_Functions * system , String filename , Editing_File_Name * canon_name ) {
2016-08-26 17:52:35 +00:00
canon_name - > name = make_fixed_width_string ( canon_name - > name_ ) ;
2017-03-23 19:15:05 +00:00
canon_name - > name . size = system - > get_canonical ( filename . str , filename . size , canon_name - > name . str , canon_name - > name . memory_size ) ;
2016-08-26 17:52:35 +00:00
terminate_with_null ( & canon_name - > name ) ;
b32 result = ( canon_name - > name . size ! = 0 ) ;
return ( result ) ;
}
2016-08-24 14:36:29 +00:00
internal void
2018-10-10 04:59:42 +00:00
buffer_bind_file ( System_Functions * system , Heap * heap , Working_Set * working_set , Editing_File * file , String canon_filename ) {
2017-12-01 18:04:07 +00:00
Assert ( file - > unique_name . name . size = = 0 ) ;
2016-08-26 17:52:35 +00:00
Assert ( file - > canon . name . size = = 0 ) ;
2016-08-24 14:36:29 +00:00
2016-08-26 17:52:35 +00:00
file - > canon . name = make_fixed_width_string ( file - > canon . name_ ) ;
2018-03-25 06:43:56 +00:00
copy ( & file - > canon . name , canon_filename ) ;
2016-08-27 14:42:47 +00:00
terminate_with_null ( & file - > canon . name ) ;
2017-01-14 03:01:35 +00:00
system - > add_listener ( file - > canon . name . str ) ;
2018-08-18 08:16:52 +00:00
if ( ! working_set_canon_add ( heap , working_set , file , file - > canon . name ) ) {
2018-03-25 06:43:56 +00:00
InvalidCodePath ;
}
2016-08-24 14:36:29 +00:00
}
internal void
2016-08-26 21:30:08 +00:00
buffer_unbind_file ( System_Functions * system , Working_Set * working_set , Editing_File * file ) {
2017-12-01 18:04:07 +00:00
Assert ( file - > unique_name . name . size = = 0 ) ;
2016-08-26 17:52:35 +00:00
Assert ( file - > canon . name . size ! = 0 ) ;
2016-08-24 14:36:29 +00:00
2016-08-26 21:30:08 +00:00
system - > remove_listener ( file - > canon . name_ ) ;
2016-08-26 17:52:35 +00:00
working_set_canon_remove ( working_set , file - > canon . name ) ;
file - > canon . name . size = 0 ;
2016-08-24 14:36:29 +00:00
}
2017-11-30 23:25:49 +00:00
internal b32
buffer_name_has_conflict ( Working_Set * working_set , String base_name ) {
b32 hit_conflict = false ;
File_Node * used_nodes = & working_set - > used_sentinel ;
for ( File_Node * node = used_nodes - > next ; node ! = used_nodes ; node = node - > next ) {
2017-12-01 18:04:07 +00:00
Editing_File * file_ptr = ( Editing_File * ) node ; if ( file_is_ready ( file_ptr ) & & match ( base_name , file_ptr - > unique_name . name ) ) {
2017-11-30 23:25:49 +00:00
hit_conflict = true ;
break ;
}
}
return ( hit_conflict ) ;
}
2016-08-24 14:36:29 +00:00
internal void
2017-11-30 23:25:49 +00:00
buffer_resolve_name_low_level ( Working_Set * working_set , Editing_File_Name * name , String base_name ) {
Assert ( name - > name . str ! = 0 ) ;
2017-12-01 18:04:07 +00:00
copy ( & name - > name , base_name ) ;
2017-11-30 23:25:49 +00:00
i32 original_len = name - > name . size ;
i32 file_x = 0 ;
for ( b32 hit_conflict = true ; hit_conflict ; ) {
hit_conflict = buffer_name_has_conflict ( working_set , name - > name ) ;
if ( hit_conflict ) {
+ + file_x ;
name - > name . size = original_len ;
2017-12-01 18:04:07 +00:00
append ( & name - > name , " ( " ) ;
2017-11-30 23:25:49 +00:00
append_int_to_str ( & name - > name , file_x ) ;
2017-12-01 18:04:07 +00:00
append ( & name - > name , " ) " ) ;
2017-11-30 23:25:49 +00:00
}
}
}
internal void
2018-08-18 08:16:52 +00:00
buffer_bind_name_low_level ( Heap * heap , Working_Set * working_set , Editing_File * file , String base_name , String name ) {
2017-12-01 18:04:07 +00:00
Assert ( file - > base_name . name . size = = 0 ) ;
Assert ( file - > unique_name . name . size = = 0 ) ;
2016-08-24 14:36:29 +00:00
2018-11-20 08:18:54 +00:00
Editing_File_Name new_name = { } ;
2018-03-25 06:43:56 +00:00
new_name . name = make_fixed_width_string ( new_name . name_ ) ;
2017-11-30 23:25:49 +00:00
buffer_resolve_name_low_level ( working_set , & new_name , name ) ;
2016-08-24 14:36:29 +00:00
2018-03-25 06:43:56 +00:00
file - > base_name . name = make_fixed_width_string ( file - > base_name . name_ ) ;
2017-12-01 18:04:07 +00:00
copy ( & file - > base_name . name , base_name ) ;
2016-08-24 14:36:29 +00:00
2018-03-25 06:43:56 +00:00
file - > unique_name . name = make_fixed_width_string ( file - > unique_name . name_ ) ;
2017-12-01 18:04:07 +00:00
copy ( & file - > unique_name . name , new_name . name ) ;
2018-08-18 08:16:52 +00:00
if ( ! working_set_add_name ( heap , working_set , file , file - > unique_name . name ) ) {
2018-03-25 06:43:56 +00:00
InvalidCodePath ;
}
2016-08-24 14:36:29 +00:00
}
internal void
2017-11-30 23:25:49 +00:00
buffer_unbind_name_low_level ( Working_Set * working_set , Editing_File * file ) {
2017-12-01 18:04:07 +00:00
Assert ( file - > base_name . name . size ! = 0 ) ;
Assert ( file - > unique_name . name . size ! = 0 ) ;
working_set_remove_name ( working_set , file - > unique_name . name ) ;
file - > base_name . name . size = 0 ;
file - > unique_name . name . size = 0 ;
2016-08-24 14:36:29 +00:00
}
2018-03-25 06:43:56 +00:00
internal void
2018-08-18 08:16:52 +00:00
buffer_bind_name ( Models * models , Heap * heap , Partition * scratch ,
2018-03-25 06:43:56 +00:00
Working_Set * working_set ,
Editing_File * file , String base_name ) {
Temp_Memory temp = begin_temp_memory ( scratch ) ;
// List of conflict files.
Editing_File * * conflict_file_ptrs = push_array ( scratch , Editing_File * , 0 ) ;
int32_t conflict_count = 0 ;
{
Editing_File * * new_file_ptr = push_array ( scratch , Editing_File * , 1 ) ;
* new_file_ptr = file ;
+ + conflict_count ;
}
File_Node * used_nodes = & working_set - > used_sentinel ;
for ( File_Node * node = used_nodes - > next ; node ! = used_nodes ; node = node - > next ) {
Editing_File * file_ptr = ( Editing_File * ) node ;
if ( file_is_ready ( file_ptr ) & & match ( base_name , file_ptr - > base_name . name ) ) {
Editing_File * * new_file_ptr = push_array ( scratch , Editing_File * , 1 ) ;
* new_file_ptr = file_ptr ;
+ + conflict_count ;
}
}
// Fill conflict array.
Buffer_Name_Conflict_Entry * conflicts = push_array ( scratch , Buffer_Name_Conflict_Entry , conflict_count ) ;
for ( int32_t i = 0 ; i < conflict_count ; + + i ) {
Editing_File * file_ptr = conflict_file_ptrs [ i ] ;
Buffer_Name_Conflict_Entry * entry = & conflicts [ i ] ;
entry - > buffer_id = file_ptr - > id . id ;
String file_name = push_string ( scratch , file_ptr - > canon . name ) ;
entry - > file_name = file_name . str ;
entry - > file_name_len = file_name . size ;
String term_base_name = push_string ( scratch , base_name ) ;
entry - > base_name = term_base_name . str ;
entry - > base_name_len = term_base_name . size ;
String b = base_name ;
if ( i > 0 ) {
b = file_ptr - > unique_name . name ;
}
i32 unique_name_capacity = 256 ;
String unique_name = push_string ( scratch , b , unique_name_capacity ) ;
entry - > unique_name_in_out = unique_name . str ;
entry - > unique_name_len_in_out = unique_name . size ;
entry - > unique_name_capacity = unique_name_capacity ;
}
// Get user's resolution data.
if ( models - > buffer_name_resolver ! = 0 ) {
models - > buffer_name_resolver ( & models - > app_links , conflicts , conflict_count ) ;
}
// Re-bind all of the files
for ( int32_t i = 0 ; i < conflict_count ; + + i ) {
Editing_File * file_ptr = conflict_file_ptrs [ i ] ;
if ( file_ptr - > unique_name . name . str ! = 0 ) {
buffer_unbind_name_low_level ( working_set , file_ptr ) ;
}
}
for ( int32_t i = 0 ; i < conflict_count ; + + i ) {
Editing_File * file_ptr = conflict_file_ptrs [ i ] ;
Buffer_Name_Conflict_Entry * entry = & conflicts [ i ] ;
String unique_name = make_string ( entry - > unique_name_in_out , entry - > unique_name_len_in_out ) ;
2018-08-18 08:16:52 +00:00
buffer_bind_name_low_level ( heap , working_set , file_ptr , base_name , unique_name ) ;
2018-03-25 06:43:56 +00:00
}
end_temp_memory ( temp ) ;
}
////////////////////////////////
internal Editing_File *
open_file ( System_Functions * system , Models * models , String filename ) {
Editing_File * file = 0 ;
2018-11-20 08:18:54 +00:00
Editing_File_Name canon_name = { } ;
2018-03-25 06:43:56 +00:00
if ( terminate_with_null ( & filename ) & &
get_canon_name ( system , filename , & canon_name ) ) {
Working_Set * working_set = & models - > working_set ;
file = working_set_contains_canon ( working_set , canon_name . name ) ;
if ( file = = 0 ) {
Plat_Handle handle ;
if ( system - > load_handle ( canon_name . name . str , & handle ) ) {
Mem_Options * mem = & models - > mem ;
2018-08-18 08:16:52 +00:00
Heap * heap = & mem - > heap ;
2018-03-25 06:43:56 +00:00
Partition * part = & mem - > part ;
2018-08-18 08:16:52 +00:00
file = working_set_alloc_always ( working_set , heap , & models - > lifetime_allocator ) ;
buffer_bind_file ( system , heap , working_set , file , canon_name . name ) ;
buffer_bind_name ( models , heap , part , working_set , file , front_of_directory ( filename ) ) ;
2018-03-25 06:43:56 +00:00
Temp_Memory temp = begin_temp_memory ( part ) ;
2018-06-09 04:52:25 +00:00
i32 size = system - > load_size ( handle ) ;
char * buffer = push_array ( part , char , size ) ;
b32 gen_buffer = false ;
2018-03-25 06:43:56 +00:00
if ( buffer = = 0 ) {
2018-08-18 08:16:52 +00:00
buffer = heap_array ( heap , char , size ) ;
2018-06-09 04:52:25 +00:00
Assert ( buffer ! = 0 ) ;
gen_buffer = true ;
2018-03-25 06:43:56 +00:00
}
2018-06-09 04:52:25 +00:00
b32 good_load = system - > load_file ( handle , buffer , size ) ;
system - > load_close ( handle ) ;
if ( good_load ) {
2018-03-25 06:43:56 +00:00
init_normal_file ( system , models , buffer , size , file ) ;
}
if ( gen_buffer ) {
2018-08-18 08:16:52 +00:00
heap_free ( heap , buffer ) ;
2018-03-25 06:43:56 +00:00
}
end_temp_memory ( temp ) ;
}
}
}
return ( file ) ;
}
2016-02-21 17:44:23 +00:00
// BOTTOM