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
*
2017-01-03 20:05:35 +00:00
* Working_Set data structure for 4 coder
2016-02-21 17:44:23 +00:00
*
*/
// TOP
2017-01-03 20:05:35 +00:00
//
// Working_Set of files
//
2016-02-21 17:44:23 +00:00
2016-03-11 21:54:32 +00:00
struct Non_File_Table_Entry {
String name ;
2016-05-19 18:01:36 +00:00
Buffer_Slot_ID id ;
2016-03-11 21:54:32 +00:00
} ;
2016-03-08 23:06:27 +00:00
struct File_Array {
Editing_File * files ;
i32 size ;
} ;
2016-02-21 17:44:23 +00:00
struct Working_Set {
2016-03-08 23:06:27 +00:00
File_Array * file_arrays ;
2016-03-05 04:10:55 +00:00
i32 file_count , file_max ;
2016-03-08 23:06:27 +00:00
i16 array_count , array_max ;
2017-01-03 20:05:35 +00:00
File_Node free_sentinel ;
2016-03-04 21:26:00 +00:00
File_Node used_sentinel ;
2016-02-21 17:44:23 +00:00
2016-08-26 17:52:35 +00:00
Table canon_table ;
2016-08-24 14:36:29 +00:00
Table name_table ;
2016-02-21 17:44:23 +00:00
2017-01-03 20:05:35 +00:00
String clipboards [ 64 ] ;
i32 clipboard_size , clipboard_max_size ;
i32 clipboard_current , clipboard_rolling ;
2016-05-19 18:01:36 +00:00
2017-02-24 02:30:29 +00:00
//u64 unique_file_counter;
2016-07-20 16:16:02 +00:00
File_Node * sync_check_iter ;
2016-09-22 00:01:12 +00:00
i32 default_display_width ;
2016-10-24 23:02:10 +00:00
i32 default_minimum_base_display_width ;
2016-02-21 17:44:23 +00:00
} ;
2016-08-24 14:36:29 +00:00
struct File_Name_Entry {
String name ;
Buffer_Slot_ID id ;
} ;
2017-01-03 20:05:35 +00:00
2016-08-24 14:36:29 +00:00
internal i32
tbl_name_compare ( void * a , void * b , void * arg ) {
String * fa = ( String * ) a ;
File_Name_Entry * fb = ( File_Name_Entry * ) b ;
i32 result = 1 ;
2016-08-28 04:31:06 +00:00
if ( match_ss ( * fa , fb - > name ) ) {
2016-08-24 14:36:29 +00:00
result = 0 ;
}
return ( result ) ;
}
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 ;
2017-03-11 18:53:48 +00:00
Buffer_Slot_ID id = { 0 } ;
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 *
working_set_alloc ( Working_Set * working_set ) {
Editing_File * result = 0 ;
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 ;
2017-01-03 20:05:35 +00:00
* result = null_editing_file ;
2016-03-08 23:06:27 +00:00
result - > id = id ;
2017-02-24 02:30:29 +00:00
//result->unique_buffer_id = ++working_set->unique_file_counter;
2016-03-08 23:06:27 +00:00
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 ;
2017-02-24 02:30:29 +00:00
init_file_markers_state ( & result - > markers ) ;
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
}
internal Editing_File *
2017-01-14 03:01:35 +00:00
working_set_alloc_always ( Working_Set * working_set , General_Memory * general ) {
2016-03-08 23:06:27 +00:00
Editing_File * result = 0 ;
2017-02-24 02:30:29 +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 ) ;
Editing_File * new_chunk = gen_array ( general , Editing_File , new_count ) ;
2016-03-08 23:06:27 +00:00
working_set_extend_memory ( working_set , new_chunk , new_count ) ;
}
result = working_set_alloc ( working_set ) ;
return ( result ) ;
}
inline void
2017-02-24 02:30:29 +00:00
working_set_free_file ( General_Memory * general , 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 ;
}
2016-05-29 22:01:27 +00:00
file - > is_dummy = 1 ;
2017-02-24 02:30:29 +00:00
clear_file_markers_state ( general , & file - > markers ) ;
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 ) ;
2016-05-29 22:01:27 +00:00
if ( result & & 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 ) {
Editing_File * result ;
result = working_set_get_active_file ( working_set , to_file_id ( id ) ) ;
return ( result ) ;
}
2016-03-11 03:33:19 +00:00
internal void
2017-01-14 03:01:35 +00:00
working_set_init ( Working_Set * working_set , Partition * partition , General_Memory * general ) {
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 ) ;
2017-01-14 03:01:35 +00:00
void * mem = general_memory_allocate ( general , 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 ) ;
2017-01-14 03:01:35 +00:00
void * mem = general_memory_allocate ( general , 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
2017-01-14 03:01:35 +00:00
working_set__grow_if_needed ( Table * table , General_Memory * general , void * arg , Hash_Function * hash_func , Compare_Function * comp_func ) {
2016-03-15 14:12:06 +00:00
if ( table_at_capacity ( table ) ) {
2016-08-24 14:36:29 +00:00
Table btable = { 0 } ;
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 ) ;
2017-01-14 03:01:35 +00:00
void * mem = general_memory_allocate ( general , 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 ) ;
2017-01-14 03:01:35 +00:00
general_memory_free ( general , 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
2017-01-14 03:01:35 +00:00
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 ) ;
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
2017-01-14 03:01:35 +00:00
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 ) ;
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
2017-11-30 23:25:49 +00:00
working_set_add_name ( General_Memory * general , Working_Set * working_set , Editing_File * file , String name ) {
2017-01-14 03:01:35 +00:00
b32 result = working_set_add_basic ( general , 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 ;
{
2016-08-24 14:36:29 +00:00
// TODO(allen): use the name table for this
2016-03-08 23:06:27 +00:00
File_Node * node , * used_nodes ;
used_nodes = & working_set - > used_sentinel ;
for ( dll_items ( node , used_nodes ) ) {
file = ( Editing_File * ) node ;
2017-11-30 23:25:49 +00:00
if ( string . size = = 0 | | match_ss ( string , file - > name . name ) ) {
2016-03-08 23:06:27 +00:00
break ;
}
}
if ( node = = used_nodes ) file = 0 ;
}
2017-01-03 20:05:35 +00:00
if ( ! file ) {
2016-03-08 23:06:27 +00:00
File_Node * node , * used_nodes ;
used_nodes = & working_set - > used_sentinel ;
for ( dll_items ( node , used_nodes ) ) {
file = ( Editing_File * ) node ;
2017-11-30 23:25:49 +00:00
if ( string . size = = 0 | | has_substr_s ( file - > name . name , string ) ) {
2016-03-08 23:06:27 +00:00
break ;
}
}
if ( node = = used_nodes ) file = 0 ;
2017-01-03 20:05:35 +00:00
}
2016-03-08 23:06:27 +00:00
2017-01-03 20:05:35 +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 ) {
2016-05-29 20:50:07 +00:00
if ( file ) {
2016-05-29 22:01:27 +00:00
Assert ( ! file - > is_dummy ) ;
2016-05-29 20:50:07 +00:00
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
2016-07-20 15:19:54 +00:00
2017-01-03 20:05:35 +00:00
//
// Name Binding
//
2016-07-02 22:59:16 +00:00
2016-08-24 14:36:29 +00:00
internal void
editing_file_name_init ( Editing_File_Name * name ) {
2017-11-30 23:25:49 +00:00
name - > name = make_fixed_width_string ( name - > name_ ) ;
2016-08-24 14:36:29 +00:00
}
2016-08-26 17:52:35 +00:00
internal b32
2017-11-30 23:25:49 +00:00
get_canon_name ( System_Functions * system , Editing_File_Name * canon_name , String filename ) {
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
2017-01-03 20:05:35 +00:00
buffer_bind_file ( System_Functions * system , General_Memory * general , Working_Set * working_set , Editing_File * file , String canon_filename ) {
2017-11-30 23:25:49 +00:00
Assert ( file - > 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_ ) ;
2016-08-28 04:31:06 +00:00
copy_ss ( & 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 ) ;
b32 result = working_set_canon_add ( general , working_set , file , file - > canon . name ) ;
2016-08-26 17:52:35 +00:00
Assert ( result ) ; AllowLocal ( result ) ;
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-11-30 23:25:49 +00:00
Assert ( file - > 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 ) {
Editing_File * file_ptr = ( Editing_File * ) node ;
if ( file_is_ready ( file_ptr ) & & match_ss ( base_name , file_ptr - > name . name ) ) {
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 ) ;
copy_ss ( & name - > name , base_name ) ;
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 ;
append_ss ( & name - > name , make_lit_string ( " ## " ) ) ;
append_int_to_str ( & name - > name , file_x ) ;
}
}
}
internal void
buffer_bind_name_low_level ( General_Memory * general , Working_Set * working_set , Editing_File * file , String name ) {
Assert ( file - > name . name . size = = 0 ) ;
2016-08-24 14:36:29 +00:00
2017-11-30 23:25:49 +00:00
Editing_File_Name new_name = { 0 } ;
2016-08-24 14:36:29 +00:00
editing_file_name_init ( & new_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
editing_file_name_init ( & file - > name ) ;
2017-11-30 23:25:49 +00:00
copy_ss ( & file - > name . name , new_name . name ) ;
2016-08-24 14:36:29 +00:00
2017-11-30 23:25:49 +00:00
b32 result = working_set_add_name ( general , working_set , file , file - > name . name ) ;
2016-08-26 17:52:35 +00:00
Assert ( result ) ; AllowLocal ( result ) ;
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 ) {
Assert ( file - > name . name . size ! = 0 ) ;
working_set_remove_name ( working_set , file - > name . name ) ;
file - > name . name . size = 0 ;
2016-08-24 14:36:29 +00:00
}
2016-02-21 17:44:23 +00:00
// BOTTOM