├── .github └── workflows │ └── main.yml ├── .gitmodules ├── 4coder_byp.cpp ├── 4coder_byp_bindings.cpp ├── 4coder_byp_build.cpp ├── 4coder_byp_colors.cpp ├── 4coder_byp_commands.cpp ├── 4coder_byp_cpp_lexer_gen.cpp ├── 4coder_byp_draw.cpp ├── 4coder_byp_helper.h ├── 4coder_byp_hooks.cpp ├── 4coder_byp_reformat.cpp ├── 4coder_byp_snippets.inc ├── 4coder_byp_token.cpp ├── 4coder_byp_token.h ├── 4coder_vimrc.h ├── README.md ├── apply.bat ├── apply.sh ├── build.bat ├── build.sh ├── build_lexer.bat ├── custom ├── 4coder_app_links_allocator.cpp ├── 4coder_async_tasks.cpp ├── 4coder_async_tasks.h ├── 4coder_audio.cpp ├── 4coder_audio.h ├── 4coder_auto_indent.cpp ├── 4coder_auto_indent.h ├── 4coder_base_commands.cpp ├── 4coder_base_types.cpp ├── 4coder_base_types.h ├── 4coder_buffer_seek_constructors.cpp ├── 4coder_build_commands.cpp ├── 4coder_build_commands.h ├── 4coder_cli_command.cpp ├── 4coder_clipboard.cpp ├── 4coder_clipboard.h ├── 4coder_code_index.cpp ├── 4coder_code_index.h ├── 4coder_code_index_listers.cpp ├── 4coder_codepoint_map.cpp ├── 4coder_combined_write_commands.cpp ├── 4coder_combined_write_commands.h ├── 4coder_command_map.cpp ├── 4coder_command_map.h ├── 4coder_config.cpp ├── 4coder_config.h ├── 4coder_config_grammar.txt ├── 4coder_custom.cpp ├── 4coder_default_bindings.cpp ├── 4coder_default_colors.cpp ├── 4coder_default_colors.h ├── 4coder_default_framework.cpp ├── 4coder_default_framework.h ├── 4coder_default_framework_variables.cpp ├── 4coder_default_hooks.cpp ├── 4coder_default_include.cpp ├── 4coder_default_include.h ├── 4coder_default_map.cpp ├── 4coder_delta_rule.cpp ├── 4coder_delta_rule.h ├── 4coder_doc_commands.cpp ├── 4coder_doc_content_types.cpp ├── 4coder_doc_content_types.h ├── 4coder_docs.cpp ├── 4coder_draw.cpp ├── 4coder_draw.h ├── 4coder_dynamic_bindings.cpp ├── 4coder_eol.cpp ├── 4coder_events.cpp ├── 4coder_events.h ├── 4coder_examples.cpp ├── 4coder_fancy.cpp ├── 4coder_file.cpp ├── 4coder_file.h ├── 4coder_file_moving.h ├── 4coder_font_helper.cpp ├── 4coder_function_list.cpp ├── 4coder_function_list.h ├── 4coder_hash_functions.cpp ├── 4coder_helper.cpp ├── 4coder_helper.h ├── 4coder_insertion.cpp ├── 4coder_insertion.h ├── 4coder_jump_lister.cpp ├── 4coder_jump_lister.h ├── 4coder_jump_sticky.cpp ├── 4coder_jump_sticky.h ├── 4coder_jumping.cpp ├── 4coder_jumping.h ├── 4coder_keyboard_macro.cpp ├── 4coder_layout.cpp ├── 4coder_layout_rule.cpp ├── 4coder_layout_rule.h ├── 4coder_lister_base.cpp ├── 4coder_lister_base.h ├── 4coder_lists.cpp ├── 4coder_log.cpp ├── 4coder_log_parser.cpp ├── 4coder_log_parser.h ├── 4coder_mac_map.cpp ├── 4coder_malloc_allocator.cpp ├── 4coder_metadata_generator.cpp ├── 4coder_miblo_numbers.cpp ├── 4coder_prj_v1.cpp ├── 4coder_prj_v1.h ├── 4coder_profile.cpp ├── 4coder_profile.h ├── 4coder_profile_inspect.cpp ├── 4coder_profile_inspect.h ├── 4coder_profile_static_disable.cpp ├── 4coder_profile_static_enable.cpp ├── 4coder_project_commands.cpp ├── 4coder_project_commands.h ├── 4coder_scope_commands.cpp ├── 4coder_scope_commands.h ├── 4coder_search.cpp ├── 4coder_search.h ├── 4coder_search_list.cpp ├── 4coder_search_list.h ├── 4coder_string_match.cpp ├── 4coder_string_match.h ├── 4coder_stringf.cpp ├── 4coder_system_allocator.cpp ├── 4coder_system_helpers.cpp ├── 4coder_system_types.h ├── 4coder_table.cpp ├── 4coder_table.h ├── 4coder_token.cpp ├── 4coder_token.h ├── 4coder_tutorial.cpp ├── 4coder_tutorial.h ├── 4coder_types.h ├── 4coder_variables.cpp ├── 4coder_variables.h ├── 4coder_version.h ├── bin │ ├── build_metadata.bat │ ├── build_metadata.sh │ ├── build_one_time.bat │ ├── build_one_time.sh │ ├── buildsuper_x64-linux.sh │ ├── buildsuper_x64-mac.sh │ ├── buildsuper_x64-win.bat │ ├── buildsuper_x86-linux.sh │ ├── buildsuper_x86-win.bat │ ├── detect_os.sh │ ├── setup_cl_generic.bat │ ├── setup_cl_x64.bat │ └── setup_cl_x86.bat ├── generated │ ├── 4coder_event_codes.h │ ├── command_metadata.h │ ├── custom_api.cpp │ ├── custom_api.h │ ├── custom_api_constructor.cpp │ ├── custom_api_master_list.h │ ├── lexer_cpp.cpp │ ├── lexer_cpp.h │ ├── managed_id_metadata.cpp │ ├── system_api.cpp │ ├── system_api.h │ ├── system_api_constructor.cpp │ └── system_api_master_list.h ├── languages │ ├── 4coder_cpp_lexer_gen.cpp │ └── 4coder_cpp_lexer_test.cpp ├── lexer_generator │ ├── 4coder_lex_gen_hand_written.cpp │ ├── 4coder_lex_gen_hand_written.h │ ├── 4coder_lex_gen_main.cpp │ ├── pcg_basic.c │ └── pcg_basic.h └── stb_sprintf.h ├── project.4coder ├── run_test.bat └── theme-byp.4coder /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Download 2 | 3 | on: push 4 | 5 | jobs: 6 | build_4coder_byp: 7 | name: Build 4coder_byp 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | include: 12 | - suffix: x64-win 13 | os: windows-latest 14 | build_cmd: custom\bin\buildsuper_x64-win.bat 15 | - suffix: x64-linux 16 | os: ubuntu-latest 17 | build_cmd: ./custom/bin/buildsuper_x64-linux.sh 18 | - suffix: x64-mac 19 | os: macos-13 20 | build_cmd: ./custom/bin/buildsuper_x64-mac.sh 21 | # - suffix: arm64-mac 22 | # os: macos-latest 23 | # build_cmd: ./custom/bin/buildsuper_arm64-mac.sh 24 | runs-on: ${{ matrix.os }} 25 | steps: 26 | - uses: actions/checkout@v4 27 | with: 28 | submodules: true 29 | - uses: ilammy/msvc-dev-cmd@v1.4.1 # this is a no-op on Linux and macOS 30 | - name: Build 4coder_byp-${{ matrix.suffix }} 31 | run: ${{ matrix.build_cmd }} 4coder_byp.cpp release 32 | - name: Generate 4coder_byp Artifacts 33 | uses: actions/upload-artifact@v4.6.0 34 | with: 35 | name: 4coder_byp-${{ matrix.suffix }} 36 | compression-level: 6 37 | overwrite: true 38 | path: custom_4coder.* 39 | 40 | create_gh_release: 41 | if: startsWith(github.ref, 'refs/tags/') 42 | needs: build_4coder_byp 43 | name: Upload 44 | runs-on: ubuntu-latest 45 | steps: 46 | - name: Download 4coder_byp Artifacts 47 | uses: actions/download-artifact@v4 48 | with: 49 | path: artifacts_dir 50 | pattern: 4coder_byp-* 51 | - run: | 52 | cd artifacts_dir 53 | for f in ./* ; do zip -r "$f.zip" $f ; done; 54 | - name: Upload Artifacts to Release 55 | uses: softprops/action-gh-release@v2 56 | with: 57 | files: artifacts_dir/4coder_byp-*.zip 58 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "4coder_vim"] 2 | path = 4coder_vim 3 | url = https://github.com/B-Y-P/4coder_vim.git 4 | -------------------------------------------------------------------------------- /4coder_byp.cpp: -------------------------------------------------------------------------------- 1 | #ifndef _4CODER_BYP_CPP 2 | 3 | #if OS_WINDOWS 4 | #define SNIPPET_EXPANSION "4coder_byp_snippets.inc" 5 | #endif 6 | 7 | #include "4coder_default_include.h" 8 | #include "4coder_byp_token.h" 9 | 10 | function Lister_Result vim_run_lister(Application_Links *app, Lister *lister); 11 | #define run_lister vim_run_lister 12 | 13 | CUSTOM_ID(colors, defcolor_function); 14 | CUSTOM_ID(colors, defcolor_type); 15 | CUSTOM_ID(colors, defcolor_primitive); 16 | CUSTOM_ID(colors, defcolor_macro); 17 | CUSTOM_ID(colors, defcolor_enum); 18 | CUSTOM_ID(colors, defcolor_global); 19 | CUSTOM_ID(colors, defcolor_control); 20 | CUSTOM_ID(colors, defcolor_struct); 21 | CUSTOM_ID(colors, defcolor_non_text); 22 | 23 | #include "4coder_vimrc.h" 24 | #include "4coder_vim/4coder_vim_include.h" 25 | 26 | #include "4coder_default_include.cpp" 27 | 28 | #include "4coder_vim/4coder_vim_include.cpp" 29 | 30 | #include "4coder_byp_helper.h" 31 | 32 | #include "4coder_byp_token.cpp" 33 | 34 | #include "4coder_byp_build.cpp" 35 | #include "4coder_byp_colors.cpp" 36 | #include "4coder_byp_reformat.cpp" 37 | #include "4coder_byp_commands.cpp" 38 | 39 | #include "4coder_byp_draw.cpp" 40 | 41 | #include "4coder_byp_bindings.cpp" 42 | #include "4coder_byp_hooks.cpp" 43 | 44 | 45 | #if !defined(META_PASS) 46 | #include "generated/managed_id_metadata.cpp" 47 | #endif 48 | 49 | void 50 | custom_layer_init(Application_Links *app){ 51 | default_framework_init(app); 52 | set_all_default_hooks(app); 53 | 54 | vim_buffer_peek_list[ArrayCount(vim_default_peek_list) + 0] = BYP_peek_list[0]; 55 | vim_buffer_peek_list[ArrayCount(vim_default_peek_list) + 1] = BYP_peek_list[1]; 56 | vim_request_vtable[VIM_REQUEST_COUNT + BYP_REQUEST_Title] = byp_apply_title; 57 | vim_request_vtable[VIM_REQUEST_COUNT + BYP_REQUEST_Comment] = byp_apply_comment; 58 | vim_request_vtable[VIM_REQUEST_COUNT + BYP_REQUEST_UnComment] = byp_apply_uncomment; 59 | 60 | vim_text_object_vtable[VIM_TEXT_OBJECT_COUNT + BYP_OBJECT_param0] = {',', (Vim_Text_Object_Func *)byp_object_param}; 61 | vim_text_object_vtable[VIM_TEXT_OBJECT_COUNT + BYP_OBJECT_param1] = {';', (Vim_Text_Object_Func *)byp_object_param}; 62 | vim_text_object_vtable[VIM_TEXT_OBJECT_COUNT + BYP_OBJECT_camel0] = {'_', (Vim_Text_Object_Func *)byp_object_camel}; 63 | vim_text_object_vtable[VIM_TEXT_OBJECT_COUNT + BYP_OBJECT_camel1] = {'-', (Vim_Text_Object_Func *)byp_object_camel}; 64 | vim_init(app); 65 | 66 | set_custom_hook(app, HookID_SaveFile, byp_file_save); 67 | set_custom_hook(app, HookID_BufferRegion, byp_buffer_region); 68 | set_custom_hook(app, HookID_RenderCaller, byp_render_caller); 69 | set_custom_hook(app, HookID_WholeScreenRenderCaller, vim_draw_whole_screen); 70 | 71 | set_custom_hook(app, HookID_Tick, byp_tick); 72 | set_custom_hook(app, HookID_NewFile, byp_new_file); 73 | set_custom_hook(app, HookID_BeginBuffer, byp_begin_buffer); 74 | set_custom_hook(app, HookID_BufferEditRange, vim_buffer_edit_range); 75 | set_custom_hook(app, HookID_ViewChangeBuffer, vim_view_change_buffer); 76 | set_custom_hook(app, HookID_ViewEventHandler, vim_view_input_handler); 77 | 78 | Thread_Context *tctx = get_thread_context(app); 79 | mapping_init(tctx, &framework_mapping); 80 | String_ID global_map_id = vars_save_string_lit("keys_global"); 81 | String_ID file_map_id = vars_save_string_lit("keys_file"); 82 | String_ID code_map_id = vars_save_string_lit("keys_code"); 83 | byp_essential_mapping(&framework_mapping, global_map_id, file_map_id, code_map_id); 84 | byp_default_bindings(&framework_mapping, global_map_id, file_map_id, code_map_id); 85 | 86 | vim_default_bindings(app, KeyCode_BackwardSlash); 87 | byp_vim_bindings(app); 88 | } 89 | 90 | #define _4CODER_BYP_CPP 91 | #endif 92 | -------------------------------------------------------------------------------- /4coder_byp_colors.cpp: -------------------------------------------------------------------------------- 1 | 2 | global Color_Table target_color_table = {}; 3 | global Color_Table cached_color_table = {}; 4 | 5 | function b32 6 | byp_is_theme(String_Const_u8 name){ 7 | String_Const_u8 target_prefix = string_u8_litexpr("theme-"); 8 | String_Const_u8 target_suffix = string_u8_litexpr(".4coder"); 9 | String_Const_u8 actual_prefix = string_prefix(name, target_prefix.size); 10 | String_Const_u8 actual_suffix = string_postfix(name, target_suffix.size); 11 | return string_match(actual_prefix, target_prefix) && string_match(actual_suffix, target_suffix); 12 | } 13 | 14 | // TODO(BYP): Check for way to get highest color sub_id instead of hard-coding 14 15 | function Color_Table 16 | byp_init_color_table(Application_Links *app){ 17 | Color_Table result = make_color_table(app, &global_permanent_arena); 18 | foreach(i, result.count){ 19 | result.arrays[i].vals = push_array(&global_permanent_arena, u32, 14); 20 | result.arrays[i].count = 14; 21 | } 22 | return result; 23 | } 24 | 25 | function void 26 | byp_copy_color_table(Color_Table *dst, Color_Table table){ 27 | foreach(i, table.count){ 28 | Color_Array *nxt_array = &dst->arrays[i]; 29 | Color_Array *array = &table.arrays[i]; 30 | nxt_array->count = array->count; 31 | foreach(j, array->count){ 32 | nxt_array->vals[j] = array->vals[j]; 33 | } 34 | } 35 | } 36 | 37 | function void 38 | byp_tick_colors(Application_Links *app, Frame_Info frame_info){ 39 | // If another function sets active, correct this to not write into a loaded theme 40 | if(active_color_table.arrays != cached_color_table.arrays){ 41 | if(active_color_table.arrays && active_color_table.arrays->vals && active_color_table.arrays->count > 0){ 42 | byp_copy_color_table(&target_color_table, active_color_table); 43 | active_color_table = cached_color_table; 44 | } 45 | } 46 | b32 needs_animate = false; 47 | foreach(i, active_color_table.count){ 48 | Color_Array *nxt_array = &target_color_table.arrays[i]; 49 | Color_Array *cur_array = &active_color_table.arrays[i]; 50 | foreach(j, cur_array->count){ 51 | Vec4_f32 nxt_v = unpack_color(nxt_array->vals[j]); 52 | Vec4_f32 cur_v = unpack_color(cur_array->vals[j]); 53 | Vec4_f32 diff = nxt_v - cur_v; 54 | cur_v += diff*frame_info.animation_dt*10.f; 55 | cur_array->vals[j] = pack_color(cur_v); 56 | 57 | needs_animate |= (!near_zero(diff, 0.001f)); 58 | } 59 | } 60 | if(needs_animate){ animate_in_n_milliseconds(app, 0); } 61 | } 62 | 63 | function void 64 | byp_theme_navigate(Application_Links *app, View_ID view, Lister *lister, i32 index_delta){ 65 | lister__navigate__default(app, view, lister, index_delta); 66 | Color_Table *result = (Color_Table *)lister_get_user_data(lister, lister->raw_item_index); 67 | if(result){ byp_copy_color_table(&target_color_table, *result); } 68 | } 69 | 70 | 71 | CUSTOM_UI_COMMAND_SIG(byp_theme_lister) 72 | CUSTOM_DOC("Opens an interactive list of all registered themes.") 73 | { 74 | Color_Table_List *color_table_list = &global_theme_list; 75 | 76 | Scratch_Block scratch(app); 77 | Lister_Block lister(app, scratch); 78 | vim_lister_set_default_handlers(lister); 79 | vim_reset_bottom_text(); 80 | string_append(&vim_bot_text, string_u8_litexpr("Theme:")); 81 | 82 | lister_add_item(lister, string_u8_litexpr("4coder"), string_u8_litexpr(""), 83 | (void*)&default_color_table, 0); 84 | 85 | if(color_table_list->first){ 86 | byp_copy_color_table(&target_color_table, color_table_list->first->table); 87 | } 88 | for(Color_Table_Node *node = color_table_list->first; node; node = node->next){ 89 | lister_add_item(lister, node->name, string_u8_litexpr(""), (void*)&node->table, 0); 90 | } 91 | 92 | lister.lister.current->handlers.navigate = byp_theme_navigate; 93 | Lister_Result l_result = vim_run_lister(app, lister); 94 | 95 | Color_Table *result = 0; 96 | if(!l_result.canceled){ result = (Color_Table*)l_result.user_data; } 97 | 98 | if(result != 0){ byp_copy_color_table(&target_color_table, *result); } 99 | } 100 | -------------------------------------------------------------------------------- /4coder_byp_helper.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define string_starts_with(src, str) block_match(src, str, sizeof(str)-1) 4 | 5 | function b32 6 | string_ends_with(String_Const_u8 string, String_Const_u8 pred){ 7 | return block_match(string.str+string.size-pred.size, pred.str, pred.size); 8 | } 9 | 10 | function void 11 | draw_circle_outline(Application_Links *app, Vec2_f32 center, f32 radius, ARGB_Color color){ 12 | Rect_f32 rect = Rect_f32{center.x-radius, center.y-radius, center.x+radius, center.y+radius}; 13 | draw_rectangle(app, rect, radius, color); 14 | } 15 | 16 | function void 17 | draw_circle(Application_Links *app, Vec2_f32 center, f32 radius, ARGB_Color color){ 18 | Rect_f32 rect = Rect_f32{center.x-radius, center.y-radius, center.x+radius, center.y+radius}; 19 | draw_rectangle(app, rect, radius, color); 20 | } 21 | 22 | function void 23 | draw_circle_fcolor(Application_Links *app, Vec2_f32 center, f32 radius, FColor color){ 24 | Rect_f32 rect = Rect_f32{center.x-radius, center.y-radius, center.x+radius, center.y+radius}; 25 | draw_rectangle_fcolor(app, rect, radius, color); 26 | } 27 | 28 | function void 29 | draw_circle_outline_fcolor(Application_Links *app, Vec2_f32 center, f32 radius, f32 thickness, FColor color){ 30 | Rect_f32 rect = Rect_f32{center.x-radius, center.y-radius, center.x+radius, center.y+radius}; 31 | draw_rectangle_outline_fcolor(app, rect, radius, thickness, color); 32 | } 33 | 34 | function void 35 | draw_circle_gradient(Application_Links *app, Vec2_f32 center, f32 radius, ARGB_Color c1, ARGB_Color c2){ 36 | Rect_f32 rect = Rf32(center - radius*V2f32(1,1), center + radius*V2f32(1,1)); 37 | for(f32 y=rect.y0; y<=rect.y1; y+=1.f){ 38 | ARGB_Color color = argb_color_blend(c1, (y-rect.y0)/(rect.y1-rect.y0), c2); 39 | draw_set_clip(app, Rf32(rect.x0, y, rect.x1, y+1.f)); 40 | draw_rectangle(app, rect, radius, color); 41 | } 42 | } 43 | 44 | function Audio_Clip 45 | load_wav(Arena *arena, char *file_name){ 46 | Audio_Clip result = {}; 47 | FILE *file = def_search_normal_fopen(arena, file_name, "rb"); 48 | if(file != 0){ 49 | result = audio_clip_from_wav_FILE(&global_permanent_arena, file); 50 | fclose(file); 51 | } 52 | return result; 53 | } 54 | 55 | 56 | #ifndef PCG_SEED 57 | #define PCG_SEED time(NULL) 58 | #endif 59 | #ifndef PCG_INC 60 | #define PCG_INC 1 61 | #endif 62 | 63 | function u32 pcg_rand(){ 64 | static u64 state = PCG_SEED; 65 | state = state * 6364136223846793005ULL + (PCG_INC|1); 66 | #ifdef PCG_SPEED 67 | return (state ^ (state >> 22)) >> (22 + (state >> 61)); 68 | #else 69 | u64 xsh = (state ^ (state >> 18)) >> 27; 70 | i32 r_bits = i32(state >> 59); 71 | return u32((xsh >> r_bits) | (xsh << ((-r_bits) & 31))); 72 | #endif 73 | } 74 | 75 | function f32 rand01(){ return pcg_rand()/f32(max_u32); } 76 | 77 | #define rand_array(a) ArraySafe(a, i32(rand01()*ArrayCount(a))) 78 | -------------------------------------------------------------------------------- /4coder_byp_reformat.cpp: -------------------------------------------------------------------------------- 1 | 2 | function void 3 | byp_reformat_buffer(Application_Links *app, Buffer_ID buffer){ 4 | Token_Array arr = get_token_array_from_buffer(app, buffer); 5 | if(arr.tokens == 0){ return; } 6 | Face_ID face = get_face_id(app, buffer); 7 | Face_Metrics metrics = get_face_metrics(app, face); 8 | 9 | Scratch_Block scratch(app); 10 | String_Const_u8 spaces = string_u8_litexpr(" "); 11 | 12 | Batch_Edit *batch_first = 0; 13 | Batch_Edit *batch_last = 0; 14 | i64 line_count = buffer_get_line_count(app, buffer); 15 | for(i64 line = 1; line <= line_count; line += 1){ 16 | i64 line_start = get_line_side_pos(app, buffer, line, Side_Min); 17 | i64 line_end = get_line_side_pos(app, buffer, line, Side_Max); 18 | if(line_start == line_end){ continue; } // line is empty 19 | 20 | Token* token = get_token_from_pos(app, &arr, line_start); 21 | if(token == 0){ continue; } 22 | i64 token_end = token->pos + token->size; 23 | b32 is_whitespace = (token->kind == TokenBaseKind_Whitespace); 24 | b32 on_same_line = (token_end < line_end); 25 | b32 clear_blank = (is_whitespace && !on_same_line); 26 | 27 | i64 ws_end = (!is_whitespace ? line_start : // Need to insert spaces 28 | on_same_line ? token_end // Need to replace ws-token 29 | /* - else - */ : line_end); // Need to clear line 30 | i64 count = 0; 31 | 32 | if(!clear_blank){ 33 | f32 x = buffer_relative_box_of_pos(app, buffer, 1e9f, face, line, ws_end).x0; 34 | count = (i64)(x / metrics.space_advance); 35 | if(count < 0){ continue; } // impossible, but better safe than sorry 36 | 37 | if(count == ws_end-line_start){ 38 | // spaced correctly, might be able to skip 39 | b32 all_spaces = true; 40 | for(i64 i=0; iedit.text = string_prefix(spaces, count); 55 | batch->edit.range = Ii64(line_start, ws_end); 56 | } 57 | 58 | if(batch_first != 0){ 59 | buffer_batch_edit(app, buffer, batch_first); 60 | } 61 | } 62 | 63 | function void 64 | trim_leading_whitespace(Application_Links *app, Buffer_ID buffer){ 65 | 66 | Scratch_Block scratch(app); 67 | Batch_Edit *batch_first = 0; 68 | Batch_Edit *batch_last = 0; 69 | i64 line_count = buffer_get_line_count(app, buffer); 70 | for(i64 line_number = 1; line_number <= line_count; line_number += 1){ 71 | i64 line_start = get_line_side_pos(app, buffer, line_number, Side_Min); 72 | i64 line_end = get_line_side_pos(app, buffer, line_number, Side_Max); 73 | i64 ws_start = line_start; 74 | i64 ws_end = -1; 75 | 76 | { 77 | Temp_Memory_Block temp(scratch); 78 | String_Const_u8 line = push_buffer_range(app, scratch, buffer, Ii64(line_start, line_end)); 79 | for(u64 i=0; iedit.text = string_u8_empty; 90 | batch->edit.range = Ii64(ws_start, ws_end); 91 | } 92 | 93 | if (batch_first != 0){ 94 | buffer_batch_edit(app, buffer, batch_first); 95 | } 96 | } -------------------------------------------------------------------------------- /4coder_byp_snippets.inc: -------------------------------------------------------------------------------- 1 | 2 | {"ints", "#include \ntypedef uint8_t b8; \ntypedef uint16_t b16; \ntypedef uint32_t b32; \ntypedef uint64_t b64; \n\ntypedef uint8_t u8; \ntypedef uint16_t u16; \ntypedef uint32_t u32; \ntypedef uint64_t u64; \n\ntypedef int8_t i8; \ntypedef int16_t i16; \ntypedef int32_t i32; \ntypedef int64_t i64; \n\ntypedef float f32; \ntypedef double f64; \n\n#define function static \n#define local static \n#define global static \n#define global_const static const \n\n#define ArrayCount(a) (sizeof(a)/sizeof((a)[0])) \n#define InRange(a,v,b) ((a) <= (v) && (v) < (b)) \n#define foreach(i,N) for(i32 i=0; i 12 | 13 | ### Common issue for Windows: 14 | 15 | `'cl' is not recognized as an internal or external command, operable program or batch file.` 16 | 17 | #### If you already have Visual Studio installed and just want to build 18 | - Search for `x64 Native Tools Command Prompt for VS ` (make sure it's `x64` not `x86_64`)\ 19 | - Open and navigate to `4coder_byp\` and run `build release` 20 | 21 |
22 | 23 | #### If you're looking to streamline building projects on Windows in this manner 24 | - In `Program Files\Microsoft Visual Studio\\Community\VC\Auxiliary\Build`\ 25 | - Running `vcvarsall.bat amd64` sets up your environment allowing it to run `cl.exe` 26 | 27 |
28 | 29 | #### An example for how to cache this is given [here](https://gist.github.com/mmozeiko/37f511bac135337fc273f4bda0ebca1c) for VS 2019 30 | 31 |
32 | 33 | #### If you don't have Visual Studio installed and don't want to download 4 GB of... stuff 34 | - [Download MSVC without installing full Visual Studio](https://gist.github.com/mmozeiko/7f3162ec2988e81e56d5c4e22cde9977) creates a `setup.bat` to call before running `cl.exe` 35 | - [PortableBuildTools](https://github.com/Data-Oriented-House/PortableBuildTools) provides a simple GUI to do the same 36 | 37 |
38 | 39 | If all goes well, running `4ed.exe` will look something like this 40 | --- 41 | ![4coder_byp example](https://github.com/B-Y-P/4coder_byp/assets/69936251/e50bfefa-997d-401b-8b40-a77c22feb5b9) 42 | -------------------------------------------------------------------------------- /apply.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | copy .\custom_4coder.* ..\custom_4coder.* 3 | copy .\custom_4coder.* ..\4coder_byp\custom_4coder.* 4 | -------------------------------------------------------------------------------- /apply.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cp ./custom_4coder.* ../custom_4coder.* 4 | cp ./custom_4coder.* ../4coder_byp/custom_4coder.* 5 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set byp_dir=%cd% 3 | IF NOT exist ..\test_build ( 4 | mkdir ..\test_build 5 | xcopy /E ..\themes\ ..\test_build\themes\ 6 | xcopy /E ..\fonts\ ..\test_build\fonts\ 7 | copy ..\4ed.exe ..\test_build\4ed.exe 8 | copy ..\4ed_app.dll ..\test_build\4ed_app.dll 9 | copy ..\config.4coder ..\test_build\config.4coder 10 | ) 11 | pushd ..\test_build 12 | call %byp_dir%\custom\bin\buildsuper_x64-win.bat %byp_dir%\4coder_byp.cpp %1 13 | call %byp_dir%\apply.bat 14 | popd 15 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | byp_dir=$(pwd) 4 | 5 | if [ ! -d ../test_build ]; then 6 | mkdir ../test_build 7 | cp -r ../themes/ ../test_build/themes/ 8 | cp -r ../fonts/ ../test_build/fonts/ 9 | cp ../4ed ../test_build/4ed 10 | cp ../4ed_app.so ../test_build/4ed_app.so 11 | cp ../config.4coder ../test_build/config.4coder 12 | fi 13 | 14 | 15 | cd ../test_build 16 | ${byp_dir}/custom/bin/buildsuper_x64-linux.sh ${byp_dir}/4coder_byp.cpp $1 17 | ${byp_dir}/apply.sh 18 | -------------------------------------------------------------------------------- /build_lexer.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM For build_one_time.bat: 4 | REM params %1 and %2 are relative to 4coder_byp\ directory (same directory as build_lexer.bat) 5 | 6 | call .\custom\bin\build_one_time.bat 4coder_byp_cpp_lexer_gen.cpp ..\ && ..\one_time.exe 7 | 8 | del ..\4coder_byp_cpp_lexer_gen.obj 9 | del ..\one_time.* 10 | REM copy ..\custom\generated\lexer_cpp.* .\generated\lexer_cpp.* 11 | -------------------------------------------------------------------------------- /custom/4coder_app_links_allocator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder app links base allocator 3 | */ 4 | 5 | // TOP 6 | 7 | Scratch_Block::Scratch_Block(Application_Links *app){ 8 | Thread_Context *t = this->tctx = get_thread_context(app); 9 | this->arena = tctx_reserve(t); 10 | this->temp = begin_temp(this->arena); 11 | } 12 | 13 | Scratch_Block::Scratch_Block(Application_Links *app, Arena *a1){ 14 | Thread_Context *t = this->tctx = get_thread_context(app); 15 | this->arena = tctx_reserve(t, a1); 16 | this->temp = begin_temp(this->arena); 17 | } 18 | 19 | Scratch_Block::Scratch_Block(Application_Links *app, Arena *a1, Arena *a2){ 20 | Thread_Context *t = this->tctx = get_thread_context(app); 21 | this->arena = tctx_reserve(t, a1, a2); 22 | this->temp = begin_temp(this->arena); 23 | } 24 | 25 | Scratch_Block::Scratch_Block(Application_Links *app, Arena *a1, Arena *a2, Arena *a3){ 26 | Thread_Context *t = this->tctx = get_thread_context(app); 27 | this->arena = tctx_reserve(t, a1, a2, a3); 28 | this->temp = begin_temp(this->arena); 29 | } 30 | 31 | // BOTTOM 32 | -------------------------------------------------------------------------------- /custom/4coder_async_tasks.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder_async_tasks.cpp - Types for the custom layer asynchronous task system. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_ASYNC_TASKS_H) 8 | #define FCODER_ASYNC_TASKS_H 9 | 10 | typedef void Async_Task_Function_Type(struct Async_Context *actx, String_Const_u8 data); 11 | typedef u64 Async_Task; 12 | 13 | struct Async_Thread{ 14 | struct Async_System *async_system; 15 | System_Thread thread; 16 | struct Async_Node *node; 17 | Async_Task task; 18 | b32 cancel_signal; 19 | }; 20 | 21 | struct Async_Node{ 22 | union{ 23 | Async_Node *next; 24 | Node node; 25 | }; 26 | Async_Task task; 27 | Async_Thread *thread; 28 | Async_Task_Function_Type *func; 29 | String_Const_u8 data; 30 | }; 31 | 32 | struct Async_System{ 33 | void *cmd_context; 34 | 35 | Heap node_heap; 36 | Arena node_arena; 37 | System_Mutex mutex; 38 | System_Condition_Variable cv; 39 | System_Condition_Variable join_cv; 40 | Async_Task task_id_counter; 41 | Async_Node *free_nodes; 42 | Node task_sent; 43 | i32 task_count; 44 | 45 | Async_Thread thread; 46 | }; 47 | 48 | struct Async_Context{ 49 | Application_Links *app; 50 | Async_Thread *thread; 51 | }; 52 | 53 | #endif 54 | 55 | // BOTTOM 56 | -------------------------------------------------------------------------------- /custom/4coder_audio.h: -------------------------------------------------------------------------------- 1 | /* date = November 23rd 2020 1:18 pm */ 2 | 3 | #ifndef FCODER_AUDIO_H 4 | #define FCODER_AUDIO_H 5 | 6 | //////////////////////////////// 7 | // NOTE(allen): Default Mixer Types 8 | 9 | struct Audio_Control{ 10 | volatile f32 channel_volume[2]; 11 | volatile u32 generation; 12 | volatile u32 last_played_sample_index; 13 | volatile b32 loop; 14 | }; 15 | 16 | struct Audio_Clip{ 17 | i16 *samples; 18 | Audio_Control *control; 19 | f32 channel_volume[2]; 20 | 21 | u32 sample_count; 22 | u32 at_sample_index; 23 | }; 24 | 25 | struct Audio_System{ 26 | volatile u32 quit; 27 | volatile u32 ticket; 28 | volatile u32 serving; 29 | volatile u32 generation; 30 | 31 | Audio_Clip playing_clips[64]; 32 | 33 | // NOTE(casey): Requests to play sounds are written to a pending array to avoid long locking 34 | volatile u32 pending_clip_count; 35 | Audio_Clip pending_clips[64]; 36 | }; 37 | 38 | //////////////////////////////// 39 | // NOTE(allen): Default Mixer 40 | 41 | function void def_audio_init(void); 42 | function void def_audio_play_clip(Audio_Clip clip, Audio_Control *control); 43 | function b32 def_audio_is_playing(Audio_Control *control); 44 | function void def_audio_stop(Audio_Control *control); 45 | 46 | function void def_audio_mix_sources(void *ctx, f32 *mix_buffer, u32 sample_count); 47 | function void def_audio_mix_destination(i16 *dst, f32 *src, u32 sample_count); 48 | 49 | //////////////////////////////// 50 | // NOTE(allen): Loading Clip 51 | 52 | function Audio_Clip audio_clip_from_wav_data(String_Const_u8 data); 53 | function Audio_Clip audio_clip_from_wav_FILE(Arena *arena, FILE *file); 54 | function Audio_Clip audio_clip_from_wav_file_name(Arena *arena, char *file_name); 55 | 56 | #endif //4CODER_AUDIO_H 57 | -------------------------------------------------------------------------------- /custom/4coder_auto_indent.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_auto_indent.h - Auto-indentation types. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_AUTO_INDENT_H) 8 | #define FCODER_AUTO_INDENT_H 9 | 10 | typedef u32 Indent_Flag; 11 | enum{ 12 | Indent_ClearLine = 0x1, 13 | Indent_UseTab = 0x2, 14 | Indent_FullTokens = 0x4, 15 | }; 16 | 17 | struct Nest{ 18 | Nest *next; 19 | Token_Base_Kind kind; 20 | i64 indent; 21 | }; 22 | 23 | struct Nest_Alloc{ 24 | Nest *free_nest; 25 | }; 26 | 27 | struct Indent_Line_Cache{ 28 | i64 where_token_starts; 29 | i64 line_number_for_cached_indent; 30 | i64 start_pos; 31 | i64 one_past_last_pos; 32 | Indent_Info indent_info; 33 | }; 34 | 35 | #endif 36 | 37 | // BOTTOM 38 | -------------------------------------------------------------------------------- /custom/4coder_buffer_seek_constructors.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Buffer seek descriptor constructors. 3 | */ 4 | 5 | // TOP 6 | 7 | static Buffer_Seek 8 | seek_pos(i64 pos){ 9 | Buffer_Seek result; 10 | result.type = buffer_seek_pos; 11 | result.pos = pos; 12 | return(result); 13 | } 14 | 15 | static Buffer_Seek 16 | seek_line_col(i64 line, i64 col){ 17 | Buffer_Seek result; 18 | result.type = buffer_seek_line_col; 19 | result.line = line; 20 | result.col = col; 21 | return(result); 22 | } 23 | 24 | // BOTTOM 25 | -------------------------------------------------------------------------------- /custom/4coder_build_commands.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_build_commands.h - Commands for building types. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_BUILD_COMMANDS_H) 8 | #define FCODER_BUILD_COMMANDS_H 9 | 10 | function void comp_error(Application_Links *app, String_Const_u8 error_text); 11 | 12 | #endif 13 | 14 | // BOTTOM 15 | -------------------------------------------------------------------------------- /custom/4coder_cli_command.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_system_command.cpp - Commands for executing arbitrary system command line instructions. 3 | */ 4 | 5 | // TOP 6 | 7 | CUSTOM_COMMAND_SIG(execute_previous_cli) 8 | CUSTOM_DOC("If the command execute_any_cli has already been used, this will execute a CLI reusing the most recent buffer name and command.") 9 | { 10 | String_Const_u8 out_buffer = SCu8(out_buffer_space); 11 | String_Const_u8 cmd = SCu8(command_space); 12 | String_Const_u8 hot_directory = SCu8(hot_directory_space); 13 | 14 | if (out_buffer.size > 0 && cmd.size > 0 && hot_directory.size > 0){ 15 | View_ID view = get_active_view(app, Access_Always); 16 | Buffer_Identifier id = buffer_identifier(out_buffer); 17 | exec_system_command(app, view, id, hot_directory, cmd, CLI_OverlapWithConflict|CLI_CursorAtEnd|CLI_SendEndSignal); 18 | lock_jump_buffer(app, out_buffer); 19 | } 20 | } 21 | 22 | CUSTOM_COMMAND_SIG(execute_any_cli) 23 | CUSTOM_DOC("Queries for an output buffer name and system command, runs the system command as a CLI and prints the output to the specified buffer."){ 24 | Scratch_Block scratch(app); 25 | Query_Bar_Group group(app); 26 | 27 | Query_Bar bar_out = {}; 28 | bar_out.prompt = string_u8_litexpr("Output Buffer: "); 29 | bar_out.string = SCu8(out_buffer_space, (u64)0); 30 | bar_out.string_capacity = sizeof(out_buffer_space); 31 | if (!query_user_string(app, &bar_out)) return; 32 | bar_out.string.size = clamp_top(bar_out.string.size, sizeof(out_buffer_space) - 1); 33 | out_buffer_space[bar_out.string.size] = 0; 34 | 35 | Query_Bar bar_cmd = {}; 36 | bar_cmd.prompt = string_u8_litexpr("Command: "); 37 | bar_cmd.string = SCu8(command_space, (u64)0); 38 | bar_cmd.string_capacity = sizeof(command_space); 39 | if (!query_user_string(app, &bar_cmd)) return; 40 | bar_cmd.string.size = clamp_top(bar_cmd.string.size, sizeof(command_space) - 1); 41 | command_space[bar_cmd.string.size] = 0; 42 | 43 | String_Const_u8 hot = push_hot_directory(app, scratch); 44 | { 45 | u64 size = clamp_top(hot.size, sizeof(hot_directory_space)); 46 | block_copy(hot_directory_space, hot.str, size); 47 | hot_directory_space[hot.size] = 0; 48 | } 49 | 50 | execute_previous_cli(app); 51 | } 52 | 53 | // BOTTOM 54 | -------------------------------------------------------------------------------- /custom/4coder_clipboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_clipboard.cpp - Copy paste commands and clipboard related setup. 3 | */ 4 | 5 | // TOP 6 | 7 | #ifndef FCODER_CLIPBOARD_H 8 | #define FCODER_CLIPBOARD_H 9 | 10 | struct Clipboard{ 11 | Arena arena; 12 | Heap heap; 13 | String_Const_u8 *clips; 14 | u32 clip_index; 15 | u32 clip_capacity; 16 | }; 17 | 18 | #endif //4CODER_CLIPBOARD_H 19 | 20 | // BOTTOM 21 | -------------------------------------------------------------------------------- /custom/4coder_code_index.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_code_index.h - Generic code indexing system for layout, definition jumps, etc. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_CODE_INDEX_H) 8 | #define FCODER_CODE_INDEX_H 9 | 10 | struct Code_Index_Nest_List{ 11 | struct Code_Index_Nest *first; 12 | struct Code_Index_Nest *last; 13 | i32 count; 14 | }; 15 | 16 | struct Code_Index_Nest_Ptr_Array{ 17 | struct Code_Index_Nest **ptrs; 18 | i32 count; 19 | }; 20 | 21 | typedef i32 Code_Index_Nest_Kind; 22 | enum{ 23 | CodeIndexNest_Scope, 24 | CodeIndexNest_Paren, 25 | CodeIndexNest_Preprocessor, 26 | CodeIndexNest_Statement, 27 | }; 28 | 29 | struct Code_Index_Nest{ 30 | Code_Index_Nest *next; 31 | 32 | Code_Index_Nest_Kind kind; 33 | b32 is_closed; 34 | Range_i64 open; 35 | Range_i64 close; 36 | 37 | struct Code_Index_File *file; 38 | Code_Index_Nest *parent; 39 | 40 | Code_Index_Nest_List nest_list; 41 | Code_Index_Nest_Ptr_Array nest_array; 42 | }; 43 | 44 | typedef i64 Code_Index_Note_Kind; 45 | enum{ 46 | CodeIndexNote_Type, 47 | CodeIndexNote_Function, 48 | CodeIndexNote_Macro, 49 | CodeIndexNote_Enum, 50 | CodeIndexNote_Global, 51 | CodeIndexNote_4coderCommand, 52 | }; 53 | 54 | struct Code_Index_Note{ 55 | Code_Index_Note *next; 56 | Code_Index_Note_Kind note_kind; 57 | Range_i64 pos; 58 | String_Const_u8 text; 59 | struct Code_Index_File *file; 60 | Code_Index_Nest *parent; 61 | 62 | Code_Index_Note *prev_in_hash; 63 | Code_Index_Note *next_in_hash; 64 | }; 65 | 66 | struct Code_Index_Note_List{ 67 | Code_Index_Note *first; 68 | Code_Index_Note *last; 69 | i32 count; 70 | }; 71 | 72 | struct Code_Index_Note_Ptr_Array{ 73 | Code_Index_Note **ptrs; 74 | i32 count; 75 | }; 76 | 77 | struct Code_Index_File{ 78 | Code_Index_Nest_List nest_list; 79 | Code_Index_Nest_Ptr_Array nest_array; 80 | Code_Index_Note_List note_list; 81 | Code_Index_Note_Ptr_Array note_array; 82 | Buffer_ID buffer; 83 | }; 84 | 85 | struct Code_Index_File_Storage{ 86 | Code_Index_File_Storage *next; 87 | Code_Index_File_Storage *prev; 88 | Arena arena; 89 | Code_Index_File *file; 90 | }; 91 | 92 | struct Code_Index{ 93 | System_Mutex mutex; 94 | Arena node_arena; 95 | Table_u64_u64 buffer_to_index_file; 96 | Code_Index_File_Storage *free_storage; 97 | Code_Index_File_Storage *storage_first; 98 | Code_Index_File_Storage *storage_last; 99 | i32 storage_count; 100 | 101 | Code_Index_Note_List name_hash[4099]; 102 | }; 103 | 104 | //////////////////////////////// 105 | 106 | struct Generic_Parse_State{ 107 | Application_Links *app; 108 | Arena *arena; 109 | String_Const_u8 contents; 110 | Token_Iterator_Array it; 111 | u8 *prev_line_start; 112 | b32 finished; 113 | 114 | i32 scope_counter; 115 | i32 paren_counter; 116 | b32 in_preprocessor; 117 | b32 in_statement; 118 | 119 | b32 do_cpp_parse; 120 | }; 121 | 122 | #endif 123 | 124 | // BOTTOM 125 | -------------------------------------------------------------------------------- /custom/4coder_code_index_listers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_code_index_listers.cpp - Listers for exploring the contents of the code index. 3 | */ 4 | 5 | // TOP 6 | 7 | struct Tiny_Jump{ 8 | Buffer_ID buffer; 9 | i64 pos; 10 | }; 11 | 12 | CUSTOM_UI_COMMAND_SIG(jump_to_definition) 13 | CUSTOM_DOC("List all definitions in the code index and jump to one chosen by the user.") 14 | { 15 | char *query = "Definition:"; 16 | 17 | Scratch_Block scratch(app); 18 | Lister_Block lister(app, scratch); 19 | lister_set_query(lister, query); 20 | lister_set_default_handlers(lister); 21 | 22 | code_index_lock(); 23 | for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); 24 | buffer != 0; 25 | buffer = get_buffer_next(app, buffer, Access_Always)){ 26 | Code_Index_File *file = code_index_get_file(buffer); 27 | if (file != 0){ 28 | for (i32 i = 0; i < file->note_array.count; i += 1){ 29 | Code_Index_Note *note = file->note_array.ptrs[i]; 30 | Tiny_Jump *jump = push_array(scratch, Tiny_Jump, 1); 31 | jump->buffer = buffer; 32 | jump->pos = note->pos.first; 33 | 34 | Code_Index_Note_Kind kind = note->note_kind; 35 | String_Const_u8 sort = (kind == CodeIndexNote_Type ? string_u8_litexpr("type") : 36 | kind == CodeIndexNote_Function ? string_u8_litexpr("function") : 37 | kind == CodeIndexNote_Macro ? string_u8_litexpr("macro") : 38 | kind == CodeIndexNote_Enum ? string_u8_litexpr("enum") : 39 | kind == CodeIndexNote_Global ? string_u8_litexpr("global") : string_u8_empty); 40 | lister_add_item(lister, note->text, sort, jump, 0); 41 | } 42 | } 43 | } 44 | code_index_unlock(); 45 | 46 | Lister_Result l_result = run_lister(app, lister); 47 | Tiny_Jump result = {}; 48 | if (!l_result.canceled && l_result.user_data != 0){ 49 | block_copy_struct(&result, (Tiny_Jump*)l_result.user_data); 50 | } 51 | 52 | if (result.buffer != 0){ 53 | View_ID view = get_this_ctx_view(app, Access_Always); 54 | point_stack_push_view_cursor(app, view); 55 | jump_to_location(app, view, result.buffer, result.pos); 56 | } 57 | } 58 | 59 | CUSTOM_UI_COMMAND_SIG(jump_to_definition_at_cursor) 60 | CUSTOM_DOC("Jump to the first definition in the code index matching an identifier at the cursor") 61 | { 62 | View_ID view = get_active_view(app, Access_Visible); 63 | 64 | if (view != 0){ 65 | Scratch_Block scratch(app); 66 | String_Const_u8 query = push_token_or_word_under_active_cursor(app, scratch); 67 | 68 | code_index_lock(); 69 | for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); 70 | buffer != 0; 71 | buffer = get_buffer_next(app, buffer, Access_Always)){ 72 | Code_Index_File *file = code_index_get_file(buffer); 73 | if (file != 0){ 74 | for (i32 i = 0; i < file->note_array.count; i += 1){ 75 | Code_Index_Note *note = file->note_array.ptrs[i]; 76 | if (string_match(note->text, query)){ 77 | point_stack_push_view_cursor(app, view); 78 | jump_to_location(app, view, buffer, note->pos.first); 79 | goto done; 80 | } 81 | } 82 | } 83 | } 84 | done:; 85 | code_index_unlock(); 86 | } 87 | } 88 | 89 | // BOTTOM 90 | -------------------------------------------------------------------------------- /custom/4coder_codepoint_map.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_codepoint_map.cpp - Codepoint map to index 3 | */ 4 | 5 | // TOP 6 | 7 | function b32 8 | codepoint_index_map_read(Codepoint_Index_Map *map, u32 codepoint, u16 *index_out){ 9 | b32 success = true; 10 | if (codepoint == 0 && map->has_zero_index){ 11 | *index_out = map->zero_index; 12 | } 13 | else if (table_read(&map->table, codepoint, index_out)){ 14 | // NOTE(allen): do nothing 15 | } 16 | else{ 17 | success = false; 18 | } 19 | return(success); 20 | } 21 | 22 | function u16 23 | codepoint_index_map_count(Codepoint_Index_Map *map){ 24 | return(map->max_index + 1); 25 | } 26 | 27 | function f32 28 | font_get_glyph_advance(Face_Advance_Map *map, Face_Metrics *metrics, u32 codepoint, f32 tab_multiplier){ 29 | f32 result = 0.f; 30 | if (codepoint == '\t'){ 31 | result = metrics->space_advance*tab_multiplier; 32 | } 33 | else{ 34 | if (character_is_whitespace(codepoint)){ 35 | codepoint = ' '; 36 | } 37 | u16 index = 0; 38 | if (codepoint_index_map_read(&map->codepoint_to_index, codepoint, &index)){ 39 | if (index < map->index_count){ 40 | result = map->advance[index]; 41 | } 42 | } 43 | } 44 | return(result); 45 | } 46 | 47 | function f32 48 | font_get_max_glyph_advance_range(Face_Advance_Map *map, Face_Metrics *metrics, 49 | u32 codepoint_first, u32 codepoint_last, 50 | f32 tab_multiplier){ 51 | f32 result = font_get_glyph_advance(map, metrics, codepoint_first, tab_multiplier); 52 | for (u32 i = codepoint_first + 1; i <= codepoint_last; i += 1){ 53 | f32 a = font_get_glyph_advance(map, metrics, i, tab_multiplier); 54 | result = Max(a, result); 55 | } 56 | return(result); 57 | } 58 | 59 | function f32 60 | font_get_average_glyph_advance_range(Face_Advance_Map *map, Face_Metrics *metrics, 61 | u32 codepoint_first, u32 codepoint_last, 62 | f32 tab_multiplier){ 63 | f32 result = 0.f; 64 | for (u32 i = codepoint_first; i <= codepoint_last; i += 1){ 65 | result += font_get_glyph_advance(map, metrics, i, tab_multiplier); 66 | } 67 | result /= (f32)(codepoint_last - codepoint_first + 1); 68 | return(result); 69 | } 70 | 71 | // BOTTOM 72 | -------------------------------------------------------------------------------- /custom/4coder_combined_write_commands.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_combined_write_commands.cpp - Commands for writing text specialized for particular contexts. 3 | */ 4 | 5 | // TOP 6 | 7 | struct Snippet{ 8 | char *name; 9 | char *text; 10 | i32 cursor_offset; 11 | i32 mark_offset; 12 | }; 13 | 14 | struct Snippet_Array{ 15 | Snippet *snippets; 16 | i32 count; 17 | }; 18 | 19 | // BOTTOM 20 | -------------------------------------------------------------------------------- /custom/4coder_command_map.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_command_map.h - Command management types 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_CODEPOINT_MAP_H) 8 | #define FCODER_CODEPOINT_MAP_H 9 | 10 | typedef i64 Command_Map_ID; 11 | 12 | struct Command_Trigger{ 13 | Command_Trigger *next; 14 | Input_Event_Kind kind; 15 | u32 sub_code; 16 | Input_Modifier_Set mods; 17 | }; 18 | 19 | struct Command_Trigger_List{ 20 | Command_Trigger *first; 21 | Command_Trigger *last; 22 | }; 23 | 24 | struct Command_Binding{ 25 | union{ 26 | Custom_Command_Function *custom; 27 | char *name; 28 | }; 29 | 30 | Command_Binding(); 31 | Command_Binding(Custom_Command_Function *c); 32 | Command_Binding(char *n); 33 | 34 | operator Custom_Command_Function*(); 35 | operator char*(); 36 | }; 37 | 38 | struct Command_Modified_Binding{ 39 | Command_Modified_Binding *next; 40 | SNode order_node; 41 | Input_Modifier_Set mods; 42 | Command_Binding binding; 43 | }; 44 | 45 | struct Command_Binding_List{ 46 | Command_Binding_List *next; 47 | SNode *first; 48 | SNode *last; 49 | i32 count; 50 | }; 51 | 52 | struct Command_Map{ 53 | Command_Map *next; 54 | Command_Map *prev; 55 | Command_Map_ID id; 56 | Command_Map_ID parent; 57 | Command_Binding text_input_command; 58 | Arena node_arena; 59 | Table_u64_u64 event_code_to_binding_list; 60 | Table_u64_u64 cmd_to_binding_trigger; 61 | Command_Modified_Binding *binding_first; 62 | Command_Modified_Binding *binding_last; 63 | Command_Binding_List *list_first; 64 | Command_Binding_List *list_last; 65 | 66 | struct Binding_Unit *real_beginning; 67 | }; 68 | 69 | struct Mapping{ 70 | Arena node_arena; 71 | Heap heap; 72 | Base_Allocator heap_wrapper; 73 | Table_u64_u64 id_to_map; 74 | Command_Map_ID id_counter; 75 | Command_Map *first_map; 76 | Command_Map *last_map; 77 | Command_Map *free_maps; 78 | Command_Modified_Binding *free_bindings; 79 | Command_Binding_List *free_lists; 80 | }; 81 | 82 | typedef i32 Binding_Match_Rule; 83 | enum{ 84 | BindingMatchRule_Strict, 85 | BindingMatchRule_Loose, 86 | }; 87 | 88 | struct Map_Event_Breakdown{ 89 | Input_Modifier_Set *mod_set; 90 | u64 key; 91 | Key_Code skip_self_mod; 92 | }; 93 | 94 | #endif 95 | 96 | // BOTTOM 97 | -------------------------------------------------------------------------------- /custom/4coder_config_grammar.txt: -------------------------------------------------------------------------------- 1 | sconfig := [version] {assignment} 2 | 3 | version := "version" "(" INTEGER ")" ";" 4 | assignment := lvalue "=" rvalue ";" 5 | lvalue := IDENTIFIER [ "[" INTEGER "]" ] 6 | rvalue := lvalue | BOOLEAN | INTEGER | STRING | CHARACTER | "{" compound_body 7 | compound_body := compound_element {"," compound_element} [","] "}" 8 | compound_element := ["." (IDENTIFIER | INTEGER) "="] rvalue 9 | -------------------------------------------------------------------------------- /custom/4coder_custom.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_custom.cpp 3 | */ 4 | 5 | // TOP 6 | 7 | extern "C" b32 8 | get_version(i32 maj, i32 min, i32 patch){ 9 | return(maj == MAJOR && min == MINOR && patch == PATCH); 10 | } 11 | 12 | extern "C" Custom_Layer_Init_Type* 13 | init_apis(API_VTable_custom *custom_vtable, API_VTable_system *system_vtable){ 14 | custom_api_read_vtable(custom_vtable); 15 | system_api_read_vtable(system_vtable); 16 | return(custom_layer_init); 17 | } 18 | 19 | // BOTTOM 20 | -------------------------------------------------------------------------------- /custom/4coder_default_bindings.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_default_bidings.cpp - Supplies the default bindings used for default 4coder behavior. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_DEFAULT_BINDINGS_CPP) 8 | #define FCODER_DEFAULT_BINDINGS_CPP 9 | 10 | #include "4coder_default_include.cpp" 11 | 12 | // NOTE(allen): Users can declare their own managed IDs here. 13 | 14 | #if !defined(META_PASS) 15 | #include "generated/managed_id_metadata.cpp" 16 | #endif 17 | 18 | void 19 | custom_layer_init(Application_Links *app){ 20 | Thread_Context *tctx = get_thread_context(app); 21 | 22 | // NOTE(allen): setup for default framework 23 | default_framework_init(app); 24 | 25 | // NOTE(allen): default hooks and command maps 26 | set_all_default_hooks(app); 27 | mapping_init(tctx, &framework_mapping); 28 | String_ID global_map_id = vars_save_string_lit("keys_global"); 29 | String_ID file_map_id = vars_save_string_lit("keys_file"); 30 | String_ID code_map_id = vars_save_string_lit("keys_code"); 31 | #if OS_MAC 32 | setup_mac_mapping(&framework_mapping, global_map_id, file_map_id, code_map_id); 33 | #else 34 | setup_default_mapping(&framework_mapping, global_map_id, file_map_id, code_map_id); 35 | #endif 36 | setup_essential_mapping(&framework_mapping, global_map_id, file_map_id, code_map_id); 37 | } 38 | 39 | #endif //FCODER_DEFAULT_BINDINGS 40 | 41 | // BOTTOM 42 | -------------------------------------------------------------------------------- /custom/4coder_default_colors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Default color slots 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_DEFAULT_COLORS_H) 8 | #define FCODER_DEFAULT_COLORS_H 9 | 10 | CUSTOM_ID(colors, defcolor_bar); 11 | CUSTOM_ID(colors, defcolor_base); 12 | CUSTOM_ID(colors, defcolor_pop1); 13 | CUSTOM_ID(colors, defcolor_pop2); 14 | CUSTOM_ID(colors, defcolor_back); 15 | CUSTOM_ID(colors, defcolor_margin); 16 | CUSTOM_ID(colors, defcolor_margin_hover); 17 | CUSTOM_ID(colors, defcolor_margin_active); 18 | CUSTOM_ID(colors, defcolor_list_item); 19 | CUSTOM_ID(colors, defcolor_list_item_hover); 20 | CUSTOM_ID(colors, defcolor_list_item_active); 21 | CUSTOM_ID(colors, defcolor_cursor); 22 | CUSTOM_ID(colors, defcolor_at_cursor); 23 | CUSTOM_ID(colors, defcolor_highlight_cursor_line); 24 | CUSTOM_ID(colors, defcolor_highlight); 25 | CUSTOM_ID(colors, defcolor_at_highlight); 26 | CUSTOM_ID(colors, defcolor_mark); 27 | CUSTOM_ID(colors, defcolor_text_default); 28 | CUSTOM_ID(colors, defcolor_comment); 29 | CUSTOM_ID(colors, defcolor_comment_pop); 30 | CUSTOM_ID(colors, defcolor_keyword); 31 | CUSTOM_ID(colors, defcolor_str_constant); 32 | CUSTOM_ID(colors, defcolor_char_constant); 33 | CUSTOM_ID(colors, defcolor_int_constant); 34 | CUSTOM_ID(colors, defcolor_float_constant); 35 | CUSTOM_ID(colors, defcolor_bool_constant); 36 | CUSTOM_ID(colors, defcolor_preproc); 37 | CUSTOM_ID(colors, defcolor_include); 38 | CUSTOM_ID(colors, defcolor_special_character); 39 | CUSTOM_ID(colors, defcolor_ghost_character); 40 | CUSTOM_ID(colors, defcolor_highlight_junk); 41 | CUSTOM_ID(colors, defcolor_highlight_white); 42 | CUSTOM_ID(colors, defcolor_paste); 43 | CUSTOM_ID(colors, defcolor_undo); 44 | CUSTOM_ID(colors, defcolor_back_cycle); 45 | CUSTOM_ID(colors, defcolor_text_cycle); 46 | CUSTOM_ID(colors, defcolor_line_numbers_back); 47 | CUSTOM_ID(colors, defcolor_line_numbers_text); 48 | 49 | struct Color_Table_Node{ 50 | Color_Table_Node *next; 51 | String_Const_u8 name; 52 | Color_Table table; 53 | }; 54 | 55 | struct Color_Table_List{ 56 | Color_Table_Node *first; 57 | Color_Table_Node *last; 58 | i32 count; 59 | }; 60 | 61 | global Color_Table active_color_table = {}; 62 | global Color_Table default_color_table = {}; 63 | 64 | global Arena global_theme_arena = {}; 65 | global Color_Table_List global_theme_list = {}; 66 | 67 | #endif 68 | 69 | // BOTTOM 70 | -------------------------------------------------------------------------------- /custom/4coder_default_framework.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_default_framework.cpp - Sets up the basics of the framework that is used for default 4coder behaviour. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_DEFAULT_FRAMEWORK_H) 8 | #define FCODER_DEFAULT_FRAMEWORK_H 9 | 10 | //////////////////////////////// 11 | 12 | typedef i64 Rewrite_Type; 13 | enum{ 14 | Rewrite_None, 15 | Rewrite_NoChange, 16 | Rewrite_Paste, 17 | Rewrite_WordComplete 18 | }; 19 | 20 | //////////////////////////////// 21 | 22 | struct ID_Line_Column_Jump_Location{ 23 | Buffer_ID buffer_id; 24 | i32 line; 25 | i32 column; 26 | }; 27 | typedef ID_Line_Column_Jump_Location ID_Based_Jump_Location; 28 | 29 | struct ID_Pos_Jump_Location{ 30 | Buffer_ID buffer_id; 31 | i64 pos; 32 | }; 33 | 34 | struct Name_Line_Column_Location{ 35 | String_Const_u8 file; 36 | i32 line; 37 | i32 column; 38 | }; 39 | 40 | struct Parsed_Jump{ 41 | b32 success; 42 | Name_Line_Column_Location location; 43 | i32 colon_position; 44 | b32 is_sub_jump; 45 | b32 sub_jump_indented; 46 | b32 sub_jump_note; 47 | b32 is_ms_style; 48 | b32 has_rust_arrow; 49 | }; 50 | 51 | struct ID_Pos_Jump_Location_Array{ 52 | struct ID_Pos_Jump_Location *jumps; 53 | i32 count; 54 | }; 55 | 56 | //////////////////////////////// 57 | 58 | #define POINT_STACK_DEPTH 100 59 | 60 | struct Point_Stack_Slot{ 61 | Buffer_ID buffer; 62 | Managed_Object object; 63 | }; 64 | 65 | struct Point_Stack{ 66 | Point_Stack_Slot markers[POINT_STACK_DEPTH + 1]; 67 | i32 top; 68 | i32 bot; 69 | }; 70 | 71 | //////////////////////////////// 72 | 73 | typedef i32 Fallback_Dispatch_Result_Code; 74 | enum{ 75 | FallbackDispatch_Unhandled, 76 | FallbackDispatch_DidCall, 77 | FallbackDispatch_DelayedUICall, 78 | }; 79 | 80 | struct Fallback_Dispatch_Result{ 81 | Fallback_Dispatch_Result_Code code; 82 | Custom_Command_Function *func; 83 | }; 84 | 85 | //////////////////////////////// 86 | 87 | typedef void View_Render_Hook(Application_Links *app, View_ID view, Frame_Info frame_info, Rect_f32 inner); 88 | 89 | //////////////////////////////// 90 | 91 | function b32 92 | do_buffer_kill_user_check(Application_Links *app, Buffer_ID buffer, View_ID view); 93 | 94 | function b32 95 | do_4coder_close_user_check(Application_Links *app, View_ID view); 96 | 97 | //////////////////////////////// 98 | 99 | struct Buffer_Modified_Node{ 100 | Buffer_Modified_Node *next; 101 | Buffer_Modified_Node *prev; 102 | Buffer_ID buffer; 103 | }; 104 | 105 | struct Buffer_Modified_Set{ 106 | Arena arena; 107 | Buffer_Modified_Node *free; 108 | Buffer_Modified_Node *first; 109 | Buffer_Modified_Node *last; 110 | Table_u64_u64 id_to_node; 111 | }; 112 | 113 | //////////////////////////////// 114 | 115 | struct Fade_Range{ 116 | Fade_Range *next; 117 | Buffer_ID buffer_id; 118 | f32 t; 119 | f32 full_t; 120 | ARGB_Color color; 121 | b32 negate_fade_direction; 122 | Range_i64 range; 123 | 124 | void (*finish_call)(Application_Links *app, struct Fade_Range *range); 125 | void *opaque[4]; 126 | }; 127 | 128 | struct Fade_Range_List{ 129 | Fade_Range *first; 130 | Fade_Range *last; 131 | i32 count; 132 | }; 133 | 134 | #endif 135 | 136 | //////////////////////////////// 137 | 138 | struct Implicit_Map_Result{ 139 | String_ID map; 140 | Custom_Command_Function *command; 141 | }; 142 | 143 | typedef Implicit_Map_Result Implicit_Map_Function(Application_Links *app, 144 | String_ID buffer_language, 145 | String_ID global_mode, 146 | Input_Event *event); 147 | 148 | global Implicit_Map_Function *implicit_map_function = 0; 149 | 150 | // BOTTOM 151 | -------------------------------------------------------------------------------- /custom/4coder_default_framework_variables.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_default_framework_variables.cpp - Declares the global variables used by the framework for 3 | the default 4coder behavior. 4 | */ 5 | 6 | // TOP 7 | 8 | CUSTOM_ID(attachment, view_rewrite_loc); 9 | CUSTOM_ID(attachment, view_next_rewrite_loc); 10 | CUSTOM_ID(attachment, view_paste_index_loc); 11 | CUSTOM_ID(attachment, view_is_passive_loc); 12 | CUSTOM_ID(attachment, view_snap_mark_to_cursor); 13 | CUSTOM_ID(attachment, view_ui_data); 14 | CUSTOM_ID(attachment, view_highlight_range); 15 | CUSTOM_ID(attachment, view_highlight_buffer); 16 | CUSTOM_ID(attachment, view_render_hook); 17 | CUSTOM_ID(attachment, view_word_complete_menu); 18 | CUSTOM_ID(attachment, view_lister_loc); 19 | CUSTOM_ID(attachment, view_previous_buffer); 20 | 21 | CUSTOM_ID(attachment, buffer_map_id); 22 | CUSTOM_ID(attachment, buffer_eol_setting); 23 | CUSTOM_ID(attachment, buffer_lex_task); 24 | CUSTOM_ID(attachment, buffer_wrap_lines); 25 | 26 | CUSTOM_ID(attachment, sticky_jump_marker_handle); 27 | CUSTOM_ID(attachment, attachment_tokens); 28 | 29 | //////////////////////////////// 30 | 31 | #if 0 32 | CUSTOM_ID(command_map, mapid_global); 33 | CUSTOM_ID(command_map, mapid_file); 34 | CUSTOM_ID(command_map, mapid_code); 35 | #endif 36 | 37 | //////////////////////////////// 38 | 39 | global b32 allow_immediate_close_without_checking_for_changes = false; 40 | 41 | global char *default_extensions[] = { 42 | "cpp", 43 | "hpp", 44 | "c", 45 | "h", 46 | "cc", 47 | "cs", 48 | "java", 49 | "rs", 50 | "glsl", 51 | "m", 52 | }; 53 | 54 | #if !defined(AUTO_CENTER_AFTER_JUMPS) 55 | #define AUTO_CENTER_AFTER_JUMPS true 56 | #endif 57 | global b32 auto_center_after_jumps = AUTO_CENTER_AFTER_JUMPS; 58 | global u8 locked_buffer_space[256]; 59 | global String_Const_u8 locked_buffer = {}; 60 | 61 | 62 | global View_ID build_footer_panel_view_id = 0; 63 | 64 | global u8 out_buffer_space[1024]; 65 | global u8 command_space[1024]; 66 | global char hot_directory_space[1024]; 67 | 68 | global b32 suppressing_mouse = false; 69 | 70 | global b32 show_fps_hud = false; 71 | 72 | // TODO(allen): REMOVE THIS! 73 | global Heap global_heap; 74 | 75 | enum{ 76 | FCoderMode_Original = 0, 77 | FCoderMode_NotepadLike = 1, 78 | }; 79 | global i32 fcoder_mode = FCoderMode_Original; 80 | 81 | global ID_Pos_Jump_Location prev_location = {}; 82 | 83 | global Arena global_permanent_arena = {}; 84 | 85 | global Arena global_config_arena = {}; 86 | 87 | global char previous_isearch_query[256] = {}; 88 | 89 | global Mapping framework_mapping = {}; 90 | 91 | global Buffer_Modified_Set global_buffer_modified_set = {}; 92 | 93 | global b32 def_enable_virtual_whitespace = false; 94 | 95 | //////////////////////////////// 96 | 97 | global b32 global_keyboard_macro_is_recording = false; 98 | global Range_i64 global_keyboard_macro_range = {}; 99 | 100 | //////////////////////////////// 101 | 102 | global Fade_Range_List buffer_fade_ranges = {}; 103 | global Arena fade_range_arena = {}; 104 | global Fade_Range *free_fade_ranges = 0; 105 | 106 | //////////////////////////////// 107 | 108 | global Point_Stack point_stack = {}; 109 | 110 | //////////////////////////////// 111 | 112 | global Clipboard clipboard0 = {}; 113 | 114 | // BOTTOM 115 | -------------------------------------------------------------------------------- /custom/4coder_default_include.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_default_include.cpp - Default set of commands and setup used in 4coder. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_DEFAULT_INCLUDE_CPP) 8 | #define FCODER_DEFAULT_INCLUDE_CPP 9 | 10 | #if !defined(FCODER_DEFAULT_INCLUDE_H) 11 | #include "4coder_default_include.h" 12 | #endif 13 | 14 | #include "4coder_base_types.cpp" 15 | #include "4coder_stringf.cpp" 16 | #include "4coder_app_links_allocator.cpp" 17 | #include "4coder_system_allocator.cpp" 18 | 19 | #include "4coder_file.cpp" 20 | 21 | #define DYNAMIC_LINK_API 22 | #include "generated/custom_api.cpp" 23 | #define DYNAMIC_LINK_API 24 | #include "generated/system_api.cpp" 25 | #include "4coder_system_helpers.cpp" 26 | #include "4coder_layout.cpp" 27 | #include "4coder_profile.cpp" 28 | #include "4coder_profile_static_enable.cpp" 29 | #include "4coder_events.cpp" 30 | #include "4coder_custom.cpp" 31 | #include "4coder_log.cpp" 32 | #include "4coder_hash_functions.cpp" 33 | #include "4coder_table.cpp" 34 | #include "4coder_codepoint_map.cpp" 35 | #include "4coder_async_tasks.cpp" 36 | #include "4coder_string_match.cpp" 37 | #include "4coder_buffer_seek_constructors.cpp" 38 | #include "4coder_token.cpp" 39 | #include "4coder_command_map.cpp" 40 | 41 | #include "generated/lexer_cpp.cpp" 42 | 43 | #include "4coder_default_map.cpp" 44 | #include "4coder_mac_map.cpp" 45 | 46 | #include "4coder_default_framework_variables.cpp" 47 | #include "4coder_default_colors.cpp" 48 | #include "4coder_helper.cpp" 49 | #include "4coder_delta_rule.cpp" 50 | #include "4coder_layout_rule.cpp" 51 | #include "4coder_code_index.cpp" 52 | #include "4coder_fancy.cpp" 53 | #include "4coder_draw.cpp" 54 | #include "4coder_font_helper.cpp" 55 | #include "4coder_config.cpp" 56 | #include "4coder_dynamic_bindings.cpp" 57 | #include "4coder_default_framework.cpp" 58 | #include "4coder_clipboard.cpp" 59 | #include "4coder_lister_base.cpp" 60 | #include "4coder_base_commands.cpp" 61 | #include "4coder_insertion.cpp" 62 | #include "4coder_eol.cpp" 63 | #include "4coder_lists.cpp" 64 | #include "4coder_auto_indent.cpp" 65 | #include "4coder_search.cpp" 66 | #include "4coder_jumping.cpp" 67 | #include "4coder_jump_sticky.cpp" 68 | #include "4coder_jump_lister.cpp" 69 | #include "4coder_code_index_listers.cpp" 70 | #include "4coder_log_parser.cpp" 71 | #include "4coder_keyboard_macro.cpp" 72 | #include "4coder_cli_command.cpp" 73 | #include "4coder_build_commands.cpp" 74 | #include "4coder_project_commands.cpp" 75 | #include "4coder_prj_v1.cpp" 76 | #include "4coder_function_list.cpp" 77 | #include "4coder_scope_commands.cpp" 78 | #include "4coder_combined_write_commands.cpp" 79 | #include "4coder_miblo_numbers.cpp" 80 | #include "4coder_profile_inspect.cpp" 81 | #include "4coder_tutorial.cpp" 82 | #include "4coder_doc_content_types.cpp" 83 | #include "4coder_doc_commands.cpp" 84 | #include "4coder_docs.cpp" 85 | #include "4coder_variables.cpp" 86 | #include "4coder_audio.cpp" 87 | #include "4coder_search_list.cpp" 88 | 89 | #include "4coder_examples.cpp" 90 | 91 | #include "4coder_default_hooks.cpp" 92 | 93 | #endif 94 | 95 | // BOTTOM 96 | -------------------------------------------------------------------------------- /custom/4coder_default_include.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_default_include.h - Default set of commands and setup used in 4coder. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_DEFAULT_INCLUDE_H) 8 | #define FCODER_DEFAULT_INCLUDE_H 9 | 10 | #if !defined(FCODER_TRANSITION_TO) 11 | #define FCODER_TRANSITION_TO 0 12 | #endif 13 | 14 | #include 15 | #include 16 | 17 | #include "4coder_base_types.h" 18 | #include "4coder_version.h" 19 | #include "4coder_table.h" 20 | #include "4coder_events.h" 21 | #include "4coder_types.h" 22 | #include "4coder_doc_content_types.h" 23 | #include "4coder_default_colors.h" 24 | #define DYNAMIC_LINK_API 25 | #include "generated/custom_api.h" 26 | #include "4coder_system_types.h" 27 | #define DYNAMIC_LINK_API 28 | #include "generated/system_api.h" 29 | #if !defined(META_PASS) 30 | #include "generated/command_metadata.h" 31 | #endif 32 | 33 | #include "4coder_token.h" 34 | #include "generated/lexer_cpp.h" 35 | 36 | #include "4coder_variables.h" 37 | #include "4coder_audio.h" 38 | #include "4coder_profile.h" 39 | #include "4coder_async_tasks.h" 40 | #include "4coder_string_match.h" 41 | #include "4coder_helper.h" 42 | #include "4coder_delta_rule.h" 43 | #include "4coder_layout_rule.h" 44 | #include "4coder_code_index.h" 45 | #include "4coder_draw.h" 46 | #include "4coder_insertion.h" 47 | #include "4coder_command_map.h" 48 | #include "4coder_lister_base.h" 49 | #include "4coder_clipboard.h" 50 | #include "4coder_default_framework.h" 51 | #include "4coder_config.h" 52 | #include "4coder_auto_indent.h" 53 | #include "4coder_search.h" 54 | #include "4coder_build_commands.h" 55 | #include "4coder_jumping.h" 56 | #include "4coder_jump_sticky.h" 57 | #include "4coder_jump_lister.h" 58 | #include "4coder_project_commands.h" 59 | #include "4coder_prj_v1.h" 60 | #include "4coder_function_list.h" 61 | #include "4coder_scope_commands.h" 62 | #include "4coder_combined_write_commands.h" 63 | #include "4coder_log_parser.h" 64 | #include "4coder_profile_inspect.h" 65 | #include "4coder_tutorial.h" 66 | #include "4coder_search_list.h" 67 | 68 | #endif 69 | 70 | // BOTTOM 71 | -------------------------------------------------------------------------------- /custom/4coder_delta_rule.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_delta_rule.h - Types for built in delta rules and delta rule helpers. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_DELTA_RULE_H) 8 | #define FCODER_DELTA_RULE_H 9 | 10 | union Delta_Context_Header{ 11 | Buffer_Point point; 12 | Vec2_f32 p; 13 | }; 14 | struct Buffer_Point_Delta_Result{ 15 | Buffer_Point point; 16 | b32 still_animating; 17 | }; 18 | struct Vec2_f32_Delta_Result{ 19 | Vec2_f32 p; 20 | b32 still_animating; 21 | }; 22 | 23 | struct Smooth_Step{ 24 | f32 p; 25 | f32 v; 26 | }; 27 | 28 | #endif 29 | 30 | // BOTTOM 31 | -------------------------------------------------------------------------------- /custom/4coder_doc_commands.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 14.12.2019 5 | * 6 | * Documentation of the custom layer's primary api. 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | function Doc_Cluster* 13 | doc_commands(Arena *arena){ 14 | Doc_Cluster *cluster = new_doc_cluster(arena, "Commands", "commands"); 15 | for (i32 i = 0; i < ArrayCount(fcoder_metacmd_table); i += 1){ 16 | String_Const_u8 cmd_name = SCu8(fcoder_metacmd_table[i].name, 17 | fcoder_metacmd_table[i].name_len); 18 | String_Const_u8 title = push_u8_stringf(arena, "Command %S", cmd_name); 19 | Doc_Page *page = new_doc_page(arena, cluster, (char*)title.str, (char*)cmd_name.str); 20 | Doc_Block *block = new_doc_block(arena, page, "brief"); 21 | doc_text(arena, block, fcoder_metacmd_table[i].description); 22 | } 23 | return(cluster); 24 | } 25 | 26 | function Doc_Cluster* 27 | doc_default_bindings(Arena *arena, i32 map_count, Mapping *mapping_array, char **page_titles, char **page_names, 28 | i64 global_id, i64 file_id, i64 code_id){ 29 | Doc_Cluster *cluster = new_doc_cluster(arena, "Bindings", "bindings"); 30 | 31 | for (i32 i = 0; i < map_count; i += 1){ 32 | Mapping *mapping = &mapping_array[i]; 33 | Doc_Page *page = new_doc_page(arena, cluster, page_titles[i], page_names[i]); 34 | for (Command_Map *map = mapping->first_map; 35 | map != 0; 36 | map = map->next){ 37 | char *map_name = ""; 38 | if (map->id == global_id){ 39 | map_name = "Global"; 40 | } 41 | else if (map->id == file_id){ 42 | map_name = "File"; 43 | } 44 | else if (map->id == code_id){ 45 | map_name = "Code"; 46 | } 47 | 48 | Doc_Block *block = new_doc_block(arena, page, map_name); 49 | Doc_Paragraph *par = new_doc_par_table(arena, block); 50 | 51 | struct Bind_Node{ 52 | Bind_Node *next; 53 | Input_Event_Kind kind; 54 | u32 sub_code; 55 | Input_Modifier_Set mods; 56 | Command_Binding binding; 57 | u32 j; 58 | }; 59 | 60 | Bind_Node *first = 0; 61 | Bind_Node *last = 0; 62 | i32 node_count = 0; 63 | 64 | if (map->text_input_command.name != 0){ 65 | Bind_Node *node = push_array_zero(arena, Bind_Node, 1); 66 | sll_queue_push(first, last, node); 67 | node_count += 1; 68 | node->binding = map->text_input_command; 69 | node->j = max_u32; 70 | } 71 | 72 | u32 counts[] = { 73 | KeyCode_COUNT, 74 | KeyCode_COUNT, 75 | MouseCode_COUNT, 76 | MouseCode_COUNT, 77 | 1, 78 | 1, 79 | CoreCode_COUNT, 80 | }; 81 | 82 | u32 event_codes[] = { 83 | InputEventKind_KeyStroke, 84 | InputEventKind_KeyRelease, 85 | InputEventKind_MouseButton, 86 | InputEventKind_MouseButtonRelease, 87 | InputEventKind_MouseWheel, 88 | InputEventKind_MouseMove, 89 | InputEventKind_Core, 90 | }; 91 | 92 | char *mouse_wheel_name[] = {"MoveWheel"}; 93 | char *mouse_move_name[] = {"MoveMove"}; 94 | 95 | char **event_names[] = { 96 | key_code_name, 97 | key_code_name, 98 | mouse_code_name, 99 | mouse_code_name, 100 | mouse_wheel_name, 101 | mouse_move_name, 102 | core_code_name, 103 | }; 104 | 105 | b32 is_release[] = { 106 | false, 107 | true, 108 | false, 109 | true, 110 | false, 111 | false, 112 | false, 113 | }; 114 | 115 | for (u32 j = 0; j < ArrayCount(counts); j += 1){ 116 | for (u32 code = 0; code < counts[j]; code += 1){ 117 | u64 key = mapping__key(event_codes[j], code); 118 | Table_Lookup lookup = table_lookup(&map->event_code_to_binding_list, key); 119 | if (lookup.found_match){ 120 | u64 val = 0; 121 | table_read(&map->event_code_to_binding_list, lookup, &val); 122 | Command_Binding_List *list = (Command_Binding_List*)IntAsPtr(val); 123 | for (SNode *snode = list->first; 124 | snode != 0; 125 | snode = snode->next){ 126 | Command_Modified_Binding *mod_binding = CastFromMember(Command_Modified_Binding, order_node, snode); 127 | 128 | Bind_Node *node = push_array_zero(arena, Bind_Node, 1); 129 | sll_queue_push(first, last, node); 130 | node_count += 1; 131 | node->kind = event_codes[j]; 132 | node->sub_code = code; 133 | node->mods = mod_binding->mods; 134 | node->binding = mod_binding->binding; 135 | node->j = j; 136 | } 137 | } 138 | } 139 | } 140 | 141 | Vec2_i32 table_dims = V2i32(2, node_count); 142 | Doc_Content_List *vals = push_array_zero(arena, Doc_Content_List, table_dims.x*table_dims.y); 143 | Bind_Node *bnode = first; 144 | for (i32 y = 0; y < table_dims.y; y += 1, bnode = bnode->next){ 145 | Doc_Content_List *line = &vals[y*table_dims.x]; 146 | doc_text(arena, &line[0], "["); 147 | if (bnode->j != max_u32){ 148 | doc_text(arena, &line[0], event_names[bnode->j][bnode->sub_code]); 149 | if (is_release[bnode->j]){ 150 | doc_text(arena, &line[0], "Release"); 151 | } 152 | 153 | Input_Modifier_Set *mods = &bnode->mods; 154 | for (i32 k = 0; k < mods->count; k += 1){ 155 | doc_text(arena, &line[0], key_code_name[mods->mods[k]]); 156 | } 157 | } 158 | else{ 159 | doc_text(arena, &line[0], "TextInput"); 160 | } 161 | doc_text(arena, &line[0], "]"); 162 | 163 | Doc_Content *content = doc_text(arena, &line[1], bnode->binding.name); 164 | content->page_link = SCu8(bnode->binding.name); 165 | } 166 | 167 | par->table.dim = table_dims; 168 | par->table.vals = vals; 169 | } 170 | } 171 | 172 | return(cluster); 173 | } 174 | 175 | // BOTTOM 176 | -------------------------------------------------------------------------------- /custom/4coder_doc_content_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_doc_content_types.h - Documentation content types 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FRED_DOC_CONTENT_TYPES_H) 8 | #define FRED_DOC_CONTENT_TYPES_H 9 | 10 | typedef i32 Doc_Month; 11 | enum{ 12 | None, 13 | January, 14 | February, 15 | March, 16 | April, 17 | May, 18 | June, 19 | July, 20 | August, 21 | September, 22 | October, 23 | November, 24 | December, 25 | }; 26 | char *doc_month_names[] = { 27 | "None", 28 | "January", 29 | "February", 30 | "March", 31 | "April", 32 | "May", 33 | "June", 34 | "July", 35 | "August", 36 | "September", 37 | "October", 38 | "November", 39 | "December", 40 | }; 41 | char *doc_day_names[] = { 42 | "0", 43 | "1st", 44 | "2nd", 45 | "3rd", 46 | "4th", 47 | "5th", 48 | "6th", 49 | "7th", 50 | "8th", 51 | "9th", 52 | "10th", 53 | "11th", 54 | "12th", 55 | "13th", 56 | "14th", 57 | "15th", 58 | "16th", 59 | "17th", 60 | "18th", 61 | "19th", 62 | "20th", 63 | "21st", 64 | "22nd", 65 | "23rd", 66 | "24th", 67 | "25th", 68 | "26th", 69 | "27th", 70 | "28th", 71 | "29th", 72 | "30th", 73 | "31st", 74 | }; 75 | 76 | struct Doc_Date{ 77 | i32 day; 78 | Doc_Month month; 79 | i32 year; 80 | }; 81 | 82 | typedef i32 Doc_Content_Emphasis; 83 | enum{ 84 | DocContentEmphasis_Normal, 85 | DocContentEmphasis_SmallHeader, 86 | DocContentEmphasis_Heavy, 87 | DocContentEmphasis_Stylish, 88 | DocContentEmphasis_Code, 89 | }; 90 | struct Doc_Content{ 91 | Doc_Content *next; 92 | String_Const_u8 text; 93 | String_Const_u8 page_link; 94 | String_Const_u8 block_link; 95 | Doc_Content_Emphasis emphasis; 96 | }; 97 | struct Doc_Content_List{ 98 | Doc_Content *first; 99 | Doc_Content *last; 100 | u64 total_size; 101 | i32 node_count; 102 | }; 103 | 104 | typedef i32 Doc_Code_Language; 105 | enum{ 106 | DocCodeLanguage_None, 107 | DocCodeLanguage_Cpp, 108 | DocCodeLanguage_Bat, 109 | }; 110 | char *doc_language_name[] = { 111 | "none", 112 | "C++", 113 | "Batch", 114 | }; 115 | struct Doc_Code_Sample{ 116 | Doc_Code_Sample *next; 117 | String_Const_u8 contents; 118 | Doc_Code_Language language; 119 | }; 120 | struct Doc_Code_Sample_List{ 121 | Doc_Code_Sample *first; 122 | Doc_Code_Sample *last; 123 | i32 count; 124 | }; 125 | 126 | typedef i32 Doc_Paragraph_Kind; 127 | enum{ 128 | DocParagraphKind_Text, 129 | DocParagraphKind_Code, 130 | DocParagraphKind_Table, 131 | }; 132 | struct Doc_Paragraph{ 133 | Doc_Paragraph *next; 134 | Doc_Paragraph_Kind kind; 135 | union{ 136 | Doc_Content_List text; 137 | Doc_Code_Sample_List code; 138 | struct{ 139 | Vec2_i32 dim; 140 | Doc_Content_List *vals; 141 | } table; 142 | }; 143 | }; 144 | 145 | struct Doc_Block{ 146 | Doc_Block *next; 147 | 148 | struct Doc_Page *owner; 149 | 150 | String_Const_u8 name; 151 | 152 | Doc_Paragraph *first_par; 153 | Doc_Paragraph *last_par; 154 | i32 par_count; 155 | }; 156 | 157 | struct Doc_Block_Ptr{ 158 | Doc_Block_Ptr *next; 159 | Doc_Block *block; 160 | }; 161 | 162 | struct Doc_Block_List{ 163 | Doc_Block_Ptr *first; 164 | Doc_Block_Ptr *last; 165 | i32 count; 166 | }; 167 | 168 | struct Doc_Page{ 169 | Doc_Page *next; 170 | 171 | struct Doc_Cluster *owner; 172 | 173 | String_Const_u8 title; 174 | String_Const_u8 name; 175 | 176 | Doc_Block *first_block; 177 | Doc_Block *last_block; 178 | i32 block_count; 179 | 180 | Doc_Block_List quick_jumps; 181 | }; 182 | 183 | struct Doc_Log{ 184 | Doc_Log *next; 185 | String_Const_u8 content; 186 | }; 187 | 188 | struct Doc_Cluster{ 189 | String_Const_u8 title; 190 | String_Const_u8 name; 191 | Doc_Date gen_date; 192 | 193 | Doc_Page *first_page; 194 | Doc_Page *last_page; 195 | i32 page_count; 196 | 197 | Doc_Log *first_log; 198 | Doc_Log *last_log; 199 | }; 200 | 201 | #endif 202 | 203 | // BOTTOM 204 | -------------------------------------------------------------------------------- /custom/4coder_docs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_docs.cpp - Documentation explorers 3 | */ 4 | 5 | // TOP 6 | 7 | function Doc_Page* 8 | get_doc_page_from_user(Application_Links *app, Doc_Cluster *doc, String_Const_u8 query){ 9 | Scratch_Block scratch(app); 10 | Lister_Block lister(app, scratch); 11 | lister_set_query(lister, query); 12 | lister_set_default_handlers(lister); 13 | 14 | for (Doc_Page *page = doc->first_page; 15 | page != 0; 16 | page = page->next){ 17 | lister_add_item(lister, page->name, SCu8(""), page, 0); 18 | } 19 | Lister_Result l_result = run_lister(app, lister); 20 | Doc_Page *result = 0; 21 | if (!l_result.canceled){ 22 | result = (Doc_Page*)l_result.user_data; 23 | } 24 | return(result); 25 | } 26 | 27 | function Doc_Page* 28 | get_doc_page_from_user(Application_Links *app, Doc_Cluster *doc, char *query){ 29 | return(get_doc_page_from_user(app, doc, SCu8(query))); 30 | } 31 | 32 | function void 33 | render_doc_page__content(Application_Links *app, Buffer_Insertion *insert, Doc_Content_List *list){ 34 | for (Doc_Content *content = list->first; 35 | content != 0; 36 | content = content->next){ 37 | // TODO(allen): actually implement links 38 | 39 | if (content->emphasis == DocContentEmphasis_SmallHeader){ 40 | insertf(insert, "\n"); 41 | } 42 | if (content->emphasis == DocContentEmphasis_Heavy){ 43 | insertf(insert, "_"); 44 | } 45 | if (content->emphasis == DocContentEmphasis_Stylish){ 46 | insertf(insert, "*"); 47 | } 48 | 49 | insertf(insert, "%S", content->text); 50 | if (content->page_link.size > 0){ 51 | insertf(insert, " (link page %S)", content->page_link); 52 | } 53 | else if (content->block_link.size > 0){ 54 | insertf(insert, " (link block %S)", content->block_link); 55 | } 56 | 57 | if (content->emphasis == DocContentEmphasis_Heavy){ 58 | insertf(insert, "_"); 59 | } 60 | if (content->emphasis == DocContentEmphasis_Stylish){ 61 | insertf(insert, "*"); 62 | } 63 | if (content->emphasis == DocContentEmphasis_SmallHeader){ 64 | insertf(insert, "\n"); 65 | } 66 | else{ 67 | if (content->next != 0){ 68 | insertf(insert, " "); 69 | } 70 | } 71 | } 72 | } 73 | 74 | function void 75 | render_doc_page__code(Application_Links *app, Buffer_Insertion *insert, Doc_Code_Sample_List *code){ 76 | for (Doc_Code_Sample *sample = code->first; 77 | sample != 0; 78 | sample = sample->next){ 79 | insertf(insert, "language: "); 80 | switch (sample->language){ 81 | case DocCodeLanguage_Cpp: 82 | { 83 | insertf(insert, "C++\n"); 84 | }break; 85 | case DocCodeLanguage_Bat: 86 | { 87 | insertf(insert, "Batch\n\n"); 88 | }break; 89 | } 90 | insertf(insert, "\n%S\n", sample->contents); 91 | } 92 | } 93 | 94 | function void 95 | render_doc_page__table(Application_Links *app, Buffer_Insertion *insert, Vec2_i32 dim, Doc_Content_List *vals){ 96 | // TODO(allen): align better or something 97 | Doc_Content_List *val = vals; 98 | for (i32 y = 0; y < dim.y; y += 1){ 99 | for (i32 x = 0; x < dim.x; x += 1){ 100 | render_doc_page__content(app, insert, val); 101 | insertf(insert, "; "); 102 | val += 1; 103 | } 104 | insertf(insert, "\n"); 105 | } 106 | } 107 | 108 | function Buffer_ID 109 | render_doc_page(Application_Links *app, Doc_Page *page){ 110 | Scratch_Block scratch(app); 111 | 112 | String_Const_u8 doc_buffer_name = push_u8_stringf(scratch, "*doc: %S*", page->name); 113 | 114 | Buffer_Create_Flag flags = BufferCreate_NeverAttachToFile; 115 | Buffer_ID buffer = create_buffer(app, doc_buffer_name, flags); 116 | if (buffer != 0){ 117 | buffer_set_setting(app, buffer, BufferSetting_RecordsHistory, false); 118 | buffer_set_setting(app, buffer, BufferSetting_ReadOnly, true); 119 | buffer_set_setting(app, buffer, BufferSetting_Unimportant, true); 120 | 121 | i64 size = buffer_get_size(app, buffer); 122 | if (size != 0){ 123 | buffer_replace_range(app, buffer, Ii64(0, size), SCu8("")); 124 | } 125 | Buffer_Insertion insert = begin_buffer_insertion_at_buffered(app, buffer, 0, scratch, KB(16)); 126 | 127 | char dashes[] = 128 | "----------------------------------------------------------------" 129 | "----------------------------------------------------------------" 130 | "----------------------------------------------------------------" 131 | "----------------------------------------------------------------"; 132 | 133 | insertf(&insert, "%S\n%.*s\n", page->title, page->title.size, dashes); 134 | 135 | for (Doc_Block *block = page->first_block; 136 | block != 0; 137 | block = block->next){ 138 | insertf(&insert, "%S\n\n", block->name); 139 | 140 | for (Doc_Paragraph *par = block->first_par; 141 | par != 0; 142 | par = par->next){ 143 | switch (par->kind){ 144 | case DocParagraphKind_Text: 145 | { 146 | render_doc_page__content(app, &insert, &par->text); 147 | }break; 148 | 149 | case DocParagraphKind_Code: 150 | { 151 | render_doc_page__code(app, &insert, &par->code); 152 | }break; 153 | 154 | case DocParagraphKind_Table: 155 | { 156 | render_doc_page__table(app, &insert, par->table.dim, par->table.vals); 157 | }break; 158 | } 159 | 160 | insert_string(&insert, string_u8_litexpr("\n")); 161 | } 162 | 163 | insertf(&insert, "%.*s\n", page->title.size, dashes); 164 | } 165 | 166 | end_buffer_insertion(&insert); 167 | } 168 | 169 | return(buffer); 170 | } 171 | 172 | CUSTOM_UI_COMMAND_SIG(custom_api_documentation) 173 | CUSTOM_DOC("Prompts the user to select a Custom API item then loads a doc buffer for that item") 174 | { 175 | View_ID view = get_this_ctx_view(app, Access_ReadWrite); 176 | if (view != 0){ 177 | Scratch_Block scratch(app); 178 | Doc_Cluster *docs = get_custom_layer_boundary_docs(app, scratch); 179 | Doc_Page *page = get_doc_page_from_user(app, docs, "Doc Page:"); 180 | if (page != 0){ 181 | Buffer_ID buffer = render_doc_page(app, page); 182 | view_set_buffer(app, view, buffer, 0); 183 | } 184 | } 185 | } 186 | 187 | CUSTOM_UI_COMMAND_SIG(command_documentation) 188 | CUSTOM_DOC("Prompts the user to select a command then loads a doc buffer for that item") 189 | { 190 | View_ID view = get_this_ctx_view(app, Access_Always); 191 | if (view != 0){ 192 | Scratch_Block scratch(app); 193 | Doc_Cluster *docs = doc_commands(scratch); 194 | Doc_Page *page = get_doc_page_from_user(app, docs, "Doc Page:"); 195 | if (page != 0){ 196 | Buffer_ID buffer = render_doc_page(app, page); 197 | view_set_buffer(app, view, buffer, 0); 198 | } 199 | } 200 | } 201 | 202 | // BOTTOM 203 | -------------------------------------------------------------------------------- /custom/4coder_draw.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_draw.h - Layout and rendering types of standard UI pieces (including buffers) 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_DRAW_H) 8 | #define FCODER_DRAW_H 9 | 10 | struct Comment_Highlight_Pair{ 11 | String_Const_u8 needle; 12 | ARGB_Color color; 13 | }; 14 | 15 | typedef i32 Range_Highlight_Kind; 16 | enum{ 17 | RangeHighlightKind_LineHighlight, 18 | RangeHighlightKind_CharacterHighlight, 19 | }; 20 | 21 | #endif 22 | 23 | // BOTTOM 24 | -------------------------------------------------------------------------------- /custom/4coder_dynamic_bindings.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_dynamic_bindings.cpp - Dynamic Bindings 3 | */ 4 | 5 | // TOP 6 | 7 | function Key_Code 8 | dynamic_binding_key_code_from_string(String_Const_u8 key_string){ 9 | Key_Code result = 0; 10 | for (i32 i = 1; i < KeyCode_COUNT; i += 1){ 11 | String_Const_u8 str = SCu8(key_code_name[i]); 12 | if (string_match(str, key_string)){ 13 | result = i; 14 | break; 15 | } 16 | } 17 | return result; 18 | } 19 | 20 | function b32 21 | dynamic_binding_load_from_file(Application_Links *app, Mapping *mapping, String_Const_u8 filename){ 22 | b32 result = false; 23 | 24 | Scratch_Block scratch(app); 25 | 26 | String_Const_u8 filename_copied = push_string_copy(scratch, filename); 27 | String8List search_list = {}; 28 | def_search_normal_load_list(scratch, &search_list); 29 | String_Const_u8 full_path = def_search_get_full_path(scratch, &search_list, filename_copied); 30 | 31 | { 32 | String8 message = push_stringf(scratch, "loading bindings: %S\n", full_path); 33 | print_message(app, message); 34 | } 35 | 36 | FILE *file = 0; 37 | if (full_path.size > 0){ 38 | file = fopen((char*)full_path.str, "rb"); 39 | } 40 | 41 | if (file != 0){ 42 | String_Const_u8 data = dump_file_handle(scratch, file); 43 | Config *parsed = def_config_from_text(app, scratch, filename, data); 44 | fclose(file); 45 | 46 | if (parsed != 0){ 47 | result = true; 48 | 49 | Thread_Context* tctx = get_thread_context(app); 50 | mapping_release(tctx, mapping); 51 | mapping_init(tctx, mapping); 52 | MappingScope(); 53 | SelectMapping(mapping); 54 | 55 | for (Config_Assignment *assignment = parsed->first; 56 | assignment != 0; 57 | assignment = assignment->next){ 58 | Config_LValue *l = assignment->l; 59 | if (l != 0 && l->index == 0){ 60 | Config_Get_Result rvalue = config_evaluate_rvalue(parsed, assignment, assignment->r); 61 | if (rvalue.type == ConfigRValueType_Compound){ 62 | String_Const_u8 map_name = l->identifier; 63 | String_ID map_name_id = vars_save_string(map_name); 64 | 65 | SelectMap(map_name_id); 66 | 67 | 68 | Config_Compound *compound = rvalue.compound; 69 | 70 | Config_Get_Result_List list = typed_compound_array_reference_list(scratch, parsed, compound); 71 | for (Config_Get_Result_Node *node = list.first; node != 0; node = node->next){ 72 | Config_Compound *src = node->result.compound; 73 | String_Const_u8 cmd_string = {0}; 74 | String_Const_u8 key_string = {0}; 75 | String_Const_u8 mod_string[9] = {0}; 76 | 77 | if (!config_compound_string_member(parsed, src, "cmd", 0, &cmd_string)){ 78 | def_config_push_error(scratch, parsed, node->result.pos, "Command string is required in binding"); 79 | goto finish_map; 80 | } 81 | 82 | if (!config_compound_string_member(parsed, src, "key", 1, &key_string)){ 83 | def_config_push_error(scratch, parsed, node->result.pos, "Key string is required in binding"); 84 | goto finish_map; 85 | } 86 | 87 | for (i32 mod_idx = 0; mod_idx < ArrayCount(mod_string); mod_idx += 1){ 88 | String_Const_u8 str = push_stringf(scratch, "mod_%i", mod_idx); 89 | if (config_compound_string_member(parsed, src, str, 2 + mod_idx, &mod_string[mod_idx])){ 90 | // NOTE(rjf): No-Op 91 | } 92 | } 93 | 94 | // NOTE(rjf): Map read in successfully. 95 | { 96 | // NOTE(rjf): Find command. 97 | Command_Metadata *command = get_command_metadata_from_name(cmd_string); 98 | 99 | // NOTE(rjf): Find keycode. 100 | Key_Code keycode = dynamic_binding_key_code_from_string(key_string); 101 | 102 | // NOTE(rjf): Find mods. 103 | i32 mod_count = 0; 104 | Key_Code mods[ArrayCount(mod_string)] = {0}; 105 | for (i32 i = 0; i < ArrayCount(mod_string); i += 1){ 106 | if (mod_string[i].str){ 107 | mods[mod_count] = dynamic_binding_key_code_from_string(mod_string[i]); 108 | mod_count += 1; 109 | } 110 | } 111 | 112 | if (keycode != 0 && command != 0){ 113 | Input_Modifier_Set mods_set = { mods, mod_count, }; 114 | map_set_binding(mapping, map, command->proc, InputEventKind_KeyStroke, keycode, &mods_set); 115 | } 116 | else{ 117 | def_config_push_error(scratch, parsed, node->result.pos, 118 | (keycode != 0) ? (char*)"Invalid command" : 119 | (command != 0) ? (char*)"Invalid key": 120 | (char*)"Invalid command and key"); 121 | } 122 | } 123 | 124 | finish_map:; 125 | } 126 | 127 | 128 | if (parsed->errors.first != 0){ 129 | String_Const_u8 error_text = config_stringize_errors(app, scratch, parsed); 130 | print_message(app, error_text); 131 | } 132 | } 133 | } 134 | } 135 | } 136 | } 137 | 138 | return(result); 139 | } 140 | 141 | // BOTTOM 142 | -------------------------------------------------------------------------------- /custom/4coder_eol.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder_eol.cpp - Commands and routines for controling the end-of-line encoding 3 | * of files. 4 | */ 5 | 6 | // TOP 7 | 8 | function void 9 | rewrite_lines_to_crlf(Application_Links *app, Buffer_ID buffer){ 10 | ProfileScope(app, "rewrite lines to crlf"); 11 | Scratch_Block scratch(app); 12 | i64 size = buffer_get_size(app, buffer); 13 | 14 | Batch_Edit *first = 0; 15 | Batch_Edit *last = 0; 16 | 17 | ProfileBlockNamed(app, "build batch edit", profile_batch); 18 | i64 pos = -1; 19 | Character_Predicate pred_cr = character_predicate_from_character('\r'); 20 | Character_Predicate pred_lf = character_predicate_from_character('\n'); 21 | Character_Predicate pred = character_predicate_or(&pred_cr, &pred_lf); 22 | for (;;){ 23 | String_Match match = buffer_seek_character_class(app, buffer, &pred, 24 | Scan_Forward, pos); 25 | if (match.range.min == match.range.max){ 26 | break; 27 | } 28 | pos = match.range.min; 29 | 30 | u8 c1 = buffer_get_char(app, buffer, pos); 31 | u8 c2 = buffer_get_char(app, buffer, pos + 1); 32 | if (c1 == '\r'){ 33 | if (pos + 1 == size || c2 != '\n'){ 34 | Batch_Edit *edit = push_array(scratch, Batch_Edit, 1); 35 | sll_queue_push(first, last, edit); 36 | edit->edit.text = string_u8_litexpr(""); 37 | edit->edit.range = match.range; 38 | } 39 | else{ 40 | pos += 1; 41 | } 42 | } 43 | else{ 44 | Batch_Edit *edit = push_array(scratch, Batch_Edit, 1); 45 | sll_queue_push(first, last, edit); 46 | edit->edit.text = string_u8_litexpr("\r"); 47 | edit->edit.range = Ii64(pos); 48 | } 49 | } 50 | ProfileCloseNow(profile_batch); 51 | 52 | buffer_batch_edit(app, buffer, first); 53 | } 54 | 55 | function void 56 | rewrite_lines_to_lf(Application_Links *app, Buffer_ID buffer){ 57 | ProfileScope(app, "rewrite lines to lf"); 58 | Scratch_Block scratch(app); 59 | 60 | Batch_Edit *first = 0; 61 | Batch_Edit *last = 0; 62 | 63 | ProfileBlockNamed(app, "build batch edit", profile_batch); 64 | i64 pos = -1; 65 | Character_Predicate pred = character_predicate_from_character('\r'); 66 | for (;;){ 67 | String_Match match = buffer_seek_character_class(app, buffer, &pred, 68 | Scan_Forward, pos); 69 | if (match.range.min == match.range.max){ 70 | break; 71 | } 72 | pos = match.range.min; 73 | 74 | Batch_Edit *edit = push_array(scratch, Batch_Edit, 1); 75 | sll_queue_push(first, last, edit); 76 | edit->edit.text = string_u8_litexpr(""); 77 | edit->edit.range = match.range; 78 | } 79 | ProfileCloseNow(profile_batch); 80 | 81 | buffer_batch_edit(app, buffer, first); 82 | } 83 | 84 | //////////////////////////////// 85 | 86 | CUSTOM_COMMAND_SIG(set_eol_mode_to_crlf) 87 | CUSTOM_DOC("Puts the buffer in crlf line ending mode.") 88 | { 89 | View_ID view = get_active_view(app, Access_ReadWriteVisible); 90 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); 91 | Managed_Scope scope = buffer_get_managed_scope(app, buffer); 92 | Line_Ending_Kind *eol_setting = scope_attachment(app, scope, buffer_eol_setting, 93 | Line_Ending_Kind); 94 | if (eol_setting != 0){ 95 | *eol_setting = LineEndingKind_CRLF; 96 | } 97 | } 98 | 99 | CUSTOM_COMMAND_SIG(set_eol_mode_to_lf) 100 | CUSTOM_DOC("Puts the buffer in lf line ending mode.") 101 | { 102 | View_ID view = get_active_view(app, Access_ReadWriteVisible); 103 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); 104 | Managed_Scope scope = buffer_get_managed_scope(app, buffer); 105 | Line_Ending_Kind *eol_setting = scope_attachment(app, scope, buffer_eol_setting, 106 | Line_Ending_Kind); 107 | if (eol_setting != 0){ 108 | *eol_setting = LineEndingKind_LF; 109 | } 110 | } 111 | 112 | CUSTOM_COMMAND_SIG(set_eol_mode_to_binary) 113 | CUSTOM_DOC("Puts the buffer in bin line ending mode.") 114 | { 115 | View_ID view = get_active_view(app, Access_ReadWriteVisible); 116 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); 117 | Managed_Scope scope = buffer_get_managed_scope(app, buffer); 118 | Line_Ending_Kind *eol_setting = scope_attachment(app, scope, buffer_eol_setting, 119 | Line_Ending_Kind); 120 | if (eol_setting != 0){ 121 | *eol_setting = LineEndingKind_Binary; 122 | } 123 | } 124 | 125 | CUSTOM_COMMAND_SIG(set_eol_mode_from_contents) 126 | CUSTOM_DOC("Sets the buffer's line ending mode to match the contents of the buffer.") 127 | { 128 | View_ID view = get_active_view(app, Access_ReadWriteVisible); 129 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); 130 | Line_Ending_Kind setting = guess_line_ending_kind_from_buffer(app, buffer); 131 | Managed_Scope scope = buffer_get_managed_scope(app, buffer); 132 | Line_Ending_Kind *eol_setting = scope_attachment(app, scope, buffer_eol_setting, 133 | Line_Ending_Kind); 134 | if (eol_setting != 0){ 135 | *eol_setting = setting; 136 | } 137 | } 138 | 139 | // BOTTOM 140 | -------------------------------------------------------------------------------- /custom/4coder_events.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder event types 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_EVENTS_H) 8 | #define FCODER_EVENTS_H 9 | 10 | typedef void Custom_Command_Function(struct Application_Links *app); 11 | 12 | typedef u32 Key_Code; 13 | typedef u32 Mouse_Code; 14 | typedef u32 Core_Code; 15 | #include "generated/4coder_event_codes.h" 16 | 17 | typedef u32 Input_Event_Kind; 18 | enum{ 19 | InputEventKind_None, 20 | InputEventKind_TextInsert, 21 | InputEventKind_KeyStroke, 22 | InputEventKind_KeyRelease, 23 | InputEventKind_MouseButton, 24 | InputEventKind_MouseButtonRelease, 25 | InputEventKind_MouseWheel, 26 | InputEventKind_MouseMove, 27 | InputEventKind_Core, 28 | InputEventKind_CustomFunction, 29 | 30 | InputEventKind_COUNT, 31 | }; 32 | 33 | typedef u32 Key_Flags; 34 | enum{ 35 | KeyFlag_IsDeadKey = (1 << 0), 36 | }; 37 | 38 | global_const i32 Input_MaxModifierCount = 8; 39 | 40 | struct Input_Modifier_Set{ 41 | Key_Code *mods; 42 | i32 count; 43 | }; 44 | 45 | struct Input_Modifier_Set_Fixed{ 46 | Key_Code mods[Input_MaxModifierCount]; 47 | i32 count; 48 | }; 49 | 50 | struct Input_Event{ 51 | Input_Event_Kind kind; 52 | b32 virtual_event; 53 | union{ 54 | struct{ 55 | String_Const_u8 string; 56 | 57 | // used internally 58 | Input_Event *next_text; 59 | b32 blocked; 60 | } text; 61 | struct{ 62 | Key_Code code; 63 | Key_Flags flags; 64 | Input_Modifier_Set modifiers; 65 | 66 | // used internally 67 | Input_Event *first_dependent_text; 68 | } key; 69 | struct{ 70 | Mouse_Code code; 71 | Vec2_i32 p; 72 | Input_Modifier_Set modifiers; 73 | } mouse; 74 | struct{ 75 | f32 value; 76 | Vec2_i32 p; 77 | Input_Modifier_Set modifiers; 78 | } mouse_wheel; 79 | struct{ 80 | Vec2_i32 p; 81 | Input_Modifier_Set modifiers; 82 | } mouse_move; 83 | struct{ 84 | Core_Code code; 85 | union{ 86 | String_Const_u8 string; 87 | i32 id; 88 | struct{ 89 | String_Const_u8_Array flag_strings; 90 | String_Const_u8_Array file_names; 91 | }; 92 | }; 93 | } core; 94 | Custom_Command_Function *custom_func; 95 | }; 96 | }; 97 | 98 | struct Input_Event_Node{ 99 | Input_Event_Node *next; 100 | Input_Event event; 101 | }; 102 | 103 | struct Input_List{ 104 | Input_Event_Node *first; 105 | Input_Event_Node *last; 106 | i32 count; 107 | }; 108 | 109 | typedef u32 Event_Property; 110 | enum{ 111 | EventProperty_AnyKey = 0x0001, 112 | EventProperty_Escape = 0x0002, 113 | EventProperty_AnyKeyRelease = 0x0004, 114 | EventProperty_MouseButton = 0x0008, 115 | EventProperty_MouseRelease = 0x0010, 116 | EventProperty_MouseWheel = 0x0020, 117 | EventProperty_MouseMove = 0x0040, 118 | EventProperty_Animate = 0x0080, 119 | EventProperty_ViewActivation = 0x0100, 120 | EventProperty_TextInsert = 0x0200, 121 | EventProperty_AnyFile = 0x0400, 122 | EventProperty_Startup = 0x0800, 123 | EventProperty_Exit = 0x1000, 124 | EventProperty_Clipboard = 0x2000, 125 | EventProperty_CustomFunction = 0x4000, 126 | }; 127 | enum{ 128 | EventPropertyGroup_AnyKeyboardEvent = 129 | EventProperty_AnyKey| 130 | EventProperty_Escape| 131 | EventProperty_AnyKeyRelease| 132 | EventProperty_TextInsert, 133 | EventPropertyGroup_AnyMouseEvent = 134 | EventProperty_MouseButton| 135 | EventProperty_MouseRelease| 136 | EventProperty_MouseWheel| 137 | EventProperty_MouseMove, 138 | EventPropertyGroup_AnyUserInput = 139 | EventPropertyGroup_AnyKeyboardEvent| 140 | EventPropertyGroup_AnyMouseEvent, 141 | EventPropertyGroup_AnyCore = 142 | EventProperty_Animate| 143 | EventProperty_ViewActivation| 144 | EventProperty_AnyFile| 145 | EventProperty_Startup| 146 | EventProperty_Exit| 147 | EventProperty_Clipboard| 148 | EventProperty_Animate, 149 | EventPropertyGroup_Any = 150 | EventPropertyGroup_AnyUserInput| 151 | EventPropertyGroup_AnyCore| 152 | EventProperty_CustomFunction, 153 | }; 154 | 155 | #endif 156 | 157 | // BOTTOM 158 | -------------------------------------------------------------------------------- /custom/4coder_file.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 03.10.2019 5 | * 6 | * Basic helpers for C std file handling. 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | #include 13 | 14 | function String_Const_u8 15 | data_from_file(Arena *arena, FILE *file){ 16 | String_Const_u8 result = {}; 17 | if (file != 0){ 18 | fseek(file, 0, SEEK_END); 19 | result.size = ftell(file); 20 | fseek(file, 0, SEEK_SET); 21 | result.str = push_array(arena, u8, result.size + 1); 22 | fread(result.str, 1, (size_t)result.size, file); 23 | result.str[result.size] = 0; 24 | } 25 | return(result); 26 | } 27 | 28 | // BOTTOM 29 | -------------------------------------------------------------------------------- /custom/4coder_font_helper.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_font_helper.cpp - Procedures for font setting operations 3 | */ 4 | 5 | // TOP 6 | 7 | internal Face_Description 8 | get_buffer_face_description(Application_Links *app, Buffer_ID buffer){ 9 | Face_ID current_id = get_face_id(app, buffer); 10 | Face_Description description = {}; 11 | if (current_id != 0){ 12 | description = get_face_description(app, current_id); 13 | } 14 | return(description); 15 | } 16 | 17 | internal Face_Description 18 | get_global_face_description(Application_Links *app){ 19 | return(get_buffer_face_description(app, 0)); 20 | } 21 | 22 | internal b32 23 | font_load_location_match(Font_Load_Location *a, Font_Load_Location *b){ 24 | return(string_match(a->file_name, b->file_name)); 25 | } 26 | 27 | internal b32 28 | face_load_parameters_match(Face_Load_Parameters *a, Face_Load_Parameters *b){ 29 | return(block_compare(a, b, sizeof(*a)) == 0); 30 | } 31 | 32 | internal b32 33 | face_description_match(Face_Description *a, Face_Description *b){ 34 | b32 result = false; 35 | if (font_load_location_match(&a->font, &b->font) && 36 | face_load_parameters_match(&a->parameters, &b->parameters)){ 37 | result = true; 38 | } 39 | return(result); 40 | } 41 | 42 | internal Face_ID 43 | face_id_from_font_load_target(Application_Links *app, Font_Load_Location *font){ 44 | Face_ID largest_id = get_largest_face_id(app); 45 | Face_ID result = 0; 46 | for (Face_ID id = 1; id <= largest_id; ++id){ 47 | Face_Description compare = get_face_description(app, id); 48 | if (font_load_location_match(&compare.font, font)){ 49 | result = id; 50 | break; 51 | } 52 | } 53 | return(result); 54 | } 55 | 56 | internal Face_ID 57 | face_id_from_face_load_parameters(Application_Links *app, Face_Load_Parameters *parameters){ 58 | Face_ID largest_id = get_largest_face_id(app); 59 | Face_ID result = 0; 60 | for (Face_ID id = 1; id <= largest_id; ++id){ 61 | Face_Description compare = get_face_description(app, id); 62 | if (face_load_parameters_match(&compare.parameters, parameters)){ 63 | result = id; 64 | break; 65 | } 66 | } 67 | return(result); 68 | } 69 | 70 | internal Face_ID 71 | face_id_from_description(Application_Links *app, Face_Description *description){ 72 | Face_ID largest_id = get_largest_face_id(app); 73 | Face_ID result = 0; 74 | for (Face_ID id = 1; id <= largest_id; ++id){ 75 | Face_Description compare = get_face_description(app, id); 76 | if (face_description_match(&compare, description)){ 77 | result = id; 78 | break; 79 | } 80 | } 81 | return(result); 82 | } 83 | 84 | internal b32 85 | modify_global_face_by_description(Application_Links *app, Face_Description description){ 86 | Face_ID face_id = get_face_id(app, 0); 87 | return(try_modify_face(app, face_id, &description)); 88 | } 89 | 90 | internal void 91 | set_buffer_face_by_description(Application_Links *app, Buffer_ID buffer, Face_Description *description){ 92 | Face_ID id = face_id_from_description(app, description); 93 | if (id == 0){ 94 | id = try_create_new_face(app, description); 95 | } 96 | if (id != 0){ 97 | buffer_set_face(app, buffer, id); 98 | } 99 | } 100 | 101 | internal void 102 | set_buffer_face_by_font_load_location(Application_Links *app, Buffer_ID buffer, Font_Load_Location *font){ 103 | Face_Description description = get_buffer_face_description(app, buffer); 104 | description.font = *font; 105 | set_buffer_face_by_description(app, buffer, &description); 106 | } 107 | 108 | internal void 109 | set_buffer_face_by_face_load_parameters(Application_Links *app, Buffer_ID buffer, Face_Load_Parameters *parameters){ 110 | Face_Description description = get_buffer_face_description(app, buffer); 111 | description.parameters = *parameters; 112 | set_buffer_face_by_description(app, buffer, &description); 113 | } 114 | 115 | // BOTTOM 116 | -------------------------------------------------------------------------------- /custom/4coder_function_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_function_list.cpp - Command for listing all functions in a C/C++ file in a jump list. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_FUNCTION_LIST_H) 8 | #define FCODER_FUNCTION_LIST_H 9 | 10 | struct Function_Positions{ 11 | i64 sig_start_index; 12 | i64 sig_end_index; 13 | i64 open_paren_pos; 14 | }; 15 | 16 | struct Get_Positions_Results{ 17 | i64 positions_count; 18 | i64 next_token_index; 19 | b32 still_looping; 20 | }; 21 | 22 | #endif 23 | 24 | // BOTTOM 25 | -------------------------------------------------------------------------------- /custom/4coder_hash_functions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 26.08.2018 5 | * 6 | * Generic hash functions 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | #if !defined(FCODER_HASH_FUNCTIONS_CPP) 13 | #define FCODER_HASH_FUNCTIONS_CPP 14 | 15 | static u64 16 | table_hash_u8(u8 *v, u64 size){ 17 | u64 hash = 0; 18 | for (u8 *p = v, *e = v + size; p < e; p += 1){ 19 | u8 k = *p; 20 | k *= 81; 21 | k = ((u8)(k << 4)) | ((u8)(k >> 4)); 22 | hash ^= k; 23 | hash *= 11; 24 | hash += 237; 25 | } 26 | return(hash); 27 | } 28 | static u64 29 | table_hash_u16(u16 *v, u64 size){ 30 | u64 hash = 0; 31 | for (u16 *p = v, *e = v + size; p < e; p += 1){ 32 | u16 k = *p; 33 | k *= 11601; 34 | k = ((u16)(k << 8)) | ((u16)(k >> 8)); 35 | hash ^= k; 36 | hash *= 11; 37 | hash += 12525; 38 | } 39 | return(hash); 40 | } 41 | static u64 42 | table_hash_u32(u32 *v, u64 size){ 43 | u64 hash = 0; 44 | for (u32 *p = v, *e = v + size; p < e; p += 1){ 45 | u32 k = *p; 46 | k *= 3432918353U; 47 | k = ((u32)(k << 16)) | ((u32)(k >> 16)); 48 | hash ^= k; 49 | hash *= 11; 50 | hash += 2041000173U; 51 | } 52 | return(hash); 53 | } 54 | static u64 55 | table_hash_u64(u64 *v, u64 size){ 56 | u64 hash = 0; 57 | for (u64 *p = v, *e = v + size; p < e; p += 1){ 58 | u64 k = *p; 59 | k *= 14744272059406101841ULL; 60 | k = ((u64)(k << 32)) | ((u64)(k >> 32)); 61 | hash ^= k; 62 | hash *= 11; 63 | hash += 8766028991911375085ULL; 64 | } 65 | return(hash); 66 | } 67 | static u64 68 | table_hash(void *v, i32 it_size, u64 size){ 69 | u64 hash = 0; 70 | switch (it_size){ 71 | case 1: 72 | { 73 | hash = table_hash_u8((u8*)v, size); 74 | }break; 75 | case 2: 76 | { 77 | hash = table_hash_u16((u16*)v, size); 78 | }break; 79 | case 4: 80 | { 81 | hash = table_hash_u32((u32*)v, size); 82 | }break; 83 | case 8: 84 | { 85 | hash = table_hash_u64((u64*)v, size); 86 | }break; 87 | default: 88 | { 89 | hash = table_hash_u8((u8*)v, it_size*size); 90 | }break; 91 | } 92 | return(hash); 93 | } 94 | 95 | #endif 96 | 97 | // BOTTOM 98 | -------------------------------------------------------------------------------- /custom/4coder_helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Miscellaneous helpers for common operations. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_HELPER_H) 8 | #define FCODER_HELPER_H 9 | 10 | struct File_Name_Data{ 11 | String_Const_u8 file_name; 12 | String_Const_u8 data; 13 | }; 14 | 15 | struct View_Context_Block{ 16 | Application_Links *app; 17 | View_ID view; 18 | 19 | View_Context_Block(Application_Links *app, View_ID view, View_Context *ctx); 20 | ~View_Context_Block(); 21 | }; 22 | 23 | //////////////////////////////// 24 | 25 | typedef i32 Position_Within_Line; 26 | enum{ 27 | PositionWithinLine_Start, 28 | PositionWithinLine_SkipLeadingWhitespace, 29 | PositionWithinLine_End, 30 | }; 31 | 32 | typedef u32 Buffer_Seek_String_Flags; 33 | enum{ 34 | BufferSeekString_Backward = 1, 35 | BufferSeekString_CaseInsensitive = 2, 36 | }; 37 | 38 | //////////////////////////////// 39 | 40 | typedef b8 Character_Predicate_Function(u8 c); 41 | 42 | global Character_Predicate character_predicate_alpha = { { 43 | 0, 0, 0, 0, 0, 0, 0, 0, 44 | 254, 255, 255, 7, 254, 255, 255, 7, 45 | 0, 0, 0, 0, 0, 0, 0, 0, 46 | 0, 0, 0, 0, 0, 0, 0, 0, 47 | } }; 48 | 49 | global Character_Predicate character_predicate_alpha_numeric = { { 50 | 0, 0, 0, 0, 0, 0, 255, 3, 51 | 254, 255, 255, 7, 254, 255, 255, 7, 52 | 0, 0, 0, 0, 0, 0, 0, 0, 53 | 0, 0, 0, 0, 0, 0, 0, 0, 54 | } }; 55 | 56 | global Character_Predicate character_predicate_alpha_numeric_underscore = { { 57 | 0, 0, 0, 0, 0, 0, 255, 3, 58 | 254, 255, 255, 135, 254, 255, 255, 7, 59 | 0, 0, 0, 0, 0, 0, 0, 0, 60 | 0, 0, 0, 0, 0, 0, 0, 0, 61 | } }; 62 | 63 | global Character_Predicate character_predicate_uppercase = { { 64 | 0, 0, 0, 0, 0, 0, 0, 0, 65 | 254, 255, 255, 7, 0, 0, 0, 0, 66 | 0, 0, 0, 0, 0, 0, 0, 0, 67 | 0, 0, 0, 0, 0, 0, 0, 0, 68 | } }; 69 | 70 | global Character_Predicate character_predicate_lowercase = { { 71 | 0, 0, 0, 0, 0, 0, 0, 0, 72 | 0, 0, 0, 0, 254, 255, 255, 7, 73 | 0, 0, 0, 0, 0, 0, 0, 0, 74 | 0, 0, 0, 0, 0, 0, 0, 0, 75 | } }; 76 | 77 | global Character_Predicate character_predicate_base10 = { { 78 | 0, 0, 0, 0, 0, 0, 255, 3, 79 | 0, 0, 0, 0, 0, 0, 0, 0, 80 | 0, 0, 0, 0, 0, 0, 0, 0, 81 | 0, 0, 0, 0, 0, 0, 0, 0, 82 | } }; 83 | 84 | global Character_Predicate character_predicate_base16 = { { 85 | 0, 0, 0, 0, 0, 0, 255, 3, 86 | 126, 0, 0, 0, 126, 0, 0, 0, 87 | 0, 0, 0, 0, 0, 0, 0, 0, 88 | 0, 0, 0, 0, 0, 0, 0, 0, 89 | } }; 90 | 91 | global Character_Predicate character_predicate_whitespace = { { 92 | 0, 62, 0, 0, 1, 0, 0, 0, 93 | 0, 0, 0, 0, 0, 0, 0, 0, 94 | 0, 0, 0, 0, 0, 0, 0, 0, 95 | 0, 0, 0, 0, 0, 0, 0, 0, 96 | } }; 97 | 98 | global Character_Predicate character_predicate_non_whitespace = { { 99 | 255, 193, 255, 255, 254, 255, 255, 255, 100 | 255, 255, 255, 255, 255, 255, 255, 255, 101 | 255, 255, 255, 255, 255, 255, 255, 255, 102 | 255, 255, 255, 255, 255, 255, 255, 255, 103 | } }; 104 | 105 | global Character_Predicate character_predicate_utf8_byte = { { 106 | 0, 0, 0, 0, 0, 0, 0, 0, 107 | 0, 0, 0, 0, 0, 0, 0, 0, 108 | 255, 255, 255, 255, 255, 255, 255, 255, 109 | 255, 255, 255, 255, 255, 255, 255, 255, 110 | } }; 111 | 112 | global Character_Predicate character_predicate_alpha_numeric_utf8 = { { 113 | 0, 0, 0, 0, 0, 0, 255, 3, 114 | 254, 255, 255, 7, 254, 255, 255, 7, 115 | 255, 255, 255, 255, 255, 255, 255, 255, 116 | 255, 255, 255, 255, 255, 255, 255, 255, 117 | } }; 118 | 119 | global Character_Predicate character_predicate_alpha_numeric_underscore_utf8 = { { 120 | 0, 0, 0, 0, 0, 0, 255, 3, 121 | 254, 255, 255, 135, 254, 255, 255, 7, 122 | 255, 255, 255, 255, 255, 255, 255, 255, 123 | 255, 255, 255, 255, 255, 255, 255, 255, 124 | } }; 125 | 126 | typedef i64 Boundary_Function(Application_Links *app, Buffer_ID buffer, Side side, Scan_Direction direction, i64 pos); 127 | 128 | struct Boundary_Function_Node{ 129 | Boundary_Function_Node *next; 130 | Boundary_Function *func; 131 | }; 132 | struct Boundary_Function_List{ 133 | Boundary_Function_Node *first; 134 | Boundary_Function_Node *last; 135 | i32 count; 136 | }; 137 | 138 | typedef Range_i64 Enclose_Function(Application_Links *app, Buffer_ID buffer, Range_i64 range); 139 | 140 | struct Indent_Info{ 141 | i64 first_char_pos; 142 | i32 indent_pos; 143 | b32 is_blank; 144 | b32 all_space; 145 | }; 146 | 147 | //////////////////////////////// 148 | 149 | struct Sort_Pair_i32{ 150 | i32 index; 151 | i32 key; 152 | }; 153 | 154 | //////////////////////////////// 155 | 156 | struct History_Group{ 157 | Application_Links *app; 158 | Buffer_ID buffer; 159 | History_Record_Index first; 160 | }; 161 | 162 | //////////////////////////////// 163 | 164 | typedef i32 View_Split_Kind; 165 | enum{ 166 | ViewSplitKind_Ratio, 167 | ViewSplitKind_FixedPixels, 168 | }; 169 | 170 | //////////////////////////////// 171 | 172 | typedef i32 Nest_Delimiter_Kind; 173 | enum{ 174 | NestDelim_None = 0, 175 | NestDelim_Open = 1, 176 | NestDelim_Close = 2, 177 | }; 178 | 179 | typedef u32 Find_Nest_Flag; 180 | enum{ 181 | FindNest_Scope = 1, 182 | FindNest_Paren = 2, 183 | FindNest_EndOfToken = 4, 184 | FindNest_Balanced = 8, 185 | }; 186 | 187 | #endif 188 | 189 | // BOTTOM 190 | -------------------------------------------------------------------------------- /custom/4coder_insertion.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Serial inserts helpers 3 | */ 4 | 5 | // TOP 6 | 7 | function Buffer_Insertion 8 | begin_buffer_insertion_at(Application_Links *app, Buffer_ID buffer_id, i64 at){ 9 | Buffer_Insertion result = {}; 10 | result.app = app; 11 | result.buffer = buffer_id; 12 | result.at = at; 13 | return(result); 14 | } 15 | 16 | function Buffer_Insertion 17 | begin_buffer_insertion_at_buffered(Application_Links *app, Buffer_ID buffer_id, i64 at, Cursor *cursor){ 18 | Buffer_Insertion result = begin_buffer_insertion_at(app, buffer_id, at); 19 | result.buffering = true; 20 | result.cursor = cursor; 21 | result.temp = begin_temp(cursor); 22 | return(result); 23 | } 24 | 25 | function Buffer_Insertion 26 | begin_buffer_insertion_at_buffered(Application_Links *app, Buffer_ID buffer_id, i64 at, Arena *buffer_memory, u64 buffer_memory_size){ 27 | Cursor *cursor = push_array(buffer_memory, Cursor, 1); 28 | *cursor = make_cursor(push_array(buffer_memory, u8, buffer_memory_size), buffer_memory_size); 29 | return(begin_buffer_insertion_at_buffered(app, buffer_id, at, cursor)); 30 | } 31 | 32 | function Buffer_Insertion 33 | begin_buffer_insertion(Application_Links *app){ 34 | View_ID view = get_active_view(app, Access_Always); 35 | Buffer_ID buffer = view_get_buffer(app, view, Access_Always); 36 | i64 cursor_pos = view_get_cursor_pos(app, view); 37 | Buffer_Insertion result = begin_buffer_insertion_at(app, buffer, cursor_pos); 38 | return(result); 39 | } 40 | 41 | function void 42 | insert_string__no_buffering(Buffer_Insertion *insertion, String_Const_u8 string){ 43 | buffer_replace_range(insertion->app, insertion->buffer, Ii64(insertion->at), string); 44 | insertion->at += string.size; 45 | } 46 | 47 | function void 48 | insert__flush(Buffer_Insertion *insertion){ 49 | Cursor *cursor = insertion->cursor; 50 | u64 pos = insertion->temp.temp_memory_cursor.pos; 51 | String_Const_u8 string = SCu8(cursor->base + pos, cursor->pos - pos); 52 | insert_string__no_buffering(insertion, string); 53 | end_temp(insertion->temp); 54 | } 55 | 56 | function char* 57 | insert__reserve(Buffer_Insertion *insertion, u64 size){ 58 | char *space = push_array(insertion->cursor, char, size); 59 | if (space == 0){ 60 | insert__flush(insertion); 61 | space = push_array(insertion->cursor, char, size); 62 | } 63 | return(space); 64 | } 65 | 66 | function void 67 | end_buffer_insertion(Buffer_Insertion *insertion){ 68 | if (insertion->buffering){ 69 | insert__flush(insertion); 70 | } 71 | } 72 | 73 | function void 74 | insert_string(Buffer_Insertion *insertion, String_Const_u8 string){ 75 | if (!insertion->buffering){ 76 | insert_string__no_buffering(insertion, string); 77 | } 78 | else{ 79 | char *space = insert__reserve(insertion, string.size); 80 | if (space != 0){ 81 | block_copy(space, string.str, string.size); 82 | } 83 | else{ 84 | insert_string__no_buffering(insertion, string); 85 | } 86 | } 87 | } 88 | 89 | function u64 90 | insertf(Buffer_Insertion *insertion, char *format, ...){ 91 | Scratch_Block scratch(insertion->app); 92 | va_list args; 93 | va_start(args, format); 94 | String_Const_u8 string = push_u8_stringfv(scratch, format, args); 95 | va_end(args); 96 | insert_string(insertion, string); 97 | return(string.size); 98 | } 99 | 100 | function void 101 | insertc(Buffer_Insertion *insertion, char C){ 102 | insert_string(insertion, SCu8(&C, 1)); 103 | } 104 | 105 | function b32 106 | insert_line_from_buffer(Buffer_Insertion *insertion, Buffer_ID buffer_id, i32 line, i32 truncate_at){ 107 | b32 success = is_valid_line(insertion->app, buffer_id, line); 108 | if (success){ 109 | Scratch_Block scratch(insertion->app); 110 | insert_string(insertion, push_buffer_line(insertion->app, scratch, buffer_id, line)); 111 | } 112 | return(success); 113 | } 114 | 115 | function b32 116 | insert_line_from_buffer(Buffer_Insertion *insertion, Buffer_ID buffer_id, i32 line){ 117 | return(insert_line_from_buffer(insertion, buffer_id, line, 0)); 118 | } 119 | 120 | // BOTTOM 121 | -------------------------------------------------------------------------------- /custom/4coder_insertion.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Serial inserts helpers 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FRED_INSERTION_H) 8 | #define FRED_INSERTION_H 9 | 10 | struct Buffer_Insertion{ 11 | Application_Links *app; 12 | Buffer_ID buffer; 13 | i64 at; 14 | b32 buffering; 15 | Cursor *cursor; 16 | Temp_Memory temp; 17 | }; 18 | 19 | #endif 20 | 21 | // BOTTOM 22 | -------------------------------------------------------------------------------- /custom/4coder_jump_lister.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_jump_lister.cpp - Lister for jump buffers. 3 | */ 4 | 5 | // TOP 6 | 7 | function Jump_Lister_Result 8 | get_jump_index_from_user(Application_Links *app, Marker_List *list, 9 | String_Const_u8 query){ 10 | Jump_Lister_Result result = {}; 11 | if (list != 0){ 12 | Scratch_Block scratch(app); 13 | Lister_Block lister(app, scratch); 14 | lister_set_query(lister, query); 15 | lister_set_default_handlers(lister); 16 | 17 | Buffer_ID list_buffer = list->buffer_id; 18 | 19 | i32 option_count = list->jump_count; 20 | Managed_Object stored_jumps = list->jump_array; 21 | for (i32 i = 0; i < option_count; i += 1){ 22 | Sticky_Jump_Stored stored = {}; 23 | managed_object_load_data(app, stored_jumps, i, 1, &stored); 24 | String_Const_u8 line = push_buffer_line(app, scratch, list_buffer, 25 | stored.list_line); 26 | lister_add_item(lister, line, SCu8(), IntAsPtr(i), 0); 27 | } 28 | 29 | Lister_Result l_result = run_lister(app, lister); 30 | if (!l_result.canceled){ 31 | result.success = true; 32 | result.index = (i32)PtrAsInt(l_result.user_data); 33 | } 34 | } 35 | 36 | return(result); 37 | } 38 | 39 | function Jump_Lister_Result 40 | get_jump_index_from_user(Application_Links *app, Marker_List *list, char *query){ 41 | return(get_jump_index_from_user(app, list, SCu8(query))); 42 | } 43 | 44 | function void 45 | jump_to_jump_lister_result(Application_Links *app, View_ID view, 46 | Marker_List *list, Jump_Lister_Result *jump){ 47 | if (jump->success){ 48 | ID_Pos_Jump_Location location = {}; 49 | if (get_jump_from_list(app, list, jump->index, &location)){ 50 | Buffer_ID jump_dst_buffer = {}; 51 | if (get_jump_buffer(app, &jump_dst_buffer, &location)){ 52 | view_set_active(app, view); 53 | jump_to_location(app, view, jump_dst_buffer, location); 54 | } 55 | } 56 | } 57 | } 58 | 59 | CUSTOM_COMMAND_SIG(view_jump_list_with_lister) 60 | CUSTOM_DOC("When executed on a buffer with jumps, creates a persistent lister for all the jumps") 61 | { 62 | Heap *heap = &global_heap; 63 | View_ID view = get_active_view(app, Access_Always); 64 | Buffer_ID buffer = view_get_buffer(app, view, Access_Always); 65 | Marker_List *list = get_or_make_list_for_buffer(app, heap, buffer); 66 | if (list != 0){ 67 | Jump_Lister_Result jump = get_jump_index_from_user(app, list, "Jump:"); 68 | jump_to_jump_lister_result(app, view, list, &jump); 69 | } 70 | } 71 | 72 | // BOTTOM 73 | -------------------------------------------------------------------------------- /custom/4coder_jump_lister.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_jump_lister.h - Lister for jump buffers. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_JUMP_LISTER_H) 8 | #define FCODER_JUMP_LISTER_H 9 | 10 | typedef i32 Jump_Lister_Activation_Rule; 11 | enum{ 12 | JumpListerActivation_OpenInUIView = 0, 13 | JumpListerActivation_OpenInTargetViewKeepUI = 1, 14 | JumpListerActivation_OpenInTargetViewCloseUI = 2, 15 | JumpListerActivation_OpenInNextViewKeepUI = 3, 16 | JumpListerActivation_OpenInNextViewCloseUI = 4, 17 | }; 18 | 19 | struct Jump_Lister_Parameters{ 20 | Buffer_ID list_buffer_id; 21 | Jump_Lister_Activation_Rule activation_rule; 22 | View_ID target_view_id; 23 | }; 24 | 25 | struct Jump_Lister_Result{ 26 | b32 success; 27 | i32 index; 28 | }; 29 | 30 | #endif 31 | 32 | // BOTTOM -------------------------------------------------------------------------------- /custom/4coder_jump_sticky.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_jump_sticky.h - Types for persistant jump positions. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_JUMP_STICKY_H) 8 | #define FCODER_JUMP_STICKY_H 9 | 10 | struct Sticky_Jump{ 11 | i64 list_line; 12 | i64 list_colon_index; 13 | b32 is_sub_error; 14 | Buffer_ID jump_buffer_id; 15 | i64 jump_pos; 16 | }; 17 | 18 | struct Sticky_Jump_Stored{ 19 | i64 list_line; 20 | i64 list_colon_index; 21 | b32 is_sub_error; 22 | Buffer_ID jump_buffer_id; 23 | i32 index_into_marker_array; 24 | }; 25 | 26 | struct Sticky_Jump_Node{ 27 | Sticky_Jump_Node *next; 28 | Sticky_Jump jump; 29 | }; 30 | 31 | struct Sticky_Jump_Array{ 32 | Sticky_Jump *jumps; 33 | i32 count; 34 | }; 35 | 36 | struct Sticky_Jump_Node_Header{ 37 | Managed_Object memory; 38 | Managed_Object markers; 39 | i32 first_index; 40 | i32 count; 41 | }; 42 | 43 | enum Jump_Location_Flag{ 44 | JumpFlag_IsSubJump = 0x1, 45 | }; 46 | 47 | struct Marker_List{ 48 | Managed_Object jump_array; 49 | i32 jump_count; 50 | i32 previous_size; 51 | Buffer_ID buffer_id; 52 | }; 53 | 54 | struct Marker_List_Node{ 55 | Marker_List_Node *next; 56 | Marker_List_Node *prev; 57 | Marker_List list; 58 | Buffer_ID buffer_id; 59 | }; 60 | 61 | struct Locked_Jump_State{ 62 | View_ID view; 63 | Marker_List *list; 64 | i32 list_index; 65 | }; 66 | 67 | #endif 68 | 69 | // BOTTOM 70 | -------------------------------------------------------------------------------- /custom/4coder_jumping.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_jumping.h - Typesused when writing code to jump to locations and seek through jump lists. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_JUMPING_H) 8 | #define FCODER_JUMPING_H 9 | 10 | typedef u32 Jump_Flag; 11 | enum{ 12 | JumpFlag_SkipSubs = 1, 13 | }; 14 | 15 | #endif 16 | 17 | // BOTTOM -------------------------------------------------------------------------------- /custom/4coder_keyboard_macro.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_keyboard_macro.cpp - Keyboard macro recording and replaying commands. 3 | */ 4 | 5 | // TOP 6 | 7 | function Buffer_ID 8 | get_keyboard_log_buffer(Application_Links *app){ 9 | return(get_buffer_by_name(app, string_u8_litexpr("*keyboard*"), Access_Always)); 10 | } 11 | 12 | function void 13 | keyboard_macro_play_single_line(Application_Links *app, String_Const_u8 macro_line){ 14 | Scratch_Block scratch(app); 15 | Input_Event event = parse_keyboard_event(scratch, macro_line); 16 | if (event.kind != InputEventKind_None){ 17 | enqueue_virtual_event(app, &event); 18 | } 19 | } 20 | 21 | function void 22 | keyboard_macro_play(Application_Links *app, String_Const_u8 macro){ 23 | Scratch_Block scratch(app); 24 | List_String_Const_u8 lines = string_split(scratch, macro, (u8*)"\n", 1); 25 | for (Node_String_Const_u8 *node = lines.first; 26 | node != 0; 27 | node = node->next){ 28 | String_Const_u8 line = string_skip_chop_whitespace(node->string); 29 | keyboard_macro_play_single_line(app, line); 30 | } 31 | } 32 | 33 | function b32 34 | get_current_input_is_virtual(Application_Links *app){ 35 | User_Input input = get_current_input(app); 36 | return(input.event.virtual_event); 37 | } 38 | 39 | //////////////////////////////// 40 | 41 | CUSTOM_COMMAND_SIG(keyboard_macro_start_recording) 42 | CUSTOM_DOC("Start macro recording, do nothing if macro recording is already started") 43 | { 44 | if (global_keyboard_macro_is_recording || 45 | get_current_input_is_virtual(app)){ 46 | return; 47 | } 48 | 49 | Buffer_ID buffer = get_keyboard_log_buffer(app); 50 | global_keyboard_macro_is_recording = true; 51 | global_keyboard_macro_range.first = buffer_get_size(app, buffer); 52 | } 53 | 54 | CUSTOM_COMMAND_SIG(keyboard_macro_finish_recording) 55 | CUSTOM_DOC("Stop macro recording, do nothing if macro recording is not already started") 56 | { 57 | if (!global_keyboard_macro_is_recording || 58 | get_current_input_is_virtual(app)){ 59 | return; 60 | } 61 | 62 | Buffer_ID buffer = get_keyboard_log_buffer(app); 63 | global_keyboard_macro_is_recording = false; 64 | i64 end = buffer_get_size(app, buffer); 65 | Buffer_Cursor cursor = buffer_compute_cursor(app, buffer, seek_pos(end)); 66 | Buffer_Cursor back_cursor = buffer_compute_cursor(app, buffer, seek_line_col(cursor.line - 1, 1)); 67 | global_keyboard_macro_range.one_past_last = back_cursor.pos; 68 | 69 | #if 0 70 | Scratch_Block scratch(app); 71 | String_Const_u8 macro = push_buffer_range(app, scratch, buffer, global_keyboard_macro_range); 72 | print_message(app, string_u8_litexpr("recorded:\n")); 73 | print_message(app, macro); 74 | #endif 75 | } 76 | 77 | CUSTOM_COMMAND_SIG(keyboard_macro_replay) 78 | CUSTOM_DOC("Replay the most recently recorded keyboard macro") 79 | { 80 | if (global_keyboard_macro_is_recording || 81 | get_current_input_is_virtual(app)){ 82 | return; 83 | } 84 | 85 | Buffer_ID buffer = get_keyboard_log_buffer(app); 86 | Scratch_Block scratch(app); 87 | String_Const_u8 macro = push_buffer_range(app, scratch, buffer, global_keyboard_macro_range); 88 | keyboard_macro_play(app, macro); 89 | } 90 | 91 | // BOTTOM 92 | -------------------------------------------------------------------------------- /custom/4coder_layout_rule.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_layout_rule.h - Built in layout rule types. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_LAYOUT_RULE_H) 8 | #define FCODER_LAYOUT_RULE_H 9 | 10 | struct Newline_Layout_Vars{ 11 | i64 newline_character_index; 12 | b32 consuming_newline_characters; 13 | b32 prev_did_emit_newline; 14 | }; 15 | 16 | struct LefRig_TopBot_Layout_Vars{ 17 | Face_Advance_Map *advance_map; 18 | Face_Metrics *metrics; 19 | f32 tab_width; 20 | f32 line_to_text_shift; 21 | 22 | Vec2_f32 blank_dim; 23 | 24 | Vec2_f32 p; 25 | f32 line_y; 26 | f32 text_y; 27 | f32 width; 28 | }; 29 | 30 | struct Layout_Reflex{ 31 | Layout_Item_List *list; 32 | Buffer_ID buffer; 33 | f32 width; 34 | Face_ID face; 35 | }; 36 | 37 | typedef i32 Layout_Wrap_Kind; 38 | enum{ 39 | Layout_Unwrapped, 40 | Layout_Wrapped, 41 | }; 42 | 43 | typedef i32 Layout_Virtual_Indent; 44 | enum{ 45 | LayoutVirtualIndent_Off, 46 | LayoutVirtualIndent_On, 47 | }; 48 | 49 | #endif 50 | 51 | // BOTTOM 52 | -------------------------------------------------------------------------------- /custom/4coder_lister_base.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Lister base 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_LISTER_BASE_H) 8 | #define FCODER_LISTER_BASE_H 9 | 10 | typedef i32 Lister_Activation_Code; 11 | enum{ 12 | ListerActivation_Finished = 0, 13 | ListerActivation_Continue = 1, 14 | ListerActivation_ContinueAndRefresh = 2, 15 | }; 16 | 17 | typedef void Lister_Regenerate_List_Function_Type(Application_Links *app, struct Lister *lister); 18 | 19 | struct Lister_Node{ 20 | Lister_Node *next; 21 | Lister_Node *prev; 22 | String_Const_u8 string; 23 | union{ 24 | String_Const_u8 status; 25 | i32 index; 26 | }; 27 | void *user_data; 28 | i32 raw_index; 29 | }; 30 | 31 | struct Lister_Node_List{ 32 | Lister_Node *first; 33 | Lister_Node *last; 34 | i32 count; 35 | }; 36 | 37 | struct Lister_Node_Ptr_Array{ 38 | Lister_Node **node_ptrs; 39 | i32 count; 40 | }; 41 | 42 | typedef Lister_Activation_Code Lister_Write_Character_Function(Application_Links *app); 43 | typedef Lister_Activation_Code Lister_Key_Stroke_Function(Application_Links *app); 44 | typedef void Lister_Navigate_Function(Application_Links *app, 45 | View_ID view, struct Lister *lister, 46 | i32 index_delta); 47 | 48 | struct Lister_Handlers{ 49 | Lister_Regenerate_List_Function_Type *refresh; 50 | Lister_Write_Character_Function *write_character; 51 | Custom_Command_Function *backspace; 52 | Lister_Navigate_Function *navigate; 53 | Lister_Key_Stroke_Function *key_stroke; 54 | }; 55 | 56 | struct Lister_Result{ 57 | b32 canceled; 58 | b32 activated_by_click; 59 | String_Const_u8 text_field; 60 | void *user_data; 61 | }; 62 | 63 | struct Lister{ 64 | Arena *arena; 65 | Temp_Memory restore_all_point; 66 | 67 | Lister_Handlers handlers; 68 | 69 | Mapping *mapping; 70 | Command_Map *map; 71 | 72 | u8 query_space[256]; 73 | u8 text_field_space[256]; 74 | u8 key_string_space[256]; 75 | String_u8 query; 76 | String_u8 text_field; 77 | String_u8 key_string; 78 | 79 | Lister_Node_List options; 80 | Temp_Memory filter_restore_point; 81 | Lister_Node_Ptr_Array filtered; 82 | 83 | b32 set_vertical_focus_to_item; 84 | Lister_Node *highlighted_node; 85 | void *hot_user_data; 86 | i32 item_index; 87 | i32 raw_item_index; 88 | 89 | Basic_Scroll scroll; 90 | i32 visible_count; 91 | 92 | Lister_Result out; 93 | }; 94 | 95 | struct Lister_Prev_Current{ 96 | Lister *prev; 97 | Lister *current; 98 | }; 99 | 100 | struct Lister_Block{ 101 | Application_Links *app; 102 | Lister_Prev_Current lister; 103 | Lister_Block(Application_Links *app, Arena *arena); 104 | ~Lister_Block(); 105 | operator Lister *(); 106 | }; 107 | 108 | struct Lister_Prealloced_String{ 109 | String_Const_u8 string; 110 | }; 111 | 112 | struct Lister_Filtered{ 113 | Lister_Node_Ptr_Array exact_matches; 114 | Lister_Node_Ptr_Array before_extension_matches; 115 | Lister_Node_Ptr_Array substring_matches; 116 | }; 117 | 118 | //////////////////////////////// 119 | 120 | struct Lister_Choice{ 121 | Lister_Choice *next; 122 | String_Const_u8 string; 123 | String_Const_u8 status; 124 | Key_Code key_code; 125 | union{ 126 | u64 user_data; 127 | void *user_data_ptr; 128 | }; 129 | }; 130 | 131 | struct Lister_Choice_List{ 132 | Lister_Choice *first; 133 | Lister_Choice *last; 134 | }; 135 | 136 | #endif 137 | 138 | // BOTTOM 139 | -------------------------------------------------------------------------------- /custom/4coder_log.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 14.08.2019 5 | * 6 | * Logging helpers. 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | #if !defined(FCODER_LOG_CPP) 13 | #define FCODER_LOG_CPP 14 | 15 | internal String_Const_u8 16 | log_event(Arena *arena, String_Const_u8 event_name, String_Const_u8 src_name, i32 line_number, i32 buffer, i32 view, i32 thread_id){ 17 | List_String_Const_u8 list = {}; 18 | string_list_pushf(arena, &list, "%S:%d: %S", src_name, line_number, event_name); 19 | if (thread_id != 0){ 20 | string_list_pushf(arena, &list, " [thread=%d]", thread_id); 21 | } 22 | if (buffer != 0){ 23 | string_list_pushf(arena, &list, " [buffer=%d]", buffer); 24 | } 25 | if (view != 0){ 26 | string_list_pushf(arena, &list, " [view=%d]", view); 27 | } 28 | string_list_push(arena, &list, string_u8_litexpr("\n")); 29 | return(string_list_flatten(arena, list)); 30 | } 31 | 32 | #define LogEventStr(log_call, arena, B, V, T, E) \ 33 | Stmnt(Temp_Memory temp_LOG = begin_temp(arena); \ 34 | String_Const_u8 M = log_event(arena, E, \ 35 | string_u8_litexpr(__FILE__), \ 36 | __LINE__, (B), (V), (T)); \ 37 | log_call; \ 38 | end_temp(temp_LOG); ) 39 | 40 | #define LogEventLit(log_call, arena, B, V, T, Elit) \ 41 | LogEventStr(log_call, arena, (B), (V), (T), string_u8_litexpr(Elit)) 42 | 43 | #define LogEventF(log_call, arena, B, V, T, Ef, ...) \ 44 | Stmnt(Temp_Memory temp_LOG_F = begin_temp(arena); \ 45 | String_Const_u8 E = push_u8_stringf(arena, Ef, __VA_ARGS__); \ 46 | LogEventStr(log_call, arena, B, V, T, E); \ 47 | end_temp(temp_LOG_F); ) 48 | 49 | #endif 50 | 51 | // BOTTOM 52 | -------------------------------------------------------------------------------- /custom/4coder_log_parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 14.08.2019 5 | * 6 | * Log parser. 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | #if !defined(FCODER_LOG_PARSER_H) 13 | #define FCODER_LOG_PARSER_H 14 | 15 | typedef i64 Log_Tag_Kind; 16 | enum{ 17 | LogTagKind_Null, 18 | LogTagKind_Integer, 19 | LogTagKind_String, 20 | }; 21 | 22 | typedef i32 Log_String_Source; 23 | enum{ 24 | LogParse_ExternalString, 25 | LogParse_PreAllocatedString, 26 | }; 27 | 28 | struct Log_Tag_Value{ 29 | Log_Tag_Kind kind; 30 | union{ 31 | u64 value; 32 | i64 value_s; 33 | }; 34 | }; 35 | 36 | struct Log_Sort_Key{ 37 | Log_Tag_Value value; 38 | i32 number; 39 | }; 40 | 41 | struct Log_Tag_Name_Value{ 42 | u64 name; 43 | Log_Tag_Value value; 44 | }; 45 | 46 | struct Log_Tag{ 47 | Log_Tag *next; 48 | u64 name; 49 | Log_Tag_Value value; 50 | }; 51 | 52 | struct Log_Event{ 53 | Log_Event *next; 54 | u64 src_file_name; 55 | u64 event_name; 56 | u64 line_number; 57 | 58 | Log_Tag *first_tag; 59 | Log_Tag *last_tag; 60 | i32 tag_count; 61 | 62 | i32 event_number; 63 | 64 | Table_u64_u64 tag_name_to_tag_ptr_table; 65 | }; 66 | 67 | struct Log_Event_Ptr_Node{ 68 | Log_Event_Ptr_Node *next; 69 | Log_Event *event; 70 | }; 71 | 72 | struct Log_Event_List{ 73 | Log_Event_Ptr_Node *first; 74 | Log_Event_Ptr_Node *last; 75 | i32 count; 76 | }; 77 | 78 | struct Log_Event_Ptr_Array{ 79 | Log_Event **events; 80 | i32 count; 81 | }; 82 | 83 | struct Log_Tag_Value_Array{ 84 | Log_Tag_Value *vals; 85 | i32 count; 86 | }; 87 | 88 | struct Log_Parse{ 89 | Arena *arena; 90 | 91 | Log_Event *first_event; 92 | Log_Event *last_event; 93 | i32 event_count; 94 | 95 | u64 string_id_counter; 96 | Table_Data_u64 string_to_id_table; 97 | Table_u64_Data id_to_string_table; 98 | 99 | Table_Data_u64 tag_value_to_event_list_table; 100 | Table_u64_u64 tag_name_to_event_list_table; 101 | }; 102 | 103 | //////////////////////////////// 104 | 105 | struct Log_Graph_Thread_Bucket{ 106 | Log_Graph_Thread_Bucket *next; 107 | Range_i32 range; 108 | b32 had_a_tag; 109 | u64 thread_id_value; 110 | }; 111 | 112 | struct Log_Graph_Box{ 113 | Log_Graph_Box *next; 114 | Rect_f32 rect; 115 | Log_Event *event; 116 | }; 117 | 118 | typedef i32 Log_Filter_Kind; 119 | enum{ 120 | LogFilter_ERROR, 121 | LogFilter_TagValue, 122 | LogFilter_Tag, 123 | }; 124 | 125 | struct Log_Filter{ 126 | Log_Filter *next; 127 | Log_Filter *prev; 128 | Log_Filter_Kind kind; 129 | u64 tag_name_code; 130 | Log_Tag_Value tag_value; 131 | }; 132 | 133 | struct Log_Filter_Set{ 134 | Log_Filter filters_memory[20]; 135 | Log_Filter *free_filters; 136 | Log_Filter *first; 137 | Log_Filter *last; 138 | i32 count; 139 | i32 alter_counter; 140 | }; 141 | 142 | typedef i32 Log_Graph_List_Tab; 143 | enum{ 144 | LogTab_ERROR, 145 | LogTab_Filters, 146 | LogTab_Previews, 147 | LogTab_COUNT, 148 | }; 149 | 150 | struct Log_Graph{ 151 | b32 holding_temp; 152 | Temp_Memory temp; 153 | Rect_f32 layout_region; 154 | Face_ID face_id; 155 | i32 filter_alter_counter; 156 | i32 preview_alter_counter; 157 | Log_Graph_List_Tab tab; 158 | Rect_f32 details_region; 159 | Log_Event_List filtered_list; 160 | Log_Event_Ptr_Array event_array; 161 | Log_Graph_Thread_Bucket *first_bucket; 162 | Log_Graph_Thread_Bucket *last_bucket; 163 | i32 bucket_count; 164 | Log_Graph_Box *first_box; 165 | Log_Graph_Box *last_box; 166 | i32 box_count; 167 | f32 y_scroll; 168 | f32 max_y_scroll; 169 | Log_Event *selected_event; 170 | b32 has_unused_click; 171 | Vec2_f32 unused_click; 172 | }; 173 | 174 | #endif 175 | 176 | // BOTTOM 177 | -------------------------------------------------------------------------------- /custom/4coder_malloc_allocator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder malloc base allocator 3 | */ 4 | 5 | // TOP 6 | 7 | #include 8 | 9 | #if !OS_MAC 10 | # include 11 | #endif 12 | 13 | internal void* 14 | base_reserve__malloc(void *user_data, u64 size, u64 *size_out, String_Const_u8 location){ 15 | *size_out = size; 16 | return(malloc((size_t)size)); 17 | } 18 | 19 | internal void 20 | base_free__malloc(void *user_data, void *ptr){ 21 | free(ptr); 22 | } 23 | 24 | internal Base_Allocator 25 | make_malloc_base_allocator(void){ 26 | return(make_base_allocator(base_reserve__malloc, 0, 0, 27 | base_free__malloc, 0, 0)); 28 | } 29 | 30 | global Base_Allocator malloc_base_allocator = {}; 31 | 32 | internal Base_Allocator* 33 | get_allocator_malloc(void){ 34 | if (malloc_base_allocator.reserve == 0){ 35 | malloc_base_allocator = make_malloc_base_allocator(); 36 | } 37 | return(&malloc_base_allocator); 38 | } 39 | 40 | internal Arena 41 | make_arena_malloc(u64 chunk_size, u64 align){ 42 | Base_Allocator *allocator = get_allocator_malloc(); 43 | return(make_arena(allocator, chunk_size, align)); 44 | } 45 | 46 | internal Arena 47 | make_arena_malloc(u64 chunk_size){ 48 | return(make_arena_malloc(chunk_size, 8)); 49 | } 50 | 51 | internal Arena 52 | make_arena_malloc(void){ 53 | return(make_arena_malloc(KB(16), 8)); 54 | } 55 | 56 | // BOTTOM 57 | -------------------------------------------------------------------------------- /custom/4coder_prj_v1.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_prj_v1.h - type header paired with 4coder_prj_v1.cpp 3 | */ 4 | 5 | // TOP 6 | 7 | #ifndef FCODER_PRJ_V1_H 8 | #define FCODER_PRJ_V1_H 9 | 10 | /////////////////////////////// 11 | // NOTE(allen): Project v0-v1 Structure 12 | 13 | struct Prj_V1_File_Load_Path{ 14 | String8 path; 15 | b32 recursive; 16 | b32 relative; 17 | }; 18 | 19 | struct Prj_V1_File_Load_Path_Array{ 20 | Prj_V1_File_Load_Path *paths; 21 | i32 count; 22 | }; 23 | 24 | struct Prj_V1_Command{ 25 | String8 name; 26 | String8 cmd; 27 | String8 out; 28 | b32 footer_panel; 29 | b32 save_dirty_files; 30 | b32 cursor_at_end; 31 | }; 32 | 33 | struct Prj_V1_Command_Array{ 34 | Prj_V1_Command *commands; 35 | i32 count; 36 | }; 37 | 38 | struct Prj_V1{ 39 | b32 loaded; 40 | 41 | String8 dir; 42 | String8 name; 43 | 44 | Prj_Pattern_List pattern_list; 45 | Prj_Pattern_List blacklist_pattern_list; 46 | Prj_V1_File_Load_Path_Array load_path_array; 47 | Prj_V1_Command_Array command_array; 48 | 49 | i32 fkey_commands[16]; 50 | }; 51 | 52 | enum Prj_V1_OS_Match_Level{ 53 | PrjV1OSMatchLevel_NoMatch = 0, 54 | PrjV1OSMatchLevel_PassiveMatch = 1, 55 | PrjV1OSMatchLevel_ActiveMatch = 2, 56 | }; 57 | 58 | 59 | //////////////////////////////// 60 | // NOTE(allen): Project v0-v1 -> v2 Function 61 | 62 | function Variable_Handle prj_v1_to_v2(Application_Links *app, String8 dir, Config *parsed); 63 | 64 | 65 | #endif //4CODER_PRJ_V1_H 66 | 67 | // BOTTOM 68 | -------------------------------------------------------------------------------- /custom/4coder_profile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder_profile.cpp - Built in self profiling report. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_PROFILE_H) 8 | #define FCODER_PROFILE_H 9 | 10 | struct Profile_Global_List{ 11 | System_Mutex mutex; 12 | Arena node_arena; 13 | Arena_Node *first_arena; 14 | Arena_Node *last_arena; 15 | Profile_Thread *first_thread; 16 | Profile_Thread *last_thread; 17 | i32 thread_count; 18 | Profile_Enable_Flag disable_bits; 19 | }; 20 | 21 | struct Profile_Block{ 22 | Thread_Context *tctx; 23 | Profile_Global_List *list; 24 | b32 is_closed; 25 | Profile_ID id; 26 | 27 | Profile_Block(Thread_Context *tctx, Profile_Global_List *list, 28 | String_Const_u8 name, String_Const_u8 location); 29 | Profile_Block(Application_Links *app, String_Const_u8 name, String_Const_u8 location); 30 | ~Profile_Block(); 31 | void close_now(); 32 | }; 33 | 34 | struct Profile_Scope_Block{ 35 | Thread_Context *tctx; 36 | Profile_Global_List *list; 37 | b32 is_closed; 38 | Profile_ID id; 39 | 40 | Profile_Scope_Block(Thread_Context *tctx, Profile_Global_List *list, 41 | String_Const_u8 name, String_Const_u8 location); 42 | Profile_Scope_Block(Application_Links *app, String_Const_u8 name, String_Const_u8 location); 43 | ~Profile_Scope_Block(); 44 | void close_now(); 45 | }; 46 | 47 | #endif 48 | 49 | // BOTTOM 50 | -------------------------------------------------------------------------------- /custom/4coder_profile_inspect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder_profile_inspect.h - Built in self profiling UI. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_PROFILE_INSPECT_H) 8 | #define FCODER_PROFILE_INSPECT_H 9 | 10 | struct Profile_Node_Ptr{ 11 | Profile_Node_Ptr *next; 12 | struct Profile_Node *ptr; 13 | }; 14 | 15 | struct Profile_Slot{ 16 | Profile_Slot *next; 17 | String_Const_u8 location; 18 | String_Const_u8 name; 19 | 20 | u64 total_time; 21 | b32 corrupted_time; 22 | 23 | i32 hit_count; 24 | Profile_Node_Ptr *first_hit; 25 | Profile_Node_Ptr *last_hit; 26 | }; 27 | 28 | struct Profile_Node{ 29 | Profile_Node *next; 30 | Profile_Node *parent; 31 | Profile_Slot *slot; 32 | struct Profile_Inspection_Thread *thread; 33 | Range_u64 time; 34 | Profile_ID id; 35 | u64 unique_counter; 36 | 37 | Profile_Node *first_child; 38 | Profile_Node *last_child; 39 | i32 child_count; 40 | 41 | b32 closed; 42 | }; 43 | 44 | struct Profile_Inspection_Thread{ 45 | i32 thread_id; 46 | String_Const_u8 name; 47 | Profile_Node root; 48 | u64 active_time; 49 | }; 50 | 51 | struct Profile_Error{ 52 | Profile_Error *next; 53 | String_Const_u8 message; 54 | String_Const_u8 location; 55 | }; 56 | 57 | typedef i32 Profile_Inspection_Tab; 58 | enum{ 59 | ProfileInspectTab_None, 60 | ProfileInspectTab_Threads, 61 | ProfileInspectTab_Blocks, 62 | ProfileInspectTab_Errors, 63 | ProfileInspectTab_Memory, 64 | ProfileInspectTab_Selection, 65 | }; 66 | 67 | struct Profile_Inspection{ 68 | Profile_Slot *first_slot; 69 | Profile_Slot *last_slot; 70 | Profile_Error *first_error; 71 | Profile_Error *last_error; 72 | Profile_Inspection_Thread *threads; 73 | i32 slot_count; 74 | i32 thread_count; 75 | i32 error_count; 76 | 77 | Profile_Inspection_Tab tab_id; 78 | Profile_Inspection_Thread *selected_thread; 79 | Profile_Slot *selected_slot; 80 | Profile_Node *selected_node; 81 | 82 | Profile_Inspection_Tab tab_id_hovered; 83 | String_Const_u8 full_name_hovered; 84 | u64 unique_counter_hovered; 85 | String_Const_u8 location_jump_hovered; 86 | Profile_Inspection_Thread *hover_thread; 87 | Profile_Slot *hover_slot; 88 | Profile_Node *hover_node; 89 | }; 90 | 91 | global Profile_Inspection global_profile_inspection = {}; 92 | 93 | struct Memory_Bucket{ 94 | Memory_Bucket *next; 95 | Memory_Annotation annotation; 96 | String_Const_u8 location; 97 | u64 total_memory; 98 | }; 99 | 100 | #endif 101 | 102 | // TOP 103 | -------------------------------------------------------------------------------- /custom/4coder_profile_static_disable.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder_profile_static_disable.cpp - Statically removes all profile posting code 3 | * that follows until the next 4coder_profile_static_enable.cpp 4 | */ 5 | 6 | // TOP 7 | 8 | #if defined(ProfileBlock) 9 | #undef ProfileBlock 10 | #undef ProfileScope 11 | #undef ProfileBlockNamed 12 | #undef ProfileScopeNamed 13 | 14 | #undef ProfileTLBlock 15 | #undef ProfileTLScope 16 | #undef ProfileTLBlockNamed 17 | #undef ProfileTLScopeNamed 18 | 19 | #undef ProfileCloseNow 20 | #endif 21 | 22 | #define ProfileBlock(T,N) 23 | #define ProfileScope(T,N) 24 | #define ProfileBlockNamed(T,N,M) 25 | #define ProfileScopeNamed(T,N,M) 26 | 27 | #define ProfileTLBlock(T,L,N) 28 | #define ProfileTLScope(T,L,N) 29 | #define ProfileTLBlockNamed(T,L,N,M) 30 | #define ProfileTLScopeNamed(T,L,N,M) 31 | 32 | #define ProfileCloseNow(O) 33 | 34 | // BOTTOM 35 | -------------------------------------------------------------------------------- /custom/4coder_profile_static_enable.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder_profile_static_enable.cpp - Macro interface for self profiler. 3 | */ 4 | 5 | // TOP 6 | 7 | #if defined(ProfileBlock) 8 | #undef ProfileBlock 9 | #undef ProfileScope 10 | #undef ProfileBlockNamed 11 | #undef ProfileScopeNamed 12 | 13 | #undef ProfileTLBlock 14 | #undef ProfileTLScope 15 | #undef ProfileTLBlockNamed 16 | #undef ProfileTLScopeNamed 17 | 18 | #undef ProfileCloseNow 19 | #endif 20 | 21 | #define ProfileBlock(T,N) \ 22 | Profile_Block glue(profile_block_, __LINE__) \ 23 | ((T), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number)) 24 | 25 | #define ProfileScope(T,N) \ 26 | Profile_Scope_Block glue(profile_block_, __LINE__) \ 27 | ((T), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number)) 28 | 29 | #define ProfileBlockNamed(T,N,M) \ 30 | Profile_Block M \ 31 | ((T), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number)) 32 | 33 | #define ProfileScopeNamed(T,N,M) \ 34 | Profile_Scope_Block M \ 35 | ((T), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number)) 36 | 37 | 38 | 39 | #define ProfileTLBlock(T,L,N) \ 40 | Profile_Block glue(profile_block_, __LINE__) \ 41 | ((T), (L), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number)) 42 | 43 | #define ProfileTLScope(T,L,N) \ 44 | Profile_Scope_Block glue(profile_block_, __LINE__) \ 45 | ((T), (L), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number)) 46 | 47 | #define ProfileTLBlockNamed(T,L,N,M) \ 48 | Profile_Block M \ 49 | ((T), (L), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number)) 50 | 51 | #define ProfileTLScopeNamed(T,L,N,M) \ 52 | Profile_Scope_Block M \ 53 | ((T), (L), string_u8_litexpr(N), string_u8_litexpr(file_name_line_number)) 54 | 55 | 56 | 57 | #define ProfileCloseNow(B) ((B).close_now()) 58 | 59 | // BOTTOM 60 | -------------------------------------------------------------------------------- /custom/4coder_project_commands.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_project_commands.h - type header paired with 4coder_project_commands.cpp 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_PROJECT_COMMANDS_H) 8 | #define FCODER_PROJECT_COMMANDS_H 9 | 10 | //////////////////////////////// 11 | // NOTE(allen): Match Pattern Types 12 | 13 | struct Prj_Pattern{ 14 | String8List absolutes; 15 | }; 16 | 17 | struct Prj_Pattern_Node{ 18 | Prj_Pattern_Node *next; 19 | Prj_Pattern pattern; 20 | }; 21 | 22 | struct Prj_Pattern_List{ 23 | Prj_Pattern_Node *first; 24 | Prj_Pattern_Node *last; 25 | i32 count; 26 | }; 27 | 28 | typedef u32 Prj_Open_File_Flags; 29 | enum{ 30 | PrjOpenFileFlag_Recursive = 1, 31 | }; 32 | 33 | /////////////////////////////// 34 | // NOTE(allen): Project Files 35 | 36 | struct Prj_Setup_Status{ 37 | b32 bat_exists; 38 | b32 sh_exists; 39 | b32 project_exists; 40 | b32 everything_exists; 41 | }; 42 | 43 | struct Prj_Key_Strings{ 44 | b32 success; 45 | String8 script_file; 46 | String8 code_file; 47 | String8 output_dir; 48 | String8 binary_file; 49 | }; 50 | 51 | typedef u32 Prj_Setup_Script_Flags; 52 | enum{ 53 | PrjSetupScriptFlag_Project = 0x1, 54 | PrjSetupScriptFlag_Bat = 0x2, 55 | PrjSetupScriptFlag_Sh = 0x4, 56 | }; 57 | 58 | //////////////////////////////// 59 | // NOTE(allen): File Pattern Operators 60 | 61 | function Prj_Pattern_List prj_pattern_list_from_extension_array(Arena *arena, String8Array list); 62 | function Prj_Pattern_List prj_pattern_list_from_var(Arena *arena, Variable_Handle var); 63 | function Prj_Pattern_List prj_get_standard_blacklist(Arena *arena); 64 | 65 | function b32 prj_match_in_pattern_list(String8 string, Prj_Pattern_List list); 66 | 67 | function void prj_close_files_with_ext(Application_Links *app, String8Array extension_array); 68 | function void prj_open_files_pattern_filter(Application_Links *app, String8 dir, Prj_Pattern_List whitelist, Prj_Pattern_List blacklist, Prj_Open_File_Flags flags); 69 | function void prj_open_all_files_with_ext_in_hot(Application_Links *app, String8Array array, Prj_Open_File_Flags flags); 70 | 71 | //////////////////////////////// 72 | // NOTE(allen): Project Files 73 | 74 | function void prj_stringize_project(Application_Links *app, Arena *arena, Variable_Handle project, String8List *out); 75 | 76 | function Prj_Setup_Status prj_file_is_setup(Application_Links *app, String8 script_path, String8 script_file); 77 | function b32 prj_generate_bat(Arena *scratch, String8 opts, String8 compiler, String8 script_path, String8 script_file, String8 code_file, String8 output_dir, String8 binary_file); 78 | function b32 prj_generate_sh(Arena *scratch, String8 opts, String8 compiler, String8 script_path, String8 script_file, String8 code_file, String8 output_dir, String8 binary_file); 79 | function b32 prj_generate_project(Arena *scratch, String8 script_path, String8 script_file, String8 output_dir, String8 binary_file); 80 | 81 | function void prj_setup_scripts(Application_Links *app, Prj_Setup_Script_Flags flags); 82 | 83 | //////////////////////////////// 84 | // NOTE(allen): Project Operations 85 | 86 | function void prj_exec_command(Application_Links *app, Variable_Handle cmd_var); 87 | function Variable_Handle prj_command_from_name(Application_Links *app, String8 cmd_name); 88 | function void prj_exec_command_name(Application_Links *app, String8 cmd_name); 89 | function void prj_exec_command_fkey_index(Application_Links *app, i32 fkey_index); 90 | 91 | function String8 prj_full_file_path_from_project(Arena *arena, Variable_Handle project); 92 | function String8 prj_path_from_project(Arena *arena, Variable_Handle project); 93 | function Variable_Handle prj_cmd_from_user(Application_Links *app, Variable_Handle prj_var, String8 query); 94 | 95 | #endif 96 | 97 | // BOTTOM 98 | -------------------------------------------------------------------------------- /custom/4coder_scope_commands.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_scope_commands.cpp - A set of commands and helpers relevant for scope level navigation and editing. 3 | */ 4 | 5 | // TOP 6 | 7 | function void 8 | select_next_scope_after_pos(Application_Links *app, View_ID view, Buffer_ID buffer, 9 | i64 pos){ 10 | Find_Nest_Flag flags = FindNest_Scope; 11 | Range_i64 range = {}; 12 | if (find_nest_side(app, buffer, pos + 1, flags, Scan_Forward, NestDelim_Open, 13 | &range) && 14 | find_nest_side(app, buffer, range.end, 15 | flags|FindNest_Balanced|FindNest_EndOfToken, Scan_Forward, 16 | NestDelim_Close, &range.end)){ 17 | select_scope(app, view, range); 18 | } 19 | } 20 | 21 | function b32 22 | range_is_scope_selection(Application_Links *app, Buffer_ID buffer, Range_i64 range){ 23 | return (buffer_get_char(app, buffer, range.min) == '{' && 24 | buffer_get_char(app, buffer, range.max - 1) == '}'); 25 | } 26 | 27 | CUSTOM_COMMAND_SIG(select_surrounding_scope) 28 | CUSTOM_DOC("Finds the scope enclosed by '{' '}' surrounding the cursor and puts the cursor and mark on the '{' and '}'.") 29 | { 30 | View_ID view = get_active_view(app, Access_ReadVisible); 31 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); 32 | i64 pos = view_get_cursor_pos(app, view); 33 | Range_i64 range = {}; 34 | if (find_surrounding_nest(app, buffer, pos, FindNest_Scope, &range)){ 35 | select_scope(app, view, range); 36 | } 37 | } 38 | 39 | CUSTOM_COMMAND_SIG(select_surrounding_scope_maximal) 40 | CUSTOM_DOC("Selects the top-most scope that surrounds the cursor.") 41 | { 42 | View_ID view = get_active_view(app, Access_ReadVisible); 43 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); 44 | i64 pos = view_get_cursor_pos(app, view); 45 | Range_i64 range = {}; 46 | if (find_surrounding_nest(app, buffer, pos, FindNest_Scope, &range)){ 47 | for (;;){ 48 | pos = range.min; 49 | if (!find_surrounding_nest(app, buffer, pos, FindNest_Scope, &range)){ 50 | break; 51 | } 52 | } 53 | select_scope(app, view, range); 54 | } 55 | } 56 | 57 | CUSTOM_COMMAND_SIG(select_next_scope_absolute) 58 | CUSTOM_DOC("Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.") 59 | { 60 | View_ID view = get_active_view(app, Access_ReadVisible); 61 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); 62 | i64 pos = view_get_cursor_pos(app, view); 63 | select_next_scope_after_pos(app, view, buffer, pos); 64 | } 65 | 66 | CUSTOM_COMMAND_SIG(select_next_scope_after_current) 67 | CUSTOM_DOC("If a scope is selected, find first scope that starts after the selected scope. Otherwise find the first scope that starts after the cursor.") 68 | { 69 | View_ID view = get_active_view(app, Access_ReadVisible); 70 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); 71 | i64 cursor_pos = view_get_cursor_pos(app, view); 72 | i64 mark_pos = view_get_mark_pos(app, view); 73 | Range_i64 range = Ii64(cursor_pos, mark_pos); 74 | if (range_is_scope_selection(app, buffer, range)){ 75 | select_next_scope_after_pos(app, view, buffer, range.max); 76 | } 77 | else{ 78 | select_next_scope_after_pos(app, view, buffer, cursor_pos); 79 | } 80 | } 81 | 82 | CUSTOM_COMMAND_SIG(select_prev_scope_absolute) 83 | CUSTOM_DOC("Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.") 84 | { 85 | View_ID view = get_active_view(app, Access_ReadVisible); 86 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); 87 | i64 pos = view_get_cursor_pos(app, view); 88 | Find_Nest_Flag flags = FindNest_Scope; 89 | Range_i64 range = {}; 90 | if (find_nest_side(app, buffer, pos - 1, 91 | flags, Scan_Backward, NestDelim_Open, &range) && 92 | find_nest_side(app, buffer, range.end, 93 | flags|FindNest_Balanced|FindNest_EndOfToken, Scan_Forward, 94 | NestDelim_Close, &range.end)){ 95 | select_scope(app, view, range); 96 | } 97 | } 98 | 99 | CUSTOM_COMMAND_SIG(select_prev_top_most_scope) 100 | CUSTOM_DOC("Finds the first scope that starts before the cursor, then finds the top most scope that contains that scope.") 101 | { 102 | select_prev_scope_absolute(app); 103 | select_surrounding_scope_maximal(app); 104 | } 105 | 106 | CUSTOM_COMMAND_SIG(place_in_scope) 107 | CUSTOM_DOC("Wraps the code contained in the range between cursor and mark with a new curly brace scope.") 108 | { 109 | place_begin_and_end_on_own_lines(app, "{", "}"); 110 | } 111 | 112 | CUSTOM_COMMAND_SIG(delete_current_scope) 113 | CUSTOM_DOC("Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.") 114 | { 115 | View_ID view = get_active_view(app, Access_ReadWriteVisible); 116 | Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); 117 | 118 | Range_i64 range = get_view_range(app, view); 119 | if (range_is_scope_selection(app, buffer, range)){ 120 | i32 top_len = 1; 121 | i32 bot_len = 1; 122 | if (buffer_get_char(app, buffer, range.min - 1) == '\n'){ 123 | top_len = 2; 124 | } 125 | if (buffer_get_char(app, buffer, range.max + 1) == '\n'){ 126 | bot_len = 2; 127 | } 128 | 129 | Batch_Edit batch_first = {}; 130 | Batch_Edit batch_last = {}; 131 | 132 | batch_first.edit.text = SCu8(); 133 | batch_first.edit.range = Ii64(range.min + 1 - top_len, range.min + 1); 134 | batch_first.next = &batch_last; 135 | batch_last.edit.text = SCu8(); 136 | batch_last.edit.range = Ii64((i32)(range.max - 1), (i32)(range.max - 1 + bot_len)); 137 | 138 | buffer_batch_edit(app, buffer, &batch_first); 139 | } 140 | } 141 | 142 | // BOTTOM 143 | -------------------------------------------------------------------------------- /custom/4coder_scope_commands.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_scope_commands.cpp - A set of commands and helpers relevant for scope level navigation and editing. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_SCOPE_COMMANDS_H) 8 | #define FCODER_SCOPE_COMMANDS_H 9 | 10 | #endif 11 | 12 | // BOTTOM 13 | -------------------------------------------------------------------------------- /custom/4coder_search.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_search.h - Types that are used in the search accross all buffers procedures. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_SEARCH_H) 8 | #define FCODER_SEARCH_H 9 | 10 | typedef u32 List_All_Locations_Flag; 11 | enum{ 12 | ListAllLocationsFlag_CaseSensitive = 1, 13 | ListAllLocationsFlag_MatchSubstring = 2, 14 | }; 15 | 16 | struct Word_Complete_Iterator{ 17 | Application_Links *app; 18 | Arena *arena; 19 | 20 | Temp_Memory arena_restore; 21 | Buffer_ID first_buffer; 22 | Buffer_ID current_buffer; 23 | b32 scan_all_buffers; 24 | String_Const_u8 needle; 25 | 26 | List_String_Const_u8 list; 27 | Node_String_Const_u8 *node; 28 | Table_Data_u64 already_used_table; 29 | }; 30 | 31 | struct Word_Complete_Menu{ 32 | Render_Caller_Function *prev_render_caller; 33 | Word_Complete_Iterator *it; 34 | String_Const_u8 options[8]; 35 | i32 count; 36 | }; 37 | 38 | #endif 39 | 40 | // BOTOTM 41 | -------------------------------------------------------------------------------- /custom/4coder_search_list.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 01.10.2019 5 | * 6 | * Search list helper. 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | //////////////////////////////// 13 | // NOTE(allen): Search List Builders 14 | 15 | function void 16 | def_search_list_add_path(Arena *arena, List_String_Const_u8 *list, String_Const_u8 path){ 17 | String_Const_u8 path_copy = push_string_copy(arena, path); 18 | string_list_push(arena, list, path_copy); 19 | } 20 | 21 | function void 22 | def_search_list_add_system_path(Arena *arena, List_String_Const_u8 *list, System_Path_Code path){ 23 | String_Const_u8 path_string = system_get_path(arena, path); 24 | string_list_push(arena, list, path_string); 25 | } 26 | 27 | //////////////////////////////// 28 | // NOTE(allen): Search List Functions 29 | 30 | function String_Const_u8 31 | def_search_get_full_path(Arena *arena, List_String_Const_u8 *list, String_Const_u8 relative){ 32 | String_Const_u8 result = {}; 33 | 34 | Temp_Memory temp = begin_temp(arena); 35 | 36 | u8 slash = '/'; 37 | 38 | for (Node_String_Const_u8 *node = list->first; 39 | node != 0; 40 | node = node->next){ 41 | String_Const_u8 full_name = {}; 42 | full_name.size = node->string.size + 1 + relative.size; 43 | full_name.str = push_array(arena, u8, full_name.size + 1); 44 | block_copy(full_name.str, node->string.str, node->string.size); 45 | full_name.str[node->string.size] = slash; 46 | block_copy(full_name.str + node->string.size + 1, relative.str, relative.size); 47 | full_name.str[full_name.size] = 0; 48 | 49 | File_Attributes attribs = system_quick_file_attributes(arena, full_name); 50 | if (attribs.last_write_time > 0){ 51 | result = full_name; 52 | break; 53 | } 54 | 55 | end_temp(temp); 56 | } 57 | 58 | return(result); 59 | } 60 | 61 | function FILE* 62 | def_search_fopen(Arena *arena, List_String_Const_u8 *list, char *file_name, char *opt){ 63 | Temp_Memory_Block block(arena); 64 | String_Const_u8 full_path = def_search_get_full_path(arena, list, SCu8(file_name)); 65 | FILE *file = 0; 66 | if (full_path.size > 0){ 67 | file = fopen((char*)full_path.str, opt); 68 | } 69 | return(file); 70 | } 71 | 72 | // BOTTOM 73 | -------------------------------------------------------------------------------- /custom/4coder_search_list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 01.10.2019 5 | * 6 | * Search list helper. 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | #if !defined(FRED_SEARCH_LIST_H) 13 | #define FRED_SEARCH_LIST_H 14 | 15 | //////////////////////////////// 16 | // NOTE(allen): Search List Builders 17 | 18 | function void def_search_add_path(Arena *arena, List_String_Const_u8 *list, String_Const_u8 path); 19 | function void def_search_list_add_system_path(Arena *arena, List_String_Const_u8 *list, System_Path_Code path); 20 | 21 | //////////////////////////////// 22 | // NOTE(allen): Search List Functions 23 | 24 | function String_Const_u8 def_search_get_full_path(Arena *arena, List_String_Const_u8 *list, String_Const_u8 file_name); 25 | function FILE *def_search_fopen(Arena *arena, List_String_Const_u8 *list, char *file_name, char *opt); 26 | 27 | #endif 28 | 29 | // BOTTOM 30 | -------------------------------------------------------------------------------- /custom/4coder_string_match.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 17.06.2019 5 | * 6 | * Routines for operating on the String_Match and String_Match_List types. 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | internal void 13 | string_match_list_push(Arena *arena, String_Match_List *list, 14 | Buffer_ID buffer, i32 string_id, String_Match_Flag flags, Range_i64 range){ 15 | String_Match *match = push_array(arena, String_Match, 1); 16 | sll_queue_push(list->first, list->last, match); 17 | list->count += 1; 18 | match->buffer = buffer; 19 | match->string_id = string_id; 20 | match->flags = flags; 21 | match->range = range; 22 | } 23 | 24 | internal void 25 | string_match_list_push(Arena *arena, String_Match_List *list, 26 | Buffer_ID buffer, i32 string_id, String_Match_Flag flags, i64 start, i64 length){ 27 | string_match_list_push(arena, list, buffer, string_id, flags, 28 | Ii64(start, start + length)); 29 | } 30 | 31 | internal String_Match_List 32 | string_match_list_join(String_Match_List *a, String_Match_List *b){ 33 | String_Match_List list = *a; 34 | block_zero_struct(a); 35 | if (list.last != 0){ 36 | list.last->next = b->first; 37 | if (b->last != 0){ 38 | list.last = b->last; 39 | } 40 | } 41 | else{ 42 | list.first = b->first; 43 | list.last = b->last; 44 | } 45 | list.count += b->count; 46 | block_zero_struct(b); 47 | return(list); 48 | } 49 | 50 | internal void 51 | string_match_list_filter_flags(String_Match_List *list, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags){ 52 | String_Match_List new_list = {}; 53 | if ((must_have_flags & must_not_have_flags) == 0){ 54 | for (String_Match *node = list->first, *next = 0; 55 | node != 0; 56 | node = next){ 57 | next = node->next; 58 | if ((node->flags & must_have_flags) == must_have_flags && (node->flags & must_not_have_flags) == 0){ 59 | sll_queue_push(new_list.first, new_list.last, node); 60 | new_list.count += 1; 61 | } 62 | } 63 | } 64 | *list = new_list; 65 | } 66 | 67 | internal void 68 | string_match_list_filter_remove_buffer(String_Match_List *list, Buffer_ID buffer){ 69 | String_Match_List new_list = {}; 70 | for (String_Match *node = list->first, *next = 0; 71 | node != 0; 72 | node = next){ 73 | next = node->next; 74 | if (node->buffer != buffer){ 75 | sll_queue_push(new_list.first, new_list.last, node); 76 | new_list.count += 1; 77 | } 78 | } 79 | *list = new_list; 80 | } 81 | 82 | internal void 83 | string_match_list_filter_remove_buffer_predicate(Application_Links *app, String_Match_List *list, Buffer_Predicate *predicate){ 84 | String_Match_List new_list = {}; 85 | for (String_Match *node = list->first, *next = 0; 86 | node != 0; 87 | node = next){ 88 | next = node->next; 89 | if (!predicate(app, node->buffer)){ 90 | sll_queue_push(new_list.first, new_list.last, node); 91 | new_list.count += 1; 92 | } 93 | } 94 | *list = new_list; 95 | } 96 | 97 | internal String_Match_List 98 | string_match_list_merge_nearest(String_Match_List *a, String_Match_List *b, Range_i64 range){ 99 | String_Match_List list = {}; 100 | String_Match *node_a = a->first; 101 | String_Match *node_b = b->first; 102 | for (String_Match *next_a = node_a, *next_b = node_b; 103 | node_a != 0 && node_b != 0; 104 | node_a = next_a, node_b = next_b){ 105 | i64 dist_a = range_distance(node_a->range, range); 106 | i64 dist_b = range_distance(node_b->range, range); 107 | if (dist_a <= dist_b){ 108 | next_a = next_a->next; 109 | sll_queue_push(list.first, list.last, node_a); 110 | list.count += 1; 111 | } 112 | else{ 113 | next_b = next_b->next; 114 | sll_queue_push(list.first, list.last, node_b); 115 | list.count += 1; 116 | } 117 | } 118 | Assert(node_a == 0 || node_b == 0); 119 | // TODO(allen): this is dumb O(n) work that could be O(1) 120 | String_Match *node = 0; 121 | if (node_a != 0){ 122 | node = node_a; 123 | } 124 | else if (node_b != 0){ 125 | node = node_b; 126 | } 127 | for (String_Match *next = 0; 128 | node != 0; 129 | node = next){ 130 | next = node->next; 131 | sll_queue_push(list.first, list.last, node); 132 | list.count += 1; 133 | } 134 | block_zero_struct(a); 135 | block_zero_struct(b); 136 | return(list); 137 | } 138 | 139 | internal String_Match_List 140 | string_match_list_merge_front_to_back(String_Match_List *a, String_Match_List *b){ 141 | return(string_match_list_merge_nearest(a, b, Ii64((i64)0))); 142 | } 143 | 144 | // BOTTOM 145 | -------------------------------------------------------------------------------- /custom/4coder_string_match.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Mr. 4th Dimention - Allen Webster 3 | * 4 | * 30.07.2019 5 | * 6 | * Types for operating on the String_Match and String_Match_List types. 7 | * 8 | */ 9 | 10 | // TOP 11 | 12 | #if !defined(FCODER_STRING_MATCH_H) 13 | #define FCODER_STRING_MATCH_H 14 | 15 | typedef b32 Buffer_Predicate(Application_Links *app, Buffer_ID buffer); 16 | 17 | #endif 18 | 19 | // BOTTOM -------------------------------------------------------------------------------- /custom/4coder_system_allocator.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder malloc base allocator 3 | */ 4 | 5 | // TOP 6 | 7 | internal void* 8 | base_reserve__system(void *user_data, u64 size, u64 *size_out, String_Const_u8 location){ 9 | u64 extra_size = 128; 10 | u64 increased_size = size + extra_size; 11 | size = round_up_u64(increased_size, KB(4)); 12 | *size_out = size - extra_size; 13 | void *ptr = system_memory_allocate(size, location); 14 | *(u64*)ptr = size; 15 | ptr = (u8*)ptr + extra_size; 16 | return(ptr); 17 | } 18 | 19 | internal void 20 | base_free__system(void *user_data, void *ptr){ 21 | u64 extra_size = 128; 22 | ptr = (u8*)ptr - extra_size; 23 | u64 size = *(u64*)ptr; 24 | system_memory_free(ptr, size); 25 | } 26 | 27 | internal Base_Allocator 28 | make_base_allocator_system(void){ 29 | return(make_base_allocator(base_reserve__system, 0, 0, base_free__system, 0, 0)); 30 | } 31 | 32 | global Base_Allocator base_allocator_system = {}; 33 | 34 | internal Base_Allocator* 35 | get_base_allocator_system(void){ 36 | if (base_allocator_system.reserve == 0){ 37 | base_allocator_system = make_base_allocator_system(); 38 | } 39 | return(&base_allocator_system); 40 | } 41 | 42 | internal Arena 43 | make_arena_system(u64 chunk_size, u64 align){ 44 | return(make_arena(get_base_allocator_system(), chunk_size, align)); 45 | } 46 | 47 | internal Arena 48 | make_arena_system(u64 chunk_size){ 49 | return(make_arena_system(chunk_size, 8)); 50 | } 51 | 52 | internal Arena 53 | make_arena_system(void){ 54 | return(make_arena_system(KB(16), 8)); 55 | } 56 | 57 | // BOTTOM 58 | -------------------------------------------------------------------------------- /custom/4coder_system_helpers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder_system_types.h - Implementation of universal (cross platform) helpers 3 | */ 4 | 5 | // TOP 6 | 7 | Mutex_Lock::Mutex_Lock(System_Mutex m){ 8 | system_mutex_acquire(m); 9 | this->mutex = m; 10 | } 11 | 12 | Mutex_Lock::~Mutex_Lock(){ 13 | system_mutex_release(this->mutex); 14 | } 15 | 16 | Mutex_Lock::operator System_Mutex(){ 17 | return(this->mutex); 18 | } 19 | 20 | // BOTTOM 21 | -------------------------------------------------------------------------------- /custom/4coder_system_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder_system_types.h - Types relating to the system api. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_SYSTEM_TYPES_H) 8 | #define FCODER_SYSTEM_TYPES_H 9 | 10 | typedef i32 Key_Mode; 11 | enum{ 12 | KeyMode_LanguageArranged, 13 | KeyMode_Physical, 14 | }; 15 | 16 | struct Plat_Handle{ 17 | u32 d[4]; 18 | }; 19 | typedef Plat_Handle System_Library; 20 | typedef Plat_Handle System_Thread; 21 | typedef Plat_Handle System_Mutex; 22 | typedef Plat_Handle System_Condition_Variable; 23 | typedef void Thread_Function(void *ptr); 24 | struct CLI_Handles{ 25 | Plat_Handle proc; 26 | Plat_Handle out_read; 27 | Plat_Handle out_write; 28 | Plat_Handle in_read; 29 | Plat_Handle in_write; 30 | u32 scratch_space[4]; 31 | i32 exit; 32 | }; 33 | 34 | typedef i32 System_Path_Code; 35 | enum{ 36 | SystemPath_CurrentDirectory, 37 | SystemPath_Binary, 38 | SystemPath_UserDirectory, 39 | }; 40 | 41 | struct Memory_Annotation_Node{ 42 | Memory_Annotation_Node *next; 43 | String_Const_u8 location; 44 | void *address; 45 | u64 size; 46 | }; 47 | 48 | struct Memory_Annotation{ 49 | Memory_Annotation_Node *first; 50 | Memory_Annotation_Node *last; 51 | i32 count; 52 | }; 53 | 54 | struct Mutex_Lock{ 55 | Mutex_Lock(System_Mutex mutex); 56 | ~Mutex_Lock(); 57 | operator System_Mutex(); 58 | System_Mutex mutex; 59 | }; 60 | 61 | #endif 62 | 63 | // BOTTOM 64 | -------------------------------------------------------------------------------- /custom/4coder_table.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder tables 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_TABLES_H) 8 | #define FCODER_TABLES_H 9 | 10 | struct Table_Lookup{ 11 | u64 hash; 12 | u32 index; 13 | b8 found_match; 14 | b8 found_empty_slot; 15 | b8 found_erased_slot; 16 | }; 17 | 18 | struct Table_u64_u64{ 19 | Base_Allocator *allocator; 20 | void *memory; 21 | u64 *keys; 22 | u64 *vals; 23 | u32 slot_count; 24 | u32 used_count; 25 | u32 dirty_count; 26 | }; 27 | 28 | struct Table_u32_u16{ 29 | Base_Allocator *allocator; 30 | void *memory; 31 | u32 *keys; 32 | u16 *vals; 33 | u32 slot_count; 34 | u32 used_count; 35 | u32 dirty_count; 36 | }; 37 | 38 | struct Table_Data_u64{ 39 | Base_Allocator *allocator; 40 | void *memory; 41 | u64 *hashes; 42 | String_Const_u8 *keys; 43 | u64 *vals; 44 | u32 slot_count; 45 | u32 used_count; 46 | u32 dirty_count; 47 | }; 48 | 49 | struct Table_u64_Data{ 50 | Base_Allocator *allocator; 51 | void *memory; 52 | u64 *keys; 53 | String_Const_u8 *vals; 54 | u32 slot_count; 55 | u32 used_count; 56 | u32 dirty_count; 57 | }; 58 | 59 | struct Table_Data_Data{ 60 | Base_Allocator *allocator; 61 | void *memory; 62 | u64 *hashes; 63 | String_Const_u8 *keys; 64 | String_Const_u8 *vals; 65 | u32 slot_count; 66 | u32 used_count; 67 | u32 dirty_count; 68 | }; 69 | 70 | #endif 71 | 72 | // BOTTOM 73 | -------------------------------------------------------------------------------- /custom/4coder_token.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 4coder token types 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_TOKEN_H) 8 | #define FCODER_TOKEN_H 9 | 10 | typedef i16 Token_Base_Kind; 11 | enum{ 12 | TokenBaseKind_EOF = 0, 13 | TokenBaseKind_Whitespace = 1, 14 | TokenBaseKind_LexError = 2, 15 | TokenBaseKind_Comment = 3, 16 | TokenBaseKind_Keyword = 4, 17 | TokenBaseKind_Preprocessor = 5, 18 | TokenBaseKind_Identifier = 6, 19 | TokenBaseKind_Operator = 7, 20 | TokenBaseKind_LiteralInteger = 8, 21 | TokenBaseKind_LiteralFloat = 9, 22 | TokenBaseKind_LiteralString = 10, 23 | TokenBaseKind_ScopeOpen = 11, 24 | TokenBaseKind_ScopeClose = 12, 25 | TokenBaseKind_ParentheticalOpen = 13, 26 | TokenBaseKind_ParentheticalClose = 14, 27 | TokenBaseKind_StatementClose = 15, 28 | 29 | TokenBaseKind_COUNT = 16, 30 | }; 31 | 32 | char *token_base_kind_names[] ={ 33 | "EOF", 34 | "Whitespace", 35 | "LexError", 36 | "Comment", 37 | "Keyword", 38 | "Preprocessor", 39 | "Identifier", 40 | "Operator", 41 | "LiteralInteger", 42 | "LiteralFloat", 43 | "LiteralString", 44 | "ScopeOpen", 45 | "ScopeClose", 46 | "ParentheticalOpen", 47 | "ParentheticalClose", 48 | "StatementClose", 49 | }; 50 | 51 | typedef u16 Token_Base_Flag; 52 | enum{ 53 | TokenBaseFlag_PreprocessorBody = 1, 54 | }; 55 | 56 | struct Token{ 57 | i64 pos; 58 | i64 size; 59 | Token_Base_Kind kind; 60 | Token_Base_Flag flags; 61 | i16 sub_kind; 62 | u16 sub_flags; 63 | }; 64 | 65 | struct Token_Pair{ 66 | Token a; 67 | Token b; 68 | }; 69 | 70 | struct Token_Array{ 71 | Token *tokens; 72 | i64 count; 73 | i64 max; 74 | }; 75 | 76 | struct Token_Block{ 77 | Token_Block *next; 78 | Token_Block *prev; 79 | Token *tokens; 80 | i64 count; 81 | i64 max; 82 | }; 83 | 84 | struct Token_List{ 85 | Token_Block *first; 86 | Token_Block *last; 87 | i64 node_count; 88 | i64 total_count; 89 | }; 90 | 91 | struct Token_Relex{ 92 | b32 successful_resync; 93 | i64 first_resync_index; 94 | }; 95 | 96 | struct Token_Iterator_Array{ 97 | u64 user_id; 98 | Token *ptr; 99 | Token *tokens; 100 | i64 count; 101 | }; 102 | 103 | struct Token_Iterator_List{ 104 | u64 user_id; 105 | i64 index; 106 | Token *ptr; 107 | Token_Block *block; 108 | Token_Block *first; 109 | Token_Block *last; 110 | i64 node_count; 111 | i64 total_count; 112 | }; 113 | 114 | typedef i32 Token_Iterator_Kind; 115 | enum{ 116 | TokenIterator_Array, 117 | TokenIterator_List, 118 | }; 119 | 120 | struct Token_Iterator{ 121 | Token_Iterator_Kind kind; 122 | union{ 123 | Token_Iterator_Array array; 124 | Token_Iterator_List list; 125 | }; 126 | }; 127 | 128 | #endif 129 | 130 | // BOTTOM 131 | -------------------------------------------------------------------------------- /custom/4coder_tutorial.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_tutorial.h - Guided graphical tutorial system. 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_TUTORIAL_H) 8 | #define FCODER_TUTORIAL_H 9 | 10 | typedef i32 Tutorial_Action; 11 | enum{ 12 | TutorialAction_None, 13 | TutorialAction_Minimize, 14 | TutorialAction_Maximize, 15 | TutorialAction_Prev, 16 | TutorialAction_Next, 17 | TutorialAction_Exit, 18 | TutorialAction_Restart, 19 | }; 20 | 21 | struct Tutorial_Slide{ 22 | Fancy_Block long_details; 23 | Fancy_Line short_details; 24 | }; 25 | 26 | typedef Tutorial_Slide Tutorial_Slide_Function(Application_Links *app, Arena *arena); 27 | 28 | struct Tutorial_State{ 29 | b32 in_tutorial; 30 | View_ID view; 31 | Face_ID face; 32 | b32 is_active; 33 | Tutorial_Action hover_action; 34 | Tutorial_Action depressed_action; 35 | 36 | i32 slide_index; 37 | Tutorial_Slide_Function **slide_func_ptrs; 38 | i32 slide_count; 39 | }; 40 | 41 | #endif 42 | 43 | // BOTTOM 44 | -------------------------------------------------------------------------------- /custom/4coder_variables.h: -------------------------------------------------------------------------------- 1 | /* 2 | 4coder_variables.h - Variables system 3 | */ 4 | 5 | // TOP 6 | 7 | #if !defined(FCODER_VARIABLES_H) 8 | #define FCODER_VARIABLES_H 9 | 10 | //////////////////////////////// 11 | // NOTE(allen): Types 12 | 13 | typedef u64 String_ID; 14 | 15 | struct Variable{ 16 | Variable *parent; 17 | Variable *next; 18 | String_ID key; 19 | String_ID string; 20 | Variable *first; 21 | Variable *last; 22 | }; 23 | 24 | struct Variable_Handle{ 25 | Variable *ptr; 26 | }; 27 | 28 | //////////////////////////////// 29 | // NOTE(allen): Functions 30 | 31 | // TODO(allen): fix names fuck you for picking these allen: 32 | // read_string 33 | // read_keyu 34 | // save_string 35 | 36 | function String_ID vars_save_string(String_Const_u8 string); 37 | #define vars_save_string_lit(S) vars_save_string(string_u8_litexpr(S)) 38 | function String8 vars_read_string(Arena *arena, String_ID id); 39 | 40 | function Variable_Handle vars_get_root(void); 41 | function Variable_Handle vars_get_nil(void); 42 | function b32 vars_is_nil(Variable_Handle var); 43 | function b32 vars_is_nil(Variable *var); 44 | function b32 vars_match(Variable_Handle a, Variable_Handle b); 45 | 46 | function Variable_Handle vars_first_child(Variable_Handle var); 47 | function Variable_Handle vars_next_sibling(Variable_Handle var); 48 | function Variable_Handle vars_parent(Variable_Handle var); 49 | 50 | #define Vars_Children(it, par) Variable_Handle it = vars_first_child(par); !vars_is_nil(it); it = vars_next_sibling(it) 51 | 52 | function Variable_Handle vars_read_key(Variable_Handle var, String_ID key); 53 | function String_ID vars_key_id_from_var(Variable_Handle var); 54 | function String8 vars_key_from_var(Arena *arena, Variable_Handle var); 55 | 56 | function String_ID vars_string_id_from_var(Variable_Handle var); 57 | function String8 vars_string_from_var(Arena *arena, Variable_Handle var); 58 | function b32 vars_b32_from_var(Variable_Handle var); 59 | function u64 vars_u64_from_var(Application_Links *app, Variable_Handle var); 60 | 61 | function void vars_set_string(Variable_Handle var, String_ID string); 62 | function void vars_erase(Variable_Handle var, String_ID key); 63 | function Variable_Handle vars_new_variable(Variable_Handle var, String_ID key); 64 | function Variable_Handle vars_new_variable(Variable_Handle var, String_ID key, String_ID string); 65 | function void vars_clear_keys(Variable_Handle var); 66 | 67 | function void vars_print_indented(Application_Links *app, Variable_Handle var, i32 indent); 68 | function void vars_print(Application_Links *app, Variable_Handle var); 69 | 70 | #endif //4CODER_VARIABLES_H 71 | 72 | // BOTTOM 73 | -------------------------------------------------------------------------------- /custom/4coder_version.h: -------------------------------------------------------------------------------- 1 | #define MAJOR 4 2 | #define MINOR 1 3 | #define PATCH 8 4 | 5 | // string 6 | #define VN__(a,b,c) #a "." #b "." #c 7 | #define VN_(a,b,c) VN__(a,b,c) 8 | #define VERSION_NUMBER VN_(MAJOR,MINOR,PATCH) 9 | #define VERSION_STRING "beta " VERSION_NUMBER 10 | 11 | #define ST__(s) #s 12 | #define ST_(s) ST__(s) 13 | #define MAJOR_STR ST_(MAJOR) 14 | #define MINOR_STR ST_(MINOR) 15 | #define PATCH_STR ST_(PATCH) 16 | 17 | #if defined(FRED_SUPER) 18 | #define VERSION_TYPE " super!" 19 | #else 20 | #define VERSION_TYPE 21 | #endif 22 | 23 | // string 24 | #define VN__(a,b,c) #a "." #b "." #c 25 | #define VN_(a,b,c) VN__(a,b,c) 26 | #define VERSION_NUMBER VN_(MAJOR,MINOR,PATCH) 27 | #define VERSION_STRING "beta " VERSION_NUMBER 28 | 29 | #define VERSION VERSION_STRING VERSION_TYPE 30 | 31 | #define WINDOW_NAME "4coder: " VERSION 32 | 33 | // long string 34 | #define L_VN__(a,b,c) L#a L"." L#b L"." L#c 35 | #define L_VN_(a,b,c) L_VN__(a,b,c) 36 | #define L_VERSION_NUMBER L_VN_(MAJOR,MINOR,PATCH) 37 | #define L_VERSION_STRING L"beta " L_VERSION_NUMBER 38 | 39 | #if defined(FRED_SUPER) 40 | #define L_VERSION_TYPE L" super!" 41 | #else 42 | #define L_VERSION_TYPE 43 | #endif 44 | 45 | #define L_VERSION L_VERSION_STRING L_VERSION_TYPE 46 | 47 | #define L_WINDOW_NAME L"4coder: " L_VERSION -------------------------------------------------------------------------------- /custom/bin/build_metadata.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set code_home=%~dp0 4 | if %code_home:~-1%==\ (set code_home=%code_home:~0,-1%) 5 | 6 | set src=%1 7 | if "%src%" == "" set src=4coder_default_bindings.cpp 8 | 9 | set opts=/W4 /wd4310 /wd4100 /wd4201 /wd4505 /wd4996 /wd4127 /wd4510 /wd4512 /wd4610 /wd4390 /WX 10 | set opts=%opts% /GR- /EHa- /nologo /FC 11 | 12 | pushd ..\build 13 | set preproc_file=4coder_command_metadata.i 14 | set meta_macros=/DMETA_PASS 15 | cl /I"%code_home%" %opts% %debug% %code_home%\%src% /P /Fi%preproc_file% %meta_macros% 16 | cl %opts% ..\code\4coder_metadata_generator.cpp /Zi /Femetadata_generator 17 | metadata_generator -R "%code_home%" "%cd%\\%preproc_file%" 18 | 19 | popd 20 | -------------------------------------------------------------------------------- /custom/bin/build_metadata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Store the real CWD 4 | REAL_PWD="$PWD" 5 | 6 | # Find the code home folder 7 | TARGET_FILE="$0" 8 | cd `dirname $TARGET_FILE` 9 | TARGET_FILE=`basename $TARGET_FILE` 10 | while [ -L "$TARGET_FILE" ] 11 | do 12 | TARGET_FILE=`readlink $TARGET_FILE` 13 | cd `dirname $TARGET_FILE` 14 | TARGET_FILE=`basename $TARGET_FILE` 15 | done 16 | PHYS_DIR=`pwd -P` 17 | SCRIPT_FILE=$PHYS_DIR/$TARGET_FILE 18 | code_home=$(dirname "$SCRIPT_FILE") 19 | 20 | # Find the most reasonable candidate build file 21 | SOURCE="$1" 22 | if [ -z "$SOURCE" ]; then 23 | SOURCE="$code_home/4coder_default_bindings.cpp" 24 | fi 25 | 26 | TARGET_FILE="$SOURCE" 27 | cd `dirname $TARGET_FILE` 28 | TARGET_FILE=`basename $TARGET_FILE` 29 | while [ -L "$TARGET_FILE" ] 30 | do 31 | TARGET_FILE=`readlink $TARGET_FILE` 32 | cd `dirname $TARGET_FILE` 33 | TARGET_FILE=`basename $TARGET_FILE` 34 | done 35 | PHYS_DIR=`pwd -P` 36 | SOURCE=$PHYS_DIR/$TARGET_FILE 37 | 38 | opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -Wno-writable-strings -g" 39 | 40 | cd ../build > /dev/null 41 | preproc_file=4coder_command_metadata.i 42 | meta_macros="-DMETA_PASS" 43 | g++ -I"$code_home" $meta_macros $opts -std=gnu++0x "$SOURCE" -E -o $preproc_file 44 | g++ -I"$code_home" $opts -std=gnu++0x ../code/4coder_metadata_generator.cpp -o metadata_generator 45 | ./metadata_generator -R "$code_home" "$PWD/$preproc_file" 46 | cd $code_home > /dev/null 47 | -------------------------------------------------------------------------------- /custom/bin/build_one_time.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM usage: