various bug fixes

This commit is contained in:
Allen Webster 2016-03-07 00:13:20 -05:00
parent 32da95069c
commit 264100d81a
18 changed files with 868 additions and 710 deletions

View File

@ -1,9 +1,13 @@
// Alternative customizations, set Custom_Current to select which to apply.
#define Custom_Default 0
#define Custom_HandmadeHero 1
// Set which customization you want to use with this define or write your own
#define Custom_Current Custom_Default
#define Custom_Default 0
// The following customization schemes are power users only:
#define Custom_HandmadeHero 1
// TOP
#include "4coder_custom.h"
#define FCPP_STRING_IMPLEMENTATION
@ -20,30 +24,32 @@
// 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
my_code_map
};
HOOK_SIG(my_start){
exec_command(app, cmdid_open_panel_vsplit);
exec_command(app, cmdid_change_active_panel);
app->change_theme(app, literal("4coder"));
app->change_font(app, literal("liberation sans"));
// Theme options:
// "4coder"
// "Handmade Hero"
// "Twilight"
// "Woverine"
// "stb"
// Font options:
// "liberation sans"
// "liberation mono"
// "hack"
// "cutive mono"
// "inconsolata"
// no meaning for return
return(0);
}
HOOK_SIG(my_file_settings){
@ -53,7 +59,7 @@ HOOK_SIG(my_file_settings){
// there are no parameter buffers.
Buffer_Summary buffer = app->get_parameter_buffer(app, 0);
assert(buffer.exists);
int treat_as_code = 0;
if (buffer.file_name && buffer.size < (16 << 20)){
@ -68,6 +74,49 @@ HOOK_SIG(my_file_settings){
push_parameter(app, par_wrap_lines, !treat_as_code);
push_parameter(app, par_key_mapid, (treat_as_code)?((int)my_code_map):((int)mapid_file));
exec_command(app, cmdid_set_settings);
// no meaning for return
return(0);
}
unsigned char blink_t = 0;
HOOK_SIG(my_frame){
// NOTE(allen|a4): Please use me sparingly! This get's called roughly once every *33 ms* if everything is going well.
// But if you start doing a lot in here, there's nothing 4codes does to stop you from making it a lot slower.
int result = 0;
Theme_Color theme_color_1[] = {
{Stag_Cursor, 0x00FF00},
{Stag_At_Cursor, 0x000000}
};
Theme_Color theme_color_2[2] = {
{Stag_Cursor, 0x000000},
{Stag_At_Cursor, 0xFFFFFF}
};
Theme_Color *theme_color;
++blink_t;
if (blink_t == 20 || blink_t == 40){
if (blink_t == 20){
theme_color = theme_color_2;
}
else{
theme_color = theme_color_1;
blink_t = 0;
}
result = 1;
app->set_theme_colors(app, theme_color, 2);
}
// return non-zero if you do anything that might change the screen!
// 4coder won't redraw unless you tell it you've changed something important.
// If you redraw *all* the time it's going to slow 4coder down and increase power consumption.
return(result);
}
static void
@ -92,19 +141,41 @@ CUSTOM_COMMAND_SIG(write_allen_note){
write_string(app, make_lit_string("// NOTE(allen): "));
}
static void
basic_seek(Application_Links *app, Command_ID seek_type, unsigned int flags){
push_parameter(app, par_flags, flags);
exec_command(app, seek_type);
}
#define SEEK_COMMAND(n, dir, flags)\
CUSTOM_COMMAND_SIG(seek_##n##_##dir){\
basic_seek(app, cmdid_seek_##dir, flags);\
}
SEEK_COMMAND(whitespace, right, BoundryWhitespace)
SEEK_COMMAND(whitespace, left, BoundryWhitespace)
SEEK_COMMAND(token, right, BoundryToken)
SEEK_COMMAND(token, left, BoundryToken)
SEEK_COMMAND(white_or_token, right, BoundryToken | BoundryWhitespace)
SEEK_COMMAND(white_or_token, left, BoundryToken | BoundryWhitespace)
SEEK_COMMAND(alphanumeric, right, BoundryAlphanumeric)
SEEK_COMMAND(alphanumeric, left, BoundryAlphanumeric)
SEEK_COMMAND(alphanumeric_or_camel, right, BoundryAlphanumeric | BoundryCamelCase)
SEEK_COMMAND(alphanumeric_or_camel, left, BoundryAlphanumeric | BoundryCamelCase)
static void
long_braces(Application_Links *app, char *text, int size){
View_Summary view;
Buffer_Summary buffer;
int pos;
view = app->get_active_view(app);
buffer = app->get_buffer(app, view.buffer_id);
pos = view.cursor.pos;
app->buffer_replace_range(app, &buffer, pos, pos, text, size);
app->view_set_cursor(app, &view, seek_pos(pos + 2), 1);
push_parameter(app, par_range_start, pos);
push_parameter(app, par_range_end, pos + size);
push_parameter(app, par_clear_blank_lines, 0);
@ -156,13 +227,13 @@ CUSTOM_COMMAND_SIG(paren_wrap){
CUSTOM_COMMAND_SIG(if0_off){
View_Summary view;
Buffer_Summary buffer;
char text1[] = "\n#if 0";
int size1 = sizeof(text1) - 1;
char text2[] = "#endif\n";
int size2 = sizeof(text2) - 1;
Range range;
int pos;
@ -177,13 +248,13 @@ CUSTOM_COMMAND_SIG(if0_off){
push_parameter(app, par_range_start, pos);
push_parameter(app, par_range_end, pos);
exec_command(app, cmdid_auto_tab_range);
app->refresh_view(app, &view);
range = get_range(&view);
pos = range.max;
app->buffer_replace_range(app, &buffer, pos, pos, text2, size2);
push_parameter(app, par_range_start, pos);
push_parameter(app, par_range_end, pos);
exec_command(app, cmdid_auto_tab_range);
@ -193,14 +264,14 @@ CUSTOM_COMMAND_SIG(backspace_word){
View_Summary view;
Buffer_Summary buffer;
int pos2, pos1;
view = app->get_active_view(app);
pos2 = view.cursor.pos;
exec_command(app, cmdid_seek_alphanumeric_left);
exec_command(app, seek_alphanumeric_left);
app->refresh_view(app, &view);
pos1 = view.cursor.pos;
buffer = app->get_buffer(app, view.buffer_id);
app->buffer_replace_range(app, &buffer, pos1, pos2, 0, 0);
}
@ -209,19 +280,19 @@ CUSTOM_COMMAND_SIG(snipe_token_or_word){
View_Summary view;
Buffer_Summary buffer;
int pos1, pos2;
view = app->get_active_view(app);
push_parameter(app, par_flags, BoundryToken | BoundryWhitespace);
exec_command(app, cmdid_seek_left);
app->refresh_view(app, &view);
pos1 = view.cursor.pos;
push_parameter(app, par_flags, BoundryToken | BoundryWhitespace);
exec_command(app, cmdid_seek_right);
app->refresh_view(app, &view);
pos2 = view.cursor.pos;
Range range = make_range(pos1, pos2);
buffer = app->get_buffer(app, view.buffer_id);
app->buffer_replace_range(app, &buffer, range.start, range.end, 0, 0);
@ -230,13 +301,13 @@ CUSTOM_COMMAND_SIG(snipe_token_or_word){
CUSTOM_COMMAND_SIG(switch_to_compilation){
View_Summary view;
Buffer_Summary buffer;
char name[] = "*compilation*";
int name_size = sizeof(name)-1;
view = app->get_active_view(app);
buffer = app->get_buffer_by_name(app, name, name_size);
app->view_set_buffer(app, &view, buffer.buffer_id);
}
@ -246,14 +317,14 @@ CUSTOM_COMMAND_SIG(move_up_10){
view = app->get_active_view(app);
x = view.preferred_x;
if (view.unwrapped_lines){
y = view.cursor.unwrapped_y;
}
else{
y = view.cursor.wrapped_y;
}
y -= 10*view.line_height;
app->view_set_cursor(app, &view, seek_xy(x, y, 0, view.unwrapped_lines), 0);
@ -265,16 +336,16 @@ CUSTOM_COMMAND_SIG(move_down_10){
view = app->get_active_view(app);
x = view.preferred_x;
if (view.unwrapped_lines){
y = view.cursor.wrapped_y;
}
else{
y = view.cursor.wrapped_y;
}
y += 10*view.line_height;
app->view_set_cursor(app, &view, seek_xy(x, y, 0, view.unwrapped_lines), 0);
}
@ -283,16 +354,16 @@ CUSTOM_COMMAND_SIG(open_file_in_quotes){
Buffer_Summary buffer;
char short_file_name[128];
int pos, start, end, size;
view = app->get_active_view(app);
buffer = app->get_buffer(app, view.buffer_id);
pos = view.cursor.pos;
app->buffer_seek_delimiter(app, &buffer, pos, '"', 1, &end);
app->buffer_seek_delimiter(app, &buffer, pos, '"', 0, &start);
++start;
size = end - start;
// NOTE(allen): This check is necessary because app->buffer_read_range
// requiers that the output buffer you provide is at least (end - start) bytes long.
if (size < sizeof(short_file_name)){
@ -315,10 +386,10 @@ CUSTOM_COMMAND_SIG(goto_line){
int line_number;
Query_Bar bar;
char string_space[256];
bar.prompt = make_lit_string("Goto Line: ");
bar.string = make_fixed_width_string(string_space);
if (query_user_number(app, &bar)){
line_number = str_to_int(bar.string);
active_view_to_line(app, line_number);
@ -334,37 +405,37 @@ isearch(Application_Links *app, int start_reversed){
Buffer_Summary buffer;
User_Input in;
Query_Bar bar;
if (app->start_query_bar(app, &bar, 0) == 0) return;
Range match;
int reverse = start_reversed;
int pos;
view = app->get_active_view(app);
buffer = app->get_buffer(app, view.buffer_id);
pos = view.cursor.pos;
match = make_range(pos, pos);
char bar_string_space[256];
bar.string = make_fixed_width_string(bar_string_space);
String isearch = make_lit_string("I-Search: ");
String rsearch = make_lit_string("Reverse-I-Search: ");
while (1){
// NOTE(allen): Change the bar's prompt to match the current direction.
if (reverse) bar.prompt = rsearch;
else bar.prompt = isearch;
in = app->get_user_input(app, EventOnAnyKey, EventOnEsc | EventOnButton);
if (in.abort) break;
// NOTE(allen): If we're getting mouse events here it's a 4coder bug, because we
// only asked to intercept key events.
assert(in.type == UserInputKey);
int made_change = 0;
if (in.key.keycode == '\n' || in.key.keycode == '\t'){
break;
@ -377,15 +448,15 @@ isearch(Application_Links *app, int start_reversed){
--bar.string.size;
made_change = 1;
}
int step_forward = 0;
int step_backward = 0;
if (CommandEqual(in.command, search) ||
in.key.keycode == key_page_down || in.key.keycode == key_down) step_forward = 1;
if (CommandEqual(in.command, reverse_search) ||
in.key.keycode == key_page_down || in.key.keycode == key_up) step_backward = 1;
in.key.keycode == key_page_up || in.key.keycode == key_up) step_backward = 1;
int start_pos = pos;
if (step_forward && reverse){
start_pos = match.start + 1;
@ -399,7 +470,7 @@ isearch(Application_Links *app, int start_reversed){
reverse = 1;
step_backward = 0;
}
if (in.key.keycode != key_back){
int new_pos;
if (reverse){
@ -432,12 +503,12 @@ isearch(Application_Links *app, int start_reversed){
else{
match.end = match.start + bar.string.size;
}
app->view_set_highlight(app, &view, match.start, match.end, 1);
}
app->view_set_highlight(app, &view, 0, 0, 0);
if (in.abort) return;
app->view_set_cursor(app, &view, seek_pos(match.min), 1);
}
@ -455,22 +526,22 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
Range range;
String string;
int is_first, i;
exec_command(app, cmdid_seek_token_left);
exec_command(app, seek_token_left);
view = app->get_active_view(app);
range.min = view.cursor.pos;
exec_command(app, cmdid_seek_token_right);
exec_command(app, seek_token_right);
app->refresh_view(app, &view);
range.max = view.cursor.pos;
string.str = (char*)app->memory;
string.size = range.max - range.min;
assert(string.size < app->memory_size);
buffer = app->get_buffer(app, view.buffer_id);
app->buffer_read_range(app, &buffer, range.min, range.max, string.str);
is_first = 1;
for (i = 0; i < string.size; ++i){
if (char_is_alpha_true(string.str[i])){
@ -481,7 +552,7 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
is_first = 1;
}
}
app->buffer_replace_range(app, &buffer, range.min, range.max, string.str, string.size);
}
@ -493,7 +564,7 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
{
rewrite = get_rewrite(app, ByToken);
string = get_rewrite_string(app, &rewrite, app->memory, app->memory_size);
is_first = 1;
for (i = 0; i < string.size; ++i){
if (char_is_alpha_true(string.str[i])){
@ -504,7 +575,7 @@ CUSTOM_COMMAND_SIG(rewrite_as_single_caps){
is_first = 1;
}
}
do_rewrite(app, &rewrite, string);
}
#endif
@ -514,17 +585,17 @@ CUSTOM_COMMAND_SIG(replace_in_range){
char replace_space[1024];
replace.prompt = make_lit_string("Replace: ");
replace.string = make_fixed_width_string(replace_space);
Query_Bar with;
char with_space[1024];
with.prompt = make_lit_string("With: ");
with.string = make_fixed_width_string(with_space);
if (!query_user_string(app, &replace)) return;
if (replace.string.size == 0) return;
if (!query_user_string(app, &with)) return;
String r, w;
r = replace.string;
w = with.string;
@ -540,7 +611,7 @@ CUSTOM_COMMAND_SIG(replace_in_range){
int pos, new_pos;
pos = range.min;
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
while (new_pos + r.size < range.end){
app->buffer_replace_range(app, &buffer, new_pos, new_pos + r.size, w.str, w.size);
range = get_range(&view);
@ -554,45 +625,45 @@ CUSTOM_COMMAND_SIG(query_replace){
char replace_space[1024];
replace.prompt = make_lit_string("Replace: ");
replace.string = make_fixed_width_string(replace_space);
Query_Bar with;
char with_space[1024];
with.prompt = make_lit_string("With: ");
with.string = make_fixed_width_string(with_space);
if (!query_user_string(app, &replace)) return;
if (replace.string.size == 0) return;
if (!query_user_string(app, &with)) return;
String r, w;
r = replace.string;
w = with.string;
Query_Bar bar;
Buffer_Summary buffer;
View_Summary view;
int pos, new_pos;
bar.prompt = make_lit_string("Replace? (y)es, (n)ext, (esc)\n");
bar.string = {};
bar.string = empty_string();
app->start_query_bar(app, &bar, 0);
view = app->get_active_view(app);
buffer = app->get_buffer(app, view.buffer_id);
pos = view.cursor.pos;
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
User_Input in = {};
User_Input in = {0};
while (new_pos < buffer.size){
Range match = make_range(new_pos, new_pos + r.size);
app->view_set_highlight(app, &view, match.min, match.max, 1);
in = app->get_user_input(app, EventOnAnyKey, EventOnButton);
if (in.abort || in.key.keycode == key_esc || !key_is_unmodified(&in.key)) break;
if (in.key.character == 'y' || in.key.character == 'Y' || in.key.character == '\n' || in.key.character == '\t'){
app->buffer_replace_range(app, &buffer, match.min, match.max, w.str, w.size);
pos = match.start + w.size;
@ -600,7 +671,7 @@ CUSTOM_COMMAND_SIG(query_replace){
else{
pos = match.max;
}
app->buffer_seek_string(app, &buffer, pos, r.str, r.size, 1, &new_pos);
}
@ -617,7 +688,7 @@ CUSTOM_COMMAND_SIG(close_all_code){
for (buffer = app->get_buffer_first(app);
buffer.exists;
app->get_buffer_next(app, &buffer)){
extension = file_extension(make_string(buffer.file_name, buffer.file_name_len));
if (match(extension, make_lit_string("cpp")) ||
match(extension, make_lit_string("hpp")) ||
@ -639,12 +710,11 @@ CUSTOM_COMMAND_SIG(open_all_code){
String dir = make_string(app->memory, 0, app->memory_size);
dir.size = app->directory_get_hot(app, dir.str, dir.memory_size);
int dir_size = dir.size;
// NOTE(allen|a3.4.4): Here we get the list of files in this directory.
// Notice that we free_file_list at the end.
File_List list = app->get_file_list(app, dir.str, dir.size);
for (int i = 0; i < list.count; ++i){
File_Info *info = list.infos + i;
if (!info->folder){
@ -660,12 +730,12 @@ CUSTOM_COMMAND_SIG(open_all_code){
dir.size = dir_size;
append(&dir, info->filename);
push_parameter(app, par_name, dir.str, dir.size);
push_parameter(app, par_do_in_background, 1);
//push_parameter(app, par_do_in_background, 1);
exec_command(app, cmdid_interactive_open);
}
}
}
app->free_file_list(app, list);
}
@ -673,18 +743,18 @@ CUSTOM_COMMAND_SIG(execute_any_cli){
Query_Bar bar_out, bar_cmd;
String hot_directory;
char space[1024], more_space[1024], even_more_space[1024];
bar_out.prompt = make_lit_string("Output Buffer: ");
bar_out.string = make_fixed_width_string(space);
if (!query_user_string(app, &bar_out)) return;
bar_cmd.prompt = make_lit_string("Command: ");
bar_cmd.string = make_fixed_width_string(more_space);
if (!query_user_string(app, &bar_cmd)) return;
hot_directory = make_fixed_width_string(even_more_space);
hot_directory.size = app->directory_get_hot(app, hot_directory.str, hot_directory.memory_size);
push_parameter(app, par_flags, CLI_OverlapWithConflict);
push_parameter(app, par_name, bar_out.string.str, bar_out.string.size);
push_parameter(app, par_cli_path, hot_directory.str, hot_directory.size);
@ -701,9 +771,9 @@ CUSTOM_COMMAND_SIG(execute_arbitrary_command){
char space[1024];
bar.prompt = make_lit_string("Command: ");
bar.string = make_fixed_width_string(space);
if (!query_user_string(app, &bar)) return;
// NOTE(allen): Here I chose to end this query bar because when I call another
// command it might ALSO have query bars and I don't want this one hanging
// around at that point. Since the bar exists on my stack the result of the query
@ -719,6 +789,12 @@ CUSTOM_COMMAND_SIG(execute_arbitrary_command){
else if (match(bar.string, make_lit_string("open menu"))){
exec_command(app, cmdid_open_menu);
}
else if (match(bar.string, make_lit_string("dos lines"))){
exec_command(app, cmdid_eol_dosify);
}
else if (match(bar.string, make_lit_string("nix lines"))){
exec_command(app, cmdid_eol_nixify);
}
else{
// TODO(allen): feedback message
}
@ -805,23 +881,23 @@ CUSTOM_COMMAND_SIG(build_search){
//
// This doesn't actually change the hot directory of 4coder, it's only effect is to
// modify the string you passed in to reflect the change in directory if that change was possible.
int keep_going = 1;
int old_size;
String dir = make_string(app->memory, 0, app->memory_size);
dir.size = app->directory_get_hot(app, dir.str, dir.memory_size);
while (keep_going){
old_size = dir.size;
append(&dir, "build.bat");
if (app->file_exists(app, dir.str, dir.size)){
dir.size = old_size;
push_parameter(app, par_flags, CLI_OverlapWithConflict);
push_parameter(app, par_name, literal("*compilation*"));
push_parameter(app, par_cli_path, dir.str, dir.size);
if (append(&dir, "build")){
push_parameter(app, par_cli_command, dir.str, dir.size);
exec_command(app, cmdid_command_line);
@ -829,7 +905,7 @@ CUSTOM_COMMAND_SIG(build_search){
else{
app->clear_parameters(app);
}
return;
}
dir.size = old_size;
@ -842,9 +918,24 @@ CUSTOM_COMMAND_SIG(build_search){
// TODO(allen): feedback message - couldn't find build.bat
}
CUSTOM_COMMAND_SIG(auto_tab_line_at_cursor){
View_Summary view = app->get_active_view(app);
push_parameter(app, par_range_start, view.cursor.pos);
push_parameter(app, par_range_end, view.cursor.pos);
push_parameter(app, par_clear_blank_lines, 0);
exec_command(app, cmdid_auto_tab_range);
}
CUSTOM_COMMAND_SIG(auto_tab_whole_file){
Buffer_Summary buffer = app->get_active_buffer(app);
push_parameter(app, par_range_start, 0);
push_parameter(app, par_range_end, buffer.size);
exec_command(app, cmdid_auto_tab_range);
}
CUSTOM_COMMAND_SIG(write_and_auto_tab){
exec_command(app, cmdid_write_character);
exec_command(app, cmdid_auto_tab_line_at_cursor);
exec_command(app, auto_tab_line_at_cursor);
}
// NOTE(allen|a4) See 4coder_styles.h for a list of available style tags.
@ -857,9 +948,9 @@ CUSTOM_COMMAND_SIG(improve_theme){
{Stag_Margin_Active, 0xDD0088},
{Stag_Cursor, 0xFF0000},
};
int count = ArrayCount(colors);
app->set_theme_colors(app, colors, count);
}
@ -871,9 +962,9 @@ CUSTOM_COMMAND_SIG(ruin_theme){
{Stag_Margin_Active, 0x323232},
{Stag_Cursor, 0x00EE00},
};
int count = ArrayCount(colors);
app->set_theme_colors(app, colors, count);
}
@ -913,7 +1004,7 @@ struct Scroll_Velocity{
};
Scroll_Velocity scroll_velocity_[16] = {0};
Scroll_Velocity *scroll_velocity = scroll_velocity_;
Scroll_Velocity *scroll_velocity = scroll_velocity_ - 1;
static int
smooth_camera_step(float target, float *current, float *vel, float S, float T){
@ -953,37 +1044,39 @@ SCROLL_RULE_SIG(smooth_scroll_rule){
velocity->x = 1.f;
velocity->y = 1.f;
}
if (smooth_camera_step(target_y, scroll_y, &velocity->y, 40.f, 1.f/4.f)){
result = 1;
}
if (smooth_camera_step(target_x, scroll_x, &velocity->x, 40.f, 1.f/4.f)){
result = 1;
}
return(result);
}
#if Custom_Current == Custom_HandmadeHero
# include "4coder_handmade_hero.cpp"
# include "power/4coder_handmade_hero.cpp"
#endif
extern "C" GET_BINDING_DATA(get_bindings){
Bind_Helper context_actual = begin_bind_helper(data, size);
Bind_Helper *context = &context_actual;
#if Custom_Current == Custom_HandmadeHero
casey_get_bindings(context);
#else
// 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.
// NOTE(allen|a3.1): 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);
//set_hook(context, hook_frame, my_frame); // Example of a frame hook, but disabled by default.
set_scroll_rule(context, smooth_scroll_rule);
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);
@ -994,17 +1087,17 @@ extern "C" GET_BINDING_DATA(get_bindings){
bind(context, 'i', MDFR_CTRL, cmdid_interactive_switch_buffer);
bind(context, 'c', MDFR_ALT, cmdid_open_color_tweaker);
bind(context, 'o', MDFR_ALT, open_in_other);
bind(context, 'm', MDFR_ALT, build_search);
bind(context, ',', MDFR_ALT, switch_to_compilation);
bind(context, 'x', MDFR_ALT, execute_arbitrary_command);
bind(context, 'z', MDFR_ALT, execute_any_cli);
// NOTE(allen): These callbacks may not actually be useful to you, but
// go look at them and see what they do.
bind(context, 'M', MDFR_ALT | MDFR_CTRL, open_my_files);
bind(context, 'M', MDFR_ALT, build_at_launch_location);
bind(context, '`', MDFR_ALT, improve_theme);
bind(context, '~', MDFR_ALT, ruin_theme);
@ -1021,8 +1114,8 @@ extern "C" GET_BINDING_DATA(get_bindings){
inherit_map(context, mapid_file);
// NOTE(allen|a3.1): Children can override parent's bindings.
bind(context, key_right, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_right);
bind(context, key_left, MDFR_CTRL, cmdid_seek_alphanumeric_or_camel_left);
bind(context, key_right, MDFR_CTRL, seek_alphanumeric_or_camel_right);
bind(context, key_left, MDFR_CTRL, seek_alphanumeric_or_camel_left);
// NOTE(allen|a3.2): Specific keys can override vanilla keys,
// and write character writes whichever character corresponds
@ -1033,11 +1126,11 @@ extern "C" GET_BINDING_DATA(get_bindings){
bind(context, ']', MDFR_NONE, write_and_auto_tab);
bind(context, ';', MDFR_NONE, write_and_auto_tab);
bind(context, '#', MDFR_NONE, write_and_auto_tab);
bind(context, '\t', MDFR_NONE, cmdid_word_complete);
bind(context, '\t', MDFR_CTRL, cmdid_auto_tab_range);
bind(context, '\t', MDFR_SHIFT, cmdid_auto_tab_line_at_cursor);
bind(context, '\t', MDFR_SHIFT, auto_tab_line_at_cursor);
bind(context, '=', MDFR_CTRL, write_increment);
bind(context, '-', MDFR_CTRL, write_decrement);
bind(context, 't', MDFR_ALT, write_allen_todo);
@ -1047,19 +1140,20 @@ extern "C" GET_BINDING_DATA(get_bindings){
bind(context, '}', MDFR_CTRL, open_long_braces_break);
bind(context, '9', MDFR_CTRL, paren_wrap);
bind(context, 'i', MDFR_ALT, if0_off);
bind(context, '1', MDFR_ALT, open_file_in_quotes);
end_map(context);
begin_map(context, mapid_file);
// NOTE(allen|a3.4.4): Binding this essentially binds
// all key combos that would normally insert a character
// into a buffer. If the code for the key is not an enum
// value such as key_left or key_back then it is a vanilla key.
// It is possible to override this binding for individual keys.
bind_vanilla_keys(context, cmdid_write_character);
bind(context, key_left, MDFR_NONE, cmdid_move_left);
bind(context, key_right, MDFR_NONE, cmdid_move_right);
bind(context, key_del, MDFR_NONE, cmdid_delete);
@ -1070,18 +1164,18 @@ extern "C" GET_BINDING_DATA(get_bindings){
bind(context, key_home, MDFR_NONE, cmdid_seek_beginning_of_line);
bind(context, key_page_up, MDFR_NONE, cmdid_page_up);
bind(context, key_page_down, MDFR_NONE, cmdid_page_down);
bind(context, key_right, MDFR_CTRL, cmdid_seek_whitespace_right);
bind(context, key_left, MDFR_CTRL, cmdid_seek_whitespace_left);
bind(context, key_right, MDFR_CTRL, seek_whitespace_right);
bind(context, key_left, MDFR_CTRL, seek_whitespace_left);
bind(context, key_up, MDFR_CTRL, cmdid_seek_whitespace_up);
bind(context, key_down, MDFR_CTRL, cmdid_seek_whitespace_down);
bind(context, key_up, MDFR_ALT, move_up_10);
bind(context, key_down, MDFR_ALT, move_down_10);
bind(context, key_back, MDFR_CTRL, backspace_word);
bind(context, key_back, MDFR_ALT, snipe_token_or_word);
bind(context, ' ', MDFR_CTRL, cmdid_set_mark);
bind(context, 'm', MDFR_CTRL, cmdid_cursor_mark_swap);
bind(context, 'c', MDFR_CTRL, cmdid_copy);
@ -1099,31 +1193,31 @@ extern "C" GET_BINDING_DATA(get_bindings){
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);
bind(context, '1', MDFR_CTRL, cmdid_eol_dosify);
bind(context, '!', MDFR_CTRL, cmdid_eol_nixify);
bind(context, 'f', MDFR_CTRL, search);
bind(context, 'r', MDFR_CTRL, reverse_search);
bind(context, 'g', MDFR_CTRL, goto_line);
bind(context, 'q', MDFR_CTRL, query_replace);
bind(context, 'a', MDFR_CTRL, replace_in_range);
bind(context, 's', MDFR_ALT, rewrite_as_single_caps);
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);
bind(context, '\n', MDFR_SHIFT, write_and_auto_tab);
bind(context, ' ', MDFR_SHIFT, cmdid_write_character);
end_map(context);
#endif
end_bind_helper(context);
return context->write_total;
}

View File

@ -154,28 +154,18 @@ typedef struct File_List{
int block_size;
} File_List;
#define MDFR_NONE 0
#define MDFR_CTRL 1
#define MDFR_ALT 2
#define MDFR_SHIFT 4
#define MDFR_NONE 0x0
#define MDFR_CTRL 0x1
#define MDFR_ALT 0x2
#define MDFR_SHIFT 0x4
enum Command_ID{
cmdid_null,
cmdid_write_character,
cmdid_seek_left,
cmdid_seek_right,
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_word_complete,
cmdid_set_mark,
cmdid_copy,
@ -206,8 +196,6 @@ enum Command_ID{
cmdid_eol_dosify,
cmdid_eol_nixify,
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,
@ -255,6 +243,7 @@ enum Param_ID{
enum Hook_ID{
hook_start,
hook_open_file,
hook_frame,
// never below this
hook_type_count
};
@ -328,7 +317,7 @@ struct Theme_Color{
#define GET_BINDING_DATA(name) int name(void *data, int size)
#define CUSTOM_COMMAND_SIG(name) void name(struct Application_Links *app)
#define HOOK_SIG(name) void name(struct Application_Links *app)
#define HOOK_SIG(name) int name(struct Application_Links *app)
#define SCROLL_RULE_SIG(name) int name(float target_x, float target_y, float *scroll_x, float *scroll_y, int view_id, int is_new_target)
extern "C"{
@ -539,8 +528,17 @@ struct Application_Links{
void *cmd_context;
};
#define _GET_VERSION_SIG(n) int n(int maj, int min, int patch)
typedef _GET_VERSION_SIG(_Get_Version_Function);
extern "C" _GET_VERSION_SIG(get_alpha_4coder_version){
int result = (maj == MAJOR && min == MINOR && patch == PATCH);
return(result);
}
struct Custom_API{
Get_Binding_Data_Function *get_bindings;
_Get_Version_Function *get_alpha_4coder_version;
};
// NOTE(allen): definitions for the buffer that communicates to 4ed.exe
@ -587,5 +585,3 @@ struct Binding_Unit{
} hook;
};
};

View File

@ -153,7 +153,7 @@ inherit_map(Bind_Helper *helper, int mapid){
}
inline void
set_hook(Bind_Helper *helper, int hook_id, Custom_Command_Function *func){
set_hook(Bind_Helper *helper, int hook_id, Hook_Function *func){
Binding_Unit unit;
unit.type = unit_hook;
unit.hook.hook_id = hook_id;

View File

@ -1,3 +1,15 @@
#define MAJOR 3
#define MINOR 4
#define PATCH 5
#define MAJOR 4
#define MINOR 0
#define PATCH 0
#define VN__(a,b,c) #a"."#b"."#c
#define VN_(a,b,c) VN__(a,b,c)
#define VERSION_NUMBER VN_(MAJOR,MINOR,PATCH)
#define VERSION_STRING "alpha " VERSION_NUMBER
#ifdef FRED_SUPER
#define VERSION_TYPE " super!"
#else
#define VERSION_TYPE
#endif
#define VERSION VERSION_STRING VERSION_TYPE

272
4ed.cpp
View File

@ -55,7 +55,7 @@ struct Complete_State{
};
struct Command_Data{
App_Models *models;
Models *models;
struct App_Vars *vars;
System_Functions *system;
Exchange *exchange;
@ -71,7 +71,7 @@ struct Command_Data{
};
struct App_Vars{
App_Models models;
Models models;
CLI_List cli_processes;
@ -88,7 +88,7 @@ struct App_Vars{
};
internal i32
app_get_or_add_map_index(App_Models *models, i32 mapid){
app_get_or_add_map_index(Models *models, i32 mapid){
i32 result;
i32 user_map_count = models->user_map_count;
i32 *map_id_table = models->map_id_table;
@ -103,7 +103,7 @@ app_get_or_add_map_index(App_Models *models, i32 mapid){
}
internal i32
app_get_map_index(App_Models *models, i32 mapid){
app_get_map_index(Models *models, i32 mapid){
i32 result;
i32 user_map_count = models->user_map_count;
i32 *map_id_table = models->map_id_table;
@ -118,7 +118,7 @@ app_get_map_index(App_Models *models, i32 mapid){
}
internal Command_Map*
app_get_map(App_Models *models, i32 mapid){
app_get_map(Models *models, i32 mapid){
Command_Map *map = 0;
if (mapid < mapid_global) map = models->user_maps + mapid;
else if (mapid == mapid_global) map = &models->map_top;
@ -130,7 +130,7 @@ app_get_map(App_Models *models, i32 mapid){
globalvar Application_Links app_links;
#define USE_MODELS(n) App_Models *n = command->models
#define USE_MODELS(n) Models *n = command->models
#define USE_VARS(n) App_Vars *n = command->vars
#define USE_PANEL(n) Panel *n = command->panel
#define USE_VIEW(n) View *n = command->view
@ -188,7 +188,7 @@ param_stack_end(Partition *part){
internal View*
panel_make_empty(System_Functions *system, Exchange *exchange, App_Vars *vars, Panel *panel){
App_Models *models = &vars->models;
Models *models = &vars->models;
View_And_ID new_view;
Assert(panel->view == 0);
@ -883,38 +883,6 @@ struct App_Open_File_Result{
b32 is_new;
};
internal App_Open_File_Result
app_open_file_background(App_Vars *vars, Exchange *exchange, Working_Set *working_set, String filename){
Get_File_Result file;
i32 file_id;
App_Open_File_Result result = {};
result.file = working_set_contains(working_set, filename);
if (result.file == 0){
result.is_new = 1;
file = working_set_get_available_file(working_set);
if (file.file){
result.file = file.file;
file_id = exchange_request_file(exchange, filename.str, filename.size);
if (file_id){
file_init_strings(result.file);
file_set_name(working_set, result.file, filename.str);
file_set_to_loading(result.file);
table_add(&working_set->table, result.file->name.source_path, file.index);
result.sys_id = file_id;
result.file_index = file.index;
}
else{
working_set_free_file(working_set, file.file);
file.file = 0;
}
}
}
return(result);
}
COMMAND_DECL(interactive_open){
ProfileMomentFunction();
USE_MODELS(models);
@ -964,7 +932,7 @@ COMMAND_DECL(interactive_open){
internal void
view_file_in_panel(Command_Data *cmd, Panel *panel, Editing_File *file){
System_Functions *system = cmd->system;
App_Models *models = cmd->models;
Models *models = cmd->models;
Partition old_part;
Temp_Memory temp;
@ -1126,15 +1094,13 @@ COMMAND_DECL(kill_buffer){
}
if (buffer_id != 0){
if (buffer_id > 0 && buffer_id < models->working_set.file_count){
file = working_set_get_file(&models->working_set, buffer_id, 1).file;
if (file){
delayed_kill(delay, file->name.source_path);
}
file = working_set_get_file(&models->working_set, buffer_id, 1).file;
if (file){
delayed_kill(delay, file);
}
}
else if (file){
delayed_try_kill(delay, file->name.live_name, view->panel);
delayed_try_kill(delay, file, view->panel);
}
}
@ -1290,7 +1256,7 @@ COMMAND_DECL(auto_tab_range){
}
}
if (file->state.token_stack.tokens && file->state.tokens_complete){
if (file->state.token_stack.tokens && file->state.tokens_complete && !file->state.still_lexing){
Range range = make_range(view->cursor.pos, view->mark);
if (start_set) range.start = r_start;
if (end_set) range.end = r_end;
@ -1298,42 +1264,6 @@ COMMAND_DECL(auto_tab_range){
}
}
COMMAND_DECL(auto_tab_line_at_cursor){
ProfileMomentFunction();
USE_MODELS(models);
REQ_OPEN_VIEW(view);
REQ_FILE(file, view);
int clear_blank_lines = 0;
Command_Parameter *end = param_stack_end(&command->part);
Command_Parameter *param = param_stack_first(&command->part, end);
for (; param < end; param = param_next(param, end)){
int p = dynamic_to_int(&param->param.param);
switch (p){
case par_clear_blank_lines:
clear_blank_lines = dynamic_to_bool(&param->param.value);
break;
}
}
if (file->state.token_stack.tokens && file->state.tokens_complete){
i32 pos = view->cursor.pos;
view_auto_tab_tokens(system, models, view, pos, pos, clear_blank_lines);
}
}
COMMAND_DECL(auto_tab_whole_file){
ProfileMomentFunction();
USE_MODELS(models);
REQ_OPEN_VIEW(view);
REQ_FILE(file, view);
if (file->state.token_stack.tokens && file->state.tokens_complete){
view_auto_tab_tokens(system, models, view, 0, buffer_size(&file->state.buffer), 1);
}
}
COMMAND_DECL(open_panel_vsplit){
ProfileMomentFunction();
USE_VARS(vars);
@ -2091,7 +2021,7 @@ extern "C"{
GET_PARAMETER_BUFFER_SIG(external_get_parameter_buffer){
Command_Data *cmd = (Command_Data*)app->cmd_context;
App_Models *models = cmd->models;
Models *models = cmd->models;
Buffer_Summary buffer = {};
if (param_index >= 0 && param_index < models->buffer_param_count){
@ -2153,7 +2083,7 @@ extern "C"{
BUFFER_SEEK_STRING_SIG(external_buffer_seek_string){
Command_Data *cmd = (Command_Data*)app->cmd_context;
App_Models *models;
Models *models;
Editing_File *file;
Working_Set *working_set;
Partition *part;
@ -2226,7 +2156,7 @@ extern "C"{
Editing_File *file;
Working_Set *working_set;
App_Models *models;
Models *models;
int result = 0;
int size;
@ -2435,23 +2365,29 @@ extern "C"{
View *vptr;
Get_File_Result file;
Working_Set *working_set;
App_Models *models;
Models *models;
int result = 0;
int view_id;
if (view->exists){
models = cmd->models;
live_set = cmd->live_set;
vptr = live_set->views + view->view_id;
working_set = &models->working_set;
file = working_set_get_file(working_set, buffer_id, 1);
view_id = view->view_id - 1;
if (view_id >= 0 && view_id < live_set->max){
vptr = live_set->views + view_id;
working_set = &models->working_set;
file = working_set_get_file(working_set, buffer_id, 1);
if (file.file){
result = 1;
view_set_file(vptr, file.file, models,
cmd->system, models->hooks[hook_open_file], &app_links);
if (file.file){
result = 1;
if (file.file != vptr->file){
view_set_file(vptr, file.file, models,
cmd->system, models->hooks[hook_open_file], &app_links);
}
}
fill_view_summary(view, vptr, live_set, working_set);
}
fill_view_summary(view, vptr, live_set, working_set);
}
return(result);
@ -2647,18 +2583,8 @@ setup_command_table(){
SET(write_character);
SET(seek_left);
SET(seek_right);
SET(seek_whitespace_right);
SET(seek_whitespace_left);
SET(seek_whitespace_up);
SET(seek_whitespace_down);
SET(seek_token_left);
SET(seek_token_right);
SET(seek_white_or_token_right);
SET(seek_white_or_token_left);
SET(seek_alphanumeric_right);
SET(seek_alphanumeric_left);
SET(seek_alphanumeric_or_camel_right);
SET(seek_alphanumeric_or_camel_left);
SET(word_complete);
SET(set_mark);
SET(copy);
@ -2688,8 +2614,6 @@ setup_command_table(){
SET(eol_dosify);
SET(eol_nixify);
SET(auto_tab_range);
SET(auto_tab_line_at_cursor);
SET(auto_tab_whole_file);
SET(open_panel_vsplit);
SET(open_panel_hsplit);
SET(close_panel);
@ -2715,7 +2639,7 @@ setup_command_table(){
// App Functions
internal void
app_hardcode_styles(App_Models *models){
app_hardcode_styles(Models *models){
Interactive_Style file_info_style;
Style *styles, *style;
styles = models->styles.styles;
@ -3120,7 +3044,7 @@ extern "C" SCROLL_RULE_SIG(fallback_scroll_rule){
App_Init_Sig(app_init){
App_Vars *vars;
App_Models *models;
Models *models;
Partition *partition;
Panel *panels, *panel;
Panel_Divider *dividers, *div;
@ -3450,13 +3374,45 @@ App_Init_Sig(app_init){
models->buffer_param_indices = push_array(partition, i32, models->buffer_param_max);
}
internal App_Open_File_Result
app_open_file_background(App_Vars *vars, Exchange *exchange, Working_Set *working_set, String filename){
Get_File_Result file;
i32 file_id;
App_Open_File_Result result = {};
result.file = working_set_contains(working_set, filename);
if (result.file == 0){
result.is_new = 1;
file = working_set_get_available_file(working_set);
if (file.file){
result.file = file.file;
file_id = exchange_request_file(exchange, filename.str, filename.size);
if (file_id){
file_init_strings(result.file);
file_set_name(working_set, result.file, filename.str);
file_set_to_loading(result.file);
table_add(&working_set->table, result.file->name.source_path, file.index);
result.sys_id = file_id;
result.file_index = file.index;
}
else{
working_set_free_file(working_set, file.file);
file.file = 0;
}
}
}
return(result);
}
App_Step_Sig(app_step){
ProfileStart(OS_syncing);
Application_Step_Result app_result = *result;
app_result.redraw = force_redraw;
App_Vars *vars = (App_Vars*)memory->vars_memory;
App_Models *models = &vars->models;
Models *models = &vars->models;
target->partition = &models->mem.part;
if (first_step || !time_step){
@ -3715,7 +3671,7 @@ App_Step_Sig(app_step){
}
}
ProfileEnd(prepare_commands);
// NOTE(allen): process the command_coroutine if it is unfinished
ProfileStart(command_coroutine);
b8 consumed_input[6] = {0};
@ -3844,7 +3800,15 @@ App_Step_Sig(app_step){
update_command_data(vars, cmd);
ProfileEnd(command_coroutine);
ProfileStart(frame_hook);
if (models->hooks[hook_frame]){
if ((models->hooks[hook_frame])(&app_links)){
app_result.redraw = 1;
}
}
ProfileStart(frame_hook);
// NOTE(allen): pass raw input to the panels
ProfileStart(step);
@ -4191,17 +4155,53 @@ App_Step_Sig(app_step){
// TODO(allen): Paramter checking in each DACT case.
switch (act->type){
case DACT_OPEN:
case DACT_TOUCH_FILE:
{
App_Open_File_Result result;
if (file){
Assert(!file->state.is_dummy);
dll_remove(&file->node);
dll_insert(&models->working_set.used_sentinel, &file->node);
}
}break;
result = app_open_file_background(vars, exchange, working_set, string);
case DACT_OPEN:
case DACT_OPEN_BACKGROUND:
{
App_Open_File_Result result = {};
{
String filename = string;
Get_File_Result file;
i32 file_id;
result.file = working_set_contains(working_set, filename);
if (result.file == 0){
result.is_new = 1;
file = working_set_get_available_file(working_set);
if (file.file){
result.file = file.file;
file_id = exchange_request_file(exchange, filename.str, filename.size);
if (file_id){
file_init_strings(result.file);
file_set_name(working_set, result.file, filename.str);
file_set_to_loading(result.file);
table_add(&working_set->table, result.file->name.source_path, file.index);
result.sys_id = file_id;
result.file_index = file.index;
}
else{
working_set_free_file(working_set, file.file);
file.file = 0;
}
}
}
}
if (result.is_new){
if (result.file){
if (result.sys_id){
Sys_App_Binding *binding = app_push_file_binding(vars, result.sys_id, result.file_index);
binding->success = SysAppCreateView;
binding->success = (act->type == DACT_OPEN) ? SysAppCreateView : 0;
binding->fail = 0;
binding->panel = panel;
}
@ -4211,27 +4211,10 @@ App_Step_Sig(app_step){
}
}
else{
Assert(result.file);
if (!result.file->state.is_loading){
view_file_in_panel(cmd, panel, result.file);
}
}
}break;
case DACT_OPEN_BACKGROUND:
{
App_Open_File_Result result;
result = app_open_file_background(vars, exchange, working_set, string);
if (result.is_new){
if (result.file){
if (result.sys_id){
Sys_App_Binding *binding = app_push_file_binding(vars, result.sys_id, result.file_index);
binding->success = 0;
binding->fail = 0;
binding->panel = panel;
}
else{
delayed_action_repush(&models->delay2, act);
if (act->type == DACT_OPEN){
Assert(result.file);
if (!result.file->state.is_loading){
view_file_in_panel(cmd, panel, result.file);
}
}
}
@ -4325,6 +4308,7 @@ App_Step_Sig(app_step){
case DACT_SWITCH:
{
Editing_File *file = working_set_lookup_file(working_set, string);
if (file){
View *view = panel->view;
@ -4336,18 +4320,15 @@ App_Step_Sig(app_step){
case DACT_KILL:
{
Editing_File *file = working_set_lookup_file(working_set, string);
if (file){
table_remove(&working_set->table, file->name.source_path);
kill_file(system, exchange, models, file);
kill_file(system, exchange, models, file,
models->hooks[hook_open_file], &app_links);
}
}break;
case DACT_TRY_KILL:
{
Editing_File *file = 0;
file = working_set_lookup_file(working_set, string);
View *view = 0;
if (panel){
view = panel->view;
@ -4356,8 +4337,6 @@ App_Step_Sig(app_step){
view = (models->layout.panels + models->layout.active_panel)->view;
}
Assert(view);
if (file){
if (buffer_needs_save(file)){
view_show_interactive(system, view, &models->map_ui,
@ -4366,7 +4345,8 @@ App_Step_Sig(app_step){
}
else{
table_remove(&working_set->table, file->name.source_path);
kill_file(system, exchange, models, file);
kill_file(system, exchange, models, file,
models->hooks[hook_open_file], &app_links);
}
}
}break;

View File

@ -21,7 +21,7 @@ struct App_Settings{
b32 lctrl_lalt_is_altgr;
};
struct App_Models{
struct Models{
Mem_Options mem;
App_Settings settings;
@ -37,7 +37,7 @@ struct App_Models{
Coroutine *command_coroutine;
u32 command_coroutine_flags[2];
Custom_Command_Function *hooks[hook_type_count];
Hook_Function *hooks[hook_type_count];
i32 *buffer_param_indices;
i32 buffer_param_count, buffer_param_max;

View File

@ -8,8 +8,7 @@
*/
// TOP
#include "4ed_version.h"
#include "4ed_config.h"
#define BUFFER_EXPERIMENT_SCALPEL 0

View File

@ -8,6 +8,7 @@ enum Action_Type{
DACT_SWITCH,
DACT_TRY_KILL,
DACT_KILL,
DACT_TOUCH_FILE,
};
struct Delayed_Action{
@ -48,6 +49,14 @@ delayed_action_(Delay *delay, Action_Type type){
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, String string){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->string = str_alloc_copy(delay->general, string);
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, Panel* panel){
Delayed_Action *result;
@ -57,10 +66,19 @@ delayed_action_(Delay *delay, Action_Type type, Panel* panel){
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, String string){
delayed_action_(Delay *delay, Action_Type type, Editing_File* file){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->string = str_alloc_copy(delay->general, string);
result->file = file;
return(result);
}
inline Delayed_Action*
delayed_action_(Delay *delay, Action_Type type, Editing_File* file, Panel* panel){
Delayed_Action *result;
result = delayed_action_(delay, type);
result->file = file;
result->panel = panel;
return(result);
}
@ -110,3 +128,4 @@ delayed_action_repush(Delay *delay, Delayed_Action *act){
#define delayed_switch(delay, ...) delayed_action_(delay, DACT_SWITCH, __VA_ARGS__)
#define delayed_try_kill(delay, ...) delayed_action_(delay, DACT_TRY_KILL, __VA_ARGS__)
#define delayed_kill(delay, ...) delayed_action_(delay, DACT_KILL, __VA_ARGS__)
#define delayed_touch_file(delay, ...) delayed_action_(delay, DACT_TOUCH_FILE, __VA_ARGS__)

View File

@ -9,25 +9,6 @@
// TOP
struct Interactive_Bar{
f32 pos_x, pos_y;
f32 text_shift_x, text_shift_y;
i32_Rect rect;
i16 font_id;
};
internal void
intbar_draw_string(Render_Target *target, Interactive_Bar *bar,
String str, u32 char_color){
i16 font_id = bar->font_id;
draw_string(target, font_id, str,
(i32)(bar->pos_x + bar->text_shift_x),
(i32)(bar->pos_y + bar->text_shift_y),
char_color);
bar->pos_x += font_string_width(target, font_id, str);
}
#include "buffer/4coder_shared.cpp"
#if BUFFER_EXPERIMENT_SCALPEL == 0
@ -360,6 +341,8 @@ internal b32
filename_match(String query, Absolutes *absolutes, String filename, b32 case_sensitive){
b32 result;
result = (query.size == 0);
replace_char(query, '\\', '/');
replace_char(filename, '\\', '/');
if (!result) result = wildcard_match(absolutes, filename, case_sensitive);
return result;
}
@ -372,6 +355,8 @@ hot_directory_first_match(Hot_Directory *hot_directory,
b32 case_sensitive){
Hot_Directory_Match result = {};
replace_char(str, '\\', '/');
Absolutes absolutes;
if (!exact_match)
get_absolutes(str, &absolutes, 1, 1);
@ -442,6 +427,7 @@ inline Editing_File*
working_set_contains(Working_Set *working, String filename){
Editing_File *result = 0;
i32 id;
replace_char(filename, '\\', '/');
if (table_find(&working->table, filename, &id)){
if (id >= 0 && id <= working->file_max){
result = working->files + id;
@ -450,10 +436,24 @@ working_set_contains(Working_Set *working, String filename){
return (result);
}
// TODO(allen): Find a way to choose an ordering for these so it picks better first options.
// TODO(allen): Pick better first options.
internal Editing_File*
working_set_lookup_file(Working_Set *working_set, String string){
Editing_File *file = working_set_contains(working_set, string);
Editing_File *file = 0;
replace_char(string, '\\', '/');
{
File_Node *node, *used_nodes;
used_nodes = &working_set->used_sentinel;
for (dll_items(node, used_nodes)){
file = (Editing_File*)node;
if (string.size == 0 || match(string, file->name.live_name)){
break;
}
}
if (node == used_nodes) file = 0;
}
if (!file){
File_Node *node, *used_nodes;

View File

@ -67,7 +67,7 @@ struct View{
View *next, *prev;
b32 in_use;
App_Models *models;
Models *models;
Panel *panel;
Command_Map *map;
@ -518,7 +518,7 @@ alloc_for_buffer(void *context, int *size){
}
internal void
file_create_from_string(System_Functions *system, App_Models *models,
file_create_from_string(System_Functions *system, Models *models,
Editing_File *file, char *filename, String val, b8 read_only = 0){
Font_Set *font_set = models->font_set;
@ -544,7 +544,11 @@ file_create_from_string(System_Functions *system, App_Models *models,
init_success = buffer_end_init(&init, part->base + part->pos, scratch_size);
AllowLocal(init_success);
Assert(init_success);
if (buffer_size(&file->state.buffer) < val.size){
file->settings.dos_write_mode = 1;
}
file_init_strings(file);
file_set_name(working_set, file, (char*)filename);
@ -588,7 +592,7 @@ file_create_from_string(System_Functions *system, App_Models *models,
internal b32
file_create_empty(System_Functions *system,
App_Models *models, Editing_File *file, char *filename){
Models *models, Editing_File *file, char *filename){
file_create_from_string(system, models, file, filename, {});
return (1);
@ -596,7 +600,7 @@ file_create_empty(System_Functions *system,
internal b32
file_create_read_only(System_Functions *system,
App_Models *models, Editing_File *file, char *filename){
Models *models, Editing_File *file, char *filename){
file_create_from_string(system, models, file, filename, {}, 1);
return (1);
@ -1107,7 +1111,7 @@ file_post_history(General_Memory *general, Editing_File *file,
inline Full_Cursor
view_compute_cursor_from_pos(View *view, i32 pos){
Editing_File *file = view->file;
App_Models *models = view->models;
Models *models = view->models;
Render_Font *font = get_font_info(models->font_set, models->global_font.font_id)->font;
Full_Cursor result = {};
@ -1122,7 +1126,7 @@ view_compute_cursor_from_pos(View *view, i32 pos){
inline Full_Cursor
view_compute_cursor_from_unwrapped_xy(View *view, f32 seek_x, f32 seek_y, b32 round_down = 0){
Editing_File *file = view->file;
App_Models *models = view->models;
Models *models = view->models;
Render_Font *font = get_font_info(models->font_set, models->global_font.font_id)->font;
Full_Cursor result = {};
@ -1139,7 +1143,7 @@ view_compute_cursor_from_unwrapped_xy(View *view, f32 seek_x, f32 seek_y, b32 ro
internal Full_Cursor
view_compute_cursor_from_wrapped_xy(View *view, f32 seek_x, f32 seek_y, b32 round_down = 0){
Editing_File *file = view->file;
App_Models *models = view->models;
Models *models = view->models;
Render_Font *font = get_font_info(models->font_set, models->global_font.font_id)->font;
Full_Cursor result = {};
@ -1156,7 +1160,7 @@ view_compute_cursor_from_wrapped_xy(View *view, f32 seek_x, f32 seek_y, b32 roun
internal Full_Cursor
view_compute_cursor_from_line_pos(View *view, i32 line, i32 pos){
Editing_File *file = view->file;
App_Models *models = view->models;
Models *models = view->models;
Render_Font *font = get_font_info(models->font_set, models->global_font.font_id)->font;
Full_Cursor result = {};
@ -1257,18 +1261,21 @@ view_get_cursor_y(View *view){
internal void
view_set_file(
// NOTE(allen): These parameters are always meaningful
View *view, Editing_File *file, App_Models *models,
View *view, Editing_File *file, Models *models,
// NOTE(allen): Necessary when file != 0
System_Functions *system, Hook_Function *open_hook, Application_Links *app){
System_Functions *system, Hook_Function *open_hook, Application_Links *app,
// other
b32 set_vui = 1){
Font_Info *fnt_info;
// NOTE(allen): This is actually more like view_set_style right?
// TODO(allen): This belongs somewhere else.
fnt_info = get_font_info(models->font_set, models->global_font.font_id);
view->font_advance = fnt_info->advance;
view->font_height = fnt_info->height;
// NOTE(allen): Stuff that doesn't assume file exists.
view->file = file;
view->cursor = {};
@ -1296,10 +1303,13 @@ view_set_file(
file->settings.is_initialized = 1;
}
}
// TODO(allen): Fix this:
view->ui_state = {};
view->showing_ui = VUI_None;
if (set_vui){
// TODO(allen): Fix this! There should be a way to easily separate setting a file,
// and switching to file mode, so that they don't cross over eachother like this.
view->ui_state = {};
view->showing_ui = VUI_None;
}
}
struct Relative_Scrolling{
@ -1389,7 +1399,7 @@ file_update_history_before_edit(Mem_Options *mem, Editing_File *file, Edit_Step
History_Mode history_mode){
if (!file->state.undo.undo.edits) return;
General_Memory *general = &mem->general;
b32 can_merge = 0, do_merge = 0;
switch (step.type){
case ED_NORMAL:
@ -1571,7 +1581,7 @@ 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;
@ -1579,11 +1589,11 @@ file_edit_cursor_fix(System_Functions *system,
f32 y_offset = 0, y_position = 0;
i32 cursor_count = 0;
View *view;
Panel *panel, *used_panels;
used_panels = &layout->used_sentinel;
for (dll_items(panel, used_panels)){
view = panel->view;
if (view->file == file){
@ -1606,14 +1616,14 @@ file_edit_cursor_fix(System_Functions *system,
desc.shift_amount + (desc.end - desc.start));
}
buffer_unsort_cursors(cursors, cursor_count);
cursor_count = 0;
for (dll_items(panel, used_panels)){
view = panel->view;
if (view && view->file == file){
view_cursor_move(view, cursors[cursor_count++].pos);
view->preferred_x = view_get_cursor_x(view);
view->mark = cursors[cursor_count++].pos + 1;
i32 new_scroll_i = cursors[cursor_count++].pos + 1;
if (view->scroll_i != new_scroll_i){
@ -1635,20 +1645,20 @@ file_edit_cursor_fix(System_Functions *system,
}
}
}
end_temp_memory(cursor_temp);
}
internal void
file_do_single_edit(System_Functions *system,
App_Models *models, Editing_File *file,
Models *models, Editing_File *file,
Edit_Spec spec, History_Mode history_mode, b32 use_high_permission = 0){
ProfileMomentFunction();
if (!use_high_permission && file->settings.read_only) return;
Mem_Options *mem = &models->mem;
Editing_Layout *layout = &models->layout;
// NOTE(allen): fixing stuff beforewards????
file_update_history_before_edit(mem, file, spec.step, spec.str, history_mode);
file_pre_edit_maintenance(system, &mem->general, file);
@ -1692,7 +1702,7 @@ file_do_single_edit(System_Functions *system,
Panel *panel, *used_panels;
used_panels = &layout->used_sentinel;
for (dll_items(panel, used_panels)){
View *view = panel->view;
if (view->file == file){
@ -1716,19 +1726,19 @@ file_do_single_edit(System_Functions *system,
}
internal void
file_do_white_batch_edit(System_Functions *system, App_Models *models, Editing_File *file,
file_do_white_batch_edit(System_Functions *system, Models *models, Editing_File *file,
Edit_Spec spec, History_Mode history_mode, b32 use_high_permission = 0){
ProfileMomentFunction();
if (!use_high_permission && file->settings.read_only) return;
Mem_Options *mem = &models->mem;
Editing_Layout *layout = &models->layout;
// NOTE(allen): fixing stuff "beforewards"???
Assert(spec.str == 0);
file_update_history_before_edit(mem, file, spec.step, 0, history_mode);
file_pre_edit_maintenance(system, &mem->general, file);
// NOTE(allen): actual text replacement
General_Memory *general = &mem->general;
Partition *part = &mem->part;
@ -1772,7 +1782,7 @@ file_do_white_batch_edit(System_Functions *system, App_Models *models, Editing_F
file_edit_cursor_fix(system, part, general, file, layout, desc);
}
// NOTE(allen): token fixing
if (file->state.tokens_complete){
Cpp_Token_Stack tokens = file->state.token_stack;
@ -1803,7 +1813,7 @@ file_do_white_batch_edit(System_Functions *system, App_Models *models, Editing_F
}
inline void
file_replace_range(System_Functions *system, App_Models *models, Editing_File *file,
file_replace_range(System_Functions *system, Models *models, Editing_File *file,
i32 start, i32 end, char *str, i32 len, i32 next_cursor, b32 use_high_permission = 0){
Edit_Spec spec = {};
spec.step.type = ED_NORMAL;
@ -1817,7 +1827,7 @@ file_replace_range(System_Functions *system, App_Models *models, Editing_File *f
}
inline void
view_replace_range(System_Functions *system, App_Models *models, View *view,
view_replace_range(System_Functions *system, Models *models, View *view,
i32 start, i32 end, char *str, i32 len, i32 next_cursor){
file_replace_range(system, models, view->file, start, end, str, len, next_cursor);
}
@ -1835,10 +1845,10 @@ view_post_paste_effect(View *view, i32 ticks, i32 start, i32 size, u32 color){
internal void
view_undo_redo(System_Functions *system,
App_Models *models, View *view,
Models *models, View *view,
Edit_Stack *stack, Edit_Type expected_type){
Editing_File *file = view->file;
if (stack->edit_count > 0){
Edit_Step step = stack->edits[stack->edit_count-1];
@ -1868,12 +1878,12 @@ view_undo_redo(System_Functions *system,
}
inline void
view_undo(System_Functions *system, App_Models *models, View *view){
view_undo(System_Functions *system, Models *models, View *view){
view_undo_redo(system, models, view, &view->file->state.undo.undo, ED_UNDO);
}
inline void
view_redo(System_Functions *system, App_Models *models, View *view){
view_redo(System_Functions *system, Models *models, View *view){
view_undo_redo(system, models, view, &view->file->state.undo.redo, ED_REDO);
}
@ -1942,7 +1952,7 @@ file_dump_history(System_Functions *system, Mem_Options *mem, Editing_File *file
#endif
internal void
view_history_step(System_Functions *system, App_Models *models, View *view, History_Mode history_mode){
view_history_step(System_Functions *system, Models *models, View *view, History_Mode history_mode){
Assert(history_mode != hist_normal);
Editing_File *file = view->file;
@ -2138,17 +2148,17 @@ file_compute_whitespace_edit(Mem_Options *mem, Editing_File *file, i32 cursor_po
}
internal void
view_clean_whitespace(System_Functions *system, App_Models *models, View *view){
view_clean_whitespace(System_Functions *system, Models *models, View *view){
Mem_Options *mem = &models->mem;
Editing_File *file = view->file;
Partition *part = &mem->part;
i32 line_count = file->state.buffer.line_count;
i32 edit_max = line_count * 2;
i32 edit_count = 0;
Assert(file && !file->state.is_dummy);
Temp_Memory temp = begin_temp_memory(part);
Buffer_Edit *edits = push_array(part, Buffer_Edit, edit_max);
@ -2199,7 +2209,7 @@ view_clean_whitespace(System_Functions *system, App_Models *models, View *view){
internal void
view_auto_tab_tokens(System_Functions *system,
App_Models *models, View *view,
Models *models, View *view,
i32 start, i32 end, b32 empty_blank_lines){
#if BUFFER_EXPERIMENT_SCALPEL <= 0
Editing_File *file = view->file;
@ -2575,9 +2585,9 @@ view_show_config(View *fview, Command_Map *gui_map){
inline void
view_show_interactive(System_Functions *system, View *view, Command_Map *gui_map,
Interactive_Action action, Interactive_Interaction interaction, String query){
App_Models *models = view->models;
Models *models = view->models;
view->ui_state = {};
view->map_for_file = view->map;
view->map = gui_map;
@ -2595,12 +2605,13 @@ view_show_interactive(System_Functions *system, View *view, Command_Map *gui_map
}
inline void
view_show_theme(View *fview, Command_Map *gui_map){
fview->ui_state = {};
fview->map_for_file = fview->map;
fview->map = gui_map;
fview->showing_ui = VUI_Theme;
fview->color_mode = CV_Mode_Library;
view_show_theme(View *view, Command_Map *gui_map){
view->ui_state = {};
view->map_for_file = view->map;
view->map = gui_map;
view->showing_ui = VUI_Theme;
view->color_mode = CV_Mode_Library;
view->color = super_color_create(0xFF000000);
}
inline void
@ -2617,30 +2628,34 @@ view_show_file(View *view, Command_Map *file_map){
internal void
interactive_view_complete(View *view){
Models *models = view->models;
Panel *panel = view->panel;
App_Models *models = view->models;
Editing_File *file = 0;
Editing_File *old_file = view->file;
switch (view->action){
case IAct_Open:
delayed_open(&models->delay1, models->hot_directory.string, panel);
delayed_touch_file(&models->delay1, old_file);
break;
case IAct_Save_As:
delayed_save_as(&models->delay1, models->hot_directory.string, panel);
file = view->file;
break;
case IAct_New:
delayed_new(&models->delay1, models->hot_directory.string, panel);
if (models->hot_directory.string.size > 0 &&
!char_is_slash(models->hot_directory.string.str[models->hot_directory.string.size-1])){
delayed_new(&models->delay1, models->hot_directory.string, panel);
}
break;
case IAct_Switch:
delayed_switch(&models->delay1, view->dest, panel);
delayed_touch_file(&models->delay1, old_file);
break;
case IAct_Kill:
delayed_try_kill(&models->delay1, view->dest, panel);
file = view->file;
break;
case IAct_Sure_To_Kill:
@ -2649,7 +2664,8 @@ interactive_view_complete(View *view){
delayed_kill(&models->delay1, view->dest, panel);
break;
case 1:break;
case 1:
break;
case 2:
// TODO(allen): This is fishy! What if the save doesn't happen this time around?
@ -2661,6 +2677,9 @@ interactive_view_complete(View *view){
break;
}
view_show_file(view, 0);
// TODO(allen): This is here to prevent the key press from being passed to the
// underlying file which is a giant pain.
view->file = 0;
}
@ -2677,9 +2696,9 @@ update_highlighting(View *view){
view->highlight = {};
return;
}
App_Models *models = view->models;
Models *models = view->models;
Style *style = &models->style;
i32 pos = view_get_cursor_pos(file_view);
char c = buffer_get_char(&file->state.buffer, pos);
@ -2749,7 +2768,7 @@ internal b32
theme_library_shit(System_Functions *system, Exchange *exchange,
View *view, UI_State *state, UI_Layout *layout){
App_Models *models = view->models;
Models *models = view->models;
Mem_Options *mem = &models->mem;
i32 result = 0;
@ -2999,11 +3018,11 @@ theme_library_shit(System_Functions *system, Exchange *exchange,
}
internal b32
theme_adjusting_shit(View *view, UI_State *state, UI_Layout *layout){
theme_adjusting_shit(View *view, UI_State *state, UI_Layout *layout, Super_Color *color){
update_highlighting(view);
App_Models *models = view->models;
Models *models = view->models;
Style *style = &models->style;
i32 result = 0;
@ -3125,14 +3144,14 @@ theme_adjusting_shit(View *view, UI_State *state, UI_Layout *layout){
bar_style->pop2_color, bar_style->bar_color,
"Bar Pop 2");
view->color = ui.color;
return result;
*color = ui.hover_color;
return (result);
}
internal b32
theme_shit(System_Functions *system, Exchange *exchange,
View *view, View *active, UI_State *state, UI_Layout *layout){
View *view, View *active, UI_State *state, UI_Layout *layout, Super_Color *color){
b32 result = 0;
if (view != active){
@ -3152,7 +3171,7 @@ theme_shit(System_Functions *system, Exchange *exchange,
break;
case CV_Mode_Adjusting:
if (theme_adjusting_shit(view, state, layout)){
if (theme_adjusting_shit(view, state, layout, color)){
result = 1;
}
break;
@ -3167,8 +3186,8 @@ interactive_shit(System_Functions *system, View *view, UI_State *state, UI_Layou
b32 new_dir = 0;
b32 complete = 0;
App_Models *models = view->models;
Models *models = view->models;
do_label(state, layout, view->query, 1.f);
b32 case_sensitive = 0;
@ -3268,8 +3287,8 @@ menu_shit(View *view, UI_State *state, UI_Layout *layout){
internal void
config_shit(View *view, UI_State *state, UI_Layout *layout){
i32 id = 0;
App_Models *models = view->models;
Models *models = view->models;
do_label(state, layout, literal("Config"), 2.f);
if (do_checkbox_list_option(++id, state, layout, make_lit_string("Left Ctrl + Left Alt = AltGr"),
@ -3278,16 +3297,35 @@ config_shit(View *view, UI_State *state, UI_Layout *layout){
}
}
struct File_Bar{
f32 pos_x, pos_y;
f32 text_shift_x, text_shift_y;
i32_Rect rect;
i16 font_id;
};
internal void
intbar_draw_string(Render_Target *target, File_Bar *bar, String str, u32 char_color){
i16 font_id = bar->font_id;
draw_string(target, font_id, str,
(i32)(bar->pos_x + bar->text_shift_x),
(i32)(bar->pos_y + bar->text_shift_y),
char_color);
bar->pos_x += font_string_width(target, font_id, str);
}
internal void
do_file_bar(View *view, Editing_File *file, UI_Layout *layout, Render_Target *target){
Interactive_Bar bar;
App_Models *models = view->models;
File_Bar bar;
Models *models = view->models;
Style_Font *font = &models->global_font;
i32 line_height = view->font_height;
Interactive_Style bar_style = models->style.main.file_info_style;
u32 back_color = bar_style.bar_color;
u32 base_color = bar_style.base_color;
u32 pop1_color = bar_style.pop1_color;
u32 pop2_color = bar_style.pop2_color;
bar.rect = layout_rect(layout, line_height + 2);
@ -3301,7 +3339,7 @@ do_file_bar(View *view, Editing_File *file, UI_Layout *layout, Render_Target *ta
draw_rectangle(target, bar.rect, back_color);
intbar_draw_string(target, &bar, file->name.live_name, base_color);
intbar_draw_string(target, &bar, make_lit_string(" - "), base_color);
intbar_draw_string(target, &bar, make_lit_string(" -"), base_color);
if (file->state.is_loading){
intbar_draw_string(target, &bar, make_lit_string(" loading"), base_color);
@ -3309,11 +3347,24 @@ do_file_bar(View *view, Editing_File *file, UI_Layout *layout, Render_Target *ta
else{
char line_number_space[30];
String line_number = make_string(line_number_space, 0, 30);
append(&line_number, "L#");
append(&line_number, " L#");
append_int_to_str(view->cursor.line, &line_number);
intbar_draw_string(target, &bar, line_number, base_color);
intbar_draw_string(target, &bar, make_lit_string(" -"), base_color);
if (file->settings.dos_write_mode){
intbar_draw_string(target, &bar, make_lit_string(" dos"), base_color);
}
else{
intbar_draw_string(target, &bar, make_lit_string(" nix"), base_color);
}
if (file->state.still_lexing){
intbar_draw_string(target, &bar, make_lit_string(" parsing"), pop1_color);
}
if (!file->settings.unimportant){
switch (buffer_get_sync(file)){
case SYNC_BEHIND_OS:
@ -3372,7 +3423,7 @@ internal i32
step_file_view(System_Functions *system, Exchange *exchange, View *view, i32_Rect rect,
b32 is_active, Input_Summary *user_input){
App_Models *models = view->models;
Models *models = view->models;
i32 result = 0;
Editing_File *file = view->file;
@ -3519,11 +3570,13 @@ step_file_view(System_Functions *system, Exchange *exchange, View *view, i32_Rec
UI_Layout layout;
begin_layout(&layout, rect);
Super_Color color = {};
switch (view->showing_ui){
case VUI_None: break;
case VUI_Theme:
{
theme_shit(system, exchange, view, 0, &state, &layout);
theme_shit(system, exchange, view, 0, &state, &layout, &color);
}break;
case VUI_Interactive:
{
@ -3539,19 +3592,26 @@ step_file_view(System_Functions *system, Exchange *exchange, View *view, i32_Rec
{
config_shit(view, &state, &layout);
}break;
}
}
if (ui_finish_frame(&view->ui_state, &state, &layout, rect, 0, 0)){
i32 did_activation = 0;
if (ui_finish_frame(&view->ui_state, &state, &layout, rect, 0, &did_activation)){
result = 1;
}
if (did_activation){
if (view->showing_ui == VUI_Theme){
view->color = color;
result = 1;
}
}
}
return(result);
}
internal i32
draw_file_loaded(View *view, i32_Rect rect, b32 is_active, Render_Target *target){
App_Models *models = view->models;
Models *models = view->models;
Editing_File *file = view->file;
Style *style = &models->style;
i32 line_height = view->font_height;
@ -3722,7 +3782,7 @@ draw_file_view(System_Functions *system, Exchange *exchange,
View *view, View *active, i32_Rect rect, b32 is_active,
Render_Target *target, Input_Summary *user_input){
App_Models *models = view->models;
Models *models = view->models;
Editing_File *file = view->file;
i32 result = 0;
@ -3776,7 +3836,9 @@ draw_file_view(System_Functions *system, Exchange *exchange,
begin_layout(&layout, rect);
rect.y0 -= widget_height;
Super_Color color = {};
switch (view->showing_ui){
case VUI_None:
{
@ -3790,7 +3852,7 @@ draw_file_view(System_Functions *system, Exchange *exchange,
case VUI_Theme:
{
theme_shit(system, exchange, view, active, &state, &layout);
theme_shit(system, exchange, view, active, &state, &layout, &color);
}break;
case VUI_Interactive:
@ -3816,18 +3878,32 @@ draw_file_view(System_Functions *system, Exchange *exchange,
return (result);
}
// TODO(allen): Passing this hook and app pointer is a hack. It can go as soon as we start
// initializing files independently of setting them to views.
internal void
kill_file(System_Functions *system, Exchange *exchange,
App_Models *models, Editing_File *file){
kill_file(System_Functions *system, Exchange *exchange, Models *models, Editing_File *file,
Hook_Function *open_hook, Application_Links *app){
File_Node *node, *used;
file_close(system, &models->mem.general, file);
working_set_free_file(&models->working_set, file);
used = &models->working_set.used_sentinel;
node = used->next;
for (View_Iter iter = file_view_iter_init(&models->layout, file, 0);
file_view_iter_good(iter);
iter = file_view_iter_next(iter)){
iter.view->file = 0;
if (node != used){
iter.view->file = 0;
view_set_file(iter.view, (Editing_File*)node, models, system, open_hook, app, 0);
node = node->next;
}
else{
iter.view->file = 0;
view_set_file(iter.view, 0, models, system, open_hook, app, 0);
}
}
file_close(system, &models->mem.general, file);
working_set_free_file(&models->working_set, file);
}
inline void
@ -4046,7 +4122,7 @@ struct Live_Views{
};
internal View_And_ID
live_set_alloc_view(Live_Views *live_set, Panel *panel, App_Models *models){
live_set_alloc_view(Live_Views *live_set, Panel *panel, Models *models){
View_And_ID result = {};
Assert(live_set->count < live_set->max);

View File

@ -64,120 +64,6 @@ free_query_slot(Query_Set *set, Query_Bar *match_bar){
}
}
#if 0
enum GUI_Piece_Type{
gui_type_text_input,
gui_type_number_input,
gui_type_label,
gui_type_slider
};
struct GUI_Piece_Header{
i32 type;
i32 padding;
};
// TODO(allen): Inline string for prompt?
struct GUI_Piece_Text_Input{
String *dest;
f32_Rect rect;
String prompt;
};
struct GUI_Piece_Number_Input{
i32 *dest;
f32_Rect rect;
String prompt;
};
struct GUI_Piece_Label{
f32_Rect rect;
String text;
};
struct GUI_Piece_Slider{
i32 *dest;
f32_Rect rect;
i32 max;
};
struct GUI_Layout_Engine{
i32_Rect region;
i32 x, y;
};
struct GUI_Target{
Partition push_buffer;
GUI_Layout_Engine layout;
};
internal void
refresh_gui(GUI_Target *target, i32_Rect region){
target->push_buffer.pos = 0;
target->layout.region = region;
target->layout.x = 0;
target->layout.y = 0;
}
internal void
push_gui_item(GUI_Target *target, GUI_Piece_Header header, void *item, i32 size){
GUI_Piece_Header *ptr;
i32 total_size;
Assert(sizeof(header) == 8);
total_size = sizeof(header) + size;
total_size = ((total_size + 7) & ~7);
ptr = (GUI_Piece_Header*)push_block(&target->push_buffer, size);
if (ptr){
*ptr = header;
memcpy(ptr + 1, item, size);
}
else{
Assert(!"bad situation");
}
}
internal void
push_gui_text_in(GUI_Target *target, String prompt, String *dest){
GUI_Piece_Header header = {};
GUI_Piece_Text_Input item = {};
header.type = gui_type_text_input;
item.dest = dest;
item.rect = gui_layout(target); // ?? what do we need here?
item.prompt = prompt;
push_gui_item(target, header, &item, sizeof(item));
}
internal void
push_gui_number_in(GUI_Target *target, String prompt, i32 *dest){
GUI_Piece_Header header = {};
GUI_Piece_Number_Input item = {};
header.type = gui_type_number_input;
item.dest = dest;
item.rect = gui_layout(target); // ?? what do we need here?
item.prompt = prompt;
push_gui_item(target, header, &item, sizeof(item));
}
internal void
push_gui_label(GUI_Target *target, String text){
GUI_Piece_Header header = {};
GUI_Piece_Label item = {};
header.type = gui_type_label;
item.rect = gui_layout(target); // ?? what do we need here?
item.text = text;
push_gui_item(target, header, &item, sizeof(item));
}
#endif
struct Single_Line_Input_Step{
b8 hit_newline;
b8 hit_ctrl_newline;
@ -1492,7 +1378,6 @@ do_live_file_list_box(System_Functions *system, UI_State *state, UI_Layout *layo
return result;
}
struct Super_Color{
Vec4 hsla;
Vec4 rgba;

View File

@ -154,6 +154,7 @@ char *daction_enum[] = {
"SWITCH",
"TRY_KILL",
"KILL",
"TOUCH_FILE",
};
char str_alloc_copy[] =
@ -186,8 +187,10 @@ enum Daction_Field_Handle{
dfph_integer,
};
Daction_Field_Handle dact_param_sets[] = {
dfph_panel, dfph_null,
dfph_string, dfph_null,
dfph_panel, dfph_null,
dfph_file, dfph_null,
dfph_file, dfph_panel, dfph_null,
dfph_string, dfph_panel, dfph_null,
dfph_string, dfph_file, dfph_null,
dfph_panel, dfph_integer, dfph_null,
@ -307,51 +310,6 @@ char* generate_delayed_action(){
return(filename);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
#define MAJOR 3
#define MINOR 4
#define PATCH 5
#define VERS3__(a,b,c) #a"."#b"."#c
#define VERS3_(a,b,c) VERS3__(a,b,c)
#define VERS3 VERS3_(MAJOR, MINOR, PATCH)
#define VERSION_STRING VERS3
char version_header[] =
"#define MAJOR %d\n"
"#define MINOR %d\n"
"#define PATCH %d\n"
"#define VERSION_NUMBER \"alpha %s\"\n"
"#ifdef FRED_SUPER\n"
"#define VERSION_TYPE \" super!\"\n"
"#else\n"
"#define VERSION_TYPE \"\"\n"
"#endif\n"
"#define VERSION VERSION_NUMBER VERSION_TYPE\n";
char version_custom[] =
"#define MAJOR %d\n"
"#define MINOR %d\n"
"#define PATCH %d\n";
char* generate_version(){
char *filename = "4ed_version.h & 4coder_version.h";
char filename_header[] = "4ed_version.h";
char filename_custom[] = "4coder_version.h";
FILE *file;
file = fopen(filename_header, "wb");
fprintf(file, version_header, MAJOR, MINOR, PATCH, VERSION_STRING);
fclose(file);
file = fopen(filename_custom, "wb");
fprintf(file, version_custom, MAJOR, MINOR, PATCH);
fclose(file);
return(filename);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
char* bar_style_fields[] = {
"bar",
@ -496,9 +454,6 @@ int main(){
filename = generate_delayed_action();
printf("gen success: %s\n", filename);
filename = generate_version();
printf("gen success: %s\n", filename);
filename = generate_style();
printf("gen success: %s\n", filename);
}

View File

@ -31,6 +31,15 @@ dll_insert(T *pos, T *v){
v->next->prev = v;
}
template<typename T>
inline void
dll_insert_back(T *pos, T *v){
v->prev = pos->prev;
v->next = pos;
pos->prev = v;
v->prev->next = v;
}
template<typename T>
inline void
dll_remove(T *v){

View File

@ -1,10 +0,0 @@
#define MAJOR 3
#define MINOR 4
#define PATCH 5
#define VERSION_NUMBER "alpha 3.4.5"
#ifdef FRED_SUPER
#define VERSION_TYPE " super!"
#else
#define VERSION_TYPE ""
#endif
#define VERSION VERSION_NUMBER VERSION_TYPE

View File

@ -1,4 +1,4 @@
@echo off
"w:\4ed\misc\build_all.bat" /DFRED_NOT_PACKAGE /Zi
"w:\4ed\misc\build_all.bat" /DFRED_SUPER /DFRED_NOT_PACKAGE /Zi
REM "w:\4ed\misc\build_all.bat" /O2 /Zi

View File

@ -7,7 +7,7 @@ SET clset=64
SET WARNINGS=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /WX
SET STUFF=/GR- /nologo
SET DEBUG=/Zi
SET EXPORTS=/EXPORT:get_bindings
SET EXPORTS=/EXPORT:get_bindings /EXPORT:get_alpha_4coder_version
SET SRC=4coder_custom.cpp
REM SET LINKS=user32.lib gdi32.lib
SET LINKS=

View File

@ -1,32 +1,37 @@
/* NOTE(casey):
/* TODO(casey): Here are our current issues
This is my attempt to make 4coder work close enough to Emacs
for me to switch!
- Display:
- Jumping to subsequent errors in a file seems to jump to an unrelated position
then scroll back to the actual position, which results in lots of extra scrolling
- Need a way of highlighting the current line like Emacs does for the benefit
of people on The Stream(TM)
- Need a way of changing some things visually so we can indicate the modal state (this has
to be something very obvious - ideally something like
1) Change the line highlight color
2) In modal mode, highlight the whole selected region (mark to cursor) potentially?
- Some way to recenter the view so that the line containing the cursor becomes the
center line vertically.
- NOTE / IMPORTANT / TODO highlighting? Ability to customize? Whatever.
NOTE(casey): Microsoft/Windows is poopsauce.
- Indentation:
- Multiple // lines don't seem to indent properly. The first one will go to the correct place, but the subsequent ones will go to the first column regardless?
- Would like the option to indent to hanging parentheses, equals signs, etc. instead of
always just "one tab in from the previous line".
- Need to have better indentation / wrapping control for typing in comments.
Right now it's a bit worse than Emacs, which does automatically put you at
the same margin as the prev. line (4coder just goes back to column 1). It'd
be nice if it got _better_ than Emacs, with no need to manually flow comments,
etc.
TODO(casey): Here are our current issues
- Buffer management:
- Have buffers normalize slashes to always be forward-slash - right now I'm doing this manually
- Have buffers normalize slashes to always be forward-slash
- Cursor setting seems to do no movement first time, and then weird scrolling behavior on
jump-to-same-line subsequently
- Switch-to-buffer with no typing, just return, should switch to the most recently
used buffer that is not currently displayed in a view.
- Kill-buffer should perform this switch automatically, or it should be easy
to build a custom kill buffer that does
- Need a way of highlighting the current line like Emacs does for the benefit
of people on The Stream(TM)
- Need a way of changing some things visually so we can indicate the modal state (this has
to be something very obvious - ideally something like
1) Change the line highlight color
2) In modal mode, highlight the whole selected region (mark to cursor) potentially?
- Macros
- Some way to recenter the view so that the line containing the cursor becomes the
center line vertically.
- NOTE / IMPORTANT / TODO highlighting? Ability to customize? Whatever.
- Need auto-complete for things like "arbitrary command", with options listed, etc.,
so this should either be built into 4ed, or the custom DLL should have the ability
to display possible completions and iterate over internal cmdid's, etc. Possibly
the latter, for maximal ability of customizers to add their own commands?
- Macro recording/playback
NOTE(allen): Things that were on the issue list that are now fixed
@ -34,13 +39,24 @@
- Need a way of changing some things visually so we can indicate the modal state (this has
to be something very obvious - ideally something like
1) Change the cursor color
2) X
3) X
4) Change the header bar color?
2) Change the header bar color?
- Need a way to set the theme from the custom config file so I don't have to pick it every
time.
- Switch-to-buffer with no typing, just return, should switch to the most recently
used buffer that is not currently displayed in a view.
- Kill-buffer should perform this switch automatically, or it should be easy
to build a custom kill buffer that does
- Seems like there's no way to switch to buffers whose names are substrings of other
buffers' names without using the mouse?
- Scroll speed seems to slow. It's behind where I am a lot of the time. Should be
_much_ more accelerated than it is, I think - presumably this will be tunable?
- Crash bug with paste-and-indent that sometimes leaves things unindented then crashes
*/
// NOTE(casey): Microsoft/Windows is poopsauce.
#include <math.h>
#include <stdio.h>
@ -273,6 +289,7 @@ HOOK_SIG(casey_start)
exec_command(app, cmdid_open_panel_vsplit);
app->change_theme(app, literal("Handmade Hero"));
app->change_font(app, literal("liberation mono"));
return(0);
}
CUSTOM_COMMAND_SIG(casey_open_in_other)
@ -291,7 +308,7 @@ CUSTOM_COMMAND_SIG(casey_clean_and_save)
CUSTOM_COMMAND_SIG(casey_newline_and_indent)
{
exec_command(app, cmdid_write_character);
exec_command(app, cmdid_auto_tab_line_at_cursor);
exec_command(app, auto_tab_line_at_cursor);
}
CUSTOM_COMMAND_SIG(casey_open_file_other_window)
@ -307,12 +324,17 @@ CUSTOM_COMMAND_SIG(casey_switch_buffer_other_window)
}
internal void
DeleteAfterCommand(struct Application_Links *app, Command_ID CommandID)
DeleteAfterCommand(struct Application_Links *app, unsigned long long CommandID)
{
View_Summary view = app->get_active_view(app);
int pos2 = view.cursor.pos;
exec_command(app, CommandID);
if (CommandID < cmdid_count){
exec_command(app, (Command_ID)CommandID);
}
else{
exec_command(app, (Custom_Command_Function*)CommandID);
}
app->refresh_view(app, &view);
int pos1 = view.cursor.pos;
@ -324,12 +346,12 @@ DeleteAfterCommand(struct Application_Links *app, Command_ID CommandID)
CUSTOM_COMMAND_SIG(casey_delete_token_left)
{
DeleteAfterCommand(app, cmdid_seek_white_or_token_left);
DeleteAfterCommand(app, (unsigned long long)seek_white_or_token_left);
}
CUSTOM_COMMAND_SIG(casey_delete_token_right)
{
DeleteAfterCommand(app, cmdid_seek_white_or_token_right);
DeleteAfterCommand(app, (unsigned long long)seek_white_or_token_right);
}
CUSTOM_COMMAND_SIG(casey_kill_to_end_of_line)
@ -362,21 +384,38 @@ CUSTOM_COMMAND_SIG(casey_paste_and_tab)
CUSTOM_COMMAND_SIG(casey_seek_beginning_of_line_and_tab)
{
exec_command(app, cmdid_seek_beginning_of_line);
exec_command(app, cmdid_auto_tab_line_at_cursor);
exec_command(app, auto_tab_line_at_cursor);
}
struct switch_to_result
{
bool Switched;
bool Loaded;
View_Summary view;
Buffer_Summary buffer;
};
inline void
SanitizeSlashes(String Value)
{
for(int At = 0;
At < Value.size;
++At)
{
if(Value.str[At] == '\\')
{
Value.str[At] = '/';
}
}
}
inline switch_to_result
SwitchToOrLoadFile(struct Application_Links *app, String FileName, bool CreateIfNotFound = false)
{
switch_to_result Result = {};
SanitizeSlashes(FileName);
View_Summary view = app->get_active_view(app);
Buffer_Summary buffer = app->get_buffer_by_name(app, FileName.str, FileName.size);
@ -399,6 +438,7 @@ SwitchToOrLoadFile(struct Application_Links *app, String FileName, bool CreateIf
Result.buffer = app->get_buffer_by_name(app, FileName.str, FileName.size);
Result.Loaded = true;
Result.Switched = true;
}
}
@ -412,6 +452,8 @@ CUSTOM_COMMAND_SIG(casey_load_todo)
SwitchToOrLoadFile(app, ToDoFileName, true);
}
inline String Empty() {String Result = {}; return(Result);}
CUSTOM_COMMAND_SIG(casey_load_handmade)
{
// NOTE(allen|a3.4.4): Here we get the list of files in this directory.
@ -854,8 +896,6 @@ CUSTOM_COMMAND_SIG(casey_quick_calc)
Range range = get_range(&view);
size_t Size = range.max - range.min;
if (Size == 0) return;
char *Stuff = (char *)malloc(Size + 1);
Stuff[Size] = 0;
@ -875,7 +915,106 @@ CUSTOM_COMMAND_SIG(casey_quick_calc)
free(Stuff);
}
CUSTOM_COMMAND_SIG(modal_toggle)
internal void
OpenProject(Application_Links *app, char *ProjectFileName)
{
FILE *ProjectFile = fopen(ProjectFileName, "r");
if(ProjectFile)
{
fgets(BuildDirectory, sizeof(BuildDirectory) - 1, ProjectFile);
size_t BuildDirSize = strlen(BuildDirectory);
if((BuildDirSize) && (BuildDirectory[BuildDirSize - 1] == '\n'))
{
--BuildDirSize;
}
if((BuildDirSize) && (BuildDirectory[BuildDirSize - 1] != '/'))
{
BuildDirectory[BuildDirSize++] = '/';
BuildDirectory[BuildDirSize] = 0;
}
char FileDirectoryName[4096];
while(fgets(FileDirectoryName, sizeof(FileDirectoryName) - 1, ProjectFile))
{
// NOTE(allen|a3.4.4): Here we get the list of files in this directory.
// Notice that we free_file_list at the end.
String dir = make_string(app->memory, 0, app->memory_size);
append(&dir, FileDirectoryName);
if(dir.size && dir.str[dir.size] == '\n')
{
--dir.size;
}
if(dir.size && dir.str[dir.size] != '/')
{
dir.str[dir.size] = '/';
++dir.size;
}
File_List list = app->get_file_list(app, dir.str, dir.size);
int dir_size = dir.size;
for (int i = 0; i < list.count; ++i)
{
File_Info *info = list.infos + i;
if (!info->folder)
{
String extension = file_extension(info->filename);
if (IsCode(extension))
{
// NOTE(allen): There's no way in the 4coder API to use relative
// paths at the moment, so everything should be full paths. Which is
// managable. Here simply set the dir string size back to where it
// was originally, so that new appends overwrite old ones.
dir.size = dir_size;
append(&dir, info->filename);
push_parameter(app, par_name, dir.str, dir.size);
push_parameter(app, par_do_in_background, 1);
exec_command(app, cmdid_interactive_open);
}
}
}
app->free_file_list(app, list);
}
fclose(ProjectFile);
}
}
CUSTOM_COMMAND_SIG(casey_execute_arbitrary_command)
{
Query_Bar bar;
char space[1024], more_space[1024];
bar.prompt = make_lit_string("Command: ");
bar.string = make_fixed_width_string(space);
if (!query_user_string(app, &bar)) return;
app->end_query_bar(app, &bar, 0);
if(match(bar.string, make_lit_string("project")))
{
// exec_command(app, open_all_code);
}
else if(match(bar.string, make_lit_string("open menu")))
{
exec_command(app, cmdid_open_menu);
}
else
{
bar.prompt = make_fixed_width_string(more_space);
append(&bar.prompt, make_lit_string("Unrecognized: "));
append(&bar.prompt, bar.string);
bar.string.size = 0;
app->start_query_bar(app, &bar, 0);
app->get_user_input(app, EventOnAnyKey | EventOnButton, 0);
}
}
internal void
UpdateModalIndicator(Application_Links *app)
{
Theme_Color normal_colors[] = {
{Stag_Cursor, 0x40FF40},
@ -897,8 +1036,6 @@ CUSTOM_COMMAND_SIG(modal_toggle)
{Stag_Bar, 0x934420}
};
GlobalEditMode = !GlobalEditMode;
if (GlobalEditMode){
app->set_theme_colors(app, edit_colors, ArrayCount(edit_colors));
}
@ -911,30 +1048,18 @@ CUSTOM_COMMAND_SIG(modal_toggle)
GetClientRect(GlobalModalIndicator, &Rect);
InvalidateRect(GlobalModalIndicator, &Rect, FALSE);
#endif
}
CUSTOM_COMMAND_SIG(casey_arbitrary_command){
Query_Bar bar;
char space[1024];
bar.prompt = make_lit_string("Command: ");
bar.string = make_fixed_width_string(space);
CUSTOM_COMMAND_SIG(begin_free_typing)
{
GlobalEditMode = false;
UpdateModalIndicator(app);
}
if (!query_user_string(app, &bar)) return;
app->end_query_bar(app, &bar, 0);
if (match(bar.string, make_lit_string("build search"))){
exec_command(app, casey_build_search);
}
else if (match(bar.string, make_lit_string("open hmh"))){
exec_command(app, casey_load_handmade);
}
else if (match(bar.string, make_lit_string("open menu"))){
exec_command(app, cmdid_open_menu);
}
else{
// TODO(allen): feedback message
}
CUSTOM_COMMAND_SIG(end_free_typing)
{
GlobalEditMode = true;
UpdateModalIndicator(app);
}
#define DEFINE_FULL_BIMODAL_KEY(binding_name,edit_code,normal_code) \
@ -993,12 +1118,12 @@ DEFINE_MODAL_KEY(modal_u, cmdid_undo);
DEFINE_MODAL_KEY(modal_v, casey_switch_buffer_other_window);
DEFINE_MODAL_KEY(modal_w, cmdid_cut);
DEFINE_MODAL_KEY(modal_x, casey_open_file_other_window);
DEFINE_MODAL_KEY(modal_y, cmdid_auto_tab_line_at_cursor);
DEFINE_MODAL_KEY(modal_y, auto_tab_line_at_cursor);
DEFINE_MODAL_KEY(modal_z, cmdid_interactive_open);
DEFINE_MODAL_KEY(modal_1, casey_build_search); // TODO(casey): Shouldn't need to bind a key for this?
DEFINE_MODAL_KEY(modal_2, casey_load_handmade); // TODO(casey): Shouldn't need to bind a key for this?
DEFINE_MODAL_KEY(modal_3, casey_arbitrary_command); // NOTE(allen): I set this for testing stuff modal_1 and modal_2 don't need to be set anymore
DEFINE_MODAL_KEY(modal_3, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_4, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_5, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_6, cmdid_write_character); // TODO(casey): Available
@ -1007,19 +1132,18 @@ DEFINE_MODAL_KEY(modal_8, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_9, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_0, cmdid_kill_buffer);
DEFINE_MODAL_KEY(modal_minus, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_equals, cmdid_write_character); // TODO(casey): Available
DEFINE_MODAL_KEY(modal_equals, casey_execute_arbitrary_command);
DEFINE_BIMODAL_KEY(modal_backspace, casey_delete_token_left, cmdid_backspace);
DEFINE_BIMODAL_KEY(modal_up, cmdid_move_up, cmdid_move_up);
DEFINE_BIMODAL_KEY(modal_down, cmdid_move_down, cmdid_move_down);
DEFINE_BIMODAL_KEY(modal_left, cmdid_seek_white_or_token_left, cmdid_move_left);
DEFINE_BIMODAL_KEY(modal_right, cmdid_seek_white_or_token_right, cmdid_move_right);
DEFINE_BIMODAL_KEY(modal_left, seek_white_or_token_left, cmdid_move_left);
DEFINE_BIMODAL_KEY(modal_right, seek_white_or_token_right, cmdid_move_right);
DEFINE_BIMODAL_KEY(modal_delete, casey_delete_token_right, cmdid_delete);
DEFINE_BIMODAL_KEY(modal_home, cmdid_seek_beginning_of_line, casey_seek_beginning_of_line_and_tab);
DEFINE_BIMODAL_KEY(modal_end, cmdid_seek_end_of_line, cmdid_seek_end_of_line);
DEFINE_BIMODAL_KEY(modal_page_up, cmdid_page_up, cmdid_seek_whitespace_up);
DEFINE_BIMODAL_KEY(modal_page_down, cmdid_page_down, cmdid_seek_whitespace_down);
//DEFINE_BIMODAL_KEY(modal_escape, cmdid_write_character, cmdid_write_character); // TODO(casey): Available
DEFINE_BIMODAL_KEY(modal_tab, cmdid_word_complete, cmdid_word_complete);
HOOK_SIG(casey_file_settings)
@ -1031,21 +1155,30 @@ HOOK_SIG(casey_file_settings)
Buffer_Summary buffer = app->get_parameter_buffer(app, 0);
int treat_as_code = 0;
int treat_as_project = 0;
if (buffer.file_name && buffer.size < (16 << 20))
{
String ext = file_extension(make_string(buffer.file_name, buffer.file_name_len));
treat_as_code = IsCode(ext);
treat_as_project = match(ext, make_lit_string("prj"));
}
push_parameter(app, par_lex_as_cpp_file, treat_as_code);
push_parameter(app, par_wrap_lines, !treat_as_code);
push_parameter(app, par_key_mapid, (treat_as_code)?((int)my_code_map):((int)mapid_file));
exec_command(app, cmdid_set_settings);
if(treat_as_project)
{
OpenProject(app, buffer.file_name);
exec_command(app, cmdid_kill_buffer);
}
return(0);
}
// NOTE(allen): This was a bit of fun so I'll leave it in,
// incase anyone would like to hack 4coder again.
// NOTE(allen): This was a bit of fun so I'll leave it in, for anyone would like to hack 4coder again.
#if UseHack4Coder
internal void
hack_place_modal_indicator(void)
@ -1116,7 +1249,7 @@ modal_indicator_window_callback(HWND Window,
internal void
hack_4coder(void)
{
HWND Window = FindWindow("4coder-win32-wndclass", "4coder-window");
HWND Window = FindWindow("4coder-win32-wndclass", "4coder-window: " VERSION);
ShowWindow(Window, SW_MAXIMIZE);
WNDCLASSA WindowClass = {};
@ -1172,14 +1305,10 @@ casey_get_bindings(Bind_Helper *context)
bind(context, 't', MDFR_NONE, casey_load_todo);
bind(context, '/', MDFR_NONE, cmdid_change_active_panel);
bind(context, 'b', MDFR_NONE, cmdid_interactive_switch_buffer);
bind(context, '3', MDFR_NONE, casey_arbitrary_command);
bind(context, key_page_up, MDFR_NONE, search);
bind(context, key_page_down, MDFR_NONE, reverse_search);
// NOTE(allen): These don't necessarily need to be here anymore.
// They are now bound to long form commands in casey_arbitrary_command.
bind(context, '2', MDFR_NONE, casey_load_handmade);
bind(context, '4', MDFR_NONE, cmdid_open_color_tweaker);
bind(context, key_page_up, MDFR_NONE, search);
bind(context, key_page_down, MDFR_NONE, reverse_search);
// NOTE(allen): I added this here myself, I believe this is what you want.
bind(context, 'm', MDFR_NONE, casey_save_and_make_without_asking);
@ -1190,9 +1319,11 @@ casey_get_bindings(Bind_Helper *context)
bind_vanilla_keys(context, cmdid_write_character);
bind(context, key_insert, MDFR_NONE, modal_toggle);
bind(context, '`', MDFR_NONE, modal_toggle);
bind(context, key_insert, MDFR_NONE, begin_free_typing);
bind(context, '`', MDFR_NONE, begin_free_typing);
bind(context, key_esc, MDFR_NONE, end_free_typing);
bind(context, '\n', MDFR_NONE, casey_newline_and_indent);
bind(context, '\n', MDFR_SHIFT, casey_newline_and_indent);
bind(context, 't', MDFR_CTRL, cmdid_timeline_scrub);

View File

@ -9,7 +9,6 @@
// TOP
#include "4ed_version.h"
#include "4ed_config.h"
#include "4ed_meta.h"
@ -434,6 +433,7 @@ Sys_Set_File_List_Sig(system_set_file_list){
info->filename.size = i;
info->filename.memory_size = info->filename.size + 1;
*name++ = 0;
replace_char(info->filename, '\\', '/');
++info;
}
more_files = FindNextFile(search, &find_data);
@ -1082,7 +1082,7 @@ Win32LoadSystemCode(){
win32vars.system->internal_debug_message = INTERNAL_system_debug_message;
#endif
win32vars.system->slash = '\\';
win32vars.system->slash = '/';
}
#include "system_shared.cpp"
@ -1685,6 +1685,7 @@ main(int argc, char **argv){
String current_directory = make_string(current_directory_mem, written, required);
terminate_with_null(&current_directory);
replace_char(current_directory, '\\', '/');
Command_Line_Parameters clparams;
clparams.argv = argv;
@ -1710,6 +1711,36 @@ main(int argc, char **argv){
printf("%.*s", output_size, memory_vars.target_memory);
}
if (output_size != 0) return 0;
#ifdef FRED_SUPER
char *custom_file_default = "4coder_custom.dll";
char *custom_file;
if (win32vars.settings.custom_dll) custom_file = win32vars.settings.custom_dll;
else custom_file = custom_file_default;
win32vars.custom = LoadLibraryA(custom_file);
if (!win32vars.custom && custom_file != custom_file_default){
if (!win32vars.settings.custom_dll_is_strict){
win32vars.custom = LoadLibraryA(custom_file_default);
}
}
if (win32vars.custom){
win32vars.custom_api.get_alpha_4coder_version = (_Get_Version_Function*)
GetProcAddress(win32vars.custom, "get_alpha_4coder_version");
//
if (win32vars.custom_api.get_alpha_4coder_version == 0 ||
win32vars.custom_api.get_alpha_4coder_version(MAJOR, MINOR, PATCH) == 0){
printf("Error: application and custom version numbers don't match");
return 22;
}
win32vars.custom_api.get_bindings = (Get_Binding_Data_Function*)
GetProcAddress(win32vars.custom, "get_bindings");
}
#endif
FreeConsole();
sysshared_filter_real_files(files, file_count);
@ -1727,25 +1758,6 @@ main(int argc, char **argv){
keycode_init();
#ifdef FRED_SUPER
char *custom_file_default = "4coder_custom.dll";
char *custom_file;
if (win32vars.settings.custom_dll) custom_file = win32vars.settings.custom_dll;
else custom_file = custom_file_default;
win32vars.custom = LoadLibraryA(custom_file);
if (!win32vars.custom && custom_file != custom_file_default){
if (!win32vars.settings.custom_dll_is_strict){
win32vars.custom = LoadLibraryA(custom_file_default);
}
}
if (win32vars.custom){
win32vars.custom_api.get_bindings = (Get_Binding_Data_Function*)
GetProcAddress(win32vars.custom, "get_bindings");
}
#endif
if (win32vars.custom_api.get_bindings == 0){
win32vars.custom_api.get_bindings = (Get_Binding_Data_Function*)get_bindings;
}