new linux shit
This commit is contained in:
parent
951b992b2f
commit
8195020bfd
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
673
4coder_custom.h
673
4coder_custom.h
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
|
504
4coder_helper.h
504
4coder_helper.h
|
@ -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)
|
||||
|
||||
|
|
2332
4coder_string.h
2332
4coder_string.h
File diff suppressed because it is too large
Load Diff
53
4cpp_lexer.h
53
4cpp_lexer.h
|
@ -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
209
4ed.cpp
|
@ -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(¶m->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
416
4ed.h
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
@echo off
|
||||
|
||||
call "w:\4ed\code\buildsuper.bat"
|
||||
call "w:\4ed\misc\builddbg.bat"
|
781
linux_4ed.cpp
781
linux_4ed.cpp
|
@ -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
|
||||
|
|
3670
win32_4ed.cpp
3670
win32_4ed.cpp
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue