word complete v1 again

This commit is contained in:
Allen Webster 2016-02-20 13:23:46 -05:00
parent 5619527d37
commit 770c48f95b
15 changed files with 3204 additions and 2334 deletions

View File

@ -174,6 +174,16 @@ CUSTOM_COMMAND_SIG(write_and_auto_tab){
exec_command(cmd_context, cmdid_auto_tab_line_at_cursor); exec_command(cmd_context, cmdid_auto_tab_line_at_cursor);
} }
// NOTE(allen|a3.4): How one might go about writing things like cut_line
// same idea works for cut word and other such composite commands.
CUSTOM_COMMAND_SIG(cut_line){
exec_command(cmd_context, cmdid_seek_beginning_of_line);
exec_command(cmd_context, cmdid_set_mark);
exec_command(cmd_context, cmdid_seek_end_of_line);
exec_command(cmd_context, cmdid_cut);
exec_command(cmd_context, cmdid_delete);
}
extern "C" GET_BINDING_DATA(get_bindings){ extern "C" GET_BINDING_DATA(get_bindings){
Bind_Helper context_actual = begin_bind_helper(data, size); Bind_Helper context_actual = begin_bind_helper(data, size);
Bind_Helper *context = &context_actual; Bind_Helper *context = &context_actual;

View File

@ -36,6 +36,11 @@ struct String{
int size; int size;
int memory_size; int memory_size;
}; };
struct Offset_String{
int offset;
int size;
};
#endif #endif
inline bool char_not_slash(char c) { return (c != '\\' && c != '/'); } inline bool char_not_slash(char c) { return (c != '\\' && c != '/'); }

176
4ed.cpp
View File

@ -38,6 +38,14 @@ struct Sys_App_Binding{
i32 app_id; i32 app_id;
}; };
struct Complete_State{
Search_Set set;
Search_Iter iter;
Table hits;
String_Space str;
i32 word_start, word_end;
};
struct App_Vars{ struct App_Vars{
Mem_Options mem; Mem_Options mem;
@ -52,6 +60,7 @@ struct App_Vars{
Command_Map *user_maps; Command_Map *user_maps;
i32 *map_id_table; i32 *map_id_table;
i32 user_map_count; i32 user_map_count;
Command_Binding prev_command;
Sys_App_Binding *sys_app_bindings; Sys_App_Binding *sys_app_bindings;
i32 sys_app_count, sys_app_max; i32 sys_app_count, sys_app_max;
@ -84,6 +93,7 @@ struct App_Vars{
App_State state; App_State state;
App_State_Resizing resizing; App_State_Resizing resizing;
Complete_State complete_state;
Panel *prev_mouse_panel; Panel *prev_mouse_panel;
Custom_API config_api; Custom_API config_api;
@ -442,70 +452,143 @@ COMMAND_DECL(word_complete){
REQ_FILE(file, view); REQ_FILE(file, view);
USE_LAYOUT(layout); USE_LAYOUT(layout);
USE_MEM(mem); USE_MEM(mem);
USE_VARS(vars);
USE_WORKING_SET(working_set);
Partition *part = &mem->part; Partition *part = &mem->part;
General_Memory *general = &mem->general;
Complete_State *complete_state = &vars->complete_state;
Search_Range *ranges;
Search_Match match;
Temp_Memory temp1, temp2; Temp_Memory temp;
Buffer_Type *buffer; Buffer_Type *buffer;
Buffer_Backify_Type loop; Buffer_Backify_Type loop;
char *data; char *data;
i32 end; i32 end;
i32 size_of_buffer;
i32 cursor_pos, word_start, word_end; i32 cursor_pos, word_start, word_end;
char c; char c;
char *str, *spare; char *spare;
i32 size; i32 size;
i32 match_start, match_end, match_size; i32 buffer_count, i, j;
Editing_File *file_ptr;
i32 match_size;
b32 do_init = 0;
buffer = &file->state.buffer; buffer = &file->state.buffer;
word_end = view->cursor.pos; size_of_buffer = buffer_size(buffer);
word_start = word_end;
cursor_pos = word_end - 1;
// TODO(allen): macros for these buffer loops and some method of breaking out of them. if (vars->prev_command.function != command_word_complete){
for (loop = buffer_backify_loop(buffer, cursor_pos, 0); do_init = 1;
buffer_backify_good(&loop); }
buffer_backify_next(&loop)){
end = loop.absolute_pos; if (do_init){
data = loop.data - loop.absolute_pos; word_end = view->cursor.pos;
for (; cursor_pos >= end; --cursor_pos){ word_start = word_end;
c = data[cursor_pos]; cursor_pos = word_end - 1;
if (char_is_alpha(c)){
word_start = cursor_pos; // TODO(allen): macros for these buffer loops and some method of breaking out of them.
} for (loop = buffer_backify_loop(buffer, cursor_pos, 0);
else if (!char_is_numeric(c)){ buffer_backify_good(&loop);
goto double_break; buffer_backify_next(&loop)){
end = loop.absolute_pos;
data = loop.data - loop.absolute_pos;
for (; cursor_pos >= end; --cursor_pos){
c = data[cursor_pos];
if (char_is_alpha(c)){
word_start = cursor_pos;
}
else if (!char_is_numeric(c)){
goto double_break;
}
} }
} }
// TODO(allen): figure out how labels are scoped.
double_break:;
size = word_end - word_start;
search_iter_init(general, &complete_state->iter, size);
buffer_stringify(buffer, word_start, word_end, complete_state->iter.word.str);
complete_state->iter.word.size = size;
buffer_count = working_set->file_index_count;
search_set_init(general, &complete_state->set, buffer_count + 1);
ranges = complete_state->set.ranges;
ranges[0].buffer = buffer;
ranges[0].start = 0;
ranges[0].size = word_start;
ranges[1].buffer = buffer;
ranges[1].start = word_end;
ranges[1].size = size_of_buffer - word_end;
file_ptr = working_set->files;
for (i = 0, j = 2; i < buffer_count; ++i, ++file_ptr){
if (file_ptr != file && !file_ptr->state.is_dummy && file_is_ready(file_ptr)){
ranges[j].buffer = &file_ptr->state.buffer;
ranges[j].start = 0;
ranges[j].size = buffer_size(ranges[j].buffer);
++j;
}
}
complete_state->set.count = j;
search_hits_init(general, &complete_state->hits, &complete_state->str, 100, Kbytes(4));
search_hit_add(general, &complete_state->hits, &complete_state->str,
complete_state->iter.word.str, complete_state->iter.word.size);
complete_state->word_start = word_start;
complete_state->word_end = word_end;
} }
// TODO(allen): figure out how labels are scoped. else{
double_break:; word_start = complete_state->word_start;
word_end = complete_state->word_end;
size = word_end - word_start; size = complete_state->iter.word.size;
}
if (size > 0){ if (size > 0){
temp1 = begin_temp_memory(part); for (;;){
match = search_next_match(part, &complete_state->set, &complete_state->iter);
str = (char*)push_array(part, char, size);
buffer_stringify(buffer, word_start, word_end, str); if (match.found_match){
temp = begin_temp_memory(part);
temp2 = begin_temp_memory(part); match_size = match.end - match.start;
spare = (char*)push_array(part, char, size); spare = (char*)push_array(part, char, match_size);
end_temp_memory(temp2); buffer_stringify(match.buffer, match.start, match.end, spare);
// TODO(allen): find string needs explicit end position if (search_hit_add(general, &complete_state->hits, &complete_state->str, spare, match_size)){
match_start = buffer_find_string(buffer, word_end, str, size, spare); view_replace_range(system, mem, view, layout, word_start, word_end, spare, match_size, word_end);
match_end = buffer_seek_word_right_assume_on_word(buffer, match_start);
match_size = match_end - match_start; complete_state->word_end = word_start + match_size;
spare = (char*)push_array(part, char, match_size); complete_state->set.ranges[1].start = word_start + match_size;
buffer_stringify(buffer, match_start, match_end, spare); break;
}
view_replace_range(system, mem, view, layout, word_start, word_end, spare, match_size, word_end); end_temp_memory(temp);
}
end_temp_memory(temp1); else{
complete_state->iter.pos = 0;
complete_state->iter.i = 0;
search_hits_init(general, &complete_state->hits, &complete_state->str, 100, Kbytes(4));
search_hit_add(general, &complete_state->hits, &complete_state->str,
complete_state->iter.word.str, complete_state->iter.word.size);
match_size = complete_state->iter.word.size;
view_replace_range(system, mem, view, layout, word_start, word_end,
complete_state->iter.word.str, match_size, word_end);
complete_state->word_end = word_start + match_size;
complete_state->set.ranges[1].start = word_start + match_size;
break;
}
}
} }
} }
@ -2159,11 +2242,11 @@ setup_file_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Co
map_add(commands, 'l', MDFR_CTRL, command_toggle_line_wrap); map_add(commands, 'l', MDFR_CTRL, command_toggle_line_wrap);
map_add(commands, '?', MDFR_CTRL, command_toggle_show_whitespace); map_add(commands, '?', MDFR_CTRL, command_toggle_show_whitespace);
map_add(commands, '|', MDFR_CTRL, command_toggle_tokens); map_add(commands, '|', MDFR_CTRL, command_toggle_tokens);
map_add(commands, 'U', MDFR_CTRL, command_to_uppercase); map_add(commands, 'u', MDFR_CTRL, command_to_uppercase);
map_add(commands, 'u', MDFR_CTRL, command_to_lowercase); map_add(commands, 'j', MDFR_CTRL, command_to_lowercase);
map_add(commands, '~', MDFR_CTRL, command_clean_all_lines); map_add(commands, '~', MDFR_CTRL, command_clean_all_lines);
map_add(commands, 'f', MDFR_CTRL, command_search); map_add(commands, 'f', MDFR_CTRL, command_search);
map_add(commands, 'j', MDFR_CTRL, command_word_complete); map_add(commands, 't', MDFR_CTRL, command_word_complete);
map_add(commands, 'r', MDFR_CTRL, command_rsearch); map_add(commands, 'r', MDFR_CTRL, command_rsearch);
map_add(commands, 'g', MDFR_CTRL, command_goto_line); map_add(commands, 'g', MDFR_CTRL, command_goto_line);
@ -3462,6 +3545,7 @@ App_Step_Sig(app_step){
app_result.redraw = 1; app_result.redraw = 1;
} }
} }
vars->prev_command = cmd;
}break; }break;
case APP_STATE_RESIZING: case APP_STATE_RESIZING:

