word complete v1 again
This commit is contained in:
parent
5619527d37
commit
770c48f95b
|
@ -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;
|
||||||
|
|
|
@ -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 != '/'); }
|
||||||
|
|
164
4ed.cpp
164
4ed.cpp
|
@ -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.
|
||||||
// TODO(allen): figure out how labels are scoped.
|
double_break:;
|
||||||
double_break:;
|
|
||||||
|
|
||||||
size = word_end - word_start;
|
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;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
word_start = complete_state->word_start;
|
||||||
|
word_end = complete_state->word_end;
|
||||||
|
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);
|
if (match.found_match){
|
||||||
buffer_stringify(buffer, word_start, word_end, str);
|
temp = begin_temp_memory(part);
|
||||||
|
match_size = match.end - match.start;
|
||||||
|
spare = (char*)push_array(part, char, match_size);
|
||||||
|
buffer_stringify(match.buffer, match.start, match.end, spare);
|
||||||
|
|
||||||
temp2 = begin_temp_memory(part);
|
if (search_hit_add(general, &complete_state->hits, &complete_state->str, spare, match_size)){
|
||||||
spare = (char*)push_array(part, char, size);
|
view_replace_range(system, mem, view, layout, word_start, word_end, spare, match_size, word_end);
|
||||||
end_temp_memory(temp2);
|
|
||||||
|
|
||||||
// TODO(allen): find string needs explicit end position
|
complete_state->word_end = word_start + match_size;
|
||||||
match_start = buffer_find_string(buffer, word_end, str, size, spare);
|
complete_state->set.ranges[1].start = word_start + match_size;
|
||||||
match_end = buffer_seek_word_right_assume_on_word(buffer, match_start);
|
break;
|
||||||
match_size = match_end - match_start;
|
}
|
||||||
spare = (char*)push_array(part, char, match_size);
|
end_temp_memory(temp);
|
||||||
buffer_stringify(buffer, match_start, match_end, spare);
|
}
|
||||||
|
else{
|
||||||
|
complete_state->iter.pos = 0;
|
||||||
|
complete_state->iter.i = 0;
|
||||||
|
|
||||||
view_replace_range(system, mem, view, layout, word_start, word_end, spare, match_size, word_end);
|
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);
|
||||||
|
|
||||||
end_temp_memory(temp1);
|
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
31
4ed.h
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -249,5 +249,7 @@ end_temp_memory(Temp_Memory temp){
|
||||||
((Partition*)temp.handle)->pos = temp.pos;
|
((Partition*)temp.handle)->pos = temp.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define reset_temp_memory end_temp_memory
|
||||||
|
|
||||||
// BOTTOM
|
// BOTTOM
|
||||||
|
|
||||||
|
|
31
4ed_system.h
31
4ed_system.h
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
490
linux_4ed.cpp
490
linux_4ed.cpp
|
@ -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],
|
||||||
|
@ -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,7 +880,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,116 +910,297 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
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 );
|
||||||
{
|
|
||||||
XStoreName(XDisplay, XWindow, "4coder");
|
|
||||||
XMapWindow(XDisplay, XWindow);
|
|
||||||
|
|
||||||
InitializeXInput(XDisplay, XWindow);
|
if(linuxvars.XWindow)
|
||||||
|
{
|
||||||
|
XStoreName(linuxvars.XDisplay, linuxvars.XWindow, "4coder-window");
|
||||||
|
XMapWindow(linuxvars.XDisplay, linuxvars.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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
189
win32_4ed.cpp
189
win32_4ed.cpp
|
@ -94,17 +94,6 @@ struct Win32_Input_Chunk{
|
||||||
Win32_Input_Chunk_Persistent pers;
|
Win32_Input_Chunk_Persistent pers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Win32_Font_Load_Parameters{
|
|
||||||
Win32_Font_Load_Parameters *next;
|
|
||||||
Win32_Font_Load_Parameters *prev;
|
|
||||||
|
|
||||||
Render_Font *font_out;
|
|
||||||
char *filename;
|
|
||||||
i32 pt_size;
|
|
||||||
i32 tab_width;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Win32_Vars{
|
struct Win32_Vars{
|
||||||
HWND window_handle;
|
HWND window_handle;
|
||||||
HDC window_hdc;
|
HDC window_hdc;
|
||||||
|
@ -154,10 +143,7 @@ struct Win32_Vars{
|
||||||
Sys_Bubble internal_bubble;
|
Sys_Bubble internal_bubble;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Win32_Font_Load_Parameters fnt_params[8];
|
Font_Load_System fnt;
|
||||||
Win32_Font_Load_Parameters used_font_param;
|
|
||||||
Win32_Font_Load_Parameters free_font_param;
|
|
||||||
Partition fnt_part;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
globalvar Win32_Vars win32vars;
|
globalvar Win32_Vars win32vars;
|
||||||
|
@ -861,41 +847,6 @@ Sys_CLI_End_Update_Sig(system_cli_end_update){
|
||||||
return close_me;
|
return close_me;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
|
||||||
fnt__remove(Win32_Font_Load_Parameters *params){
|
|
||||||
params->next->prev = params->prev;
|
|
||||||
params->prev->next = params->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
fnt__insert(Win32_Font_Load_Parameters *pos, Win32_Font_Load_Parameters *params){
|
|
||||||
params->next = pos->next;
|
|
||||||
pos->next->prev = params;
|
|
||||||
pos->next = params;
|
|
||||||
params->prev = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Font_Load_Sig(system_draw_font_load){
|
|
||||||
Win32_Font_Load_Parameters *params;
|
|
||||||
|
|
||||||
system_acquire_lock(FONT_LOCK);
|
|
||||||
params = win32vars.free_font_param.next;
|
|
||||||
fnt__remove(params);
|
|
||||||
fnt__insert(&win32vars.used_font_param, params);
|
|
||||||
system_release_lock(FONT_LOCK);
|
|
||||||
|
|
||||||
params->font_out = font_out;
|
|
||||||
params->filename = filename;
|
|
||||||
params->pt_size = pt_size;
|
|
||||||
params->tab_width = tab_width;
|
|
||||||
|
|
||||||
SendMessage(win32vars.window_handle,
|
|
||||||
WM_4coder_LOAD_FONT,
|
|
||||||
0, (i32)(params - win32vars.fnt_params));
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal b32
|
internal b32
|
||||||
Win32LoadAppCode(){
|
Win32LoadAppCode(){
|
||||||
b32 result = 0;
|
b32 result = 0;
|
||||||
|
@ -985,6 +936,38 @@ Win32LoadSystemCode(){
|
||||||
#include "system_shared.cpp"
|
#include "system_shared.cpp"
|
||||||
#include "4ed_rendering.cpp"
|
#include "4ed_rendering.cpp"
|
||||||
|
|
||||||
|
internal
|
||||||
|
Font_Load_Sig(system_draw_font_load){
|
||||||
|
Font_Load_Parameters *params;
|
||||||
|
|
||||||
|
system_acquire_lock(FONT_LOCK);
|
||||||
|
params = win32vars.fnt.free_param.next;
|
||||||
|
fnt__remove(params);
|
||||||
|
fnt__insert(&win32vars.fnt.used_param, params);
|
||||||
|
system_release_lock(FONT_LOCK);
|
||||||
|
|
||||||
|
params->font_out = font_out;
|
||||||
|
params->filename = filename;
|
||||||
|
params->pt_size = pt_size;
|
||||||
|
params->tab_width = tab_width;
|
||||||
|
|
||||||
|
SendMessage(win32vars.window_handle,
|
||||||
|
WM_4coder_LOAD_FONT,
|
||||||
|
0, (i32)(params - win32vars.fnt.params));
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
Win32LoadRenderCode(){
|
||||||
|
win32vars.target.push_clip = draw_push_clip;
|
||||||
|
win32vars.target.pop_clip = draw_pop_clip;
|
||||||
|
win32vars.target.push_piece = draw_push_piece;
|
||||||
|
|
||||||
|
win32vars.target.font_set.font_info_load = draw_font_info_load;
|
||||||
|
win32vars.target.font_set.font_load = system_draw_font_load;
|
||||||
|
win32vars.target.font_set.release_font = draw_release_font;
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
Win32RedrawScreen(HDC hdc){
|
Win32RedrawScreen(HDC hdc){
|
||||||
system_acquire_lock(RENDER_LOCK);
|
system_acquire_lock(RENDER_LOCK);
|
||||||
|
@ -994,45 +977,6 @@ Win32RedrawScreen(HDC hdc){
|
||||||
SwapBuffers(hdc);
|
SwapBuffers(hdc);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 LRESULT
|
internal LRESULT
|
||||||
Win32Callback(HWND hwnd, UINT uMsg,
|
Win32Callback(HWND hwnd, UINT uMsg,
|
||||||
WPARAM wParam, LPARAM lParam){
|
WPARAM wParam, LPARAM lParam){
|
||||||
|
@ -1298,29 +1242,29 @@ Win32Callback(HWND hwnd, UINT uMsg,
|
||||||
|
|
||||||
case WM_4coder_LOAD_FONT:
|
case WM_4coder_LOAD_FONT:
|
||||||
{
|
{
|
||||||
if (win32vars.fnt_part.base == 0){
|
if (win32vars.fnt.part.base == 0){
|
||||||
win32vars.fnt_part = Win32ScratchPartition(Mbytes(8));
|
win32vars.fnt.part = Win32ScratchPartition(Mbytes(8));
|
||||||
}
|
}
|
||||||
|
|
||||||
Win32_Font_Load_Parameters *params = win32vars.fnt_params + lParam;
|
Font_Load_Parameters *params = win32vars.fnt.params + lParam;
|
||||||
|
|
||||||
for (b32 success = 0; success == 0;){
|
for (b32 success = 0; success == 0;){
|
||||||
|
|
||||||
success = draw_font_load(win32vars.fnt_part.base,
|
success = draw_font_load(win32vars.fnt.part.base,
|
||||||
win32vars.fnt_part.max,
|
win32vars.fnt.part.max,
|
||||||
params->font_out,
|
params->font_out,
|
||||||
params->filename,
|
params->filename,
|
||||||
params->pt_size,
|
params->pt_size,
|
||||||
params->tab_width);
|
params->tab_width);
|
||||||
|
|
||||||
if (!success){
|
if (!success){
|
||||||
Win32ScratchPartitionDouble(&win32vars.fnt_part);
|
Win32ScratchPartitionDouble(&win32vars.fnt.part);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
system_acquire_lock(FONT_LOCK);
|
system_acquire_lock(FONT_LOCK);
|
||||||
fnt__remove(params);
|
fnt__remove(params);
|
||||||
fnt__insert(&win32vars.free_font_param, params);
|
fnt__insert(&win32vars.fnt.free_param, params);
|
||||||
system_release_lock(FONT_LOCK);
|
system_release_lock(FONT_LOCK);
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
@ -1598,7 +1542,7 @@ main(int argc, char **argv){
|
||||||
if (output_size != 0) return 0;
|
if (output_size != 0) return 0;
|
||||||
FreeConsole();
|
FreeConsole();
|
||||||
|
|
||||||
system_filter_real_files(files, file_count);
|
sysshared_filter_real_files(files, file_count);
|
||||||
|
|
||||||
LARGE_INTEGER lpf;
|
LARGE_INTEGER lpf;
|
||||||
QueryPerformanceFrequency(&lpf);
|
QueryPerformanceFrequency(&lpf);
|
||||||
|
@ -1664,6 +1608,10 @@ main(int argc, char **argv){
|
||||||
}
|
}
|
||||||
win32vars.DEBUG_sysmem_lock = CreateSemaphore(0, 1, 1, 0);
|
win32vars.DEBUG_sysmem_lock = CreateSemaphore(0, 1, 1, 0);
|
||||||
|
|
||||||
|
Win32LoadRenderCode();
|
||||||
|
win32vars.target.max = Mbytes(1);
|
||||||
|
win32vars.target.push_buffer = (byte*)system_get_memory(win32vars.target.max);
|
||||||
|
|
||||||
win32vars.cursor_ibeam = LoadCursor(NULL, IDC_IBEAM);
|
win32vars.cursor_ibeam = LoadCursor(NULL, IDC_IBEAM);
|
||||||
win32vars.cursor_arrow = LoadCursor(NULL, IDC_ARROW);
|
win32vars.cursor_arrow = LoadCursor(NULL, IDC_ARROW);
|
||||||
win32vars.cursor_leftright = LoadCursor(NULL, IDC_SIZEWE);
|
win32vars.cursor_leftright = LoadCursor(NULL, IDC_SIZEWE);
|
||||||
|
@ -1798,53 +1746,12 @@ main(int argc, char **argv){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
win32vars.target.push_clip = draw_push_clip;
|
|
||||||
win32vars.target.pop_clip = draw_pop_clip;
|
|
||||||
win32vars.target.push_piece = draw_push_piece;
|
|
||||||
|
|
||||||
win32vars.target.font_set.font_info_load = draw_font_info_load;
|
|
||||||
win32vars.target.font_set.font_load = system_draw_font_load;
|
|
||||||
win32vars.target.font_set.release_font = draw_release_font;
|
|
||||||
|
|
||||||
win32vars.target.max = Mbytes(1);
|
|
||||||
win32vars.target.push_buffer = (byte*)Win32GetMemory(win32vars.target.max);
|
|
||||||
|
|
||||||
File_Slot file_slots[32];
|
File_Slot file_slots[32];
|
||||||
exchange_vars.file.max = sizeof(file_slots) / sizeof(file_slots[0]);
|
sysshared_init_file_exchange(&exchange_vars, file_slots, ArrayCount(file_slots), 0);
|
||||||
exchange_vars.file.available = {};
|
|
||||||
exchange_vars.file.available.next = &exchange_vars.file.available;
|
|
||||||
exchange_vars.file.available.prev = &exchange_vars.file.available;
|
|
||||||
|
|
||||||
exchange_vars.file.active = {};
|
Font_Load_Parameters params[32];
|
||||||
exchange_vars.file.active.next = &exchange_vars.file.active;
|
sysshared_init_font_params(&win32vars.fnt, params, ArrayCount(params));
|
||||||
exchange_vars.file.active.prev = &exchange_vars.file.active;
|
|
||||||
|
|
||||||
exchange_vars.file.free_list = {};
|
|
||||||
exchange_vars.file.free_list.next = &exchange_vars.file.free_list;
|
|
||||||
exchange_vars.file.free_list.prev = &exchange_vars.file.free_list;
|
|
||||||
|
|
||||||
exchange_vars.file.files = file_slots;
|
|
||||||
memset(file_slots, 0, sizeof(file_slots));
|
|
||||||
|
|
||||||
char *filename_space = (char*)
|
|
||||||
Win32GetMemory(FileNameMax*exchange_vars.file.max);
|
|
||||||
|
|
||||||
for (int i = 0; i < exchange_vars.file.max; ++i){
|
|
||||||
File_Slot *slot = file_slots + i;
|
|
||||||
ex__file_insert(&exchange_vars.file.available, slot);
|
|
||||||
slot->filename = filename_space;
|
|
||||||
filename_space += FileNameMax;
|
|
||||||
}
|
|
||||||
|
|
||||||
win32vars.free_font_param.next = &win32vars.free_font_param;
|
|
||||||
win32vars.free_font_param.prev = &win32vars.free_font_param;
|
|
||||||
|
|
||||||
win32vars.used_font_param.next = &win32vars.used_font_param;
|
|
||||||
win32vars.used_font_param.prev = &win32vars.used_font_param;
|
|
||||||
|
|
||||||
for (i32 i = 0; i < ArrayCount(win32vars.fnt_params); ++i){
|
|
||||||
fnt__insert(&win32vars.free_font_param, win32vars.fnt_params + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
win32vars.app.init(win32vars.system, &win32vars.target,
|
win32vars.app.init(win32vars.system, &win32vars.target,
|
||||||
&memory_vars, &exchange_vars, &win32vars.key_codes,
|
&memory_vars, &exchange_vars, &win32vars.key_codes,
|
||||||
|
|
Loading…
Reference in New Issue