new linux shit

This commit is contained in:
Allen Webster 2016-02-01 00:03:42 -05:00
parent 951b992b2f
commit 8195020bfd
16 changed files with 4959 additions and 4688 deletions

View File

@ -1,318 +1,317 @@
/*
* Example use of customization API
*/
#define FCPP_STRING_IMPLEMENTATION
#include "4coder_string.h"
#include "4coder_custom.h"
#include "4coder_helper.h"
#ifndef literal
#define literal(s) s, (sizeof(s)-1)
#endif
// NOTE(allen|a3.1): All of your custom ids should be >= mapid_user_custom.
// I recommend enumerating your own map ids as shown here.
enum My_Maps{
my_code_map = mapid_user_custom,
my_html_map
};
HOOK_SIG(my_start){
exec_command(cmd_context, cmdid_open_panel_vsplit);
exec_command(cmd_context, cmdid_change_active_panel);
}
char *get_extension(const char *filename, int len, int *extension_len){
char *c = (char*)(filename + len - 1);
char *end = c;
while (*c != '.' && c > filename) --c;
*extension_len = (int)(end - c);
return c+1;
}
bool str_match(const char *a, int len_a, const char *b, int len_b){
bool result = 0;
if (len_a == len_b){
char *end = (char*)(a + len_a);
while (a < end && *a == *b){
++a; ++b;
}
if (a == end) result = 1;
}
return result;
}
HOOK_SIG(my_file_settings){
Buffer_Summary buffer = get_active_buffer(cmd_context);
int treat_as_code = 0;
// NOTE(allen|a3.1): This checks buffer.file_name just in case get_active_buffer returns back
// a null buffer (where every member is 0).
if (buffer.file_name && buffer.size < (16 << 20)){
int extension_len;
char *extension = get_extension(buffer.file_name, buffer.file_name_len, &extension_len);
if (str_match(extension, extension_len, literal("cpp"))) treat_as_code = 1;
else if (str_match(extension, extension_len, literal("h"))) treat_as_code = 1;
else if (str_match(extension, extension_len, literal("c"))) treat_as_code = 1;
else if (str_match(extension, extension_len, literal("hpp"))) treat_as_code = 1;
}
push_parameter(app, cmd_context, par_lex_as_cpp_file, treat_as_code);
push_parameter(app, cmd_context, par_wrap_lines, !treat_as_code);
push_parameter(app, cmd_context, par_key_mapid, (treat_as_code)?(my_code_map):(mapid_file));
exec_command(cmd_context, cmdid_set_settings);
}
CUSTOM_COMMAND_SIG(open_in_other){
exec_command(cmd_context, cmdid_change_active_panel);
exec_command(cmd_context, cmdid_interactive_open);
}
CUSTOM_COMMAND_SIG(open_my_files){
// NOTE(allen|a3.1): The command cmdid_interactive_open can now open
// a file specified on the parameter stack. If the file does not
// exist cmdid_interactive_open behaves as usual.
push_parameter(app, cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp"));
exec_command(cmd_context, cmdid_interactive_open);
exec_command(cmd_context, cmdid_change_active_panel);
char my_file[256];
int my_file_len;
my_file_len = sizeof("w:/4ed/data/test/basic.txt") - 1;
for (int i = 0; i < my_file_len; ++i){
my_file[i] = ("w:/4ed/data/test/basic.txt")[i];
}
// NOTE(allen|a3.1): null terminators are not needed for strings.
push_parameter(app, cmd_context, par_name, my_file, my_file_len);
exec_command(cmd_context, cmdid_interactive_open);
exec_command(cmd_context, cmdid_change_active_panel);
}
CUSTOM_COMMAND_SIG(build_at_launch_location){
// NOTE(allen|a3.3): An example of calling build by setting all
// parameters directly. This only works if build.bat can be called
// from the starting directory
push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 1);
push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*"));
push_parameter(app, cmd_context, par_cli_path, literal("."));
push_parameter(app, cmd_context, par_cli_command, literal("build"));
exec_command(cmd_context, cmdid_build);
}
CUSTOM_COMMAND_SIG(build_search){
// NOTE(allen|a3.3): An example of traversing the filesystem through parent
// directories looking for a file, in this case a batch file to execute.
//
//
// Step 1: push_directory returns a String containing the current "hot" directory
// (whatever directory you most recently visited in the 4coder file browsing interface)
//
// Step 2: app->directory_has_file queries the file system to see if "build.bat" exists
// If it does exist several parameters are pushed:
// - par_cli_overlap_with_conflict: whether to launch this process if an existing process
// is already being used for output on the same buffer
//
// - par_target_buffer_name: the name of the buffer to fill with the output from the process
//
// - par_cli_path: sets the path from which the command is executed
//
// - par_cli_command: sets the actual command to be executed, this can be almost any command
// that you could execute through a command line interface
//
//
// To set par_cli_path: push_parameter makes a copy of the dir string on the stack
// because the string allocated by push_directory is going to change again
// To set par_cli_command: app->push_parameter does not make a copy of the dir because
// dir isn't going to change again.
//
// Step 3: If the batch file did not exist try to move to the parent directory using
// app->directory_cd. The cd function can also be used to navigate to subdirectories.
// It returns true if it can actually move in the specified direction, and false otherwise.
int keep_going = 1;
String dir = push_directory(app, cmd_context);
while (keep_going){
if (app->directory_has_file(dir, "build.bat")){
push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 0);
push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*"));
push_parameter(app, cmd_context, par_cli_path, dir.str, dir.size);
if (append(&dir, "build")){
app->push_parameter(cmd_context,
dynamic_int(par_cli_command),
dynamic_string(dir.str, dir.size));
exec_command(cmd_context, cmdid_build);
}
else{
clear_parameters(cmd_context);
}
return;
}
if (app->directory_cd(&dir, "..") == 0){
keep_going = 0;
}
}
// TODO(allen): feedback message - couldn't find build.bat
}
CUSTOM_COMMAND_SIG(write_and_auto_tab){
exec_command(cmd_context, cmdid_write_character);
exec_command(cmd_context, cmdid_auto_tab_line_at_cursor);
}
extern "C" GET_BINDING_DATA(get_bindings){
Bind_Helper context_actual = begin_bind_helper(data, size);
Bind_Helper *context = &context_actual;
// NOTE(allen|a3.1): Right now hooks have no loyalties to maps, all hooks are
// global and once set they always apply, regardless of what map is active.
set_hook(context, hook_start, my_start);
set_hook(context, hook_open_file, my_file_settings);
begin_map(context, mapid_global);
bind(context, 'p', MDFR_CTRL, cmdid_open_panel_vsplit);
bind(context, '-', MDFR_CTRL, cmdid_open_panel_hsplit);
bind(context, 'P', MDFR_CTRL, cmdid_close_panel);
bind(context, 'n', MDFR_CTRL, cmdid_interactive_new);
bind(context, 'o', MDFR_CTRL, cmdid_interactive_open);
bind(context, ',', MDFR_CTRL, cmdid_change_active_panel);
bind(context, 'k', MDFR_CTRL, cmdid_interactive_kill_buffer);
bind(context, 'i', MDFR_CTRL, cmdid_interactive_switch_buffer);
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
bind(context, 'x', MDFR_ALT, cmdid_open_menu);
bind_me(context, 'o', MDFR_ALT, open_in_other);
// NOTE(allen): These callbacks may not actually be useful to you, but
// go look at them and see what they do.
bind_me(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files);
bind_me(context, 'M', MDFR_ALT, build_at_launch_location);
bind_me(context, 'm', MDFR_ALT, build_search);
end_map(context);
begin_map(context, my_code_map);
// NOTE(allen|a3.1): Set this map (my_code_map == mapid_user_custom) to
// inherit from mapid_file. When searching if a key is bound
// in this map, if it is not found here it will then search mapid_file.
//
// If this is not set, it defaults to mapid_global.
inherit_map(context, mapid_file);
// NOTE(allen|a3.1): Children can override parent's bindings.
bind(context, codes->right, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_right);
bind(context, codes->left, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_left);
// NOTE(allen|a3.2): Specific keys can override vanilla keys,
// and write character writes whichever character corresponds
// to the key that triggered the command.
bind_me(context, '\n', MDFR_NONE, write_and_auto_tab);
bind_me(context, '}', MDFR_NONE, write_and_auto_tab);
bind_me(context, ')', MDFR_NONE, write_and_auto_tab);
bind_me(context, ']', MDFR_NONE, write_and_auto_tab);
bind_me(context, ';', MDFR_NONE, write_and_auto_tab);
#if 0
bind(context, '\t', MDFR_NONE, cmdid_auto_tab_line_at_cursor);
bind(context, '\t', MDFR_CTRL, cmdid_auto_tab_range);
bind(context, '\t', MDFR_CTRL | MDFR_SHIFT, cmdid_write_character);
#endif
end_map(context);
begin_map(context, mapid_file);
// NOTE(allen|a3.1): Binding this essentially binds all key combos that
// would normally insert a character into a buffer.
// Or apply this rule (which always works): if the code for the key
// is not in the codes struct, it is a vanilla key.
// It is possible to override this binding for individual keys.
bind_vanilla_keys(context, cmdid_write_character);
bind(context, codes->left, MDFR_NONE, cmdid_move_left);
bind(context, codes->right, MDFR_NONE, cmdid_move_right);
bind(context, codes->del, MDFR_NONE, cmdid_delete);
bind(context, codes->back, MDFR_NONE, cmdid_backspace);
bind(context, codes->up, MDFR_NONE, cmdid_move_up);
bind(context, codes->down, MDFR_NONE, cmdid_move_down);
bind(context, codes->end, MDFR_NONE, cmdid_seek_end_of_line);
bind(context, codes->home, MDFR_NONE, cmdid_seek_beginning_of_line);
bind(context, codes->page_up, MDFR_NONE, cmdid_page_up);
bind(context, codes->page_down, MDFR_NONE, cmdid_page_down);
bind(context, codes->right, MDFR_CTRL, cmdid_seek_whitespace_right);
bind(context, codes->left, MDFR_CTRL, cmdid_seek_whitespace_left);
bind(context, codes->up, MDFR_CTRL, cmdid_seek_whitespace_up);
bind(context, codes->down, MDFR_CTRL, cmdid_seek_whitespace_down);
bind(context, ' ', MDFR_CTRL, cmdid_set_mark);
bind(context, 'm', MDFR_CTRL, cmdid_cursor_mark_swap);
bind(context, 'c', MDFR_CTRL, cmdid_copy);
bind(context, 'x', MDFR_CTRL, cmdid_cut);
bind(context, 'v', MDFR_CTRL, cmdid_paste);
bind(context, 'V', MDFR_CTRL, cmdid_paste_next);
bind(context, 'Z', MDFR_CTRL, cmdid_timeline_scrub);
bind(context, 'z', MDFR_CTRL, cmdid_undo);
bind(context, 'y', MDFR_CTRL, cmdid_redo);
bind(context, codes->left, MDFR_ALT, cmdid_increase_rewind_speed);
bind(context, codes->right, MDFR_ALT, cmdid_increase_fastforward_speed);
bind(context, codes->down, MDFR_ALT, cmdid_stop_rewind_fastforward);
bind(context, 'h', MDFR_CTRL, cmdid_history_backward);
bind(context, 'H', MDFR_CTRL, cmdid_history_forward);
bind(context, 'd', MDFR_CTRL, cmdid_delete_range);
bind(context, 'l', MDFR_CTRL, cmdid_toggle_line_wrap);
bind(context, 'L', MDFR_CTRL, cmdid_toggle_endline_mode);
bind(context, 'u', MDFR_CTRL, cmdid_to_uppercase);
bind(context, 'j', MDFR_CTRL, cmdid_to_lowercase);
bind(context, '?', MDFR_CTRL, cmdid_toggle_show_whitespace);
bind(context, '~', MDFR_CTRL, cmdid_clean_all_lines);
// NOTE(allen|a3.2): These now only set the mode of the file for writing to disk
// they do no longer effect the internal representation.
bind(context, '1', MDFR_CTRL, cmdid_eol_dosify);
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
bind(context, 'f', MDFR_CTRL, cmdid_search);
bind(context, 'r', MDFR_CTRL, cmdid_rsearch);
bind(context, 'g', MDFR_CTRL, cmdid_goto_line);
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);
bind(context, 'O', MDFR_CTRL, cmdid_reopen);
bind(context, 'w', MDFR_CTRL, cmdid_interactive_save_as);
bind(context, 's', MDFR_CTRL, cmdid_save);
end_map(context);
end_bind_helper(context);
return context->write_total;
}
inline void
strset_(char *dst, char *src){
do{
*dst++ = *src++;
}while (*src);
}
#define strset(d,s) if (sizeof(s) <= sizeof(d)) strset_(d,s)
extern "C" SET_EXTRA_FONT_SIG(set_extra_font){
strset(font_out->file_name, "liberation-mono.ttf");
strset(font_out->font_name, "BIG");
font_out->size = 25;
}
/*
* Example use of customization API
*/
#define FCPP_STRING_IMPLEMENTATION
#include "4coder_string.h"
#include "4coder_custom.h"
#include "4coder_helper.h"
#ifndef literal
#define literal(s) s, (sizeof(s)-1)
#endif
// NOTE(allen|a3.3): All of your custom ids should be enumerated
// as shown here, they may start at 0, and you can only have
// 2^24 of them so don't be wasteful!
enum My_Maps{
my_code_map,
my_html_map
};
HOOK_SIG(my_start){
exec_command(cmd_context, cmdid_open_panel_vsplit);
exec_command(cmd_context, cmdid_change_active_panel);
}
char *get_extension(const char *filename, int len, int *extension_len){
char *c = (char*)(filename + len - 1);
char *end = c;
while (*c != '.' && c > filename) --c;
*extension_len = (int)(end - c);
return c+1;
}
bool str_match(const char *a, int len_a, const char *b, int len_b){
bool result = 0;
if (len_a == len_b){
char *end = (char*)(a + len_a);
while (a < end && *a == *b){
++a; ++b;
}
if (a == end) result = 1;
}
return result;
}
HOOK_SIG(my_file_settings){
Buffer_Summary buffer = get_active_buffer(cmd_context);
int treat_as_code = 0;
// NOTE(allen|a3.1): This checks buffer.file_name just in case get_active_buffer returns back
// a null buffer (where every member is 0).
if (buffer.file_name && buffer.size < (16 << 20)){
int extension_len;
char *extension = get_extension(buffer.file_name, buffer.file_name_len, &extension_len);
if (str_match(extension, extension_len, literal("cpp"))) treat_as_code = 1;
else if (str_match(extension, extension_len, literal("h"))) treat_as_code = 1;
else if (str_match(extension, extension_len, literal("c"))) treat_as_code = 1;
else if (str_match(extension, extension_len, literal("hpp"))) treat_as_code = 1;
}
push_parameter(app, cmd_context, par_lex_as_cpp_file, treat_as_code);
push_parameter(app, cmd_context, par_wrap_lines, !treat_as_code);
push_parameter(app, cmd_context, par_key_mapid, (treat_as_code)?(my_code_map):(mapid_file));
exec_command(cmd_context, cmdid_set_settings);
}
CUSTOM_COMMAND_SIG(open_in_other){
exec_command(cmd_context, cmdid_change_active_panel);
exec_command(cmd_context, cmdid_interactive_open);
}
CUSTOM_COMMAND_SIG(open_my_files){
// NOTE(allen|a3.1): The command cmdid_interactive_open can now open
// a file specified on the parameter stack. If the file does not exist
// cmdid_interactive_open behaves as usual.
push_parameter(app, cmd_context, par_name, literal("w:/4ed/data/test/basic.cpp"));
exec_command(cmd_context, cmdid_interactive_open);
exec_command(cmd_context, cmdid_change_active_panel);
char my_file[256];
int my_file_len;
my_file_len = sizeof("w:/4ed/data/test/basic.txt") - 1;
for (int i = 0; i < my_file_len; ++i){
my_file[i] = ("w:/4ed/data/test/basic.txt")[i];
}
// NOTE(allen|a3.1): null terminators are not needed for strings.
push_parameter(app, cmd_context, par_name, my_file, my_file_len);
exec_command(cmd_context, cmdid_interactive_open);
exec_command(cmd_context, cmdid_change_active_panel);
}
CUSTOM_COMMAND_SIG(build_at_launch_location){
// NOTE(allen|a3.3): An example of calling build by setting all
// parameters directly. This only works if build.bat can be called
// from the starting directory
push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 1);
push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*"));
push_parameter(app, cmd_context, par_cli_path, literal("."));
push_parameter(app, cmd_context, par_cli_command, literal("build"));
exec_command(cmd_context, cmdid_build);
}
CUSTOM_COMMAND_SIG(build_search){
// NOTE(allen|a3.3): An example of traversing the filesystem through parent
// directories looking for a file, in this case a batch file to execute.
//
//
// Step 1: push_directory returns a String containing the current "hot" directory
// (whatever directory you most recently visited in the 4coder file browsing interface)
//
// Step 2: app->directory_has_file queries the file system to see if "build.bat" exists
// If it does exist several parameters are pushed:
// - par_cli_overlap_with_conflict: whether to launch this process if an existing process
// is already being used for output on the same buffer
//
// - par_target_buffer_name: the name of the buffer to fill with the output from the process
//
// - par_cli_path: sets the path from which the command is executed
//
// - par_cli_command: sets the actual command to be executed, this can be almost any command
// that you could execute through a command line interface
//
//
// To set par_cli_path: push_parameter makes a copy of the dir string on the stack
// because the string allocated by push_directory is going to change again
// To set par_cli_command: app->push_parameter does not make a copy of the dir because
// dir isn't going to change again.
//
// Step 3: If the batch file did not exist try to move to the parent directory using
// app->directory_cd. The cd function can also be used to navigate to subdirectories.
// It returns true if it can actually move in the specified direction, and false otherwise.
int keep_going = 1;
String dir = push_directory(app, cmd_context);
while (keep_going){
if (app->directory_has_file(dir, "build.bat")){
push_parameter(app, cmd_context, par_cli_overlap_with_conflict, 0);
push_parameter(app, cmd_context, par_target_buffer_name, literal("*compilation*"));
push_parameter(app, cmd_context, par_cli_path, dir.str, dir.size);
if (append(&dir, "build")){
app->push_parameter(cmd_context,
dynamic_int(par_cli_command),
dynamic_string(dir.str, dir.size));
exec_command(cmd_context, cmdid_build);
}
else{
clear_parameters(cmd_context);
}
return;
}
if (app->directory_cd(&dir, "..") == 0){
keep_going = 0;
}
}
// TODO(allen): feedback message - couldn't find build.bat
}
CUSTOM_COMMAND_SIG(write_and_auto_tab){
exec_command(cmd_context, cmdid_write_character);
exec_command(cmd_context, cmdid_auto_tab_line_at_cursor);
}
extern "C" GET_BINDING_DATA(get_bindings){
Bind_Helper context_actual = begin_bind_helper(data, size);
Bind_Helper *context = &context_actual;
// NOTE(allen|a3.1): Right now hooks have no loyalties to maps, all hooks are
// global and once set they always apply, regardless of what map is active.
set_hook(context, hook_start, my_start);
set_hook(context, hook_open_file, my_file_settings);
begin_map(context, mapid_global);
bind(context, 'p', MDFR_CTRL, cmdid_open_panel_vsplit);
bind(context, '-', MDFR_CTRL, cmdid_open_panel_hsplit);
bind(context, 'P', MDFR_CTRL, cmdid_close_panel);
bind(context, 'n', MDFR_CTRL, cmdid_interactive_new);
bind(context, 'o', MDFR_CTRL, cmdid_interactive_open);
bind(context, ',', MDFR_CTRL, cmdid_change_active_panel);
bind(context, 'k', MDFR_CTRL, cmdid_interactive_kill_buffer);
bind(context, 'i', MDFR_CTRL, cmdid_interactive_switch_buffer);
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
bind(context, 'x', MDFR_ALT, cmdid_open_menu);
bind_me(context, 'o', MDFR_ALT, open_in_other);
// NOTE(allen): These callbacks may not actually be useful to you, but
// go look at them and see what they do.
bind_me(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files);
bind_me(context, 'M', MDFR_ALT, build_at_launch_location);
bind_me(context, 'm', MDFR_ALT, build_search);
end_map(context);
begin_map(context, my_code_map);
// NOTE(allen|a3.1): Set this map (my_code_map == mapid_user_custom) to
// inherit from mapid_file. When searching if a key is bound
// in this map, if it is not found here it will then search mapid_file.
//
// If this is not set, it defaults to mapid_global.
inherit_map(context, mapid_file);
// NOTE(allen|a3.1): Children can override parent's bindings.
bind(context, codes->right, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_right);
bind(context, codes->left, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_left);
// NOTE(allen|a3.2): Specific keys can override vanilla keys,
// and write character writes whichever character corresponds
// to the key that triggered the command.
bind_me(context, '\n', MDFR_NONE, write_and_auto_tab);
bind_me(context, '}', MDFR_NONE, write_and_auto_tab);
bind_me(context, ')', MDFR_NONE, write_and_auto_tab);
bind_me(context, ']', MDFR_NONE, write_and_auto_tab);
bind_me(context, ';', MDFR_NONE, write_and_auto_tab);
bind(context, '\t', MDFR_NONE, cmdid_auto_tab_line_at_cursor);
bind(context, '\t', MDFR_CTRL, cmdid_auto_tab_range);
bind(context, '\t', MDFR_CTRL | MDFR_SHIFT, cmdid_write_character);
end_map(context);
begin_map(context, mapid_file);
// NOTE(allen|a3.1): Binding this essentially binds all key combos that
// would normally insert a character into a buffer.
// Or apply this rule (which always works): if the code for the key
// is not in the codes struct, it is a vanilla key.
// It is possible to override this binding for individual keys.
bind_vanilla_keys(context, cmdid_write_character);
bind(context, codes->left, MDFR_NONE, cmdid_move_left);
bind(context, codes->right, MDFR_NONE, cmdid_move_right);
bind(context, codes->del, MDFR_NONE, cmdid_delete);
bind(context, codes->back, MDFR_NONE, cmdid_backspace);
bind(context, codes->up, MDFR_NONE, cmdid_move_up);
bind(context, codes->down, MDFR_NONE, cmdid_move_down);
bind(context, codes->end, MDFR_NONE, cmdid_seek_end_of_line);
bind(context, codes->home, MDFR_NONE, cmdid_seek_beginning_of_line);
bind(context, codes->page_up, MDFR_NONE, cmdid_page_up);
bind(context, codes->page_down, MDFR_NONE, cmdid_page_down);
bind(context, codes->right, MDFR_CTRL, cmdid_seek_whitespace_right);
bind(context, codes->left, MDFR_CTRL, cmdid_seek_whitespace_left);
bind(context, codes->up, MDFR_CTRL, cmdid_seek_whitespace_up);
bind(context, codes->down, MDFR_CTRL, cmdid_seek_whitespace_down);
bind(context, ' ', MDFR_CTRL, cmdid_set_mark);
bind(context, 'm', MDFR_CTRL, cmdid_cursor_mark_swap);
bind(context, 'c', MDFR_CTRL, cmdid_copy);
bind(context, 'x', MDFR_CTRL, cmdid_cut);
bind(context, 'v', MDFR_CTRL, cmdid_paste);
bind(context, 'V', MDFR_CTRL, cmdid_paste_next);
bind(context, 'Z', MDFR_CTRL, cmdid_timeline_scrub);
bind(context, 'z', MDFR_CTRL, cmdid_undo);
bind(context, 'y', MDFR_CTRL, cmdid_redo);
bind(context, codes->left, MDFR_ALT, cmdid_increase_rewind_speed);
bind(context, codes->right, MDFR_ALT, cmdid_increase_fastforward_speed);
bind(context, codes->down, MDFR_ALT, cmdid_stop_rewind_fastforward);
bind(context, 'h', MDFR_CTRL, cmdid_history_backward);
bind(context, 'H', MDFR_CTRL, cmdid_history_forward);
bind(context, 'd', MDFR_CTRL, cmdid_delete_range);
bind(context, 'l', MDFR_CTRL, cmdid_toggle_line_wrap);
bind(context, 'L', MDFR_CTRL, cmdid_toggle_endline_mode);
bind(context, 'u', MDFR_CTRL, cmdid_to_uppercase);
bind(context, 'j', MDFR_CTRL, cmdid_to_lowercase);
bind(context, '?', MDFR_CTRL, cmdid_toggle_show_whitespace);
bind(context, '~', MDFR_CTRL, cmdid_clean_all_lines);
// NOTE(allen|a3.2): These now only set the mode of the file for writing to disk
// they do no longer effect the internal representation.
bind(context, '1', MDFR_CTRL, cmdid_eol_dosify);
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
bind(context, 'f', MDFR_CTRL, cmdid_search);
bind(context, 'r', MDFR_CTRL, cmdid_rsearch);
bind(context, 'g', MDFR_CTRL, cmdid_goto_line);
bind(context, 'K', MDFR_CTRL, cmdid_kill_buffer);
bind(context, 'O', MDFR_CTRL, cmdid_reopen);
bind(context, 'w', MDFR_CTRL, cmdid_interactive_save_as);
bind(context, 's', MDFR_CTRL, cmdid_save);
end_map(context);
end_bind_helper(context);
return context->write_total;
}
inline void
strset_(char *dst, char *src){
do{
*dst++ = *src++;
}while (*src);
}
#define strset(d,s) if (sizeof(s) <= sizeof(d)) strset_(d,s)
extern "C" SET_EXTRA_FONT_SIG(set_extra_font){
strset(font_out->file_name, "liberation-mono.ttf");
strset(font_out->font_name, "BIG");
font_out->size = 25;
}

View File

@ -1,337 +1,336 @@
#define MDFR_NONE 0
#define MDFR_CTRL 1
#define MDFR_ALT 2
#define MDFR_SHIFT 4
#define MDFR_NUMPAD 8
typedef unsigned char Code;
struct Key_Codes{
Code back;
Code up;
Code down;
Code left;
Code right;
Code del;
Code insert;
Code home;
Code end;
Code page_up;
Code page_down;
Code esc;
#if 0 // TODO(allen): Get these working sometime
union{
struct{
Code f1;
Code f2;
Code f3;
Code f4;
Code f5;
Code f6;
Code f7;
Code f8;
Code f9;
Code f10;
Code f11;
Code f12;
Code f13;
Code f14;
Code f15;
Code f16;
};
Code f[16];
};
#endif
};
enum Command_ID{
cmdid_null,
cmdid_write_character,
cmdid_seek_whitespace_right,
cmdid_seek_whitespace_left,
cmdid_seek_whitespace_up,
cmdid_seek_whitespace_down,
cmdid_seek_token_left,
cmdid_seek_token_right,
cmdid_seek_white_or_token_left,
cmdid_seek_white_or_token_right,
cmdid_seek_alphanumeric_left,
cmdid_seek_alphanumeric_right,
cmdid_seek_alphanumeric_or_camel_left,
cmdid_seek_alphanumeric_or_camel_right,
cmdid_search,
cmdid_rsearch,
cmdid_goto_line,
cmdid_set_mark,
cmdid_copy,
cmdid_cut,
cmdid_paste,
cmdid_paste_next,
cmdid_delete_range,
cmdid_timeline_scrub,
cmdid_undo,
cmdid_redo,
cmdid_increase_rewind_speed,
cmdid_increase_fastforward_speed,
cmdid_stop_rewind_fastforward,
cmdid_history_backward,
cmdid_history_forward,
cmdid_interactive_new,
cmdid_interactive_open,
cmdid_reopen,
cmdid_save,
cmdid_interactive_save_as,
cmdid_change_active_panel,
cmdid_interactive_switch_buffer,
cmdid_interactive_kill_buffer,
cmdid_kill_buffer,
cmdid_toggle_line_wrap,
cmdid_toggle_endline_mode,
cmdid_to_uppercase,
cmdid_to_lowercase,
cmdid_toggle_show_whitespace,
cmdid_clean_all_lines,
cmdid_eol_dosify,
cmdid_eol_nixify,
cmdid_auto_tab,
cmdid_auto_tab_range,
cmdid_auto_tab_line_at_cursor,
cmdid_auto_tab_whole_file,
cmdid_open_panel_vsplit,
cmdid_open_panel_hsplit,
cmdid_close_panel,
cmdid_move_left,
cmdid_move_right,
cmdid_delete,
cmdid_backspace,
cmdid_move_up,
cmdid_move_down,
cmdid_seek_end_of_line,
cmdid_seek_beginning_of_line,
cmdid_page_up,
cmdid_page_down,
cmdid_open_color_tweaker,
cmdid_close_minor_view,
cmdid_cursor_mark_swap,
cmdid_open_menu,
cmdid_set_settings,
cmdid_build,
//
cmdid_count
};
enum Param_ID{
par_name,
par_lex_as_cpp_file,
par_wrap_lines,
par_key_mapid,
par_target_buffer_name,
par_cli_path,
par_cli_command,
par_cli_overlap_with_conflict,
par_cli_always_bind_to_view,
// never below this
par_type_count
};
enum Hook_ID{
hook_start,
hook_open_file,
// never below this
hook_type_count
};
enum Dynamic_Type{
dynamic_type_int,
dynamic_type_string,
// never below this
dynamic_type_count
};
struct Dynamic{
int type;
union{
struct{
int str_len;
char *str_value;
};
int int_value;
};
};
inline Dynamic
dynamic_int(int x){
Dynamic result;
result.type = dynamic_type_int;
result.int_value = x;
return result;
}
inline Dynamic
dynamic_string(const char *string, int len){
Dynamic result;
result.type = dynamic_type_string;
result.str_len = len;
result.str_value = (char*)(string);
return result;
}
inline int
dynamic_to_int(Dynamic *dynamic){
int result = 0;
if (dynamic->type == dynamic_type_int){
result = dynamic->int_value;
}
return result;
}
inline char*
dynamic_to_string(Dynamic *dynamic, int *len){
char *result = 0;
if (dynamic->type == dynamic_type_string){
result = dynamic->str_value;
*len = dynamic->str_len;
}
return result;
}
inline int
dynamic_to_bool(Dynamic *dynamic){
int result = 0;
if (dynamic->type == dynamic_type_int){
result = (dynamic->int_value != 0);
}
else{
result = 1;
}
return result;
}
struct Extra_Font{
char file_name[256];
char font_name[24];
int size;
};
struct Buffer_Summary{
// NOTE(allen): None of these members nor any of the data pointed to
// by these members should be modified.
int file_id;
int size;
int file_name_len;
int buffer_name_len;
const char *file_name;
const char *buffer_name;
int file_cursor_pos;
int is_lexed;
int map_id;
};
#ifndef FRED_STRING_STRUCT
#define FRED_STRING_STRUCT
struct String{
char *str;
int size;
int memory_size;
};
#endif
#define GET_BINDING_DATA(name) int name(void *data, int size, Key_Codes *codes)
#define SET_EXTRA_FONT_SIG(name) void name(Extra_Font *font_out)
#define CUSTOM_COMMAND_SIG(name) void name(void *cmd_context, struct Application_Links *app)
#define HOOK_SIG(name) void name(void *cmd_context, struct Application_Links *app)
extern "C"{
typedef CUSTOM_COMMAND_SIG(Custom_Command_Function);
typedef GET_BINDING_DATA(Get_Binding_Data_Function);
typedef SET_EXTRA_FONT_SIG(Set_Extra_Font_Function);
typedef HOOK_SIG(Hook_Function);
}
#define PUSH_PARAMETER_SIG(name) void name(void *cmd_context, Dynamic param, Dynamic value)
#define PUSH_MEMORY_SIG(name) char* name(void *cmd_context, int len)
#define EXECUTE_COMMAND_SIG(name) void name(void *cmd_context, int command_id)
#define CLEAR_PARAMETERS_SIG(name) void name(void *cmd_context)
#define GET_ACTIVE_BUFFER_SIG(name) Buffer_Summary name(void *cmd_context)
#define DIRECTORY_GET_HOT_SIG(name) int name(void *cmd_context, char *buffer, int max)
#define DIRECTORY_HAS_FILE_SIG(name) int name(String dir, char *filename)
#define DIRECTORY_CD_SIG(name) int name(String *dir, char *rel_path)
extern "C"{
typedef EXECUTE_COMMAND_SIG(Exec_Command_Function);
typedef PUSH_PARAMETER_SIG(Push_Parameter_Function);
typedef PUSH_MEMORY_SIG(Push_Memory_Function);
typedef CLEAR_PARAMETERS_SIG(Clear_Parameters_Function);
typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function);
typedef DIRECTORY_GET_HOT_SIG(Directory_Get_Hot);
typedef DIRECTORY_HAS_FILE_SIG(Directory_Has_File);
typedef DIRECTORY_CD_SIG(Directory_CD);
}
struct Application_Links{
Exec_Command_Function *exec_command_keep_stack;
Push_Parameter_Function *push_parameter;
Push_Memory_Function *push_memory;
Clear_Parameters_Function *clear_parameters;
Get_Active_Buffer_Function *get_active_buffer;
Directory_Get_Hot *directory_get_hot;
Directory_Has_File *directory_has_file;
Directory_CD *directory_cd;
};
struct Custom_API{
Get_Binding_Data_Function *get_bindings;
Set_Extra_Font_Function *set_extra_font;
};
// NOTE(allen): definitions for the buffer that communicates to 4ed.exe
enum Binding_Unit_Type{
unit_header,
unit_map_begin,
unit_binding,
unit_callback,
unit_inherit,
unit_hook
};
enum Map_ID{
mapid_global,
mapid_file,
// NOTE(allen): mapid_nomap will remain empty even if you attempt to fill it
// it is for setting a map's parent to nothing
mapid_nomap,
mapid_user_custom = 100
};
struct Binding_Unit{
Binding_Unit_Type type;
union{
struct{ int total_size; int user_map_count; int error; } header;
struct{ int mapid; int bind_count; } map_begin;
struct{ int mapid; } map_inherit;
struct{
short code;
unsigned char modifiers;
int command_id;
} binding;
struct{
short code;
unsigned char modifiers;
Custom_Command_Function *func;
} callback;
struct{
int hook_id;
Custom_Command_Function *func;
} hook;
};
};
#define MDFR_NONE 0
#define MDFR_CTRL 1
#define MDFR_ALT 2
#define MDFR_SHIFT 4
#define MDFR_NUMPAD 8
typedef unsigned char Code;
struct Key_Codes{
Code back;
Code up;
Code down;
Code left;
Code right;
Code del;
Code insert;
Code home;
Code end;
Code page_up;
Code page_down;
Code esc;
#if 0 // TODO(allen): Get these working sometime
union{
struct{
Code f1;
Code f2;
Code f3;
Code f4;
Code f5;
Code f6;
Code f7;
Code f8;
Code f9;
Code f10;
Code f11;
Code f12;
Code f13;
Code f14;
Code f15;
Code f16;
};
Code f[16];
};
#endif
};
enum Command_ID{
cmdid_null,
cmdid_write_character,
cmdid_seek_whitespace_right,
cmdid_seek_whitespace_left,
cmdid_seek_whitespace_up,
cmdid_seek_whitespace_down,
cmdid_seek_token_left,
cmdid_seek_token_right,
cmdid_seek_white_or_token_left,
cmdid_seek_white_or_token_right,
cmdid_seek_alphanumeric_left,
cmdid_seek_alphanumeric_right,
cmdid_seek_alphanumeric_or_camel_left,
cmdid_seek_alphanumeric_or_camel_right,
cmdid_search,
cmdid_rsearch,
cmdid_goto_line,
cmdid_set_mark,
cmdid_copy,
cmdid_cut,
cmdid_paste,
cmdid_paste_next,
cmdid_delete_range,
cmdid_timeline_scrub,
cmdid_undo,
cmdid_redo,
cmdid_increase_rewind_speed,
cmdid_increase_fastforward_speed,
cmdid_stop_rewind_fastforward,
cmdid_history_backward,
cmdid_history_forward,
cmdid_interactive_new,
cmdid_interactive_open,
cmdid_reopen,
cmdid_save,
cmdid_interactive_save_as,
cmdid_change_active_panel,
cmdid_interactive_switch_buffer,
cmdid_interactive_kill_buffer,
cmdid_kill_buffer,
cmdid_toggle_line_wrap,
cmdid_toggle_endline_mode,
cmdid_to_uppercase,
cmdid_to_lowercase,
cmdid_toggle_show_whitespace,
cmdid_clean_all_lines,
cmdid_eol_dosify,
cmdid_eol_nixify,
cmdid_auto_tab,
cmdid_auto_tab_range,
cmdid_auto_tab_line_at_cursor,
cmdid_auto_tab_whole_file,
cmdid_open_panel_vsplit,
cmdid_open_panel_hsplit,
cmdid_close_panel,
cmdid_move_left,
cmdid_move_right,
cmdid_delete,
cmdid_backspace,
cmdid_move_up,
cmdid_move_down,
cmdid_seek_end_of_line,
cmdid_seek_beginning_of_line,
cmdid_page_up,
cmdid_page_down,
cmdid_open_color_tweaker,
cmdid_close_minor_view,
cmdid_cursor_mark_swap,
cmdid_open_menu,
cmdid_set_settings,
cmdid_build,
//
cmdid_count
};
enum Param_ID{
par_name,
par_lex_as_cpp_file,
par_wrap_lines,
par_key_mapid,
par_target_buffer_name,
par_cli_path,
par_cli_command,
par_cli_overlap_with_conflict,
par_cli_always_bind_to_view,
// never below this
par_type_count
};
enum Hook_ID{
hook_start,
hook_open_file,
// never below this
hook_type_count
};
enum Dynamic_Type{
dynamic_type_int,
dynamic_type_string,
// never below this
dynamic_type_count
};
struct Dynamic{
int type;
union{
struct{
int str_len;
char *str_value;
};
int int_value;
};
};
inline Dynamic
dynamic_int(int x){
Dynamic result;
result.type = dynamic_type_int;
result.int_value = x;
return result;
}
inline Dynamic
dynamic_string(const char *string, int len){
Dynamic result;
result.type = dynamic_type_string;
result.str_len = len;
result.str_value = (char*)(string);
return result;
}
inline int
dynamic_to_int(Dynamic *dynamic){
int result = 0;
if (dynamic->type == dynamic_type_int){
result = dynamic->int_value;
}
return result;
}
inline char*
dynamic_to_string(Dynamic *dynamic, int *len){
char *result = 0;
if (dynamic->type == dynamic_type_string){
result = dynamic->str_value;
*len = dynamic->str_len;
}
return result;
}
inline int
dynamic_to_bool(Dynamic *dynamic){
int result = 0;
if (dynamic->type == dynamic_type_int){
result = (dynamic->int_value != 0);
}
else{
result = 1;
}
return result;
}
struct Extra_Font{
char file_name[256];
char font_name[24];
int size;
};
struct Buffer_Summary{
// NOTE(allen): None of these members nor any of the data pointed to
// by these members should be modified.
int file_id;
int size;
int file_name_len;
int buffer_name_len;
const char *file_name;
const char *buffer_name;
int file_cursor_pos;
int is_lexed;
int map_id;
};
#ifndef FRED_STRING_STRUCT
#define FRED_STRING_STRUCT
struct String{
char *str;
int size;
int memory_size;
};
#endif
#define GET_BINDING_DATA(name) int name(void *data, int size, Key_Codes *codes)
#define SET_EXTRA_FONT_SIG(name) void name(Extra_Font *font_out)
#define CUSTOM_COMMAND_SIG(name) void name(void *cmd_context, struct Application_Links *app)
#define HOOK_SIG(name) void name(void *cmd_context, struct Application_Links *app)
extern "C"{
typedef CUSTOM_COMMAND_SIG(Custom_Command_Function);
typedef GET_BINDING_DATA(Get_Binding_Data_Function);
typedef SET_EXTRA_FONT_SIG(Set_Extra_Font_Function);
typedef HOOK_SIG(Hook_Function);
}
#define PUSH_PARAMETER_SIG(name) void name(void *cmd_context, Dynamic param, Dynamic value)
#define PUSH_MEMORY_SIG(name) char* name(void *cmd_context, int len)
#define EXECUTE_COMMAND_SIG(name) void name(void *cmd_context, int command_id)
#define CLEAR_PARAMETERS_SIG(name) void name(void *cmd_context)
#define GET_ACTIVE_BUFFER_SIG(name) Buffer_Summary name(void *cmd_context)
#define DIRECTORY_GET_HOT_SIG(name) int name(void *cmd_context, char *buffer, int max)
#define DIRECTORY_HAS_FILE_SIG(name) int name(String dir, char *filename)
#define DIRECTORY_CD_SIG(name) int name(String *dir, char *rel_path)
extern "C"{
typedef EXECUTE_COMMAND_SIG(Exec_Command_Function);
typedef PUSH_PARAMETER_SIG(Push_Parameter_Function);
typedef PUSH_MEMORY_SIG(Push_Memory_Function);
typedef CLEAR_PARAMETERS_SIG(Clear_Parameters_Function);
typedef GET_ACTIVE_BUFFER_SIG(Get_Active_Buffer_Function);
typedef DIRECTORY_GET_HOT_SIG(Directory_Get_Hot);
typedef DIRECTORY_HAS_FILE_SIG(Directory_Has_File);
typedef DIRECTORY_CD_SIG(Directory_CD);
}
struct Application_Links{
Exec_Command_Function *exec_command_keep_stack;
Push_Parameter_Function *push_parameter;
Push_Memory_Function *push_memory;
Clear_Parameters_Function *clear_parameters;
Get_Active_Buffer_Function *get_active_buffer;
Directory_Get_Hot *directory_get_hot;
Directory_Has_File *directory_has_file;
Directory_CD *directory_cd;
};
struct Custom_API{
Get_Binding_Data_Function *get_bindings;
};
// NOTE(allen): definitions for the buffer that communicates to 4ed.exe
enum Binding_Unit_Type{
unit_header,
unit_map_begin,
unit_binding,
unit_callback,
unit_inherit,
unit_hook
};
enum Map_ID{
mapid_global = (1 << 24),
mapid_file,
// NOTE(allen): mapid_nomap will remain empty even if you attempt to fill it
// it is for setting a map's parent to nothing, in cases where you don't want
// to inherit from global (which is the default).
mapid_nomap
};
struct Binding_Unit{
Binding_Unit_Type type;
union{
struct{ int total_size; int user_map_count; int error; } header;
struct{ int mapid; int bind_count; } map_begin;
struct{ int mapid; } map_inherit;
struct{
short code;
unsigned char modifiers;
int command_id;
} binding;
struct{
short code;
unsigned char modifiers;
Custom_Command_Function *func;
} callback;
struct{
int hook_id;
Custom_Command_Function *func;
} hook;
};
};

View File

@ -1,252 +1,252 @@
/*
* Bind helper struct and functions
*/
struct Bind_Helper{
Binding_Unit *cursor, *start, *end;
Binding_Unit *header, *group;
int write_total;
int error;
};
#define BH_ERR_NONE 0
#define BH_ERR_MISSING_END 1
#define BH_ERR_MISSING_BEGIN 2
#define BH_ERR_OUT_OF_MEMORY 3
inline void
copy(char *dest, const char *src, int len){
for (int i = 0; i < len; ++i){
*dest++ = *src++;
}
}
inline Binding_Unit*
write_unit(Bind_Helper *helper, Binding_Unit unit){
Binding_Unit *p = 0;
helper->write_total += sizeof(*p);
if (helper->error == 0 && helper->cursor != helper->end){
p = helper->cursor++;
*p = unit;
}
return p;
}
inline char*
write_inline_string(Bind_Helper *helper, char *value, int len){
char *dest = 0;
helper->write_total += len;
if (helper->error == 0){
dest = (char*)helper->cursor;
int cursor_advance = len + sizeof(*helper->cursor) - 1;
cursor_advance /= sizeof(*helper->cursor);
cursor_advance *= sizeof(*helper->cursor);
helper->cursor += cursor_advance;
if (helper->cursor < helper->end){
copy(dest, value, len);
}
else{
helper->error = BH_ERR_OUT_OF_MEMORY;
}
}
return dest;
}
inline Bind_Helper
begin_bind_helper(void *data, int size){
Bind_Helper result;
result.header = 0;
result.group = 0;
result.write_total = 0;
result.error = 0;
result.cursor = (Binding_Unit*)data;
result.start = result.cursor;
result.end = result.start + size / sizeof(*result.cursor);
Binding_Unit unit;
unit.type = unit_header;
unit.header.total_size = sizeof(*result.header);
result.header = write_unit(&result, unit);
result.header->header.user_map_count = 0;
return result;
}
inline void
begin_map(Bind_Helper *helper, int mapid){
if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END;
if (!helper->error && mapid >= mapid_user_custom) ++helper->header->header.user_map_count;
Binding_Unit unit;
unit.type = unit_map_begin;
unit.map_begin.mapid = mapid;
helper->group = write_unit(helper, unit);
helper->group->map_begin.bind_count = 0;
}
inline void
end_map(Bind_Helper *helper){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
helper->group = 0;
}
struct Bind_Target{
short code;
unsigned char modifiers;
};
inline Bind_Target
tkey(short code, unsigned char modifiers){
Bind_Target target;
target.code = code;
target.modifiers = modifiers;
return target;
}
inline void
bind(Bind_Helper *helper, Bind_Target target, int cmdid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = unit_binding;
unit.binding.command_id = cmdid;
unit.binding.code = target.code;
unit.binding.modifiers = target.modifiers;
write_unit(helper, unit);
}
inline void
bind_me(Bind_Helper *helper, Bind_Target target, Custom_Command_Function *func){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = unit_callback;
unit.callback.func = func;
unit.callback.code = target.code;
unit.callback.modifiers = target.modifiers;
write_unit(helper, unit);
}
inline void
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
Bind_Target target;
target = tkey(code, modifiers);
bind(helper, target, cmdid);
}
inline void
bind_me(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
Bind_Target target;
target = tkey(code, modifiers);
bind_me(helper, target, func);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, int cmdid){
bind(helper, 0, 0, cmdid);
}
inline void
bind_me_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){
bind_me(helper, 0, 0, func);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, int cmdid){
bind(helper, 0, modifiers, cmdid);
}
inline void
bind_me_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, Custom_Command_Function *func){
bind_me(helper, 0, modifiers, func);
}
inline void
inherit_map(Bind_Helper *helper, int mapid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error && mapid >= mapid_user_custom) ++helper->header->header.user_map_count;
Binding_Unit unit;
unit.type = unit_inherit;
unit.map_inherit.mapid = mapid;
write_unit(helper, unit);
}
inline void
set_hook(Bind_Helper *helper, int hook_id, Custom_Command_Function *func){
Binding_Unit unit;
unit.type = unit_hook;
unit.hook.hook_id = hook_id;
unit.hook.func = func;
write_unit(helper, unit);
}
inline void
end_bind_helper(Bind_Helper *helper){
if (helper->header){
helper->header->header.total_size = (int)(helper->cursor - helper->start);
helper->header->header.error = helper->error;
}
}
// NOTE(allen): Useful functions and overloads on app links
inline void
push_parameter(Application_Links *app, void *cmd_context, int param, int value){
app->push_parameter(cmd_context, dynamic_int(param), dynamic_int(value));
}
inline void
push_parameter(Application_Links *app, void *cmd_context, int param, const char *value, int value_len){
char *value_copy = app->push_memory(cmd_context, value_len+1);
copy(value_copy, value, value_len);
value_copy[value_len] = 0;
app->push_parameter(cmd_context, dynamic_int(param), dynamic_string(value_copy, value_len));
}
inline void
push_parameter(Application_Links *app, void *cmd_context, const char *param, int param_len, int value){
char *param_copy = app->push_memory(cmd_context, param_len+1);
copy(param_copy, param, param_len);
param_copy[param_len] = 0;
app->push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_int(value));
}
inline void
push_parameter(Application_Links *app, void *cmd_context, const char *param, int param_len, const char *value, int value_len){
char *param_copy = app->push_memory(cmd_context, param_len+1);
char *value_copy = app->push_memory(cmd_context, value_len+1);
copy(param_copy, param, param_len);
copy(value_copy, value, value_len);
value_copy[value_len] = 0;
param_copy[param_len] = 0;
app->push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_string(value_copy, value_len));
}
inline String
push_directory(Application_Links *app, void *cmd_context){
String result;
result.memory_size = 512;
result.str = app->push_memory(cmd_context, result.memory_size);
result.size = app->directory_get_hot(cmd_context, result.str, result.memory_size);
return(result);
}
#define dir_string(d) ((d).str), ((d).size)
#define exec_command_keep_stack app->exec_command_keep_stack
#define clear_parameters app->clear_parameters
#define get_active_buffer app->get_active_buffer
#define exec_command(cmd_context, id) \
exec_command_keep_stack(cmd_context, id); \
clear_parameters(cmd_context)
/*
* Bind helper struct and functions
*/
struct Bind_Helper{
Binding_Unit *cursor, *start, *end;
Binding_Unit *header, *group;
int write_total;
int error;
};
#define BH_ERR_NONE 0
#define BH_ERR_MISSING_END 1
#define BH_ERR_MISSING_BEGIN 2
#define BH_ERR_OUT_OF_MEMORY 3
inline void
copy(char *dest, const char *src, int len){
for (int i = 0; i < len; ++i){
*dest++ = *src++;
}
}
inline Binding_Unit*
write_unit(Bind_Helper *helper, Binding_Unit unit){
Binding_Unit *p = 0;
helper->write_total += sizeof(*p);
if (helper->error == 0 && helper->cursor != helper->end){
p = helper->cursor++;
*p = unit;
}
return p;
}
inline char*
write_inline_string(Bind_Helper *helper, char *value, int len){
char *dest = 0;
helper->write_total += len;
if (helper->error == 0){
dest = (char*)helper->cursor;
int cursor_advance = len + sizeof(*helper->cursor) - 1;
cursor_advance /= sizeof(*helper->cursor);
cursor_advance *= sizeof(*helper->cursor);
helper->cursor += cursor_advance;
if (helper->cursor < helper->end){
copy(dest, value, len);
}
else{
helper->error = BH_ERR_OUT_OF_MEMORY;
}
}
return dest;
}
inline Bind_Helper
begin_bind_helper(void *data, int size){
Bind_Helper result;
result.header = 0;
result.group = 0;
result.write_total = 0;
result.error = 0;
result.cursor = (Binding_Unit*)data;
result.start = result.cursor;
result.end = result.start + size / sizeof(*result.cursor);
Binding_Unit unit;
unit.type = unit_header;
unit.header.total_size = sizeof(*result.header);
result.header = write_unit(&result, unit);
result.header->header.user_map_count = 0;
return result;
}
inline void
begin_map(Bind_Helper *helper, int mapid){
if (helper->group != 0 && helper->error == 0) helper->error = BH_ERR_MISSING_END;
if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count;
Binding_Unit unit;
unit.type = unit_map_begin;
unit.map_begin.mapid = mapid;
helper->group = write_unit(helper, unit);
helper->group->map_begin.bind_count = 0;
}
inline void
end_map(Bind_Helper *helper){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
helper->group = 0;
}
struct Bind_Target{
short code;
unsigned char modifiers;
};
inline Bind_Target
tkey(short code, unsigned char modifiers){
Bind_Target target;
target.code = code;
target.modifiers = modifiers;
return target;
}
inline void
bind(Bind_Helper *helper, Bind_Target target, int cmdid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = unit_binding;
unit.binding.command_id = cmdid;
unit.binding.code = target.code;
unit.binding.modifiers = target.modifiers;
write_unit(helper, unit);
}
inline void
bind_me(Bind_Helper *helper, Bind_Target target, Custom_Command_Function *func){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error) ++helper->group->map_begin.bind_count;
Binding_Unit unit;
unit.type = unit_callback;
unit.callback.func = func;
unit.callback.code = target.code;
unit.callback.modifiers = target.modifiers;
write_unit(helper, unit);
}
inline void
bind(Bind_Helper *helper, short code, unsigned char modifiers, int cmdid){
Bind_Target target;
target = tkey(code, modifiers);
bind(helper, target, cmdid);
}
inline void
bind_me(Bind_Helper *helper, short code, unsigned char modifiers, Custom_Command_Function *func){
Bind_Target target;
target = tkey(code, modifiers);
bind_me(helper, target, func);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, int cmdid){
bind(helper, 0, 0, cmdid);
}
inline void
bind_me_vanilla_keys(Bind_Helper *helper, Custom_Command_Function *func){
bind_me(helper, 0, 0, func);
}
inline void
bind_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, int cmdid){
bind(helper, 0, modifiers, cmdid);
}
inline void
bind_me_vanilla_keys(Bind_Helper *helper, unsigned char modifiers, Custom_Command_Function *func){
bind_me(helper, 0, modifiers, func);
}
inline void
inherit_map(Bind_Helper *helper, int mapid){
if (helper->group == 0 && helper->error == 0) helper->error = BH_ERR_MISSING_BEGIN;
if (!helper->error && mapid < mapid_global) ++helper->header->header.user_map_count;
Binding_Unit unit;
unit.type = unit_inherit;
unit.map_inherit.mapid = mapid;
write_unit(helper, unit);
}
inline void
set_hook(Bind_Helper *helper, int hook_id, Custom_Command_Function *func){
Binding_Unit unit;
unit.type = unit_hook;
unit.hook.hook_id = hook_id;
unit.hook.func = func;
write_unit(helper, unit);
}
inline void
end_bind_helper(Bind_Helper *helper){
if (helper->header){
helper->header->header.total_size = (int)(helper->cursor - helper->start);
helper->header->header.error = helper->error;
}
}
// NOTE(allen): Useful functions and overloads on app links
inline void
push_parameter(Application_Links *app, void *cmd_context, int param, int value){
app->push_parameter(cmd_context, dynamic_int(param), dynamic_int(value));
}
inline void
push_parameter(Application_Links *app, void *cmd_context, int param, const char *value, int value_len){
char *value_copy = app->push_memory(cmd_context, value_len+1);
copy(value_copy, value, value_len);
value_copy[value_len] = 0;
app->push_parameter(cmd_context, dynamic_int(param), dynamic_string(value_copy, value_len));
}
inline void
push_parameter(Application_Links *app, void *cmd_context, const char *param, int param_len, int value){
char *param_copy = app->push_memory(cmd_context, param_len+1);
copy(param_copy, param, param_len);
param_copy[param_len] = 0;
app->push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_int(value));
}
inline void
push_parameter(Application_Links *app, void *cmd_context, const char *param, int param_len, const char *value, int value_len){
char *param_copy = app->push_memory(cmd_context, param_len+1);
char *value_copy = app->push_memory(cmd_context, value_len+1);
copy(param_copy, param, param_len);
copy(value_copy, value, value_len);
value_copy[value_len] = 0;
param_copy[param_len] = 0;
app->push_parameter(cmd_context, dynamic_string(param_copy, param_len), dynamic_string(value_copy, value_len));
}
inline String
push_directory(Application_Links *app, void *cmd_context){
String result;
result.memory_size = 512;
result.str = app->push_memory(cmd_context, result.memory_size);
result.size = app->directory_get_hot(cmd_context, result.str, result.memory_size);
return(result);
}
#define dir_string(d) ((d).str), ((d).size)
#define exec_command_keep_stack app->exec_command_keep_stack
#define clear_parameters app->clear_parameters
#define get_active_buffer app->get_active_buffer
#define exec_command(cmd_context, id) \
exec_command_keep_stack(cmd_context, id); \
clear_parameters(cmd_context)