31
4ed.h
View File

@ -90,37 +90,6 @@ struct Clipboard_Contents{
i32 size; i32 size;
}; };
#define FileNameMax (1 << 9)
struct File_Slot{
File_Slot *next, *prev;
byte *data;
i32 size, max;
char *filename;
i32 filename_len;
u32 flags;
};
enum File_Exchange_Flag{
FEx_Request = 0x1,
FEx_Ready = 0x2,
FEx_Not_Exist = 0x4,
FEx_Save = 0x8,
FEx_Save_Complete = 0x10,
FEx_Save_Failed = 0x20
};
struct File_Exchange{
File_Slot available, active, free_list;
File_Slot *files;
i32 num_active, max;
};
struct Exchange{
Thread_Exchange thread;
File_Exchange file;
};
struct Command_Line_Parameters{ struct Command_Line_Parameters{
char **argv; char **argv;
int argc; int argc;

View File

@ -29,6 +29,8 @@
#include "4ed_internal.h" #include "4ed_internal.h"
#include "4tech_table.cpp"
#define FCPP_LEXER_IMPLEMENTATION #define FCPP_LEXER_IMPLEMENTATION
#include "4cpp_lexer.h" #include "4cpp_lexer.h"

View File

@ -4613,13 +4613,13 @@ HANDLE_COMMAND_SIG(handle_command_file_view){
} }
else{ else{
pos = buffer_find_string(&file->state.buffer, start_pos + 1, pos = buffer_find_string(&file->state.buffer, start_pos + 1, size,
string->str, string->size, spare); string->str, string->size, spare);
if (pos < size){ if (pos < size){
if (step_forward){ if (step_forward){
file_view->isearch.pos = pos; file_view->isearch.pos = pos;
start_pos = pos; start_pos = pos;
pos = buffer_find_string(&file->state.buffer, start_pos + 1, pos = buffer_find_string(&file->state.buffer, start_pos + 1, size,
string->str, string->size, spare); string->str, string->size, spare);
if (pos == size) pos = start_pos; if (pos == size) pos = start_pos;
} }
@ -4765,5 +4765,200 @@ file_view_iter_good(File_View_Iter iter){
return(result); return(result);
} }
struct Search_Range{
Buffer_Type *buffer;
i32 start, size;
};
struct Search_Set{
Search_Range *ranges;
i32 count, max;
};
struct Search_Iter{
String word;
i32 pos;
i32 i;
};
struct Search_Match{
Buffer_Type *buffer;
i32 start, end;
b32 found_match;
};
internal void
search_iter_init(General_Memory *general, Search_Iter *iter, i32 size){
i32 str_max;
if (iter->word.str == 0){
str_max = size*2;
iter->word.str = (char*)general_memory_allocate(general, str_max, 0);
iter->word.memory_size = str_max;
}
else if (iter->word.memory_size < size){
str_max = size*2;
iter->word.str = (char*)general_memory_reallocate_nocopy(general, iter->word.str, str_max, 0);
iter->word.memory_size = str_max;
}
iter->i = 0;
iter->pos = 0;
}
internal void
search_set_init(General_Memory *general, Search_Set *set, i32 set_count){
i32 max;
if (set->ranges == 0){
max = set_count*2;
set->ranges = (Search_Range*)general_memory_allocate(general, sizeof(Search_Range)*max, 0);
set->max = max;
}
else if (set->max < set_count){
max = set_count*2;
set->ranges = (Search_Range*)general_memory_reallocate_nocopy(
general, set->ranges, sizeof(Search_Range)*max, 0);
set->max = max;
}
set->count = set_count;
}
internal void
search_hits_table_alloc(General_Memory *general, Table *hits, i32 table_size){
i32 hash_size, mem_size;
hash_size = table_size * sizeof(u32);
hash_size = (hash_size + 7) & ~7;
mem_size = hash_size + table_size * sizeof(Offset_String);
hits->hash_array = (u32*)general_memory_allocate(general, mem_size, 0);
hits->data_array = (u8*)hits->hash_array + hash_size;
hits->max = table_size;
hits->item_size = sizeof(Offset_String);
}
internal void
search_hits_init(General_Memory *general, Table *hits, String_Space *str, i32 table_size, i32 str_size){
i32 hash_size, mem_size;
if (hits->hash_array == 0){
search_hits_table_alloc(general, hits, table_size);
}
else if (hits->max < table_size){
hash_size = table_size * sizeof(u32);
hash_size = (hash_size + 7) & ~7;
mem_size = hash_size + table_size * sizeof(Offset_String);
hits->hash_array = (u32*)general_memory_reallocate_nocopy(
general, hits->hash_array, mem_size, 0);
hits->data_array = (u8*)hits->hash_array + hash_size;
hits->max = table_size;
hits->item_size = sizeof(Offset_String);
}
if (str->space == 0){
str->space = (char*)general_memory_allocate(general, str_size, 0);
str->max = str_size;
}
else if (str->max < str_size){
str->space = (char*)general_memory_reallocate_nocopy(general, str->space, str_size, 0);
str->max = str_size;
}
str->pos = str->new_pos = 0;
table_clear(hits);
}
internal b32
search_hit_add(General_Memory *general, Table *hits, String_Space *space, char *str, i32 len){
b32 result;
i32 new_size;
Offset_String ostring;
Table new_hits;
Assert(len != 0);
ostring = strspace_append(space, str, len);
if (ostring.size == 0){
new_size = Max(space->max*2, space->max + len);
space->space = (char*)general_memory_reallocate(general, space->space, space->new_pos, new_size, 0);
ostring = strspace_append(space, str, len);
}
Assert(ostring.size != 0);
if (table_at_capacity(hits)){
search_hits_table_alloc(general, &new_hits, hits->max*2);
table_clear(&new_hits);
table_rehash(hits, &new_hits, space->space, tbl_offset_string_hash, tbl_offset_string_compare);
general_memory_free(general, hits->hash_array);
*hits = new_hits;
}
if (!table_add(hits, &ostring, space->space, tbl_offset_string_hash, tbl_offset_string_compare)){
result = 1;
strspace_keep_prev(space);
}
else{
result = 0;
strspace_discard_prev(space);
}
return(result);
}
internal Search_Match
search_next_match(Partition *part, Search_Set *set, Search_Iter *iter_){
Search_Match result = {};
Search_Iter iter = *iter_;
Search_Range *range;
Temp_Memory temp;
char *spare;
i32 start_pos, end_pos, count;
temp = begin_temp_memory(part);
spare = push_array(part, char, iter.word.size);
count = set->count;
for (; iter.i < count;){
range = set->ranges + iter.i;
end_pos = range->start + range->size;
if (iter.pos + iter.word.size < end_pos){
start_pos = Max(iter.pos, range->start);
result.start = buffer_find_string(range->buffer, start_pos, end_pos, iter.word.str, iter.word.size, spare);
if (result.start < end_pos){
iter.pos = result.start + 1;
if (result.start == 0 || !char_is_alpha_numeric(buffer_get_char(range->buffer, result.start - 1))){
result.end = buffer_seek_word_right_assume_on_word(range->buffer, result.start);
if (result.end < end_pos){
result.found_match = 1;
result.buffer = range->buffer;
iter.pos = result.end;
break;
}
}
}
else{
++iter.i, iter.pos = 0;
}
}
else{
++iter.i, iter.pos = 0;
}
}
end_temp_memory(temp);
*iter_ = iter;
return(result);
}
// BOTTOM // BOTTOM

View File

@ -1,253 +1,255 @@
/* /*
* Mr. 4th Dimention - Allen Webster * Mr. 4th Dimention - Allen Webster
* *
* 13.11.2015 * 13.11.2015
* *
* Memory utils for 4coder * Memory utils for 4coder
* *
*/ */
// TOP // TOP
struct Partition{ struct Partition{
u8 *base; u8 *base;
i32 pos, max; i32 pos, max;
}; };
struct Temp_Memory{ struct Temp_Memory{
void *handle; void *handle;
int pos; int pos;
}; };
enum Memory_Bubble_Flag{ enum Memory_Bubble_Flag{
MEM_BUBBLE_USED = 0x1, MEM_BUBBLE_USED = 0x1,
MEM_BUBBLE_DEBUG = 0xD3000000, MEM_BUBBLE_DEBUG = 0xD3000000,
MEM_BUBBLE_SYS_DEBUG = 0x5D000000, MEM_BUBBLE_SYS_DEBUG = 0x5D000000,
MEM_BUBBLE_DEBUG_MASK = 0xFF000000 MEM_BUBBLE_DEBUG_MASK = 0xFF000000
}; };
struct Bubble{ struct Bubble{
Bubble *prev; Bubble *prev;
Bubble *next; Bubble *next;
u32 flags; u32 flags;
i32 size; i32 size;
u32 type; u32 type;
u32 _unused_; u32 _unused_;
}; };
struct General_Memory{ struct General_Memory{
Bubble sentinel; Bubble sentinel;
}; };
struct Mem_Options{ struct Mem_Options{
Partition part; Partition part;
General_Memory general; General_Memory general;
}; };
inline Partition inline Partition
partition_open(void *memory, i32 size){ partition_open(void *memory, i32 size){
Partition partition; Partition partition;
partition.base = (u8*)memory; partition.base = (u8*)memory;
partition.pos = 0; partition.pos = 0;
partition.max = size; partition.max = size;
return partition; return partition;
} }
inline void* inline void*
partition_allocate(Partition *data, i32 size){ partition_allocate(Partition *data, i32 size){
void *ret = 0; void *ret = 0;
if (size > 0 && data->pos + size <= data->max){ if (size > 0 && data->pos + size <= data->max){
ret = data->base + data->pos; ret = data->base + data->pos;
data->pos += size; data->pos += size;
} }
return ret; return ret;
} }
inline void inline void
partition_align(Partition *data, u32 boundary){ partition_align(Partition *data, u32 boundary){
data->pos = (data->pos + (boundary - 1)) & (~boundary); data->pos = (data->pos + (boundary - 1)) & (~boundary);
} }
inline void* inline void*
partition_current(Partition *data){ partition_current(Partition *data){
return data->base + data->pos; return data->base + data->pos;
} }
inline i32 inline i32
partition_remaining(Partition *data){ partition_remaining(Partition *data){
return data->max - data->pos; return data->max - data->pos;
} }
inline Partition inline Partition
partition_sub_part(Partition *data, i32 size){ partition_sub_part(Partition *data, i32 size){
Partition result = {}; Partition result = {};
void *d = partition_allocate(data, size); void *d = partition_allocate(data, size);
if (d) result = partition_open(d, size); if (d) result = partition_open(d, size);
return result; return result;
} }
#define push_struct(part, T) (T*)partition_allocate(part, sizeof(T)) #define push_struct(part, T) (T*)partition_allocate(part, sizeof(T))
#define push_array(part, T, size) (T*)partition_allocate(part, sizeof(T)*(size)) #define push_array(part, T, size) (T*)partition_allocate(part, sizeof(T)*(size))
#define push_block(part, size) partition_allocate(part, size) #define push_block(part, size) partition_allocate(part, size)
inline void inline void
insert_bubble(Bubble *prev, Bubble *bubble){ insert_bubble(Bubble *prev, Bubble *bubble){
bubble->prev = prev; bubble->prev = prev;
bubble->next = prev->next; bubble->next = prev->next;
bubble->prev->next = bubble; bubble->prev->next = bubble;
bubble->next->prev = bubble; bubble->next->prev = bubble;
} }
inline void inline void
remove_bubble(Bubble *bubble){ remove_bubble(Bubble *bubble){
bubble->prev->next = bubble->next; bubble->prev->next = bubble->next;
bubble->next->prev = bubble->prev; bubble->next->prev = bubble->prev;
} }
#if FRED_INTERNAL #if FRED_INTERNAL
#define MEM_BUBBLE_FLAG_INIT MEM_BUBBLE_DEBUG #define MEM_BUBBLE_FLAG_INIT MEM_BUBBLE_DEBUG
#else #else
#define MEM_BUBBLE_FLAG_INIT 0 #define MEM_BUBBLE_FLAG_INIT 0
#endif #endif
internal void internal void
general_memory_open(General_Memory *general, void *memory, i32 size){ general_memory_open(General_Memory *general, void *memory, i32 size){
general->sentinel.prev = &general->sentinel; general->sentinel.prev = &general->sentinel;
general->sentinel.next = &general->sentinel; general->sentinel.next = &general->sentinel;
general->sentinel.flags = MEM_BUBBLE_USED; general->sentinel.flags = MEM_BUBBLE_USED;
general->sentinel.size = 0; general->sentinel.size = 0;
Bubble *first = (Bubble*)memory; Bubble *first = (Bubble*)memory;
first->flags = (u32)MEM_BUBBLE_FLAG_INIT; first->flags = (u32)MEM_BUBBLE_FLAG_INIT;
first->size = size - sizeof(Bubble); first->size = size - sizeof(Bubble);
insert_bubble(&general->sentinel, first); insert_bubble(&general->sentinel, first);
} }
internal void internal void
general_memory_check(General_Memory *general){ general_memory_check(General_Memory *general){
Bubble *sentinel = &general->sentinel; Bubble *sentinel = &general->sentinel;
for (Bubble *bubble = sentinel->next; for (Bubble *bubble = sentinel->next;
bubble != sentinel; bubble != sentinel;
bubble = bubble->next){ bubble = bubble->next){
Assert(bubble); Assert(bubble);
Bubble *next = bubble->next; Bubble *next = bubble->next;
Assert(bubble == next->prev); Assert(bubble == next->prev);
if (next != sentinel){ if (next != sentinel){
Assert(bubble->next > bubble); Assert(bubble->next > bubble);
Assert(bubble > bubble->prev); Assert(bubble > bubble->prev);
char *end_ptr = (char*)(bubble + 1) + bubble->size; char *end_ptr = (char*)(bubble + 1) + bubble->size;
char *next_ptr = (char*)next; char *next_ptr = (char*)next;
AllowLocal(end_ptr); AllowLocal(end_ptr);
AllowLocal(next_ptr); AllowLocal(next_ptr);
Assert(end_ptr == next_ptr); Assert(end_ptr == next_ptr);
} }
} }
} }
#define BUBBLE_MIN_SIZE 1024 #define BUBBLE_MIN_SIZE 1024
internal void internal void
general_memory_attempt_split(Bubble *bubble, i32 wanted_size){ general_memory_attempt_split(Bubble *bubble, i32 wanted_size){
i32 remaining_size = bubble->size - wanted_size; i32 remaining_size = bubble->size - wanted_size;
if (remaining_size >= BUBBLE_MIN_SIZE){ if (remaining_size >= BUBBLE_MIN_SIZE){
bubble->size = wanted_size; bubble->size = wanted_size;
Bubble *new_bubble = (Bubble*)((u8*)(bubble + 1) + wanted_size); Bubble *new_bubble = (Bubble*)((u8*)(bubble + 1) + wanted_size);
new_bubble->flags = (u32)MEM_BUBBLE_FLAG_INIT; new_bubble->flags = (u32)MEM_BUBBLE_FLAG_INIT;
new_bubble->size = remaining_size - sizeof(Bubble); new_bubble->size = remaining_size - sizeof(Bubble);
insert_bubble(bubble, new_bubble); insert_bubble(bubble, new_bubble);
} }
} }
internal void* internal void*
general_memory_allocate(General_Memory *general, i32 size, u32 type = 0){ general_memory_allocate(General_Memory *general, i32 size, u32 type = 0){
void *result = 0; void *result = 0;
for (Bubble *bubble = general->sentinel.next; for (Bubble *bubble = general->sentinel.next;
bubble != &general->sentinel; bubble != &general->sentinel;
bubble = bubble->next){ bubble = bubble->next){
if (!(bubble->flags & MEM_BUBBLE_USED)){ if (!(bubble->flags & MEM_BUBBLE_USED)){
if (bubble->size >= size){ if (bubble->size >= size){
result = bubble + 1; result = bubble + 1;
bubble->flags |= MEM_BUBBLE_USED; bubble->flags |= MEM_BUBBLE_USED;
bubble->type = type; bubble->type = type;
general_memory_attempt_split(bubble, size); general_memory_attempt_split(bubble, size);
break; break;
} }
} }
} }
return result; return result;
} }
inline void inline void
general_memory_do_merge(Bubble *left, Bubble *right){ general_memory_do_merge(Bubble *left, Bubble *right){
Assert(left->next == right); Assert(left->next == right);
Assert(right->prev == left); Assert(right->prev == left);
left->size += sizeof(Bubble) + right->size; left->size += sizeof(Bubble) + right->size;
remove_bubble(right); remove_bubble(right);
} }
inline void inline void
general_memory_attempt_merge(Bubble *left, Bubble *right){ general_memory_attempt_merge(Bubble *left, Bubble *right){
if (!(left->flags & MEM_BUBBLE_USED) && if (!(left->flags & MEM_BUBBLE_USED) &&
!(right->flags & MEM_BUBBLE_USED)){ !(right->flags & MEM_BUBBLE_USED)){
general_memory_do_merge(left, right); general_memory_do_merge(left, right);
} }
} }
internal void internal void
general_memory_free(General_Memory *general, void *memory){ general_memory_free(General_Memory *general, void *memory){
Bubble *bubble = ((Bubble*)memory) - 1; Bubble *bubble = ((Bubble*)memory) - 1;
Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG); Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
bubble->flags &= ~MEM_BUBBLE_USED; bubble->flags &= ~MEM_BUBBLE_USED;
bubble->type = 0; bubble->type = 0;
Bubble *prev, *next; Bubble *prev, *next;
prev = bubble->prev; prev = bubble->prev;
next = bubble->next; next = bubble->next;
general_memory_attempt_merge(bubble, next); general_memory_attempt_merge(bubble, next);
general_memory_attempt_merge(prev, bubble); general_memory_attempt_merge(prev, bubble);
} }
internal void* internal void*
general_memory_reallocate(General_Memory *general, void *old, i32 old_size, i32 size, u32 type = 0){ general_memory_reallocate(General_Memory *general, void *old, i32 old_size, i32 size, u32 type = 0){
void *result = old; void *result = old;
Bubble *bubble = ((Bubble*)old) - 1; Bubble *bubble = ((Bubble*)old) - 1;
bubble->type = type; bubble->type = type;
Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG); Assert((!FRED_INTERNAL) || (bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_DEBUG);
i32 additional_space = size - bubble->size; i32 additional_space = size - bubble->size;
if (additional_space > 0){ if (additional_space > 0){
Bubble *next = bubble->next; Bubble *next = bubble->next;
if (!(next->flags & MEM_BUBBLE_USED) && if (!(next->flags & MEM_BUBBLE_USED) &&
next->size + sizeof(Bubble) >= additional_space){ next->size + sizeof(Bubble) >= additional_space){
general_memory_do_merge(bubble, next); general_memory_do_merge(bubble, next);
general_memory_attempt_split(bubble, size); general_memory_attempt_split(bubble, size);
} }
else{ else{
result = general_memory_allocate(general, size, type); result = general_memory_allocate(general, size, type);
if (old_size) memcpy(result, old, old_size); if (old_size) memcpy(result, old, old_size);
general_memory_free(general, old); general_memory_free(general, old);
} }
} }
return result; return result;
} }
inline void* inline void*
general_memory_reallocate_nocopy(General_Memory *general, void *old, i32 size, u32 type = 0){ general_memory_reallocate_nocopy(General_Memory *general, void *old, i32 size, u32 type = 0){
return general_memory_reallocate(general, old, 0, size, type); return general_memory_reallocate(general, old, 0, size, type);
} }
internal Temp_Memory internal Temp_Memory
begin_temp_memory(Partition *data){ begin_temp_memory(Partition *data){
Temp_Memory result; Temp_Memory result;
result.handle = data; result.handle = data;
result.pos = data->pos; result.pos = data->pos;
return result; return result;
} }
internal void internal void
end_temp_memory(Temp_Memory temp){ end_temp_memory(Temp_Memory temp){
((Partition*)temp.handle)->pos = temp.pos; ((Partition*)temp.handle)->pos = temp.pos;
} }
// BOTTOM #define reset_temp_memory end_temp_memory
// BOTTOM

View File

@ -187,5 +187,36 @@ struct System_Functions{
INTERNAL_System_Debug_Message *internal_debug_message; INTERNAL_System_Debug_Message *internal_debug_message;
}; };
#define FileNameMax (1 << 9)
struct File_Slot{
File_Slot *next, *prev;
byte *data;
i32 size, max;
char *filename;
i32 filename_len;
u32 flags;
};
enum File_Exchange_Flag{
FEx_Request = 0x1,
FEx_Ready = 0x2,
FEx_Not_Exist = 0x4,
FEx_Save = 0x8,
FEx_Save_Complete = 0x10,
FEx_Save_Failed = 0x20
};
struct File_Exchange{
File_Slot available, active, free_list;
File_Slot *files;
i32 num_active, max;
};
struct Exchange{
Thread_Exchange thread;
File_Exchange file;
};
// BOTTOM // BOTTOM

235
4tech_table.cpp Normal file
View File

@ -0,0 +1,235 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 14.02.2016
*
* 4tech C style genereic hash table
*
*/
// TOP
#define TableHashEmpty 0
#define TableHashDeleted 1
#define TableHashMin 0x10000000
typedef u32 Hash_Function(void *item, void *arg);
typedef i32 Compare_Function(void *key, void *item, void *arg);
struct Table{
u32 *hash_array;
u8 *data_array;
i32 count, max;
i32 item_size;
};
internal b32
table_at_capacity(Table *table){
b32 result = 1;
if (table->count * 8 < table->max * 7){
result = 0;
}
return(result);
}
internal b32
table_add(Table *table, void *item, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
u32 hash, *inspect;
i32 i;
Assert(table->count * 8 < table->max * 7);
hash = (hash_func(item, arg) | TableHashMin);
i = hash % table->max;
inspect = table->hash_array + i;
while (*inspect >= TableHashMin){
if (*inspect == hash){
if (comp_func(item, table->data_array + i*table->item_size, arg) == 0){
return(1);
}
}
++i;
++inspect;
if (i == table->max){
i = 0;
inspect = table->hash_array;
}
}
*inspect = hash;
memcpy(table->data_array + i*table->item_size, item, table->item_size);
++table->count;
return(0);
}
internal b32
table_find_pos(Table *table, void *search_key, void *arg, i32 *pos, i32 *index, Hash_Function *hash_func, Compare_Function *comp_func){
u32 hash, *inspect;
i32 i;
hash = (hash_func(search_key, arg) | TableHashMin);
i = hash % table->max;
inspect = table->hash_array + i;
while (*inspect != TableHashEmpty){
if (*inspect == hash){
if (comp_func(search_key, table->data_array + i*table->item_size, arg) == 0){
if (pos) *pos = i*table->item_size;
if (index) *index = i;
return(1);
}
}
++i;
++inspect;
if (i == table->max){
i = 0;
inspect = table->hash_array;
}
}
return(0);
}
internal void*
table_find_item(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 pos;
void *result = 0;
if (table_find_pos(table, search_key, arg, &pos, 0, hash_func, comp_func)){
result = table->data_array + pos;
}
return(result);
}
internal void
table_remove_index(Table *table, i32 index){
table->hash_array[index] = TableHashDeleted;
--table->count;
}
internal b32
table_remove_match(Table *table, void *search_key, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 index;
b32 result = 0;
if (table_find_pos(table, search_key, arg, 0, &index, hash_func, comp_func)){
table_remove_index(table, index);
result = 1;
}
return(result);
}
internal void
table_clear(Table *table){
table->count = 0;
memset(table->hash_array, 0, table->max*sizeof(*table->hash_array));
}
internal void
table_rehash(Table *src, Table *dst, void *arg, Hash_Function *hash_func, Compare_Function *comp_func){
i32 i, c, count, item_size;
u32 *hash_item;
u8 *data_item;
Assert((dst->count + src->count - 1) * 7 < dst->max * 8);
Assert(dst->item_size == src->item_size);
count = src->count;
hash_item = src->hash_array;
data_item = src->data_array;
item_size = src->item_size;
for (i = 0, c = 0; c < count; ++i, ++hash_item, data_item += item_size){
if (*hash_item >= TableHashMin){
++c;
table_add(dst, data_item, arg, hash_func, comp_func);
}
}
}
internal u32
tbl_string_hash(void *item, void *arg){
String *string = (String*)item;
char *str;
i32 i,len;
u32 x = 5381;
char c;
(void)arg;
str = string->str;
len = string->size;
i = 0;
while (i < len){
c = str[i++];
x = ((x << 5) + x) + c;
}
return(x);
}
internal i32
tbl_string_compare(void *a, void *b, void *arg){
String *stra = (String*)a;
String *strb = (String*)b;
i32 result = !match(*stra, *strb);
return(result);
}
internal u32
tbl_offset_string_hash(void *item, void *arg){
Offset_String *string = (Offset_String*)item;
char *str;
i32 i,len;
u32 x = 5381;
char c;
str = ((char*)arg) + string->offset;
len = string->size;
i = 0;
while (i < len){
c = str[i++];
x = ((x << 5) + x) + c;
}
return(x);
}
internal i32
tbl_offset_string_compare(void *a, void *b, void *arg){
Offset_String *ostra = (Offset_String*)a;
Offset_String *ostrb = (Offset_String*)b;
String stra = make_string((char*)arg + ostra->offset, ostra->size);
String strb = make_string((char*)arg + ostrb->offset, ostrb->size);
i32 result = !match(stra, strb);
return(result);
}
struct String_Space{
char *space;
i32 pos, new_pos, max;
};
internal Offset_String
strspace_append(String_Space *space, char *str, i32 len){
Offset_String result = {};
if (space->new_pos + len <= space->max){
result.offset = space->new_pos;
result.size = len;
memcpy(space->space + space->new_pos, str, len);
space->new_pos = space->pos + len;
}
return(result);
}
internal void
strspace_keep_prev(String_Space *space){
space->pos = space->new_pos;
}
internal void
strspace_discard_prev(String_Space *space){
space->new_pos = space->pos;
}
// BOTTOM

View File

@ -37,6 +37,15 @@ buffer_backify(Buffer_Type *buffer, int start, int end, char *out){
} }
} }
internal_4tech char
buffer_get_char(Buffer_Type *buffer, int i){
char out = 0;
if (i >= 0 && i < buffer_size(buffer)){
buffer_stringify(buffer, i, i+1, &out);
}
return(out);
}
internal_4tech int internal_4tech int
buffer_convert_out(Buffer_Type *buffer, char *dest, int max){ buffer_convert_out(Buffer_Type *buffer, char *dest, int max){
Buffer_Stringify_Type loop; Buffer_Stringify_Type loop;
@ -463,17 +472,14 @@ buffer_find_hard_start_end:
} }
internal_4tech int internal_4tech int
buffer_find_string(Buffer_Type *buffer, int start_pos, char *str, int len, char *spare){ buffer_find_string(Buffer_Type *buffer, int start_pos, int end_pos, char *str, int len, char *spare){
Buffer_Stringify_Type loop; Buffer_Stringify_Type loop;
char *data; char *data;
int size, end; int end, pos;
int pos;
size = buffer_size(buffer);
pos = start_pos; pos = start_pos;
if (len > 0){ if (len > 0){
for (loop = buffer_stringify_loop(buffer, start_pos, size - len + 1); for (loop = buffer_stringify_loop(buffer, start_pos, end_pos - len + 1);
buffer_stringify_good(&loop); buffer_stringify_good(&loop);
buffer_stringify_next(&loop)){ buffer_stringify_next(&loop)){
end = loop.size + loop.absolute_pos; end = loop.size + loop.absolute_pos;
@ -489,7 +495,7 @@ buffer_find_string(Buffer_Type *buffer, int start_pos, char *str, int len, char
} }
buffer_find_string_end: buffer_find_string_end:
if (pos >= size - len + 1) pos = size; if (pos >= end_pos - len + 1) pos = end_pos;
return(pos); return(pos);
} }

View File

@ -40,7 +40,8 @@
#include <GL/glx.h> #include <GL/glx.h>
#include <xmmintrin.h> #include <xmmintrin.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <X11/extensions/XInput2.h> //#include <X11/extensions/XInput2.h>
#include <X11/XKBlib.h>
#include <linux/input.h> #include <linux/input.h>
#include <time.h> #include <time.h>
#include <dlfcn.h> #include <dlfcn.h>
@ -53,6 +54,17 @@
#include <stdlib.h> #include <stdlib.h>
struct Linux_Vars{ struct Linux_Vars{
Display *XDisplay;
Window XWindow;
Render_Target target;
XIM input_method;
XIMStyle input_style;
XIC xic;
Key_Codes key_codes;
Clipboard_Contents clipboard_contents;
void *app_code; void *app_code;
void *custom; void *custom;
@ -65,6 +77,8 @@ struct Linux_Vars{
#if FRED_INTERNAL #if FRED_INTERNAL
Sys_Bubble internal_bubble; Sys_Bubble internal_bubble;
#endif #endif
Font_Load_System fnt;
}; };
globalvar Linux_Vars linuxvars; globalvar Linux_Vars linuxvars;
@ -76,25 +90,25 @@ Sys_Get_Memory_Sig(system_get_memory_){
// TODO(allen): Implement without stdlib.h // TODO(allen): Implement without stdlib.h
void *result = 0; void *result = 0;
if (size != 0){ Assert(size != 0);
#if FRED_INTERNAL #if FRED_INTERNAL
Sys_Bubble *bubble; Sys_Bubble *bubble;
result = malloc(size + sizeof(Sys_Bubble)); result = malloc(size + sizeof(Sys_Bubble));
bubble = (Sys_Bubble*)result; bubble = (Sys_Bubble*)result;
bubble->flags = MEM_BUBBLE_SYS_DEBUG; bubble->flags = MEM_BUBBLE_SYS_DEBUG;
bubble->line_number = line_number; bubble->line_number = line_number;
bubble->file_name = file_name; bubble->file_name = file_name;
bubble->size = size; bubble->size = size;
// TODO(allen): make Sys_Bubble list thread safe // TODO(allen): make Sys_Bubble list thread safe
insert_bubble(&linuxvars.internal_bubble, bubble); insert_bubble(&linuxvars.internal_bubble, bubble);
result = bubble + 1; result = bubble + 1;
#else #else
result = malloc(size); result = malloc(size);
#endif #endif
}
return(result); return(result);
} }
@ -348,6 +362,16 @@ Sys_Save_File_Sig(system_save_file){
return(result); return(result);
} }
// TODO(allen): Implement this. Also where is this
// macro define? Let's try to organize these functions
// a little better now that they're starting to settle
// into their places.
internal
Font_Load_Sig(system_draw_font_load){
return(0);
}
internal b32 internal b32
LinuxLoadAppCode(){ LinuxLoadAppCode(){
b32 result = 0; b32 result = 0;
@ -397,6 +421,40 @@ LinuxLoadSystemCode(){
#include "system_shared.cpp" #include "system_shared.cpp"
#include "4ed_rendering.cpp" #include "4ed_rendering.cpp"
internal void
LinuxLoadRenderCode(){
linuxvars.target.push_clip = draw_push_clip;
linuxvars.target.pop_clip = draw_pop_clip;
linuxvars.target.push_piece = draw_push_piece;
linuxvars.target.font_set.font_info_load = draw_font_info_load;
linuxvars.target.font_set.font_load = system_draw_font_load;
linuxvars.target.font_set.release_font = draw_release_font;
}
internal void
LinuxRedrawTarget(){
system_acquire_lock(RENDER_LOCK);
launch_rendering(&linuxvars.target);
system_release_lock(RENDER_LOCK);
glFlush();
glXSwapBuffers(linuxvars.XDisplay, linuxvars.XWindow);
}
internal void
LinuxResizeTarget(i32 width, i32 height){
if (width > 0 && height > 0){
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, -1, 1);
glScissor(0, 0, width, height);
linuxvars.target.width = width;
linuxvars.target.height = height;
}
}
// NOTE(allen): Thanks to Casey for providing the linux OpenGL launcher. // NOTE(allen): Thanks to Casey for providing the linux OpenGL launcher.
static bool ctxErrorOccurred = false; static bool ctxErrorOccurred = false;
static int XInput2OpCode = 0; static int XInput2OpCode = 0;
@ -439,7 +497,7 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
None None
}; };
printf("\nAttribs: %d %d %d %d %d\n", printf("Attribs: %d %d %d %d %d\n",
context_attribs[0], context_attribs[0],
context_attribs[1], context_attribs[1],
context_attribs[2], context_attribs[2],
@ -506,21 +564,21 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
{ {
printf( "Direct GLX rendering context obtained\n" ); printf( "Direct GLX rendering context obtained\n" );
} }
printf( "Making context current\n" ); printf( "Making context current\n" );
glXMakeCurrent( XDisplay, XWindow, ctx ); glXMakeCurrent( XDisplay, XWindow, ctx );
GLint n; GLint n;
char *Vendor = (char *)glGetString(GL_VENDOR); char *Vendor = (char *)glGetString(GL_VENDOR);
char *Renderer = (char *)glGetString(GL_RENDERER); char *Renderer = (char *)glGetString(GL_RENDERER);
char *Version = (char *)glGetString(GL_VERSION); char *Version = (char *)glGetString(GL_VERSION);
char *Extensions = (char *)glGetString(GL_EXTENSIONS); char *Extensions = (char *)glGetString(GL_EXTENSIONS);
printf("GL_VENDOR: %s\n", Vendor); printf("GL_VENDOR: %s\n", Vendor);
printf("GL_RENDERER: %s\n", Renderer); printf("GL_RENDERER: %s\n", Renderer);
printf("GL_VERSION: %s\n", Version); printf("GL_VERSION: %s\n", Version);
printf("GL_EXTENSIONS: %s\n", Extensions); printf("GL_EXTENSIONS: %s\n", Extensions);
return(ctx); return(ctx);
} }
@ -636,16 +694,23 @@ ChooseGLXConfig(Display *XDisplay, int XScreenIndex)
return(Result); return(Result);
} }
internal void struct Init_Input_Result{
XIM input_method;
XIMStyle best_style;
XIC xic;
};
internal Init_Input_Result
InitializeXInput(Display *dpy, Window XWindow) InitializeXInput(Display *dpy, Window XWindow)
{ {
#if 0
int event, error; int event, error;
if(XQueryExtension(dpy, "XInputExtension", &XInput2OpCode, &event, &error)) if(XQueryExtension(dpy, "XInputExtension", &XInput2OpCode, &event, &error))
{ {
int major = 2, minor = 0; int major = 2, minor = 0;
if(XIQueryVersion(dpy, &major, &minor) != BadRequest) if(XIQueryVersion(dpy, &major, &minor) != BadRequest)
{ {
printf("XInput initialized"); printf("XInput initialized version %d.%d\n", major, minor);
} }
else else
{ {
@ -723,11 +788,61 @@ InitializeXInput(Display *dpy, Window XWindow)
XISetMask(Mask.mask, XI_RawMotion); XISetMask(Mask.mask, XI_RawMotion);
XISelectEvents(dpy, DefaultRootWindow(dpy), &Mask, 1); XISelectEvents(dpy, DefaultRootWindow(dpy), &Mask, 1);
} }
#endif
// NOTE(allen): Annnndddd... here goes some guess work of my own.
Init_Input_Result result = {};
XIMStyle style;
XIMStyles *styles = 0;
i32 i, count;
XSetLocaleModifiers("");
printf("supported locales: %d\n", XSupportsLocale());
XSelectInput(linuxvars.XDisplay, linuxvars.XWindow, ExposureMask | KeyPressMask);
result.input_method = XOpenIM(dpy, 0, 0, 0);
if (result.input_method){
if (!XGetIMValues(result.input_method, XNQueryInputStyle, &styles, NULL) &&
styles){
result.best_style = 0;
count = styles->count_styles;
for (i = 0; i < count; ++i){
style = styles->supported_styles[i];
if (style == (XIMPreeditNothing | XIMStatusNothing)){
result.best_style = style;
break;
}
}
if (result.best_style){
XFree(styles);
result.xic =
XCreateIC(result.input_method, XNInputStyle, result.best_style,
XNClientWindow, XWindow,
XNFocusWindow, XWindow,
0, 0,
NULL);
}
else{
result = {};
printf("Could not get minimum required input style");
}
}
}
else{
result = {};
printf("Could not open X Input Method\n");
}
return(result);
} }
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
i32 COUNTER = 0;
linuxvars = {}; linuxvars = {};
exchange_vars = {}; exchange_vars = {};
@ -765,10 +880,10 @@ main(int argc, char **argv)
} }
if (curdir_req >= (1 << 13)){ if (curdir_req >= (1 << 13)){
// TODO(allen): fuckin' bullshit string APIs makin' me pissed // TODO(allen): bullshit string APIs makin' me pissed
return 57; return 57;
} }
for (curdir_size = 0; curdir_mem[curdir_size]; ++curdir_size); for (curdir_size = 0; curdir_mem[curdir_size]; ++curdir_size);
current_directory = make_string(curdir_mem, curdir_size, curdir_req); current_directory = make_string(curdir_mem, curdir_size, curdir_req);
@ -788,123 +903,304 @@ main(int argc, char **argv)
&linuxvars.settings, &linuxvars.settings,
&files, &file_count, &files, &file_count,
clparams); clparams);
if (output_size > 0){ if (output_size > 0){
// TODO(allen): crt free version // TODO(allen): crt free version
printf("%.*s", output_size, (char*)memory_vars.target_memory); printf("%.*s", output_size, (char*)memory_vars.target_memory);
} }
if (output_size != 0) return 0; if (output_size != 0) return 0;
system_filter_real_files(files, file_count); sysshared_filter_real_files(files, file_count);
Display *XDisplay = XOpenDisplay(0); keycode_init(&linuxvars.key_codes);
if(XDisplay && GLXSupportsModernContexts(XDisplay))
#ifdef FRED_SUPER
char *custom_file_default = "4coder_custom.so";
char *custom_file;
if (linuxvars.settings.custom_dll) custom_file = linuxvars.settings.custom_dll;
else custom_file = custom_file_default;
linuxvars.custom = dlopen(custom_file, RTLD_LAZY);
if (!linuxvars.custom && custom_file != custom_file_default){
if (!linuxvars.settings.custom_dll_is_strict){
linuxvars.custom = dlopen(custom_file_default, RTLD_LAZY);
}
}
if (linuxvars.custom){
linuxvars.custom_api.get_bindings = (Get_Binding_Data_Function*)
dlsym(linuxvars.custom, "get_bindings");
}
#endif
// TODO(allen): Setup background threads and locks
LinuxLoadRenderCode();
linuxvars.target.max = Mbytes(1);
linuxvars.target.push_buffer = (byte*)system_get_memory(linuxvars.target.max);
File_Slot file_slots[32];
sysshared_init_file_exchange(&exchange_vars, file_slots, ArrayCount(file_slots), 0);
Font_Load_Parameters params[8];
sysshared_init_font_params(&linuxvars.fnt, params, ArrayCount(params));
linuxvars.app.init(linuxvars.system, &linuxvars.target,
&memory_vars, &exchange_vars, &linuxvars.key_codes,
linuxvars.clipboard_contents, current_directory,
linuxvars.custom_api);
// NOTE(allen): Here begins the linux screen setup stuff.
// Behold the true nature of this wonderful OS:
// (thanks again to Casey for providing this stuff)
Colormap cmap;
XSetWindowAttributes swa;
int WinWidth, WinHeight;
b32 window_setup_success = 0;
WinWidth = 800;
WinHeight = 600;
i32 xkb_ev_code = 0, xkb_err_code = 0;
linuxvars.XDisplay = XkbOpenDisplay(0, &xkb_ev_code, &xkb_err_code, 0, 0, 0);
if(linuxvars.XDisplay && GLXSupportsModernContexts(linuxvars.XDisplay))
{ {
int XScreenCount = ScreenCount(XDisplay); int XScreenCount = ScreenCount(linuxvars.XDisplay);
for(int XScreenIndex = 0; for(int XScreenIndex = 0;
XScreenIndex < XScreenCount; XScreenIndex < XScreenCount;
++XScreenIndex) ++XScreenIndex)
{ {
Screen *XScreen = ScreenOfDisplay(XDisplay, XScreenIndex); Screen *XScreen = ScreenOfDisplay(linuxvars.XDisplay, XScreenIndex);
int WinWidth = WidthOfScreen(XScreen); i32 ScrnWidth, ScrnHeight;
int WinHeight = HeightOfScreen(XScreen); ScrnWidth = WidthOfScreen(XScreen);
ScrnHeight = HeightOfScreen(XScreen);
glx_config_result Config = ChooseGLXConfig(XDisplay, XScreenIndex);
if (ScrnWidth + 50 < WinWidth) WinWidth = ScrnWidth + 50;
if (ScrnHeight + 50 < WinHeight) WinHeight = ScrnHeight + 50;
glx_config_result Config = ChooseGLXConfig(linuxvars.XDisplay, XScreenIndex);
if(Config.Found) if(Config.Found)
{ {
Colormap cmap; swa.colormap = cmap = XCreateColormap(linuxvars.XDisplay,
XSetWindowAttributes swa; RootWindow(linuxvars.XDisplay, Config.BestInfo.screen ),
swa.colormap = cmap = XCreateColormap(XDisplay,
RootWindow(XDisplay, Config.BestInfo.screen ),
Config.BestInfo.visual, AllocNone); Config.BestInfo.visual, AllocNone);
swa.background_pixmap = None; swa.background_pixmap = None;
swa.border_pixel = 0; swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask; swa.event_mask = StructureNotifyMask;
Window XWindow = XCreateWindow(XDisplay, linuxvars.XWindow =
RootWindow(XDisplay, Config.BestInfo.screen), XCreateWindow(linuxvars.XDisplay,
0, 0, WinWidth, WinHeight, RootWindow(linuxvars.XDisplay, Config.BestInfo.screen),
0, Config.BestInfo.depth, InputOutput, 0, 0, WinWidth, WinHeight,
Config.BestInfo.visual, 0, Config.BestInfo.depth, InputOutput,
CWBorderPixel|CWColormap|CWEventMask, &swa ); Config.BestInfo.visual,
if(XWindow) CWBorderPixel|CWColormap|CWEventMask, &swa );
if(linuxvars.XWindow)
{ {
XStoreName(XDisplay, XWindow, "4coder"); XStoreName(linuxvars.XDisplay, linuxvars.XWindow, "4coder-window");
XMapWindow(XDisplay, XWindow); XMapWindow(linuxvars.XDisplay, linuxvars.XWindow);
InitializeXInput(XDisplay, XWindow); Init_Input_Result input_result =
InitializeXInput(linuxvars.XDisplay, linuxvars.XWindow);
linuxvars.input_method = input_result.input_method;
linuxvars.input_style = input_result.best_style;
linuxvars.xic = input_result.xic;
b32 IsLegacy = false; b32 IsLegacy = false;
GLXContext GLContext = GLXContext GLContext =
InitializeOpenGLContext(XDisplay, XWindow, Config.BestConfig, IsLegacy); InitializeOpenGLContext(linuxvars.XDisplay, linuxvars.XWindow, Config.BestConfig, IsLegacy);
XWindowAttributes WinAttribs; XWindowAttributes WinAttribs;
if(XGetWindowAttributes(XDisplay, XWindow, &WinAttribs)) if(XGetWindowAttributes(linuxvars.XDisplay, linuxvars.XWindow, &WinAttribs))
{ {
WinWidth = WinAttribs.width; WinWidth = WinAttribs.width;
WinHeight = WinAttribs.height; WinHeight = WinAttribs.height;
} }
XRaiseWindow(XDisplay, XWindow); XRaiseWindow(linuxvars.XDisplay, linuxvars.XWindow);
XSync(XDisplay, False); XSync(linuxvars.XDisplay, False);
for(;;) window_setup_success = 1;
{
while(XPending(XDisplay))
{
XEvent Event;
XNextEvent(XDisplay, &Event);
if((Event.xcookie.type == GenericEvent) &&
(Event.xcookie.extension == XInput2OpCode) &&
XGetEventData(XDisplay, &Event.xcookie))
{
switch(Event.xcookie.evtype)
{
case XI_Motion:
{
Window root_return, child_return;
int root_x_return, root_y_return;
int MouseX, MouseY;
unsigned int mask_return;
XQueryPointer(XDisplay,
XWindow,
&root_return, &child_return,
&root_x_return, &root_y_return,
&MouseX, &MouseY,
&mask_return);
} break;
case XI_ButtonPress:
case XI_ButtonRelease:
{
b32 Down = (Event.xcookie.evtype == XI_ButtonPress);
XIDeviceEvent *DevEvent = (XIDeviceEvent *)Event.xcookie.data;
int Button = DevEvent->detail;
} break;
case XI_KeyPress:
case XI_KeyRelease:
{
b32 Down = (Event.xcookie.evtype == XI_KeyPress);
XIDeviceEvent *DevEvent = (XIDeviceEvent *)Event.xcookie.data;
int VK = DevEvent->detail;
} break;
}
XFreeEventData(XDisplay, &Event.xcookie);
}
}
// Draw some stuff here?
glXSwapBuffers(XDisplay, XWindow);
}
} }
} }
} }
} }
XSetICFocus(linuxvars.xic);
if (window_setup_success){
LinuxResizeTarget(WinWidth, WinHeight);
for(;;)
{
while(XPending(linuxvars.XDisplay))
{
XEvent Event;
XNextEvent(linuxvars.XDisplay, &Event);
if (XFilterEvent(&Event, None) == True){
continue;
}
switch (Event.type){
case KeyPress:
{
KeySym ks = NoSymbol;
XkbLookupKeySym(linuxvars.XDisplay, Event.xkey.keycode, Event.xkey.state, NULL, &ks);
printf("keysym: %s\n", XKeysymToString(ks));
Status st;
char buff[256];
memset(buff, 0, sizeof(buff));
XmbLookupString(linuxvars.xic, &Event.xkey, buff, sizeof(buff), &ks, &st);
printf("IC status: %d, code: %u, sym: %s, str: %s\n", st, Event.xkey.keycode, XKeysymToString(ks), buff);
}break;
}
#if 0
if((Event.xcookie.type == GenericEvent) &&
(Event.xcookie.extension == XInput2OpCode) &&
XGetEventData(linuxvars.XDisplay, &Event.xcookie))
{
switch(Event.xcookie.evtype)
{
case XI_Motion:
{
Window root_return, child_return;
int root_x_return, root_y_return;
int MouseX, MouseY;
unsigned int mask_return;
XQueryPointer(linuxvars.XDisplay,
linuxvars.XWindow,
&root_return, &child_return,
&root_x_return, &root_y_return,
&MouseX, &MouseY,
&mask_return);
} break;
case XI_ButtonPress:
case XI_ButtonRelease:
{
b32 Down = (Event.xcookie.evtype == XI_ButtonPress);
XIDeviceEvent *DevEvent = (XIDeviceEvent *)Event.xcookie.data;
int Button = DevEvent->detail;
} break;
case XI_KeyPress:
case XI_KeyRelease:
{
b32 Down = (Event.xcookie.evtype == XI_KeyPress);
XIDeviceEvent *DevEvent = (XIDeviceEvent *)Event.xcookie.data;
int keycode = DevEvent->detail;
if (Down){
printf("Keycode %d\n", keycode);
// NOTE(allen): Thanks to eisbehr for providing the code
// for initializing an XKeyPressedEvent struct for use in
// Xmb8LookupString
XKeyPressedEvent eventBase = {};
eventBase.type = KeyPress;
eventBase.serial = 0xF00D;
eventBase.send_event = 1; // at least admit that this isn't a genuine event
eventBase.display = DevEvent->display;
eventBase.window = DevEvent->event;
eventBase.root = DevEvent->root;
eventBase.subwindow = 0;
eventBase.time = {}; // Let's hope we don't need a real time.
eventBase.x = 0;
eventBase.y = 0;
eventBase.x_root = 0;
eventBase.y_root = 0;
eventBase.state = 0; // state of modifiers
// Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask,
// ShiftMask, LockMask, ControlMask,
// Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask.
//eventBase.keycode = 10;//minKeyCode;
eventBase.same_screen = 1;
eventBase.keycode = keycode;
char lookup_buffer[32];
Status status;
i32 size;
KeySym keysym;
size = XmbLookupString(linuxvars.xic, &eventBase,
lookup_buffer, sizeof(lookup_buffer),
&keysym, &status);
if (status == XBufferOverflow){
printf("Buffer overflow %d\n", size);
}
else if (status == XLookupNone){
printf("nothing branch\n");
}
else if (status == XLookupChars || status == XLookupBoth){
printf("keysym %lu translation: %.*s\n", keysym, size, lookup_buffer);
}
else{
printf("unknown branch %d\n", status);
}
break;
}
} break;
}
XFreeEventData(linuxvars.XDisplay, &Event.xcookie);
}
#endif
}
b32 redraw = 1;
Key_Input_Data input_data;
Mouse_State mouse;
Application_Step_Result result;
input_data = {};
mouse = {};
result.mouse_cursor_type = APP_MOUSE_CURSOR_DEFAULT;
result.redraw = redraw;
result.lctrl_lalt_is_altgr = 0;
linuxvars.app.step(linuxvars.system,
&linuxvars.key_codes,
&input_data,
&mouse,
&linuxvars.target,
&memory_vars,
&exchange_vars,
linuxvars.clipboard_contents,
1, linuxvars.first, redraw,
&result);
if (result.redraw){
LinuxRedrawTarget();
}
glBegin(GL_QUADS);
{
glVertex2f(.5f, .5f);
glVertex2f(1.f, .5f);
glVertex2f(1.f, 1.f);
glVertex2f(.5f, 1.f);
glVertex2f(0.f, 0.f);
glVertex2f(.2f, 0.f);
glVertex2f(.2f, .2f);
glVertex2f(0.f, .2f);
}
glEnd();
glXSwapBuffers(linuxvars.XDisplay, linuxvars.XWindow);
}
}
} }
// BOTTOM // BOTTOM

View File

@ -10,7 +10,7 @@
// TOP // TOP
internal void internal void
system_filter_real_files(char **files, i32 *file_count){ sysshared_filter_real_files(char **files, i32 *file_count){
i32 i, j; i32 i, j;
i32 end; i32 end;
@ -24,5 +24,115 @@ system_filter_real_files(char **files, i32 *file_count){
*file_count = j; *file_count = j;
} }
void
ex__file_insert(File_Slot *pos, File_Slot *file){
file->next = pos->next;
file->next->prev = file;
file->prev = pos;
pos->next = file;
}
void
ex__insert_range(File_Slot *start, File_Slot *end, File_Slot *pos){
end->next->prev = start->prev;
start->prev->next = end->next;
end->next = pos->next;
start->prev = pos;
pos->next->prev = end;
pos->next = start;
}
internal void
ex__check_file(File_Slot *pos){
File_Slot *file = pos;
Assert(pos == pos->next->prev);
for (pos = pos->next;
file != pos;
pos = pos->next){
Assert(pos == pos->next->prev);
}
}
internal void
ex__check(File_Exchange *file_exchange){
ex__check_file(&file_exchange->available);
ex__check_file(&file_exchange->active);
ex__check_file(&file_exchange->free_list);
}
internal void
sysshared_init_file_exchange(
Exchange *exchange, File_Slot *slots, i32 max,
char **filename_space_out){
char *filename_space;
i32 i;
exchange->file.max = max;
exchange->file.available = {};
exchange->file.available.next = &exchange->file.available;
exchange->file.available.prev = &exchange->file.available;
exchange->file.active = {};
exchange->file.active.next = &exchange->file.active;
exchange->file.active.prev = &exchange->file.active;
exchange->file.free_list = {};
exchange->file.free_list.next = &exchange->file.free_list;
exchange->file.free_list.prev = &exchange->file.free_list;
exchange->file.files = slots;
memset(slots, 0, sizeof(File_Slot)*max);
filename_space = (char*)
system_get_memory(FileNameMax*exchange->file.max);
File_Slot *slot = slots;
for (i = 0; i < exchange->file.max; ++i, ++slot){
ex__file_insert(&exchange->file.available, slot);
slot->filename = filename_space;
filename_space += FileNameMax;
}
if (filename_space_out) *filename_space_out = filename_space;
}
internal void
fnt__remove(Font_Load_Parameters *params){
params->next->prev = params->prev;
params->prev->next = params->next;
}
internal void
fnt__insert(Font_Load_Parameters *pos, Font_Load_Parameters *params){
params->next = pos->next;
pos->next->prev = params;
pos->next = params;
params->prev = pos;
}
internal void
sysshared_init_font_params(
Font_Load_System *fnt, Font_Load_Parameters *params, i32 max){
Font_Load_Parameters *param;
i32 i;
fnt->params = params;
fnt->max = max;
fnt->free_param.next = &fnt->free_param;
fnt->free_param.prev = &fnt->free_param;
fnt->used_param.next = &fnt->free_param;
fnt->used_param.prev = &fnt->free_param;
param = params;
for (i = 0; i < max; ++i, ++param){
fnt__insert(&fnt->free_param, param);
}
}
// BOTTOM // BOTTOM

View File

@ -14,6 +14,24 @@
// the application code, but system_shared.cpp and 4ed_rendering.cpp // the application code, but system_shared.cpp and 4ed_rendering.cpp
// rely on the functions listed here. // rely on the functions listed here.
struct Font_Load_Parameters{
Font_Load_Parameters *next;
Font_Load_Parameters *prev;
Render_Font *font_out;
char *filename;
i32 pt_size;
i32 tab_width;
};
struct Font_Load_System{
Font_Load_Parameters *params;
Font_Load_Parameters used_param;
Font_Load_Parameters free_param;
Partition part;
i32 max;
};
#define Sys_Get_Memory_Sig(name) void* name(i32 size, i32 line_number, char *file_name) #define Sys_Get_Memory_Sig(name) void* name(i32 size, i32 line_number, char *file_name)
#define Sys_Free_Memory_Sig(name) void name(void *block) #define Sys_Free_Memory_Sig(name) void name(void *block)
#define Sys_File_Can_Be_Made(name) b32 name(char *filename) #define Sys_File_Can_Be_Made(name) b32 name(char *filename)

BIN
vc120.pdb

Binary file not shown.

File diff suppressed because it is too large Load Diff