diff --git a/4coder_custom.cpp b/4coder_custom.cpp index b278e2d8..dca8651a 100644 --- a/4coder_custom.cpp +++ b/4coder_custom.cpp @@ -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; } diff --git a/4coder_custom.h b/4coder_custom.h index 4af548cf..ac2a8bb8 100644 --- a/4coder_custom.h +++ b/4coder_custom.h @@ -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; }; }; - - diff --git a/4coder_helper.h b/4coder_helper.h index 5817595f..840c3896 100644 --- a/4coder_helper.h +++ b/4coder_helper.h @@ -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; diff --git a/4coder_version.h b/4coder_version.h index 76fbe46a..1c0c88d2 100644 --- a/4coder_version.h +++ b/4coder_version.h @@ -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 diff --git a/4ed.cpp b/4ed.cpp index f7797d15..69dfcefe 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -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(¶m->param.param); - switch (p){ - case par_clear_blank_lines: - clear_blank_lines = dynamic_to_bool(¶m->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; diff --git a/4ed_app_settings.h b/4ed_app_settings.h index 0387853b..c2774766 100644 --- a/4ed_app_settings.h +++ b/4ed_app_settings.h @@ -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; diff --git a/4ed_app_target.cpp b/4ed_app_target.cpp index 08883d2a..26d1958b 100644 --- a/4ed_app_target.cpp +++ b/4ed_app_target.cpp @@ -8,8 +8,7 @@ */ // TOP - -#include "4ed_version.h" + #include "4ed_config.h" #define BUFFER_EXPERIMENT_SCALPEL 0 diff --git a/4ed_delay.cpp b/4ed_delay.cpp index d8fb83d7..c5b08717 100644 --- a/4ed_delay.cpp +++ b/4ed_delay.cpp @@ -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__) diff --git a/4ed_file.cpp b/4ed_file.cpp index 23907e95..bb474a71 100644 --- a/4ed_file.cpp +++ b/4ed_file.cpp @@ -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; diff --git a/4ed_file_view.cpp b/4ed_file_view.cpp index 221b136a..c872fd7c 100644 --- a/4ed_file_view.cpp +++ b/4ed_file_view.cpp @@ -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); diff --git a/4ed_gui.cpp b/4ed_gui.cpp index 704db153..59b4baf9 100644 --- a/4ed_gui.cpp +++ b/4ed_gui.cpp @@ -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; diff --git a/4ed_metagen.cpp b/4ed_metagen.cpp index de2134f1..7128de5d 100644 --- a/4ed_metagen.cpp +++ b/4ed_metagen.cpp @@ -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); } diff --git a/4ed_template.cpp b/4ed_template.cpp index 46dbcc63..22be5e61 100644 --- a/4ed_template.cpp +++ b/4ed_template.cpp @@ -31,6 +31,15 @@ dll_insert(T *pos, T *v){ v->next->prev = v; } +template +inline void +dll_insert_back(T *pos, T *v){ + v->prev = pos->prev; + v->next = pos; + pos->prev = v; + v->prev->next = v; +} + template inline void dll_remove(T *v){ diff --git a/4ed_version.h b/4ed_version.h deleted file mode 100644 index 4982d620..00000000 --- a/4ed_version.h +++ /dev/null @@ -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 diff --git a/build.bat b/build.bat index 22479f40..80976293 100644 --- a/build.bat +++ b/build.bat @@ -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 diff --git a/buildsuper.bat b/buildsuper.bat index 20a80a32..135be59b 100644 --- a/buildsuper.bat +++ b/buildsuper.bat @@ -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= diff --git a/4coder_handmade_hero.cpp b/power/4coder_handmade_hero.cpp similarity index 81% rename from 4coder_handmade_hero.cpp rename to power/4coder_handmade_hero.cpp index 3b3a21c9..9b9a151e 100644 --- a/4coder_handmade_hero.cpp +++ b/power/4coder_handmade_hero.cpp @@ -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 #include @@ -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); diff --git a/win32_4ed.cpp b/win32_4ed.cpp index f93ed357..56209284 100644 --- a/win32_4ed.cpp +++ b/win32_4ed.cpp @@ -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(¤t_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; }