File diff suppressed because it is too large Load Diff

View File

@ -220,6 +220,7 @@ enum Cpp_Token_Type{
CPP_PP_UNKNOWN,
CPP_TOKEN_DEFINED,
CPP_TOKEN_INCLUDE_FILE,
CPP_TOKEN_ERROR_MESSAGE,
// NOTE(allen): used in the parser
CPP_TOKEN_EOF
@ -256,6 +257,7 @@ enum Cpp_Preprocessor_State{
CPP_LEX_PP_BODY,
CPP_LEX_PP_BODY_IF,
CPP_LEX_PP_NUMBER,
CPP_LEX_PP_ERROR,
CPP_LEX_PP_JUNK,
// NEVER ADD BELOW THIS
CPP_LEX_PP_COUNT
@ -450,6 +452,7 @@ FCPP_GLOBAL String_And_Flag keyword_strings[] = {
{"long", CPP_TOKEN_KEY_MODIFIER},
{"short", CPP_TOKEN_KEY_MODIFIER},
{"unsigned", CPP_TOKEN_KEY_MODIFIER},
{"const", CPP_TOKEN_KEY_QUALIFIER},
{"volatile", CPP_TOKEN_KEY_QUALIFIER},
@ -766,7 +769,7 @@ cpp_read_junk_line(Cpp_File file, int pos){
--pos;
}
result.pos = pos;
result.token.size = pos - result.token.start - 1;
result.token.size = pos - result.token.start;
}
return result;
@ -1348,6 +1351,9 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
lex.pp_state = CPP_LEX_PP_NUMBER;
break;
case CPP_PP_ERROR:
lex.pp_state = CPP_LEX_PP_ERROR;
break;
case CPP_PP_UNKNOWN:
case CPP_PP_ELSE:
case CPP_PP_ENDIF:
@ -1383,7 +1389,8 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
}
else{
if (lex.pp_state == CPP_LEX_PP_IDENTIFIER){
switch (lex.pp_state){
case CPP_LEX_PP_IDENTIFIER:
if (!char_is_alpha_numeric(current)){
has_result = 0;
lex.pp_state = CPP_LEX_PP_JUNK;
@ -1394,8 +1401,9 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
lex.pos = result.pos;
lex.pp_state = CPP_LEX_PP_JUNK;
}
}
else if (lex.pp_state == CPP_LEX_PP_MACRO_IDENTIFIER){
break;
case CPP_LEX_PP_MACRO_IDENTIFIER:
if (!char_is_alpha_numeric(current)){
has_result = 0;
lex.pp_state = CPP_LEX_PP_JUNK;
@ -1406,9 +1414,9 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
lex.pos = result.pos;
lex.pp_state = CPP_LEX_PP_BODY;
}
}
else if (lex.pp_state == CPP_LEX_PP_INCLUDE){
break;
case CPP_LEX_PP_INCLUDE:
if (current != '"' && current != '<'){
has_result = 0;
lex.pp_state = CPP_LEX_PP_JUNK;
@ -1418,8 +1426,9 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
lex.pos = result.pos;
lex.pp_state = CPP_LEX_PP_JUNK;
}
}
else if (lex.pp_state == CPP_LEX_PP_BODY){
break;
case CPP_LEX_PP_BODY:
if (current == '#'){
result = cpp_read_pp_operator(file, lex.pos);
}
@ -1428,8 +1437,9 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
}
lex.pos = result.pos;
result.token.flags |= CPP_TFLAG_PP_BODY;
}
else if (lex.pp_state == CPP_LEX_PP_BODY_IF){
break;
case CPP_LEX_PP_BODY_IF:
if (current == '#'){
result = cpp_read_pp_operator(file, lex.pos);
}
@ -1438,9 +1448,9 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
}
lex.pos = result.pos;
result.token.flags |= CPP_TFLAG_PP_BODY;
}
else if (lex.pp_state == CPP_LEX_PP_NUMBER){
break;
case CPP_LEX_PP_NUMBER:
if (!char_is_numeric(current)){
has_result = 0;
lex.pp_state = CPP_LEX_PP_JUNK;
@ -1451,8 +1461,17 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
result.token.flags |= CPP_TFLAG_PP_BODY;
lex.pp_state = CPP_LEX_PP_INCLUDE;
}
}
else{
break;
case CPP_LEX_PP_ERROR:
result = cpp_read_junk_line(file, lex.pos);
lex.pos = result.pos;
result.token.type = CPP_TOKEN_ERROR_MESSAGE;
result.token.flags |= CPP_TFLAG_PP_BODY;
break;
default:
{
bool took_comment = 0;
if (current == '/' && lex.pos + 1 < file.size){
if (file.data[lex.pos + 1] == '/'){
@ -1472,6 +1491,8 @@ cpp_lex_step(Cpp_File file, Cpp_Lex_Data *lex_data){
lex.pos = result.pos;
result.token.flags |= CPP_TFLAG_PP_BODY;
}
}break;
}
}
}

209
4ed.cpp
View File

@ -122,7 +122,7 @@ app_get_map_index(App_Vars *vars, i32 mapid){
internal Command_Map*
app_get_map(App_Vars *vars, i32 mapid){
Command_Map *map = 0;
if (mapid >= mapid_user_custom) map = vars->user_maps + mapid - mapid_user_custom;
if (mapid < mapid_global) map = vars->user_maps + mapid;
else if (mapid == mapid_global) map = &vars->map_top;
else if (mapid == mapid_file) map = &vars->map_file;
return map;
@ -1065,10 +1065,12 @@ COMMAND_DECL(kill_buffer){
COMMAND_DECL(toggle_line_wrap){
ProfileMomentFunction();
REQ_FILE_VIEW(view);
REQ_FILE(file, view);
Relative_Scrolling scrolling = view_get_relative_scrolling(view);
if (view->unwrapped_lines){
view->unwrapped_lines = 0;
file->settings.unwrapped_lines = 0;
view->target_x = 0;
view->cursor =
view_compute_cursor_from_pos(view, view->cursor.pos);
@ -1076,6 +1078,7 @@ COMMAND_DECL(toggle_line_wrap){
}
else{
view->unwrapped_lines = 1;
file->settings.unwrapped_lines = 1;
view->cursor =
view_compute_cursor_from_pos(view, view->cursor.pos);
view->preferred_x = view->cursor.unwrapped_x;
@ -1660,6 +1663,8 @@ COMMAND_DECL(set_settings){
if (view->unwrapped_lines){
if (v){
view->unwrapped_lines = 0;
file->settings.unwrapped_lines = 0;
if (!file->state.is_loading){
Relative_Scrolling scrolling = view_get_relative_scrolling(view);
view->target_x = 0;
@ -1672,6 +1677,7 @@ COMMAND_DECL(set_settings){
else{
if (!v){
view->unwrapped_lines = 1;
file->settings.unwrapped_lines = 1;
if (!file->state.is_loading){
Relative_Scrolling scrolling = view_get_relative_scrolling(view);
@ -1688,7 +1694,7 @@ COMMAND_DECL(set_settings){
int v = dynamic_to_int(&param->param.value);
if (v == mapid_global) file->settings.base_map_id = mapid_global;
else if (v == mapid_file) file->settings.base_map_id = mapid_file;
else if (v >= mapid_user_custom){
else if (v < mapid_global){
int index = app_get_map_index(vars, v);
if (index < vars->user_map_count) file->settings.base_map_id = v;
else file->settings.base_map_id = mapid_file;
@ -2047,16 +2053,23 @@ setup_debug_commands(Command_Map *commands, Partition *part, Key_Codes *codes, C
internal void
setup_ui_commands(Command_Map *commands, Partition *part, Key_Codes *codes, Command_Map *parent){
map_init(commands, part, 12, parent);
map_init(commands, part, 32, parent);
commands->vanilla_keyboard_default.function = command_null;
map_add(commands, codes->left, MDFR_NONE, command_null);
map_add(commands, codes->right, MDFR_NONE, command_null);
map_add(commands, codes->up, MDFR_NONE, command_null);
map_add(commands, codes->down, MDFR_NONE, command_null);
map_add(commands, codes->back, MDFR_NONE, command_null);
map_add(commands, codes->esc, MDFR_NONE, command_close_minor_view);
// TODO(allen): This is hacky, when the new UI stuff happens, let's fix it, and by that
// I mean actually fix it, don't just say you fixed it with something stupid again.
u8 mdfr;
u8 mdfr_array[] = {MDFR_NONE, MDFR_SHIFT, MDFR_CTRL, MDFR_SHIFT | MDFR_CTRL};
for (i32 i = 0; i < 4; ++i){
mdfr = mdfr_array[i];
map_add(commands, codes->left, mdfr, command_null);
map_add(commands, codes->right, mdfr, command_null);
map_add(commands, codes->up, mdfr, command_null);
map_add(commands, codes->down, mdfr, command_null);
map_add(commands, codes->back, mdfr, command_null);
map_add(commands, codes->esc, mdfr, command_close_minor_view);
}
}
internal void
@ -2492,86 +2505,134 @@ HOOK_SIG(default_open_file_hook){
}
enum Command_Line_Action{
CLAct_Nothing,
CLAct_Ignore,
CLAct_UserFile,
CLAct_CustomDLL,
CLAct_InitialFilePosition,
CLAct_WindowSize,
CLAct_WindowMaximize,
CLAct_WindowPosition,
CLAct_Count
};
void
init_command_line_settings(App_Settings *settings, App_Plat_Settings *plat_settings,
init_command_line_settings(App_Settings *settings, Plat_Settings *plat_settings,
Command_Line_Parameters clparams){
char *arg;
Command_Line_Action action;
Command_Line_Action action = CLAct_Nothing;
i32 i,index;
b32 strict = 0;
settings->init_files_max = ArrayCount(settings->init_files);
for (i = 1; i < clparams.argc; ++i){
arg = clparams.argv[i];
if (arg[0] == '-'){
action = CLAct_Ignore;
switch (arg[1]){
case 'u': action = CLAct_UserFile; strict = 0; break;
case 'U': action = CLAct_UserFile; strict = 1; break;
case 'd': action = CLAct_CustomDLL; strict = 0; break;
case 'D': action = CLAct_CustomDLL; strict = 1; break;
case 'l': action = CLAct_InitialFilePosition; break;
case 'w': action = CLAct_WindowSize; break;
case 'p': action = CLAct_WindowPosition; break;
}
switch (action){
for (i = 1; i <= clparams.argc; ++i){
if (i == clparams.argc) arg = "";
else arg = clparams.argv[i];
switch (action){
case CLAct_Nothing:
{
if (arg[0] == '-'){
action = CLAct_Ignore;
switch (arg[1]){
case 'u': action = CLAct_UserFile; strict = 0; break;
case 'U': action = CLAct_UserFile; strict = 1; break;
case 'd': action = CLAct_CustomDLL; strict = 0; break;
case 'D': action = CLAct_CustomDLL; strict = 1; break;
case 'l': action = CLAct_InitialFilePosition; break;
case 'w': action = CLAct_WindowSize; break;
case 'W': action = CLAct_WindowMaximize; break;
case 'p': action = CLAct_WindowPosition; break;
}
}
else if (arg[0] != 0){
if (settings->init_files_count < settings->init_files_max){
index = settings->init_files_count++;
settings->init_files[index] = arg;
}
}
}break;
case CLAct_UserFile:
{
settings->user_file_is_strict = strict;
++i;
if (i < clparams.argc){
settings->user_file = clparams.argv[i];
}
break;
action = CLAct_Nothing;
}break;
case CLAct_CustomDLL:
{
plat_settings->custom_dll_is_strict = strict;
++i;
if (i < clparams.argc){
plat_settings->custom_dll = clparams.argv[i];
}
break;
action = CLAct_Nothing;
}break;
case CLAct_InitialFilePosition:
++i;
{
if (i < clparams.argc){
settings->initial_line = str_to_int(clparams.argv[i]);
}
break;
action = CLAct_Nothing;
}break;
case CLAct_WindowSize:
break;
case CLAct_WindowPosition:
break;
}
{
if (i + 1 < clparams.argc){
plat_settings->set_window_size = 1;
plat_settings->window_w = str_to_int(clparams.argv[i]);
plat_settings->window_h = str_to_int(clparams.argv[i+1]);
++i;
}
action = CLAct_Nothing;
}break;
case CLAct_WindowMaximize:
{
--i;
plat_settings->maximize_window = 1;
action = CLAct_Nothing;
}break;
}
else{
if (settings->init_files_count < settings->init_files_max){
index = settings->init_files_count++;
settings->init_files[index] = arg;
}
case CLAct_WindowPosition:
{
if (i + 1 < clparams.argc){
plat_settings->set_window_pos = 1;
plat_settings->window_x = str_to_int(clparams.argv[i]);
plat_settings->window_y = str_to_int(clparams.argv[i+1]);
++i;
}
action = CLAct_Nothing;
}break;
}
}
}
internal App_Vars*
app_setup_memory(Application_Memory *memory){
Partition _partition = partition_open(memory->vars_memory, memory->vars_memory_size);
App_Vars *vars = push_struct(&_partition, App_Vars);
Assert(vars);
*vars = {};
vars->mem.part = _partition;
general_memory_open(&vars->mem.general, memory->target_memory, memory->target_memory_size);
return(vars);
}
App_Read_Command_Line_Sig(app_read_command_line){
i32 output_size = 0;
//init_command_line_settings();
App_Vars *vars = app_setup_memory(memory);
init_command_line_settings(&vars->settings, plat_settings, clparams);
return(output_size);
}
@ -2579,17 +2640,11 @@ App_Read_Command_Line_Sig(app_read_command_line){
App_Init_Sig(app_init){
app_links_init(system);
Partition _partition = partition_open(memory->vars_memory, memory->vars_memory_size);
App_Vars *vars = push_struct(&_partition, App_Vars);
Assert(vars);
*vars = {};
App_Vars *vars = (App_Vars*)memory->vars_memory;
vars->config_api = api;
vars->mem.part = _partition;
Partition *partition = &vars->mem.part;
target->partition = partition;
general_memory_open(&vars->mem.general, memory->target_memory, memory->target_memory_size);
i32 panel_max_count = vars->layout.panel_max_count = 16;
i32 divider_max_count = panel_max_count - 1;
vars->layout.panel_count = 1;
@ -2687,7 +2742,7 @@ App_Init_Sig(app_init){
map_init(mapptr, &vars->mem.part, table_max, global);
did_file = 1;
}
else if (mapid >= mapid_user_custom){
else if (mapid < mapid_global){
i32 index = app_get_or_add_map_index(vars, mapid);
Assert(index < user_map_count);
mapptr = vars->user_maps + index;
@ -2702,7 +2757,7 @@ App_Init_Sig(app_init){
int mapid = unit->map_inherit.mapid;
if (mapid == mapid_global) parent = &vars->map_top;
else if (mapid == mapid_file) parent = &vars->map_file;
else if (mapid >= mapid_user_custom){
else if (mapid < mapid_global){
i32 index = app_get_or_add_map_index(vars, mapid);
if (index < user_map_count) parent = vars->user_maps + index;
else parent = 0;
@ -2819,27 +2874,6 @@ App_Init_Sig(app_init){
font_set_add(partition, vars->font_set, file_name, name, pt_size);
}
#if 0
if (vars->config_api.set_extra_font){
Extra_Font extra;
extra.size = 17;
vars->config_api.set_extra_font(&extra);
memory_used = 0;
if (app_load_font(target,
vars->fonts.fonts + font_count, extra.file_name, extra.size,
partition_current(partition),
&memory_used, 4, make_string_slowly(extra.font_name))){
++font_count;
}
else{
vars->fonts.fonts[font_count] = {};
}
push_block(partition, memory_used);
}
vars->fonts.count = font_count;
#endif
}
// NOTE(allen): file setup
@ -2918,6 +2952,7 @@ App_Step_Sig(app_step){
copy(dest, make_string((char*)clipboard.str, clipboard.size));
}
// TODO(allen): profile this make sure it's not costing me too much power.
// NOTE(allen): check files are up to date
for (i32 i = 0; i < vars->working_set.file_index_count; ++i){
Editing_File *file = vars->working_set.files + i;
@ -3277,9 +3312,19 @@ App_Step_Sig(app_step){
Temp_Memory param_stack_temp = begin_temp_memory(&vars->mem.part);
command_data.part = partition_sub_part(&vars->mem.part, 16 << 10);
if (first_step && vars->hooks[hook_start]){
vars->hooks[hook_start](&command_data, &app_links);
command_data.part.pos = 0;
if (first_step){
if (vars->hooks[hook_start]){
vars->hooks[hook_start](&command_data, &app_links);
command_data.part.pos = 0;
}
char *file_name;
i32 i;
for (i = 0; i < vars->settings.init_file_count; ++i){
file_name = vars->settings.init_files[i];
// TODO(allen): open files, do not attach to view
//app_open_file(system, vars, exchange,live_set, working_set, panel,command, string.str, string.size);
}
}
// NOTE(allen): command input to active view
@ -3366,7 +3411,7 @@ App_Step_Sig(app_step){
Assert(view_->do_view);
b32 active = (panel == active_panel);
Input_Summary input = (active)?(active_input):(dead_input);
if (panel == mouse_panel){
if (panel == mouse_panel && !mouse_data.out_of_window){
input.mouse = mouse_data;
}
if (view_->do_view(system, exchange, view_, panel->inner, active_view,

416
4ed.h
View File

@ -1,205 +1,211 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.12.2014
*
* Application Layer for 4coder
*
*/
// TOP
#ifndef FRED_H
#define FRED_H
struct Application_Memory{
void *vars_memory;
i32 vars_memory_size;
void *target_memory;
i32 target_memory_size;
};
#define KEY_INPUT_BUFFER_SIZE 4
#define KEY_INPUT_BUFFER_DSIZE (KEY_INPUT_BUFFER_SIZE << 1)
enum Key_Control{
CONTROL_KEY_SHIFT,
CONTROL_KEY_CONTROL,
CONTROL_KEY_ALT,
CONTROL_KEY_CAPS,
// always last
CONTROL_KEY_COUNT
};
struct Key_Event_Data{
u8 keycode;
u8 character;
u8 character_no_caps_lock;
b8 modifiers[CONTROL_KEY_COUNT];
};
struct Key_Input_Data{
Key_Event_Data press[KEY_INPUT_BUFFER_SIZE];
Key_Event_Data hold[KEY_INPUT_BUFFER_SIZE];
i32 press_count;
i32 hold_count;
};
struct Key_Summary{
i32 count;
Key_Event_Data keys[KEY_INPUT_BUFFER_DSIZE];
};
inline Key_Event_Data
get_single_key(Key_Summary *summary, i32 index){
Assert(index >= 0 && index < summary->count);
Key_Event_Data key;
key = summary->keys[index];
return key;
}
struct Mouse_State{
b32 out_of_window;
b8 left_button, right_button;
b8 left_button_pressed, right_button_pressed;
b8 left_button_released, right_button_released;
i16 wheel;
i32 x, y;
};
struct Mouse_Summary{
i32 mx, my;
b32 l, r;
b32 press_l, press_r;
b32 release_l, release_r;
b32 out_of_window;
b32 wheel_used;
i16 wheel_amount;
};
struct Input_Summary{
Mouse_Summary mouse;
Key_Summary keys;
Key_Codes *codes;
};
// TODO(allen): This can go, and we can just use a String for it.
struct Clipboard_Contents{
u8 *str;
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
};
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{
char **argv;
int argc;
};
struct App_Plat_Settings{
char *custom_dll;
b32 custom_dll_is_strict;
};
#define App_Read_Command_Line_Sig(name) \
i32 name(System_Functions *system, \
Application_Memory *memory, \
String current_directory, \
Command_Line_Parameters clparams \
)
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
#define App_Init_Sig(name) void \
name(System_Functions *system, \
Render_Target *target, \
Application_Memory *memory, \
Exchange *exchange, \
Key_Codes *codes, \
Clipboard_Contents clipboard, \
String current_directory, \
Custom_API api)
typedef App_Init_Sig(App_Init);
enum Application_Mouse_Cursor{
APP_MOUSE_CURSOR_DEFAULT,
APP_MOUSE_CURSOR_ARROW,
APP_MOUSE_CURSOR_IBEAM,
APP_MOUSE_CURSOR_LEFTRIGHT,
APP_MOUSE_CURSOR_UPDOWN,
// never below this
APP_MOUSE_CURSOR_COUNT
};
struct Application_Step_Result{
Application_Mouse_Cursor mouse_cursor_type;
b32 redraw;
b32 lctrl_lalt_is_altgr;
};
#define App_Step_Sig(name) void \
name(System_Functions *system, \
Key_Codes *codes, \
Key_Input_Data *input, \
Mouse_State *mouse, \
Render_Target *target, \
Application_Memory *memory, \
Exchange *exchange, \
Clipboard_Contents clipboard, \
b32 time_step, b32 first_step, b32 force_redraw, \
Application_Step_Result *result)
typedef App_Step_Sig(App_Step);
#define App_Alloc_Sig(name) void *name(void *handle, i32 size)
typedef App_Alloc_Sig(App_Alloc);
#define App_Free_Sig(name) void name(void *handle, void *block)
typedef App_Free_Sig(App_Free);
struct App_Functions{
App_Read_Command_Line *read_command_line;
App_Init *init;
App_Step *step;
App_Alloc *alloc;
App_Free *free;
};
#define App_Get_Functions_Sig(name) App_Functions name()
typedef App_Get_Functions_Sig(App_Get_Functions);
#endif
// BOTTOM
/*
* Mr. 4th Dimention - Allen Webster
*
* 12.12.2014
*
* Application Layer for 4coder
*
*/
// TOP
#ifndef FRED_H
#define FRED_H
struct Application_Memory{
void *vars_memory;
i32 vars_memory_size;
void *target_memory;
i32 target_memory_size;
};
#define KEY_INPUT_BUFFER_SIZE 4
#define KEY_INPUT_BUFFER_DSIZE (KEY_INPUT_BUFFER_SIZE << 1)
enum Key_Control{
CONTROL_KEY_SHIFT,
CONTROL_KEY_CONTROL,
CONTROL_KEY_ALT,
CONTROL_KEY_CAPS,
// always last
CONTROL_KEY_COUNT
};
struct Key_Event_Data{
u8 keycode;
u8 character;
u8 character_no_caps_lock;
b8 modifiers[CONTROL_KEY_COUNT];
};
struct Key_Input_Data{
Key_Event_Data press[KEY_INPUT_BUFFER_SIZE];
Key_Event_Data hold[KEY_INPUT_BUFFER_SIZE];
i32 press_count;
i32 hold_count;
};
struct Key_Summary{
i32 count;
Key_Event_Data keys[KEY_INPUT_BUFFER_DSIZE];
};
inline Key_Event_Data
get_single_key(Key_Summary *summary, i32 index){
Assert(index >= 0 && index < summary->count);
Key_Event_Data key;
key = summary->keys[index];
return key;
}
struct Mouse_State{
b32 out_of_window;
b8 left_button, right_button;
b8 left_button_pressed, right_button_pressed;
b8 left_button_released, right_button_released;
i16 wheel;
i32 x, y;
};
struct Mouse_Summary{
i32 mx, my;
b32 l, r;
b32 press_l, press_r;
b32 release_l, release_r;
b32 out_of_window;
b32 wheel_used;
i16 wheel_amount;
};
struct Input_Summary{
Mouse_Summary mouse;
Key_Summary keys;
Key_Codes *codes;
};
// TODO(allen): This can go, and we can just use a String for it.
struct Clipboard_Contents{
u8 *str;
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
};
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{
char **argv;
int argc;
};
struct Plat_Settings{
char *custom_dll;
b32 custom_dll_is_strict;
i32 window_w, window_h;
i32 window_x, window_y;
b8 set_window_pos, set_window_size;
b8 maximize_window;
};
#define App_Read_Command_Line_Sig(name) \
i32 name(System_Functions *system, \
Application_Memory *memory, \
String current_directory, \
Plat_Settings *plat_settings, \
Command_Line_Parameters clparams \
)
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
#define App_Init_Sig(name) void \
name(System_Functions *system, \
Render_Target *target, \
Application_Memory *memory, \
Exchange *exchange, \
Key_Codes *codes, \
Clipboard_Contents clipboard, \
String current_directory, \
Custom_API api)
typedef App_Init_Sig(App_Init);
enum Application_Mouse_Cursor{
APP_MOUSE_CURSOR_DEFAULT,
APP_MOUSE_CURSOR_ARROW,
APP_MOUSE_CURSOR_IBEAM,
APP_MOUSE_CURSOR_LEFTRIGHT,
APP_MOUSE_CURSOR_UPDOWN,
// never below this
APP_MOUSE_CURSOR_COUNT
};
struct Application_Step_Result{
Application_Mouse_Cursor mouse_cursor_type;
b32 redraw;
b32 lctrl_lalt_is_altgr;
};
#define App_Step_Sig(name) void \
name(System_Functions *system, \
Key_Codes *codes, \
Key_Input_Data *input, \
Mouse_State *mouse, \
Render_Target *target, \
Application_Memory *memory, \
Exchange *exchange, \
Clipboard_Contents clipboard, \
b32 time_step, b32 first_step, b32 force_redraw, \
Application_Step_Result *result)
typedef App_Step_Sig(App_Step);
#define App_Alloc_Sig(name) void *name(void *handle, i32 size)
typedef App_Alloc_Sig(App_Alloc);
#define App_Free_Sig(name) void name(void *handle, void *block)
typedef App_Free_Sig(App_Free);
struct App_Functions{
App_Read_Command_Line *read_command_line;
App_Init *init;
App_Step *step;
App_Alloc *alloc;
App_Free *free;
};
#define App_Get_Functions_Sig(name) App_Functions name()
typedef App_Get_Functions_Sig(App_Get_Functions);
#endif
// BOTTOM

View File

@ -1,25 +1,25 @@
/*
* Mr. 4th Dimention - Allen Webster
*
* 27.01.2016
*
* Global app level settings definition
*
*/
// TOP
struct App_Settings{
char *user_file;
b32 user_file_is_strict;
char *init_files[4];
i32 init_files_count;
i32 init_files_max;
i32 initial_line;
b32 lctrl_lalt_is_altgr;
};
// BOTTOM
/*
* Mr. 4th Dimention - Allen Webster
*
* 27.01.2016
*
* Global app level settings definition
*
*/
// TOP
struct App_Settings{
char *user_file;
b32 user_file_is_strict;
char *init_files[8];
i32 init_files_count;
i32 init_files_max;
i32 initial_line;
b32 lctrl_lalt_is_altgr;
};
// BOTTOM

View File

@ -99,6 +99,7 @@ struct Editing_File_Settings{
Font_Set *set;
i32 base_map_id;
i32 dos_write_mode;
b32 unwrapped_lines;
b8 tokens_exist;
b8 super_locked;
b8 is_initialized;
@ -1111,7 +1112,8 @@ struct File_View{
f32 scroll_y, target_y, vel_y;
f32 scroll_x, target_x, vel_x;
f32 preferred_x;
Full_Cursor scroll_y_cursor;
i32 scroll_i;
union{
Incremental_Search isearch;
struct{
@ -1220,21 +1222,26 @@ file_save(System_Functions *system, Exchange *exchange, Mem_Options *mem,
i32 result = 0;
#if BUFFER_EXPERIMENT_SCALPEL <= 3
i32 max = buffer_size(&file->state.buffer) + file->state.buffer.line_count;
byte *data = (byte*)general_memory_allocate(&mem->general, max, 0);
Assert(data);
i32 size;
if (file->settings.dos_write_mode){
size = buffer_convert_out(&file->state.buffer, (char*)data, max);
}
else{
size = buffer_size(&file->state.buffer);
buffer_stringify(&file->state.buffer, 0, size, (char*)data);
}
i32 max, size;
byte *data;
b32 dos_write_mode = file->settings.dos_write_mode;
if (dos_write_mode)
max = buffer_size(&file->state.buffer) + file->state.buffer.line_count + 1;
else
max = buffer_size(&file->state.buffer);
data = (byte*)general_memory_allocate(&mem->general, max, 0);
Assert(data);
if (dos_write_mode)
size = buffer_convert_out(&file->state.buffer, (char*)data, max);
else
buffer_stringify(&file->state.buffer, 0, size = max, (char*)data);
i32 filename_len = str_size(filename);
result = exchange_save_file(exchange, filename, filename_len,
data, size, max);
data, size, max);
if (result == 0){
general_memory_free(&mem->general, data);
@ -2293,6 +2300,7 @@ view_set_file(System_Functions *system, File_View *view,
view->font_advance = info->advance;
view->font_height = info->height;
view->font_set = set;
view->unwrapped_lines = file->settings.unwrapped_lines;
file->settings.set = set;
view->cursor = {};
@ -2647,6 +2655,83 @@ file_pre_edit_maintenance(System_Functions *system,
file->state.last_4ed_edit_time = system->time();
}
struct Cursor_Fix_Descriptor{
b32 is_batch;
union{
struct{
Buffer_Edit *batch;
i32 batch_size;
};
struct{
i32 start, end;
i32 shift_amount;
};
};
};
internal void
file_edit_cursor_fix(System_Functions *system,
Partition *part, General_Memory *general,
Editing_File *file, Editing_Layout *layout,
Cursor_Fix_Descriptor desc){
Full_Cursor temp_cursor;
Temp_Memory cursor_temp = begin_temp_memory(part);
i32 cursor_max = layout->panel_max_count * 2;
Cursor_With_Index *cursors = push_array(part, Cursor_With_Index, cursor_max);
i32 panel_count = layout->panel_count;
i32 cursor_count = 0;
Panel *current_panel = layout->panels;
for (i32 i = 0; i < panel_count; ++i, ++current_panel){
File_View *current_view = view_to_file_view(current_panel->view);
if (current_view && current_view->file == file){
view_measure_wraps(system, general, current_view);
write_cursor_with_index(cursors, &cursor_count, current_view->cursor.pos);
write_cursor_with_index(cursors, &cursor_count, current_view->mark);
write_cursor_with_index(cursors, &cursor_count, current_view->scroll_i);
}
}
if (cursor_count > 0){
buffer_sort_cursors(cursors, cursor_count);
if (desc.is_batch){
buffer_batch_edit_update_cursors(cursors, cursor_count,
desc.batch, desc.batch_size);
}
else{
buffer_update_cursors(cursors, cursor_count,
desc.start, desc.end,
desc.shift_amount + (desc.end - desc.start));
}
buffer_unsort_cursors(cursors, cursor_count);
cursor_count = 0;
current_panel = layout->panels;
for (i32 i = 0; i < panel_count; ++i, ++current_panel){
File_View *current_view = view_to_file_view(current_panel->view);
if (current_view && current_view->file == file){
view_cursor_move(current_view, cursors[cursor_count++].pos);
current_view->preferred_x = view_get_cursor_x(current_view);
current_view->mark = cursors[cursor_count++].pos;
current_view->scroll_i = cursors[cursor_count++].pos;
temp_cursor = view_compute_cursor_from_pos(current_view, current_view->scroll_i);
if (current_view->unwrapped_lines){
current_view->target_y += (temp_cursor.unwrapped_y - current_view->scroll_y);
current_view->scroll_y = temp_cursor.unwrapped_y;
}
else{
current_view->target_y += (temp_cursor.wrapped_y - current_view->scroll_y);
current_view->scroll_y = temp_cursor.wrapped_y;
}
}
}
}
end_temp_memory(cursor_temp);
}
internal void
file_do_single_edit(System_Functions *system,
Mem_Options *mem, Editing_File *file,
@ -2722,40 +2807,14 @@ file_do_single_edit(System_Functions *system,
#endif
#if BUFFER_EXPERIMENT_SCALPEL <= 3
Temp_Memory cursor_temp = begin_temp_memory(&mem->part);
i32 cursor_max = layout->panel_max_count * 2;
Cursor_With_Index *cursors = push_array(&mem->part, Cursor_With_Index, cursor_max);
Cursor_Fix_Descriptor desc = {};
desc.start = start;
desc.end = end;
desc.shift_amount = shift_amount;
i32 cursor_count = 0;
current_panel = layout->panels;
for (i32 i = 0; i < panel_count; ++i, ++current_panel){
File_View *current_view = view_to_file_view(current_panel->view);
if (current_view && current_view->file == file){
view_measure_wraps(system, general, current_view);
write_cursor_with_index(cursors, &cursor_count, current_view->cursor.pos);
write_cursor_with_index(cursors, &cursor_count, current_view->mark);
}
}
file_edit_cursor_fix(system, part, general,
file, layout, desc);
if (cursor_count > 0){
buffer_sort_cursors(cursors, cursor_count);
buffer_update_cursors(cursors, cursor_count,
start, end, shift_amount + (end - start));
buffer_unsort_cursors(cursors, cursor_count);
}
cursor_count = 0;
current_panel = layout->panels;
for (i32 i = 0; i < panel_count; ++i, ++current_panel){
File_View *current_view = view_to_file_view(current_panel->view);
if (current_view && current_view->file == file){
view_cursor_move(current_view, cursors[cursor_count++].pos);
current_view->mark = cursors[cursor_count++].pos;
current_view->preferred_x = view_get_cursor_x(current_view);
}
}
end_temp_memory(cursor_temp);
#endif
}
@ -2834,41 +2893,14 @@ view_do_white_batch_edit(System_Functions *system, Mem_Options *mem, File_View *
}
// NOTE(allen): cursor fixing
{
Temp_Memory cursor_temp = begin_temp_memory(part);
i32 cursor_max = layout->panel_max_count * 2;
Cursor_With_Index *cursors = push_array(part, Cursor_With_Index, cursor_max);
Cursor_Fix_Descriptor desc = {};
desc.is_batch = 1;
desc.batch = batch;
desc.batch_size = batch_size;
i32 panel_count = layout->panel_count;
i32 cursor_count = 0;
Panel *current_panel = layout->panels;
for (i32 i = 0; i < panel_count; ++i, ++current_panel){
File_View *current_view = view_to_file_view(current_panel->view);
if (current_view && current_view->file == file){
view_measure_wraps(system, general, current_view);
write_cursor_with_index(cursors, &cursor_count, current_view->cursor.pos);
write_cursor_with_index(cursors, &cursor_count, current_view->mark);
}
}
file_edit_cursor_fix(system, part, general,
file, layout, desc);
if (cursor_count > 0){
buffer_sort_cursors(cursors, cursor_count);
buffer_batch_edit_update_cursors(cursors, cursor_count, batch, batch_size);
buffer_unsort_cursors(cursors, cursor_count);
}
cursor_count = 0;
current_panel = layout->panels;
for (i32 i = 0; i < panel_count; ++i, ++current_panel){
File_View *current_view = view_to_file_view(current_panel->view);
if (current_view && current_view->file == file){
view_cursor_move(current_view, cursors[cursor_count++].pos);
current_view->mark = cursors[cursor_count++].pos;
current_view->preferred_x = view_get_cursor_x(current_view);
}
}
end_temp_memory(cursor_temp);
}
#endif
}
@ -4168,10 +4200,27 @@ draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *t
if (font) advance_data = font->advance_data;
i32 count;
Full_Cursor render_cursor;
Buffer_Render_Options opts = {};
buffer_get_render_data(&file->state.buffer, view->line_wrap_y, items, max, &count,
(f32)rect.x0, (f32)rect.y0, view->scroll_x, view->scroll_y, !view->unwrapped_lines,
(f32)max_x, (f32)max_y, advance_data, (f32)line_height, opts);
f32 *wraps = view->line_wrap_y;
f32 scroll_x = view->scroll_x;
f32 scroll_y = view->scroll_y;
{
render_cursor = buffer_get_start_cursor(&file->state.buffer, wraps, scroll_y,
!view->unwrapped_lines, (f32)max_x, advance_data, (f32)line_height);
view->scroll_i = render_cursor.pos;
buffer_get_render_data(&file->state.buffer, items, max, &count,
(f32)rect.x0, (f32)rect.y0,
scroll_x, scroll_y, render_cursor,
!view->unwrapped_lines,
(f32)max_x, (f32)max_y,
advance_data, (f32)line_height,
opts);
}
Assert(count > 0);
@ -4212,9 +4261,11 @@ draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *t
Buffer_Render_Item *item = items;
i32 prev_ind = -1;
u32 highlight_color = 0;
u32 highlight_this_color = 0;
for (i32 i = 0; i < count; ++i, ++item){
i32 ind = item->index;
highlight_this_color = 0;
if (tokens_use && ind != prev_ind){
Cpp_Token current_token = token_stack.tokens[token_i-1];
@ -4231,23 +4282,39 @@ draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *t
}
if (current_token.type == CPP_TOKEN_JUNK &&
i >= current_token.start && i <= current_token.start + current_token.size){
i >= current_token.start && i < current_token.start + current_token.size){
highlight_color = style->main.highlight_junk_color;
}
else{
highlight_color = 0;
}
}
u32 char_color = main_color;
u32 char_color = main_color;
if (item->flags & BRFlag_Special_Character) char_color = special_color;
f32_Rect char_rect = f32R(item->x0, item->y0, item->x1, item->y1);
if (view->show_whitespace && highlight_color == 0 &&
char_is_whitespace((char)item->glyphid)){
highlight_this_color = style->main.highlight_white_color;
}
else{
highlight_this_color = highlight_color;
}
if (cursor_begin <= ind && ind < cursor_end && (ind != prev_ind || cursor_begin < ind)){
if (is_active){
draw_rectangle(target, f32R(item->x0, item->y0, item->x1, item->y1), cursor_color);
draw_rectangle(target, char_rect, cursor_color);
char_color = at_cursor_color;
}
else draw_rectangle_outline(target, f32R(item->x0, item->y0, item->x1, item->y1), cursor_color);
else{
if (!view->show_temp_highlight){
draw_rectangle_outline(target, char_rect, cursor_color);
}
}
}
else if (highlight_color){
draw_rectangle(target, f32R(item->x0, item->y0, item->x1, item->y1), highlight_color);
else if (highlight_this_color){
draw_rectangle(target, char_rect, highlight_this_color);
}
u32 fade_color = 0xFFFF00FF;
@ -4263,7 +4330,7 @@ draw_file_loaded(File_View *view, i32_Rect rect, b32 is_active, Render_Target *t
char_color = color_blend(char_color, fade_amount, fade_color);
if (ind == view->mark && prev_ind != ind){
draw_rectangle_outline(target, f32R(item->x0, item->y0, item->x1, item->y1), mark_color);
draw_rectangle_outline(target, char_rect, mark_color);
}
if (item->glyphid != 0){
font_draw_glyph(target, font_id, (u8)item->glyphid,

View File

@ -14,28 +14,19 @@
internal void
keycode_init(Key_Codes *codes){
set_dynamic_key_names(codes);
u16 code, loose;
for (u16 i = 0; i < 255; ++i){
if (i >= 'a' && i <= 'z'){
keycode_lookup_table[i] = i + ('A' - 'a');
loose_keycode_lookup_table[i] = 0;
}
else if (i >= '0' && i <= '9'){
keycode_lookup_table[i] = i;
loose_keycode_lookup_table[i] = 0;
}
else{
loose = 0;
switch (i){
}
keycode_lookup_table[i] = code;
loose_keycode_lookup_table[i] = loose;
}
}
keycode_lookup_table[KEY_BACKSPACE] = codes->back;
keycode_lookup_table[KEY_DELETE] = codes->del;
keycode_lookup_table[KEY_UP] = codes->up;
keycode_lookup_table[KEY_DOWN] = codes->down;
keycode_lookup_table[KEY_LEFT] = codes->left;
keycode_lookup_table[KEY_RIGHT] = codes->right;
keycode_lookup_table[KEY_INSERT] = codes->insert;
keycode_lookup_table[KEY_HOME] = codes->home;
keycode_lookup_table[KEY_END] = codes->end;
keycode_lookup_table[KEY_PAGEUP] = codes->page_up;
keycode_lookup_table[KEY_PAGEDOWN] = codes->page_down;
keycode_lookup_table[KEY_ESC] = codes->esc;
}
// BOTTOM

View File

@ -112,7 +112,7 @@ _OutDbgStr(u8*);
TMax(u8, 255);
TMax(u16, 65535);
TMax(u32, 4294967295);
TMax(u64, 18446744073709551615);
TMax(u64, 18446744073709551615U);
TMax(i8, 127);
TMax(i16, 32767);

View File

@ -1145,13 +1145,33 @@ struct Buffer_Render_Options{
b8 show_slash_t;
};
internal_4tech Full_Cursor
buffer_get_start_cursor(Buffer_Type *buffer, float *wraps, float scroll_y,
int wrapped, float width, float *advance_data, float font_height){
Full_Cursor result;
if (wrapped){
result = buffer_cursor_from_wrapped_xy(buffer, 0, scroll_y, 0, wraps,
width, font_height, advance_data);
}
else{
result = buffer_cursor_from_unwrapped_xy(buffer, 0, scroll_y, 0, wraps,
width, font_height, advance_data);
}
return(result);
}
internal_4tech void
buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *items, int max, int *count,
float port_x, float port_y, float scroll_x, float scroll_y, int wrapped,
float width, float height, float *advance_data, float font_height,
buffer_get_render_data(Buffer_Type *buffer, Buffer_Render_Item *items, int max, int *count,
float port_x, float port_y,
float scroll_x, float scroll_y, Full_Cursor start_cursor,
int wrapped,
float width, float height,
float *advance_data, float font_height,
Buffer_Render_Options opts){
Buffer_Stringify_Type loop;
Full_Cursor start_cursor;
Buffer_Render_Item *item;
char *data;
int size, end;
@ -1160,21 +1180,13 @@ buffer_get_render_data(Buffer_Type *buffer, float *wraps, Buffer_Render_Item *it
int i, item_i;
float ch_width, ch_width_sub;
char ch;
size = buffer_size(buffer);
shift_x = port_x - scroll_x;
shift_y = port_y - scroll_y;
if (wrapped){
start_cursor = buffer_cursor_from_wrapped_xy(buffer, 0, scroll_y, 0, wraps,
width, font_height, advance_data);
shift_y += start_cursor.wrapped_y;
}
else{
start_cursor = buffer_cursor_from_unwrapped_xy(buffer, 0, scroll_y, 0, wraps,
width, font_height, advance_data);
shift_y += start_cursor.unwrapped_y;
}
if (wrapped) shift_y += start_cursor.wrapped_y;
else shift_y += start_cursor.unwrapped_y;
x = shift_x;
y = shift_y;

View File

@ -1,3 +1,3 @@
@echo off
call "w:\4ed\code\buildsuper.bat"
call "w:\4ed\misc\builddbg.bat"

View File

@ -9,50 +9,7 @@
// TOP
#ifdef FRED_NOT_PACKAGE
#define FRED_INTERNAL 1
#define FRED_SLOW 1
#define FRED_PRINT_DEBUG 1
#define FRED_PRINT_DEBUG_FILE_LINE 0
#define FRED_PROFILING 1
#define FRED_PROFILING_OS 0
#define FRED_FULL_ERRORS 0
#else
#define FRED_SLOW 0
#define FRED_INTERNAL 0
#define FRED_PRINT_DEBUG 0
#define FRED_PRINT_DEBUG_FILE_LINE 0
#define FRED_PROFILING 0
#define FRED_PROFILING_OS 0
#define FRED_FULL_ERRORS 0
#endif
#define SOFTWARE_RENDER 0
#if FRED_INTERNAL == 0
# undef FRED_PRINT_DEBUG
# define FRED_PRINT_DEBUG 0
# undef FRED_PROFILING
# define FRED_PROFILING 0
# undef FRED_PROFILING_OS
# define FRED_PROFILING_OS 0
#endif
#if FRED_PRINT_DEBUG == 0
# undef FRED_PRINT_DEBUG_FILE_LINE
# define FRED_PRINT_DEBUG_FILE_LINE 0
# undef FRED_PRINT_DEBUG_FILE_LINE
# define FRED_PROFILING_OS 0
#endif
#define FPS 30
#define frame_useconds (1000000 / FPS)
#include "4ed_config.h"
#include "4ed_meta.h"
@ -60,334 +17,480 @@
#include "4cpp_types.h"
#define FCPP_STRING_IMPLEMENTATION
#include "4cpp_string.h"
#include "4coder_string.h"
#include "4ed_mem.cpp"
#include "4ed_math.cpp"
#include "4coder_custom.h"
#include "4ed_system.h"
#include "4ed.h"
#include "4ed_rendering.h"
#include <sys/stat.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <GL/gl.h>
#include "4ed.h"
#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <stdio.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <xmmintrin.h>
#include <linux/fs.h>
#include <X11/extensions/XInput2.h>
#include <linux/input.h>
#include "4ed_internal.h"
#include "4ed_linux_keyboard.cpp"
#define printe(m) printf("%s:%d: %s\n", __FILE__, __LINE__, #m)
// NOTE(allen): Thanks to Casey for providing the linux OpenGL launcher.
/* TODO(allen):
struct Linux_Vars{
Key_Codes codes;
Key_Input_Data input;
Mouse_State mouse;
Render_Target target;
Application_Memory mem;
b32 keep_going;
b32 force_redraw;
Clipboard_Contents clipboard;
1. get 4coder rendering it's blank self
2. get input working
(release linux version)
3. add in extra stuff as it is completed in windows
*/
void *app_code, *custom;
System_Functions *system;
App_Functions app;
Config_API config_api;
};
Linux_Vars linuxvars;
internal
Sys_Get_Memory_Sig(system_get_memory_){
void *ptr = 0;
i32 prot = PROT_READ | PROT_WRITE;
i32 flags = MAP_PRIVATE | MAP_ANON;
#if FRED_INTERNAL
ptr = mmap(0, size + sizeof(Sys_Bubble), prot, flags, -1, 0);
Sys_Bubble *bubble = (Sys_Bubble*)ptr;
bubble->flags = MEM_BUBBLE_SYS_DEBUG;
bubble->line_number = line_number;
bubble->file_name = file_name;
bubble->size = size;
//WaitForSingleObject(win32vars.DEBUG_sysmem_lock, INFINITE);
insert_bubble(&win32vars.internal_bubble, bubble);
//ReleaseSemaphore(win32vars.DEBUG_sysmem_lock, 1, 0);
ptr = bubble + 1;
#else
ptr = mmap(0, size + sizeof(i32), prot, flags, -1, 0);
i32 *size_ptr = (i32*)ptr;
*size_ptr = size;
ptr = size_ptr + 1;
#endif
return ptr;
static bool ctxErrorOccurred = false;
static int XInput2OpCode = 0;
internal int
ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
ctxErrorOccurred = true;
return 0;
}
#define system_get_memory(size) system_get_memory_(size, __LINE__, __FILE__)
internal
Sys_Free_Memory_Sig(system_free_memory){
if (block){
#if FRED_INTERNAL
Sys_Bubble *bubble = ((Sys_Bubble*)block) - 1;
Assert((bubble->flags & MEM_BUBBLE_DEBUG_MASK) == MEM_BUBBLE_SYS_DEBUG);
//WaitForSingleObject(win32vars.DEBUG_sysmem_lock, INFINITE);
remove_bubble(bubble);
//ReleaseSemaphore(win32vars.DEBUG_sysmem_lock, 1, 0);
munmap(bubble, bubble->size);
#else
i32 *size_ptr = (i32*)block - 1;
munmap(size_ptr, *size_ptr);
#endif
}
}
internal
Sys_Time_Sig(system_time){
i64 result = 0;
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0){
result = tp.tv_sec*1000000 + tp.tv_nsec/1000;
}
return result;
}
internal
Sys_Load_File_Sig(system_load_file){
File_Data result = {};
i32 prot = PROT_READ;
i32 flags = MAP_PRIVATE | MAP_ANON;
internal GLXContext
InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc, b32 &IsLegacy)
{
IsLegacy = false;
struct stat sb;
if (stat(filename, &sb) == 0){
result.size = sb.st_size;
result.data = system_get_memory(result.size);
if (result.data){
i32 file = open(filename, O_RDONLY);
i32 result_size = read(file, result.data, result.size);
Assert(result_size == result.size);
close(file);
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
const char *glxExts = glXQueryExtensionsString(XDisplay, DefaultScreen(XDisplay));
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
GLXContext ctx = 0;
ctxErrorOccurred = false;
int (*oldHandler)(Display*, XErrorEvent*) =
XSetErrorHandler(&ctxErrorHandler);
if (!glXCreateContextAttribsARB)
{
printf( "glXCreateContextAttribsARB() not found"
" ... using old-style GLX context\n" );
ctx = glXCreateNewContext( XDisplay, bestFbc, GLX_RGBA_TYPE, 0, True );
}
else
{
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
printf("\nAttribs: %d %d %d %d %d\n",
context_attribs[0],
context_attribs[1],
context_attribs[2],
context_attribs[3],
context_attribs[4]);
printf( "Creating context\n" );
ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0,
True, context_attribs );
XSync( XDisplay, False );
if ( !ctxErrorOccurred && ctx )
{
printf( "Created GL 4.3 context\n" );
}
else
{
ctxErrorOccurred = false;
context_attribs[1] = 4;
context_attribs[3] = 0;
printf( "Creating context\n" );
ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0,
True, context_attribs );
XSync( XDisplay, False );
if ( !ctxErrorOccurred && ctx )
{
printf( "Created GL 4.0 context\n" );
}
else
{
context_attribs[1] = 1;
context_attribs[3] = 0;
ctxErrorOccurred = false;
printf( "Failed to create GL 4.0 context"
" ... using old-style GLX context\n" );
ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0,
True, context_attribs );
IsLegacy = true;
}
}
}
return result;
}
XSync( XDisplay, False );
XSetErrorHandler( oldHandler );
if ( ctxErrorOccurred || !ctx )
{
printf( "Failed to create an OpenGL context\n" );
exit(1);
}
if ( ! glXIsDirect ( XDisplay, ctx ) )
{
printf( "Indirect GLX rendering context obtained\n" );
}
else
{
printf( "Direct GLX rendering context obtained\n" );
}
printf( "Making context current\n" );
glXMakeCurrent( XDisplay, XWindow, ctx );
internal
Sys_Save_File_Sig(system_save_file){
i32 file = open(filename, O_CREAT | O_WRONLY);
if (!file) return 0;
GLint n;
char *Vendor = (char *)glGetString(GL_VENDOR);
char *Renderer = (char *)glGetString(GL_RENDERER);
char *Version = (char *)glGetString(GL_VERSION);
char *Extensions = (char *)glGetString(GL_EXTENSIONS);
i32 result_size = write(file, data, size);
Assert(result_size == size);
printf("GL_VENDOR: %s\n", Vendor);
printf("GL_RENDERER: %s\n", Renderer);
printf("GL_VERSION: %s\n", Version);
printf("GL_EXTENSIONS: %s\n", Extensions);
close(file);
return 1;
return(ctx);
}
internal b32
LinuxLoadAppCode(){
b32 result = 0;
GLXSupportsModernContexts(Display *XDisplay)
{
b32 Result = false;
char app_code_file[] = "4ed_app.so";
i32 app_code_file_len = sizeof(app_code_file) - 1;
char path[1024];
i32 size = readlink("/proc/self/exe", path,
1024 - app_code_file_len - 1);
for (--size;
path[size] != '/' && size > 0;
--size);
memcpy(path + size + 1, app_code_file, app_code_file_len + 1);
linuxvars.app_code = 0;
if (linuxvars.app_code){
result = 1;
linuxvars.app.init = (App_Init*)0;
linuxvars.app.step = (App_Step*)0;
}
else{
// TODO(allen): initialization failure
printe(app_code);
}
return result;
}
int GLXMajor, GLXMinor;
internal
Sys_Acquire_Lock_Sig(system_acquire_lock){
AllowLocal(id);
}
internal
Sys_Release_Lock_Sig(system_release_lock){
AllowLocal(id);
}
internal
Sys_Force_Redraw_Sig(system_force_redraw){
linuxvars.force_redraw = 1;
}
internal void
LinuxLoadSystemCode(){
linuxvars.system->get_memory_full = system_get_memory_;
linuxvars.system->free_memory = system_free_memory;
linuxvars.system->load_file = system_load_file;
linuxvars.system->save_file = system_save_file;
#if 0
linuxvars.system->file_time_stamp = system_file_time_stamp;
linuxvars.system->time_stamp_now = system_time_stamp_now;
linuxvars.system->free_file = system_free_file;
linuxvars.system->get_current_directory = system_get_current_directory;
linuxvars.system->get_easy_directory = system_get_easy_directory;
linuxvars.system->get_file_list = system_get_file_list;
linuxvars.system->free_file_list = system_free_file_list;
linuxvars.system->post_clipboard = system_post_clipboard;
linuxvars.system->time = system_time;
linuxvars.system->cli_call = system_cli_call;
linuxvars.system->cli_begin_update = system_cli_begin_update;
linuxvars.system->cli_update_step = system_cli_update_step;
linuxvars.system->cli_end_update = system_cli_end_update;
linuxvars.system->thread_get_id = system_thread_get_id;
linuxvars.system->thread_current_job_id = system_thread_current_job_id;
linuxvars.system->post_job = system_post_job;
linuxvars.system->cancel_job = system_cancel_job;
linuxvars.system->job_is_pending = system_job_is_pending;
linuxvars.system->grow_thread_memory = system_grow_thread_memory;
linuxvars.system->acquire_lock = system_acquire_lock;
linuxvars.system->release_lock = system_release_lock;
linuxvars.system->force_redraw = system_force_redraw;
linuxvars.system->internal_sentinel = INTERNAL_system_sentinel;
linuxvars.system->internal_get_thread_states = INTERNAL_get_thread_states;
#endif
}
internal void
LinuxShowScreen(){
}
int main(){
linuxvars = {};
if (!LinuxLoadAppCode()){
return(1);
}
System_Functions system_;
System_Functions *system = &system_;
linuxvars.system = system;
LinuxLoadSystemCode();
char *XVendor = ServerVendor(XDisplay);
printf("XWindows vendor: %s\n", XVendor);
if(glXQueryVersion(XDisplay, &GLXMajor, &GLXMinor))
{
void *base;
#if FRED_INTERNAL
base = (void*)Mbytes(128);
#else
base = (void*)0;
#endif
i32 prot = PROT_READ | PROT_WRITE;
i32 flags = MAP_PRIVATE | MAP_ANON;
linuxvars.mem.vars_memory_size = Mbytes(2);
linuxvars.mem.vars_memory = mmap(base, linuxvars.mem.vars_memory_size,
prot, flags, -1, 0);
#if FRED_INTERNAL
base = (void*)Mbytes(160);
#else
base = (void*)0;
#endif
linuxvars.mem.target_memory_size = Mbytes(64);
linuxvars.mem.target_memory = mmap(base, linuxvars.mem.target_memory_size,
prot, flags, -1, 0);
}
i32 width = 800;
i32 height = 600;
i32 bpp = 24;
linuxvars.target.width = width;
linuxvars.target.height = height;
keycode_init(&linuxvars.codes);
system_acquire_lock(FRAME_LOCK);
b32 first = 1;
linuxvars.keep_going = 1;
i64 timer_start = system_time();
for (;linuxvars.keep_going;){
linuxvars.input = {};
linuxvars.clipboard = {};
linuxvars.mouse.wheel = 0;
linuxvars.force_redraw = 0;
for (;0;){
printf("GLX version %d.%d\n", GLXMajor, GLXMinor);
if(((GLXMajor == 1 ) && (GLXMinor >= 3)) ||
(GLXMajor > 1))
{
Result = true;
}
linuxvars.mouse.left_button_prev = linuxvars.mouse.left_button;
linuxvars.mouse.right_button_prev = linuxvars.mouse.right_button;
}
return(Result);
}
typedef struct glx_config_result{
b32 Found;
GLXFBConfig BestConfig;
XVisualInfo BestInfo;
} glx_config_result;
internal glx_config_result
ChooseGLXConfig(Display *XDisplay, int XScreenIndex)
{
glx_config_result Result = {0};
int DesiredAttributes[] =
{
GLX_X_RENDERABLE , True,
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
GLX_RENDER_TYPE , GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
GLX_RED_SIZE , 8,
GLX_GREEN_SIZE , 8,
GLX_BLUE_SIZE , 8,
GLX_ALPHA_SIZE , 8,
GLX_DEPTH_SIZE , 24,
GLX_STENCIL_SIZE , 8,
GLX_DOUBLEBUFFER , True,
//GLX_SAMPLE_BUFFERS , 1,
//GLX_SAMPLES , 4,
None
};
{
int ConfigCount;
GLXFBConfig *Configs = glXChooseFBConfig(XDisplay,
XScreenIndex,
DesiredAttributes,
&ConfigCount);
#if 0
Application_Step_Result app_result =
linuxvars.app.step(linuxvars.system,
&linuxvars.codes,
&linuxvars.input,
&linuxvars.mouse,
&linuxvars.target,
&linuxvars.mem,
linuxvars.clipboard,
1, first, linuxvars.force_redraw);
#else
Application_Step_Result app_result = {};
int DiffValues[GLXValueCount];
#endif
if (1 || linuxvars.force_redraw){
//glClearColor(1.f, 1.f, 0.f, 1.f);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
LinuxShowScreen();
linuxvars.force_redraw = 0;
}
i64 timer_target = timer_start + frame_useconds;
i64 timer_end = system_time();
for (;timer_end < timer_target;){
i64 samount = timer_target - timer_end;
usleep(samount);
timer_end = system_time();
}
timer_start = system_time();
{for(int ConfigIndex = 0;
ConfigIndex < ConfigCount;
++ConfigIndex)
{
GLXFBConfig &Config = Configs[ConfigIndex];
XVisualInfo *VisualInfo = glXGetVisualFromFBConfig(XDisplay, Config);
#if 0
printf(" Option %d:\n", ConfigIndex);
printf(" Depth: %d\n", VisualInfo->depth);
printf(" Bits per channel: %d\n", VisualInfo->bits_per_rgb);
printf(" Mask: R%06x G%06x B%06x\n",
(uint32)VisualInfo->red_mask,
(uint32)VisualInfo->green_mask,
(uint32)VisualInfo->blue_mask);
printf(" Class: %d\n", VisualInfo->c_class);
#endif
#if 0
{for(int ValueIndex = 0;
ValueIndex < GLXValueCount;
++ValueIndex)
{
glx_value_info &ValueInfo = GLXValues[ValueIndex];
int Value;
glXGetFBConfigAttrib(XDisplay, Config, ValueInfo.ID, &Value);
if(DiffValues[ValueIndex] != Value)
{
printf(" %s: %d\n", ValueInfo.Name, Value);
DiffValues[ValueIndex] = Value;
}
}}
#endif
// TODO(casey): How the hell are you supposed to pick a config here??
if(ConfigIndex == 0)
{
Result.Found = true;
Result.BestConfig = Config;
Result.BestInfo = *VisualInfo;
}
XFree(VisualInfo);
}}
XFree(Configs);
}
return(Result);
}
internal void
InitializeXInput(Display *dpy, Window XWindow)
{
int event, error;
if(XQueryExtension(dpy, "XInputExtension", &XInput2OpCode, &event, &error))
{
int major = 2, minor = 0;
if(XIQueryVersion(dpy, &major, &minor) != BadRequest)
{
printf("XInput initialized");
}
else
{
printf("XI2 not available. Server supports %d.%d\n", major, minor);
}
}
else
{
printf("X Input extension not available.\n");
}
/*
TODO(casey): So, this is all one big clusterfuck I guess.
The problem here is that you want to be able to get input
from all possible devices that could be a mouse or keyboard
(or gamepad, or whatever). So you'd like to be able to
register events for XIAllDevices, so that when a new
input device is connected, you will start receiving
input from it automatically, without having to periodically
poll XIQueryDevice to see if a new device has appeared.
UNFORTUNATELY, this is not actually possible in Linux because
there was a bug in Xorg (as of early 2013, it is still not
fixed in most distributions people are using, AFAICT) which
makes the XServer return an error if you actually try to
do this :(
But EVENTUALLY, if that shit gets fixed, then that is
the way this should work.
*/
#if 0
int DeviceCount;
XIDeviceInfo *DeviceInfo = XIQueryDevice(dpy, XIAllDevices, &DeviceCount);
{for(int32x DeviceIndex = 0;
DeviceIndex < DeviceCount;
++DeviceIndex)
{
XIDeviceInfo *Device = DeviceInfo + DeviceIndex;
printf("Device %d: %s\n", Device->deviceid, Device->name);
}}
XIFreeDeviceInfo(DeviceInfo);
#endif
return(0);
XIEventMask Mask = {0};
Mask.deviceid = XIAllDevices;
Mask.mask_len = XIMaskLen(XI_RawMotion);
size_t MaskSize = Mask.mask_len * sizeof(char unsigned);
Mask.mask = (char unsigned *)alloca(MaskSize);
memset(Mask.mask, 0, MaskSize);
if(Mask.mask)
{
XISetMask(Mask.mask, XI_ButtonPress);
XISetMask(Mask.mask, XI_ButtonRelease);
XISetMask(Mask.mask, XI_KeyPress);
XISetMask(Mask.mask, XI_KeyRelease);
XISetMask(Mask.mask, XI_Motion);
XISetMask(Mask.mask, XI_DeviceChanged);
XISetMask(Mask.mask, XI_Enter);
XISetMask(Mask.mask, XI_Leave);
XISetMask(Mask.mask, XI_FocusIn);
XISetMask(Mask.mask, XI_FocusOut);
XISetMask(Mask.mask, XI_HierarchyChanged);
XISetMask(Mask.mask, XI_PropertyEvent);
XISelectEvents(dpy, XWindow, &Mask, 1);
XSync(dpy, False);
Mask.deviceid = XIAllMasterDevices;
memset(Mask.mask, 0, MaskSize);
XISetMask(Mask.mask, XI_RawKeyPress);
XISetMask(Mask.mask, XI_RawKeyRelease);
XISetMask(Mask.mask, XI_RawButtonPress);
XISetMask(Mask.mask, XI_RawButtonRelease);
XISetMask(Mask.mask, XI_RawMotion);
XISelectEvents(dpy, DefaultRootWindow(dpy), &Mask, 1);
}
}
int
main(int ArgCount, char **Args)
{
Display *XDisplay = XOpenDisplay(0);
if(XDisplay && GLXSupportsModernContexts(XDisplay))
{
int XScreenCount = ScreenCount(XDisplay);
for(int XScreenIndex = 0;
XScreenIndex < XScreenCount;
++XScreenIndex)
{
Screen *XScreen = ScreenOfDisplay(XDisplay, XScreenIndex);
int WinWidth = WidthOfScreen(XScreen);
int WinHeight = HeightOfScreen(XScreen);
glx_config_result Config = ChooseGLXConfig(XDisplay, XScreenIndex);
if(Config.Found)
{
Colormap cmap;
XSetWindowAttributes swa;
swa.colormap = cmap = XCreateColormap(XDisplay,
RootWindow(XDisplay, Config.BestInfo.screen ),
Config.BestInfo.visual, AllocNone);
swa.background_pixmap = None;
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
Window XWindow = XCreateWindow(XDisplay,
RootWindow(XDisplay, Config.BestInfo.screen),
0, 0, WinWidth, WinHeight,
0, Config.BestInfo.depth, InputOutput,
Config.BestInfo.visual,
CWBorderPixel|CWColormap|CWEventMask, &swa );
if(XWindow)
{
XStoreName(XDisplay, XWindow, "4coder");
XMapWindow(XDisplay, XWindow);
InitializeXInput(XDisplay, XWindow);
b32 IsLegacy = false;
GLXContext GLContext =
InitializeOpenGLContext(XDisplay, XWindow, Config.BestConfig, IsLegacy);
XWindowAttributes WinAttribs;
if(XGetWindowAttributes(XDisplay, XWindow, &WinAttribs))
{
WinWidth = WinAttribs.width;
WinHeight = WinAttribs.height;
}
XRaiseWindow(XDisplay, XWindow);
XSync(XDisplay, False);
for(;;)
{
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);
}
}
}
}
}
}
// BOTTOM

BIN
vc120.pdb

Binary file not shown.

File diff suppressed because it is too large Load Diff