diff --git a/4ed.cpp b/4ed.cpp index c0db72c4..17f37875 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -252,7 +252,7 @@ App_Init_Sig(app_init){ working_set_init(models, &models->working_set); Mutex_Lock file_order_lock(models->working_set.mutex); - // NOTE(allen): + // NOTE(allen): global_history_init(&models->global_history); text_layout_init(tctx, &models->text_layouts); @@ -748,6 +748,10 @@ App_Step_Sig(app_step){ } } + if (models->whole_screen_render_caller != 0){ + models->whole_screen_render_caller(&app, frame); + } + models->in_render_mode = false; end_render_section(target); } diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 10539c10..aa5efd9f 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -2234,6 +2234,10 @@ set_custom_hook(Application_Links *app, Hook_ID hook_id, Void_Func *func_ptr){ { models->render_caller = (Render_Caller_Function*)func_ptr; }break; + case HookID_WholeScreenRenderCaller: + { + models->whole_screen_render_caller = (Whole_Screen_Render_Caller_Function*)func_ptr; + }break; case HookID_BufferNameResolver: { models->buffer_name_resolver = (Buffer_Name_Resolver_Function*)func_ptr; diff --git a/4ed_app_models.h b/4ed_app_models.h index 71ea3254..daf24b34 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -62,6 +62,7 @@ struct Models{ Tick_Function *tick; Render_Caller_Function *render_caller; + Whole_Screen_Render_Caller_Function *whole_screen_render_caller; Delta_Rule_Function *delta_rule; u64 delta_rule_memory_size; diff --git a/4ed_generate_keycodes.cpp b/4ed_generate_keycodes.cpp index 622da54b..b03a7583 100644 --- a/4ed_generate_keycodes.cpp +++ b/4ed_generate_keycodes.cpp @@ -123,9 +123,20 @@ make_key_list(Arena *arena){ add_code(arena, &list, string_u8_litexpr("Control")); add_code(arena, &list, string_u8_litexpr("Alt")); add_code(arena, &list, string_u8_litexpr("Command")); - for (u32 i = 1; i <= 16; i += 1){ + for (u32 i = 1; i <= 24; i += 1){ add_code(arena, &list, push_u8_stringf(arena, "F%d", i)); } + for (u32 i = '0'; i <= '9'; i += 1){ + add_code(arena, &list, push_u8_stringf(arena, "NumPad%c", i)); + } + add_code(arena, &list, string_u8_litexpr("NumPadStar")); + add_code(arena, &list, string_u8_litexpr("NumPadPlus")); + add_code(arena, &list, string_u8_litexpr("NumPadMinus")); + add_code(arena, &list, string_u8_litexpr("NumPadDot")); + add_code(arena, &list, string_u8_litexpr("NumPadSlash")); + for (i32 i = 0; i < 30; i += 1){ + add_code(arena, &list, push_u8_stringf(arena, "Ex%d", i)); + } return(list); } diff --git a/bin/4ed_build.cpp b/bin/4ed_build.cpp index 7e054818..180dc493 100644 --- a/bin/4ed_build.cpp +++ b/bin/4ed_build.cpp @@ -25,6 +25,19 @@ // OS and compiler index // +typedef u32 Tier_Code; +enum{ + Tier_Demo, + Tier_Super, + Tier_COUNT, +}; + +char *tier_names[] = { + "demo", + "super", +}; + +typedef u32 Platform_Code; enum{ Platform_Windows, Platform_Linux, @@ -40,6 +53,7 @@ char *platform_names[] = { "mac", }; +typedef u32 Compiler_Code; enum{ Compiler_CL, Compiler_GCC, @@ -55,6 +69,21 @@ char *compiler_names[] = { "clang", }; +typedef u32 Arch_Code; +enum{ + Arch_X64, + Arch_X86, + + // + Arch_COUNT, + Arch_None = Arch_COUNT, +}; + +char *arch_names[] = { + "x64", + "x86", +}; + #if OS_WINDOWS # define This_OS Platform_Windows #elif OS_LINUX @@ -115,22 +144,6 @@ char **platform_includes[Platform_COUNT][Compiler_COUNT] = { char *default_custom_target = "../code/custom/4coder_default_bindings.cpp"; -// NOTE(allen): Architectures - -enum{ - Arch_X64, - Arch_X86, - - // - Arch_COUNT, - Arch_None = Arch_COUNT, -}; - -char *arch_names[] = { - "x64", - "x86", -}; - // NOTE(allen): Build flags enum{ @@ -294,7 +307,8 @@ build(Arena *arena, u32 flags, u32 arch, char *code_path, char **code_files, cha "-Wno-write-strings " \ "-D_GNU_SOURCE -fPIC " \ "-fno-threadsafe-statics -pthread " \ -"-Wno-unused-result" +"-Wno-unused-result " \ +"-std=c++11" #define GCC_LIBS_COMMON \ "-lX11 -lpthread -lm -lrt " \ @@ -491,24 +505,20 @@ build_and_run(Arena *arena, char *cdir, char *filename, char *name, u32 flags){ { char *file = fm_str(arena, filename); - BEGIN_TIME_SECTION(); build(arena, flags, Arch_X64, cdir, file, dir, name, get_defines_from_flags(arena, flags), 0, includes); - END_TIME_SECTION(fm_str(arena, "build ", name)); } if (prev_error == 0){ char *cmd = fm_str(arena, dir, "/", name); - BEGIN_TIME_SECTION(); fm_execute_in_dir(cdir, cmd, 0); - END_TIME_SECTION(fm_str(arena, "run ", name)); } } internal void buildsuper(Arena *arena, char *cdir, char *file, u32 arch){ - printf("BUILDSUPER: cdir: %s; file: %s; arch: %u\n", cdir, file, arch); + printf("BUILDSUPER:\n cdir = %s;\n file = %s;\n arch = %s;\n", cdir, file, arch_names[arch]); + fflush(stdout); - BEGIN_TIME_SECTION(); Temp_Dir temp = fm_pushdir(fm_str(arena, BUILD_DIR)); char *build_script_postfix = ""; @@ -535,7 +545,6 @@ buildsuper(Arena *arena, char *cdir, char *file, u32 arch){ systemf("%s", build_command); fm_popdir(temp); - END_TIME_SECTION("build custom"); fflush(stdout); } @@ -549,26 +558,20 @@ build_main(Arena *arena, char *cdir, b32 update_local_theme, u32 flags, u32 arch char **build_includes = includes; - BEGIN_TIME_SECTION(); build(arena, OPTS | SHARED_CODE | flags, arch, cdir, file, dir, "4ed_app" DLL, get_defines_from_flags(arena, flags), exports, build_includes); - END_TIME_SECTION("build 4ed_app"); } { - BEGIN_TIME_SECTION(); char **inc = (char**)fm_list(arena, includes, platform_includes[This_OS][This_Compiler]); build(arena, OPTS | LIBS | ICON | flags, arch, cdir, platform_layers[This_OS], dir, "4ed", get_defines_from_flags(arena, flags), 0, inc); - END_TIME_SECTION("build 4ed"); } if (update_local_theme){ - BEGIN_TIME_SECTION(); char *themes_folder = fm_str(arena, "../build/themes"); char *source_themes_folder = fm_str(arena, "ship_files/themes"); fm_clear_folder(themes_folder); fm_make_folder_if_missing(arena, themes_folder); fm_copy_all(source_themes_folder, themes_folder); - END_TIME_SECTION("move files"); } fflush(stdout); @@ -592,12 +595,6 @@ get_4coder_dist_name(Arena *arena, u32 platform, char *tier, u32 arch){ return(name); } -enum{ - Tier_Demo, - Tier_Super, - Tier_COUNT, -}; - function void package_for_arch(Arena *arena, u32 arch, char *cdir, char *build_dir, char *pack_dir, i32 tier, char *tier_name, char *current_dist_tier, u32 flags, char** dist_files, i32 dist_file_count){ char *arch_name = arch_names[arch]; @@ -605,10 +602,10 @@ package_for_arch(Arena *arena, u32 arch, char *cdir, char *build_dir, char *pack char *dir = fm_str(arena, parent_dir, SLASH "4coder"); char *zip_dir = fm_str(arena, pack_dir, SLASH, tier_name, "_", arch_name); - printf("\nbuild: %s_%s\n", tier_name, arch_name); - printf("parent_dir: %s\n", parent_dir); - printf("dir: %s\n", dir); - printf("zip_dir: %s\n", zip_dir); + printf("\nBUILD: %s_%s\n", tier_name, arch_name); + printf(" parent_dir = %s;\n", parent_dir); + printf(" dir = %s;\n", dir); + printf(" zip_dir = %s;\n", zip_dir); fflush(stdout); buildsuper(arena, cdir, fm_str(arena, default_custom_target), arch); @@ -633,10 +630,7 @@ package_for_arch(Arena *arena, u32 arch, char *cdir, char *build_dir, char *pack if (tier == Tier_Super){ char *custom_src_dir = fm_str(arena, cdir, SLASH, "custom"); char *custom_dst_dir = fm_str(arena, dir, SLASH, "custom"); - // HACK(yuval): make_folder_if_missing seems to cause a second custom folder to be created inside the custom folder on macOS. - //if (This_OS != Platform_Mac){ fm_make_folder_if_missing(arena, custom_dst_dir); - //} fm_copy_all(custom_src_dir, custom_dst_dir); } @@ -646,8 +640,20 @@ package_for_arch(Arena *arena, u32 arch, char *cdir, char *build_dir, char *pack fm_zip(parent_dir, "4coder", zip_name); } +internal u32 +tier_flags(Tier_Code code){ + u32 result = 0; + switch (code){ + case Tier_Super: + { + result = SUPER; + }break; + } + return(result); +} + internal void -package(Arena *arena, char *cdir){ +package(Arena *arena, char *cdir, Tier_Code tier, Arch_Code arch){ // NOTE(allen): meta char *build_dir = fm_str(arena, BUILD_DIR); char *pack_dir = fm_str(arena, PACK_DIR); @@ -661,44 +667,24 @@ package(Arena *arena, char *cdir){ printf("dist files: %s, %s, %s\n", dist_files[0], dist_files[1], dist_files[2]); fflush(stdout); - char *tier_names[] = { "demo", "super", }; u32 base_flags = SHIP | DEBUG_INFO | OPTIMIZATION; - u32 tier_flags[] = { 0, SUPER, }; fm_make_folder_if_missing(arena, pack_dir); - for (u32 i = 0; i < Tier_COUNT; i += 1){ - char *tier_name = tier_names[i]; - u32 flags = base_flags | tier_flags[i]; - - Temp_Memory temp = begin_temp(arena); - char *current_dist_tier = fm_str(arena, ".." SLASH "current_dist_", tier_name); - - u32 arch_count = Arch_COUNT; - u32 arch_array[2] = { - Arch_X64, - Arch_X86, - }; - if (This_OS == Platform_Mac){ - arch_count = 1; - } - for (u32 arch_ind = 0; arch_ind < arch_count; arch_ind += 1){ - u32 arch = arch_array[arch_ind]; - package_for_arch(arena, arch, cdir, build_dir, pack_dir, i, tier_name, current_dist_tier, flags, dist_files, ArrayCount(dist_files)); - } - - end_temp(temp); - } + char *tier_name = tier_names[tier]; + u32 flags = base_flags | tier_flags(tier); + Temp_Memory temp = begin_temp(arena); + char *current_dist_tier = fm_str(arena, ".." SLASH "current_dist_", tier_name); + package_for_arch(arena, arch, cdir, build_dir, pack_dir, tier, tier_name, current_dist_tier, flags, dist_files, ArrayCount(dist_files)); + end_temp(temp); } int main(int argc, char **argv){ - Arena arena = fm_init_system(); + Arena arena = fm_init_system(DetailLevel_FileOperations); char cdir[256]; - BEGIN_TIME_SECTION(); i32 n = fm_get_current_directory(cdir, sizeof(cdir)); Assert(n < sizeof(cdir)); - END_TIME_SECTION("current directory"); u32 flags = SUPER; u32 arch = Arch_X64; @@ -715,8 +701,17 @@ int main(int argc, char **argv){ #if defined(DEV_BUILD) || defined(OPT_BUILD) || defined(DEV_BUILD_X86) || defined(OPT_BUILD_X86) standard_build(&arena, cdir, flags, arch); -#elif defined(PACKAGE) - package(&arena, cdir); +#elif defined(PACKAGE_DEMO_X64) + package(&arena, cdir, Tier_Demo, Arch_X64); + +#elif defined(PACKAGE_DEMO_X86) + package(&arena, cdir, Tier_Demo, Arch_X86); + +#elif defined(PACKAGE_SUPER_X64) + package(&arena, cdir, Tier_Super, Arch_X64); + +#elif defined(PACKAGE_SUPER_X86) + package(&arena, cdir, Tier_Super, Arch_X86); #else # error No build type specified. diff --git a/bin/build.sh b/bin/build-linux.sh similarity index 70% rename from bin/build.sh rename to bin/build-linux.sh index 0d01ab2d..bce5f56f 100755 --- a/bin/build.sh +++ b/bin/build-linux.sh @@ -3,7 +3,8 @@ # If any command errors, stop the script set -e -# Set up directories (mirrors build.bat) +# Set up directories + ME="$(readlink -f "$0")" LOCATION="$(dirname "$ME")" SRC_ROOT="$(dirname "$LOCATION")" @@ -22,15 +23,7 @@ if [ -z "$BUILD_MODE" ]; then BUILD_MODE="-DDEV_BUILD" fi -# Get the OS specific flags -chmod +rx "$BIN_ROOT/detect_os.sh" -os=$("$BIN_ROOT/detect_os.sh") - -if [[ "$os" == "linux" ]]; then WARNINGS="-Wno-write-strings -Wno-comment" -elif [[ "$os" == "mac" ]]; then -WARNINGS="-Wno-write-strings -Wno-comment -Wno-logical-op-parentheses -Wno-null-dereference -Wno-switch" -fi FLAGS="-D_GNU_SOURCE -fPIC -fpermissive $BUILD_MODE" INCLUDES="-I$SRC_ROOT -I$CUSTOM_ROOT" diff --git a/bin/build-mac.sh b/bin/build-mac.sh index 83062702..adae8015 100755 --- a/bin/build-mac.sh +++ b/bin/build-mac.sh @@ -3,7 +3,7 @@ # If any command errors, stop the script set -e -# Set up directories (mirrors build.bat) +# Set up directories # NOTE(yuval): Replaced readlink with realpath which works for both macOS and Linux ME="$(realpath "$0")" LOCATION="$(dirname "$ME")" @@ -23,15 +23,7 @@ if [ -z "$BUILD_MODE" ]; then BUILD_MODE="-DDEV_BUILD" fi -# Get the OS specific flags -chmod +rx "$BIN_ROOT/detect_os.sh" -os=$("$BIN_ROOT/detect_os.sh") - -if [[ "$os" == "linux" ]]; then -WARNINGS="-Wno-write-strings -Wno-comment" -elif [[ "$os" == "mac" ]]; then WARNINGS="-Wno-write-strings -Wno-comment -Wno-null-dereference -Wno-logical-op-parentheses -Wno-switch" -fi FLAGS="-D_GNU_SOURCE -fPIC -fpermissive $BUILD_MODE" INCLUDES="-I$SRC_ROOT -I$CUSTOM_ROOT" diff --git a/bin/build-x86-linux.sh b/bin/build-x86-linux.sh new file mode 100755 index 00000000..13a97843 --- /dev/null +++ b/bin/build-x86-linux.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +ME="$(readlink -f "$0")" +LOCATION="$(dirname "$ME")" +$LOCATION/build-linux.sh -DDEV_BUILD_X86 + + diff --git a/bin/build-x86.bat b/bin/build-x86.bat new file mode 100644 index 00000000..1c761add --- /dev/null +++ b/bin/build-x86.bat @@ -0,0 +1,3 @@ +@echo off + +build.bat /DDEV_BUILD_X86 diff --git a/bin/build_x86-mac.sh b/bin/build_x86-mac.sh deleted file mode 100644 index 3642eddf..00000000 --- a/bin/build_x86-mac.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -./build.sh -DDEV_BUILD_X86 - - diff --git a/bin/build_x86.sh b/bin/build_x86.sh deleted file mode 100644 index 3642eddf..00000000 --- a/bin/build_x86.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -./build.sh -DDEV_BUILD_X86 - - diff --git a/bin/itchio_push_all.sh b/bin/itchio_push_all.sh old mode 100644 new mode 100755 diff --git a/bin/itchio_push_linux-x86.sh b/bin/itchio_push_linux-x86.sh new file mode 100755 index 00000000..d98b1b19 --- /dev/null +++ b/bin/itchio_push_linux-x86.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +if [ "$#" -lt "3" ] +then +echo need 3 parameters +exit +else + +fake=$1 +maj=$2 +min=$3 + +vr=$fake.$maj.$min +fv=$fake-$maj-$min + +flags="--fix-permissions --userversion=$vr" +dir=../current_dist_all_os + +butler push $flags $dir/demo_x86/4coder-$fv-demo-linux-x86.zip 4coder/4coder:linux-x86-demo +butler push $flags $dir/super_x86/4coder-$fv-super-linux-x86.zip 4coder/4coder:linux-x86 + +fi diff --git a/bin/itchio_push_linux.sh b/bin/itchio_push_linux.sh new file mode 100755 index 00000000..8a829168 --- /dev/null +++ b/bin/itchio_push_linux.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +if [ "$#" -lt "3" ] +then +echo need 3 parameters +exit +else + +fake=$1 +maj=$2 +min=$3 + +vr=$fake.$maj.$min +fv=$fake-$maj-$min + +flags="--fix-permissions --userversion=$vr" +dir=../current_dist_all_os + +butler push $flags $dir/demo_x64/4coder-$fv-demo-linux-x64.zip 4coder/4coder:linux-x64-demo +butler push $flags $dir/super_x64/4coder-$fv-super-linux-x64.zip 4coder/4coder:linux-x64 + +fi diff --git a/bin/itchio_push_mac.sh b/bin/itchio_push_mac.sh index cf5a7d5b..ba8a0f03 100755 --- a/bin/itchio_push_mac.sh +++ b/bin/itchio_push_mac.sh @@ -17,6 +17,6 @@ flags="--fix-permissions --userversion=$vr" dir=../distributions butler push $flags $dir/demo_x64/4coder-$fv-demo-mac-x64.zip 4coder/4coder:mac-x64-demo -butler push $flags $dir/super_x64/4coder-$fv-super-mac-x64.zip 4coder/4coder:mac-x64 +butler push $flags $dir/super_x64/4coder-$fv-super-mac-x64.zip 4coder/4coder:mac-x64 fi diff --git a/bin/package-linux.sh b/bin/package-linux.sh new file mode 100755 index 00000000..7c627903 --- /dev/null +++ b/bin/package-linux.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +chmod +x bin/build-linux.sh +bin/build-linux.sh "-DPACKAGE_DEMO_X64" +bin/build-linux.sh "-DPACKAGE_SUPER_X64" diff --git a/bin/package-mac.sh b/bin/package-mac.sh index 92eb8a24..eacab020 100755 --- a/bin/package-mac.sh +++ b/bin/package-mac.sh @@ -1,4 +1,5 @@ #!/bin/bash -chmod 777 bin/build-mac.sh -bin/build-mac.sh "-DPACKAGE" +chmod +x bin/build-mac.sh +bin/build-mac.sh "-DPACKAGE_DEMO_X64" +bin/build-mac.sh "-DPACKAGE_SUPER_X64" diff --git a/bin/package-x86-linux.sh b/bin/package-x86-linux.sh new file mode 100755 index 00000000..96bddb19 --- /dev/null +++ b/bin/package-x86-linux.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +chmod +x bin/build-linux.sh +bin/build-linux.sh "-DPACKAGE_DEMO_X86" +bin/build-linux.sh "-DPACKAGE_SUPER_X86" diff --git a/bin/package.bat b/bin/package.bat index e9f0923d..236104d1 100644 --- a/bin/package.bat +++ b/bin/package.bat @@ -1,3 +1,6 @@ @echo off -bin\build.bat /DPACKAGE +bin\build.bat /DPACKAGE_DEMO_X64 +bin\build.bat /DPACKAGE_DEMO_X86 +bin\build.bat /DPACKAGE_SUPER_X64 +bin\build.bat /DPACKAGE_SUPER_X86 diff --git a/bin/package.sh b/bin/package.sh deleted file mode 100644 index cd5f161f..00000000 --- a/bin/package.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -chmod 777 build.sh -./build.sh "-DPACKAGE" diff --git a/custom/4coder_base_commands.cpp b/custom/4coder_base_commands.cpp index 2ac0deb8..7d7dc5f4 100644 --- a/custom/4coder_base_commands.cpp +++ b/custom/4coder_base_commands.cpp @@ -112,17 +112,6 @@ CUSTOM_DOC("Deletes the character to the left of the cursor.") } } -CUSTOM_COMMAND_SIG(test_double_backspace) -CUSTOM_DOC("Made for testing purposes (I should have deleted this if you are reading it let me know)") -{ - View_ID view = get_active_view(app, Access_ReadWriteVisible); - Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); - History_Group group = history_group_begin(app, buffer); - backspace_char(app); - backspace_char(app); - history_group_end(group); -} - CUSTOM_COMMAND_SIG(set_mark) CUSTOM_DOC("Sets the mark to the current position of the cursor.") { @@ -909,8 +898,7 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos, } isearch__update_highlight(app, view, Ii64_size(pos, match_size)); - in = get_next_input(app, EventPropertyGroup_AnyKeyboardEvent, - EventProperty_Escape|EventProperty_ViewActivation); + in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape); if (in.abort){ break; } @@ -953,9 +941,6 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos, } } - // TODO(allen): how to detect if the input corresponds to - // a search or rsearch command, a scroll wheel command? - b32 do_scan_action = false; b32 do_scroll_wheel = false; Scan_Direction change_scan = scan; @@ -965,17 +950,41 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos, change_scan = Scan_Forward; do_scan_action = true; } - if (match_key_code(&in, KeyCode_PageUp) || - match_key_code(&in, KeyCode_Up)){ + else if (match_key_code(&in, KeyCode_PageUp) || + match_key_code(&in, KeyCode_Up)){ change_scan = Scan_Backward; do_scan_action = true; } - -#if 0 - if (in.command == mouse_wheel_scroll){ - do_scroll_wheel = true; + else{ + // NOTE(allen): is the user trying to execute another command? + View_Context ctx = view_current_context(app, view); + Mapping *mapping = ctx.mapping; + Command_Map *map = mapping_get_map(mapping, ctx.map_id); + Command_Binding binding = map_get_binding_recursive(mapping, map, &in.event); + if (binding.custom != 0){ + if (binding.custom == search){ + change_scan = Scan_Forward; + do_scan_action = true; + } + else if (binding.custom == reverse_search){ + change_scan = Scan_Backward; + do_scan_action = true; + } + else{ + Command_Metadata *metadata = get_command_metadata(binding.custom); + if (metadata != 0){ + if (metadata->is_ui){ + view_enqueue_command_function(app, view, binding.custom); + break; + } + } + binding.custom(app); + } + } + else{ + leave_current_input_unhandled(app); + } } -#endif } if (string_change){ @@ -1028,9 +1037,6 @@ isearch(Application_Links *app, Scan_Direction start_scan, i64 first_pos, else if (do_scroll_wheel){ mouse_wheel_scroll(app); } - else{ - leave_current_input_unhandled(app); - } } view_disable_highlight_range(app, view); diff --git a/custom/4coder_base_types.h b/custom/4coder_base_types.h index 78ee4ea7..f8e550c8 100644 --- a/custom/4coder_base_types.h +++ b/custom/4coder_base_types.h @@ -135,17 +135,17 @@ //////////////////////////////// #if COMPILER_CL -#if _MSC_VER <= 1800 -# define snprintf _snprintf -#endif +# if _MSC_VER <= 1800 +# define snprintf _snprintf +# endif -#if (_MSC_VER <= 1500) -#define JUST_GUESS_INTS -#endif +# if (_MSC_VER <= 1500) +# define JUST_GUESS_INTS +# endif #endif // NOTE(yuval): Changed this so that CALL_CONVENTION will be defined for all platforms -#if ARCH_32BIT +#if ARCH_32BIT && OS_WINDOWS # define CALL_CONVENTION __stdcall #else # define CALL_CONVENTION @@ -527,8 +527,8 @@ union SNode{ #define zdll_remove_back_NP_(f,l,next,prev) ((f==l)?(f=l=0):(l->prev->next=0,l=l->prev)) #define zdll_remove_NP_(f,l,n,next,prev) \ ((l==n)?(zdll_remove_back_NP_(f,l,next,prev)) \ - :(f==n)?(zdll_remove_back_NP_(l,f,prev,next)) \ - : (dll_remove_NP_(n,n,next,prev))) +:(f==n)?(zdll_remove_back_NP_(l,f,prev,next)) \ +: (dll_remove_NP_(n,n,next,prev))) #define zdll_push_back(f,l,n) zdll_push_back_NP_((f),(l),(n),next,prev) #define zdll_push_front(f,l,n) zdll_push_back_NP_((l),(f),(n),prev,next) diff --git a/custom/4coder_code_index_listers.cpp b/custom/4coder_code_index_listers.cpp index fdc24c24..53f0ed29 100644 --- a/custom/4coder_code_index_listers.cpp +++ b/custom/4coder_code_index_listers.cpp @@ -15,9 +15,9 @@ CUSTOM_DOC("List all definitions in the code index and jump to one chosen by the char *query = "Definition:"; Scratch_Block scratch(app); - Lister *lister = begin_lister(app, scratch); + Lister_Block lister(app, scratch); lister_set_query(lister, query); - lister->handlers = lister_get_default_handlers(); + lister_set_default_handlers(lister); code_index_lock(); for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); diff --git a/custom/4coder_combined_write_commands.cpp b/custom/4coder_combined_write_commands.cpp index a9a03747..9652d2c4 100644 --- a/custom/4coder_combined_write_commands.cpp +++ b/custom/4coder_combined_write_commands.cpp @@ -211,9 +211,9 @@ function Snippet* get_snippet_from_user(Application_Links *app, Snippet *snippets, i32 snippet_count, String_Const_u8 query){ Scratch_Block scratch(app, Scratch_Share); - Lister *lister = begin_lister(app, scratch); + Lister_Block lister(app, scratch); lister_set_query(lister, query); - lister->handlers = lister_get_default_handlers(); + lister_set_default_handlers(lister); Snippet *snippet = snippets; for (i32 i = 0; i < snippet_count; i += 1, snippet += 1){ diff --git a/custom/4coder_config.cpp b/custom/4coder_config.cpp index aef8a748..d2134b86 100644 --- a/custom/4coder_config.cpp +++ b/custom/4coder_config.cpp @@ -1367,7 +1367,7 @@ config_parse__file_name(Application_Links *app, Arena *arena, char *file_name, C if (data.data != 0){ parsed = config_parse__data(app, arena, SCu8(file_name), SCu8(data), config); - success = true; + success = true; } } if (!success){ diff --git a/custom/4coder_default_framework.cpp b/custom/4coder_default_framework.cpp index dc5daa24..cd494599 100644 --- a/custom/4coder_default_framework.cpp +++ b/custom/4coder_default_framework.cpp @@ -103,15 +103,15 @@ open_footer_panel(Application_Links *app, View_ID view){ function void close_build_footer_panel(Application_Links *app){ - if (build_footer_panel_view_id != 0){ + if (view_exists(app, build_footer_panel_view_id)){ view_close(app, build_footer_panel_view_id); - build_footer_panel_view_id = 0; } + build_footer_panel_view_id = 0; } function View_ID open_build_footer_panel(Application_Links *app){ - if (build_footer_panel_view_id == 0){ + if (!view_exists(app, build_footer_panel_view_id)){ View_ID view = get_active_view(app, Access_Always); build_footer_panel_view_id = open_footer_panel(app, view); view_set_active(app, view); @@ -497,18 +497,18 @@ function void default_4coder_initialize(Application_Links *app, String_Const_u8_Array file_names, i32 override_font_size, b32 override_hinting){ #define M \ - "Welcome to " VERSION "\n" \ - "If you're new to 4coder there is a built in tutorial\n" \ - "Use the key combination [ X Alt ] (on mac [ X Control ])\n" \ - "Type in 'hms_demo_tutorial' and press enter\n" \ - "\n" \ - "Direct bug reports and feature requests to https://github.com/4coder-editor/4coder/issues\n" \ - "\n" \ - "Other questions and discussion can be directed to editor@4coder.net or 4coder.handmade.network\n" \ - "\n" \ - "The change log can be found in CHANGES.txt\n" \ - "\n" - print_message(app, string_u8_litexpr(M)); +"Welcome to " VERSION "\n" \ +"If you're new to 4coder there is a built in tutorial\n" \ +"Use the key combination [ X Alt ] (on mac [ X Control ])\n" \ +"Type in 'hms_demo_tutorial' and press enter\n" \ +"\n" \ +"Direct bug reports and feature requests to https://github.com/4coder-editor/4coder/issues\n" \ +"\n" \ +"Other questions and discussion can be directed to editor@4coder.net or 4coder.handmade.network\n" \ +"\n" \ +"The change log can be found in CHANGES.txt\n" \ +"\n" + print_message(app, string_u8_litexpr(M)); #undef M load_config_and_apply(app, global_config_arena, &global_config, override_font_size, override_hinting); diff --git a/custom/4coder_default_framework_variables.cpp b/custom/4coder_default_framework_variables.cpp index 3ba58805..c26dcbf7 100644 --- a/custom/4coder_default_framework_variables.cpp +++ b/custom/4coder_default_framework_variables.cpp @@ -15,6 +15,7 @@ CUSTOM_ID(attachment, view_highlight_range); CUSTOM_ID(attachment, view_highlight_buffer); CUSTOM_ID(attachment, view_render_hook); CUSTOM_ID(attachment, view_word_complete_menu); +CUSTOM_ID(attachment, view_lister_loc); CUSTOM_ID(attachment, buffer_map_id); CUSTOM_ID(attachment, buffer_eol_setting); diff --git a/custom/4coder_default_hooks.cpp b/custom/4coder_default_hooks.cpp index 16d8f335..4756c8e2 100644 --- a/custom/4coder_default_hooks.cpp +++ b/custom/4coder_default_hooks.cpp @@ -474,6 +474,20 @@ default_render_caller(Application_Links *app, Frame_Info frame_info, View_ID vie draw_set_clip(app, prev_clip); } +function void +default_whole_screen_render_caller(Application_Links *app, Frame_Info frame_info){ +#if 0 + Rect_f32 region = global_get_screen_rectangle(app); + Vec2_f32 center = rect_center(region); + + Face_ID face_id = get_face_id(app, 0); + Scratch_Block scratch(app); + draw_string_oriented(app, face_id, finalize_color(defcolor_text_default, 0), + SCu8("Hello, World!"), center, + GlyphFlag_Rotate90, V2f32(0.f, 1.f)); +#endif +} + HOOK_SIG(default_view_adjust){ // NOTE(allen): Called whenever the view layout/sizes have been modified, // including by full window resize. @@ -1022,6 +1036,7 @@ set_all_default_hooks(Application_Links *app){ set_custom_hook(app, HookID_ViewEventHandler, default_view_input_handler); set_custom_hook(app, HookID_Tick, default_tick); set_custom_hook(app, HookID_RenderCaller, default_render_caller); + set_custom_hook(app, HookID_WholeScreenRenderCaller, default_whole_screen_render_caller); #if 0 set_custom_hook(app, HookID_DeltaRule, original_delta); set_custom_hook_memory_size(app, HookID_DeltaRule, diff --git a/custom/4coder_default_include.cpp b/custom/4coder_default_include.cpp index 0e13797d..bf453a46 100644 --- a/custom/4coder_default_include.cpp +++ b/custom/4coder_default_include.cpp @@ -125,6 +125,8 @@ #include "4coder_doc_commands.cpp" #include "4coder_docs.cpp" +#include "4coder_examples.cpp" + #include "4coder_default_hooks.cpp" #endif diff --git a/custom/4coder_delta_rule.cpp b/custom/4coder_delta_rule.cpp index 83a7b1b5..9774dd19 100644 --- a/custom/4coder_delta_rule.cpp +++ b/custom/4coder_delta_rule.cpp @@ -53,7 +53,7 @@ delta_apply(Application_Links *app, View_ID view, } function Buffer_Point_Delta_Result -delta_apply(Application_Links *app, View_ID view, +delta_apply(Application_Links *app, View_ID view, Delta_Rule_Function *func, Data delta_ctx, f32 dt, Buffer_Scroll scroll){ return(delta_apply(app, view, func, delta_ctx, @@ -61,7 +61,7 @@ delta_apply(Application_Links *app, View_ID view, } function Buffer_Point_Delta_Result -delta_apply(Application_Links *app, View_ID view, +delta_apply(Application_Links *app, View_ID view, f32 dt, Buffer_Point position, Buffer_Point target){ View_Context ctx = view_current_context(app, view); Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule); @@ -70,7 +70,7 @@ delta_apply(Application_Links *app, View_ID view, } function Buffer_Point_Delta_Result -delta_apply(Application_Links *app, View_ID view, +delta_apply(Application_Links *app, View_ID view, f32 dt, Buffer_Scroll scroll){ View_Context ctx = view_current_context(app, view); Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule); @@ -119,7 +119,7 @@ delta_apply(Application_Links *app, View_ID view, } function Vec2_f32_Delta_Result -delta_apply(Application_Links *app, View_ID view, +delta_apply(Application_Links *app, View_ID view, f32 dt, Vec2_f32 position, Vec2_f32 target){ View_Context ctx = view_current_context(app, view); Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule); @@ -128,7 +128,7 @@ delta_apply(Application_Links *app, View_ID view, } function Vec2_f32_Delta_Result -delta_apply(Application_Links *app, View_ID view, +delta_apply(Application_Links *app, View_ID view, f32 dt, Basic_Scroll scroll){ View_Context ctx = view_current_context(app, view); Data delta_ctx = view_current_context_hook_memory(app, view, HookID_DeltaRule); diff --git a/custom/4coder_docs.cpp b/custom/4coder_docs.cpp index c3262b8e..1951bac1 100644 --- a/custom/4coder_docs.cpp +++ b/custom/4coder_docs.cpp @@ -7,9 +7,9 @@ function Doc_Page* get_doc_page_from_user(Application_Links *app, Doc_Cluster *doc, String_Const_u8 query){ Scratch_Block scratch(app, Scratch_Share); - Lister *lister = begin_lister(app, scratch); + Lister_Block lister(app, scratch); lister_set_query(lister, query); - lister->handlers = lister_get_default_handlers(); + lister_set_default_handlers(lister); for (Doc_Page *page = doc->first_page; page != 0; @@ -125,7 +125,7 @@ render_doc_page(Application_Links *app, Doc_Page *page){ } Buffer_Insertion insert = begin_buffer_insertion_at_buffered(app, buffer, 0, scratch, KB(16)); - char dashes[] = + char dashes[] = "----------------------------------------------------------------" "----------------------------------------------------------------" "----------------------------------------------------------------" diff --git a/custom/4coder_events.h b/custom/4coder_events.h index 90086bd9..72562eac 100644 --- a/custom/4coder_events.h +++ b/custom/4coder_events.h @@ -132,14 +132,17 @@ enum{ EventPropertyGroup_AnyUserInput = EventPropertyGroup_AnyKeyboardEvent| EventPropertyGroup_AnyMouseEvent, - EventPropertyGroup_Any = - EventPropertyGroup_AnyUserInput| + EventPropertyGroup_AnyCore = EventProperty_Animate| EventProperty_ViewActivation| EventProperty_AnyFile| EventProperty_Startup| EventProperty_Exit| EventProperty_Clipboard| + EventProperty_Animate, + EventPropertyGroup_Any = + EventPropertyGroup_AnyUserInput| + EventPropertyGroup_AnyCore| EventProperty_CustomFunction, }; diff --git a/custom/4coder_examples.cpp b/custom/4coder_examples.cpp new file mode 100644 index 00000000..5ab80a51 --- /dev/null +++ b/custom/4coder_examples.cpp @@ -0,0 +1,209 @@ +/* +4coder_examples.cpp - Commands that are included mainly to serve as example code for +customization writers. +*/ + +// TOP + +// tags: history; group +// example-of: History_Group; history_group_begin; history_group_end +CUSTOM_COMMAND_SIG(double_backspace) +CUSTOM_DOC("Example of history group helpers") +{ + /* History_Group is a wrapper around the history API that makes it easy to +group any series of edits into a single undo/redo record in the buffer's history. +Before any edits call history_group_begin and afterwards call history_group_end. +After history_group_end all of the edits to the buffer supplied in history_group_begin +will be merged, including all edits from function and command calls. */ + + View_ID view = get_active_view(app, Access_ReadWriteVisible); + Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); + History_Group group = history_group_begin(app, buffer); + backspace_char(app); + backspace_char(app); + history_group_end(group); +} + +// tags: query; bar +// example-of: Query_Bar +CUSTOM_COMMAND_SIG(play_with_a_counter) +CUSTOM_DOC("Example of query bar") +{ + /* Query bars make a quick lightweight display of a single line of text for interactive + commands, while still showing the buffer. Query bars are convenient because they don't +require any complex UI setup, or extra rendering work inside your command. + +First, constructing a Query_Bar_Group is a convenient way to make sure the query bar +states are fully cleaned up when the command ends. + +Second, we make our query bar and start showing it with start_query_bar. Until we +call end_query_bar on the same bar, or the group's destructor runs, the bar struct +needs to remain in memory. The easy way to accomplish this is to just let the bar be +on the commands stack frame. */ + + i32 counter = 0; + + Query_Bar_Group group(app); + Query_Bar dumb_bar = {}; + dumb_bar.prompt = SCu8("Goes away at >= 10"); + if (!start_query_bar(app, &dumb_bar, 0)){ + return; + } + + Query_Bar bar = {}; + bar.prompt = SCu8("Counter = "); + bar.string = SCu8(""); + if (!start_query_bar(app, &bar, 0)){ + return; + } + + for (;;){ + /* Notice here, we set the string of the query bar BEFORE we call get_next_input. + get_next_input blocks this command until the next input is sent from the core. Whatever +string we put in the bar now will be shown and remain in the bar until an event wakes +up this command and we get a chance to modify the bar again. */ + Scratch_Block scratch(app); + bar.string = push_stringf(scratch, "%d", counter); + if (counter >= 10){ + end_query_bar(app, &dumb_bar, 0); + } + + User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape); + if (in.abort){ + break; + } + + if (match_key_code(&in.event, KeyCode_Up)){ + counter += 1; + } + else if (match_key_code(&in.event, KeyCode_Down)){ + counter -= 1; + } + else{ + leave_current_input_unhandled(app); + } + } +} + +// tags: input; loop +// example-of: get_next_input; leave_current_input_unhandled +CUSTOM_COMMAND_SIG(display_key_codes) +CUSTOM_DOC("Example of input handling loop") +{ + /* In the 4coder custom layer, inputs are handled by a view context. A view context is a +thread that hands off control with the main thread of the 4coder core. When a command is +running in a view context thread, it can wait for inputs from the core by calling +get_next_input. If your command gets inputs from the core, then default input handling +isn't happening, so command bindings don't trigger unless you trigger them yourself. */ + + Query_Bar_Group group(app); + Query_Bar bar = {}; + bar.prompt = SCu8("KeyCode = "); + if (!start_query_bar(app, &bar, 0)){ + return; + } + + Key_Code code = 0; + + for (;;){ + Scratch_Block scratch(app); + if (code == 0){ + bar.string = SCu8("..."); + } + else{ + bar.string = push_stringf(scratch, "KeyCode_%s (%d)", key_code_name[code], code); + } + User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape); + if (in.abort){ + break; + } + if (in.event.kind == InputEventKind_KeyStroke){ + code = in.event.key.code; + } + else{ + /* Marking inputs as handled lets the core determine if certain inputs should + be passed to additional handlers. This is especially important for text input, + which is explained more in the example display_text_input. */ + leave_current_input_unhandled(app); + } + } +} + +// tags: text; input +// example-of: get_next_input; leave_current_input_unhandled; to_writable +CUSTOM_COMMAND_SIG(display_text_input) +CUSTOM_DOC("Example of to_writable and leave_current_input_unhandled") +{ + /* In the 4coder custom layer, inputs are handled by a view context. A view context is a +thread that hands off control with the main thread of the 4coder core. When a command is +running in a view context thread, it can wait for inputs from the core by calling +get_next_input. If your command gets inputs from the core, then default input handling +isn't happening, so command bindings don't trigger unless you trigger them yourself. */ + + Query_Bar_Group group(app); + Query_Bar bar = {}; + bar.prompt = SCu8("Weird String: "); + if (!start_query_bar(app, &bar, 0)){ + return; + } + + u8 buffer[256]; + u64 size = 0; + + for (;;){ + User_Input in = get_next_input(app, EventPropertyGroup_Any, EventProperty_Escape); + if (in.abort){ + break; + } + + String_Const_u8 in_string = to_writable(&in); + if (in_string.size > 0){ + size = clamp_top(in_string.size, sizeof(buffer)); + block_copy(buffer, in_string.str, size); + bar.string = SCu8(buffer, size); + } + else if (in.event.kind == InputEventKind_KeyStroke){ + /* If we handle a key stroke then the core marks any text input generated from that +key stroke as handled too, and the text input is never passed. By marking key strokes +as unhandled, we ensure we get text input events. */ + leave_current_input_unhandled(app); + } + } +} + +// tags: string; number; query; user +// example-of: query_user_string; query_user_number +CUSTOM_COMMAND_SIG(string_repeat) +CUSTOM_DOC("Example of query_user_string and query_user_number") +{ + Query_Bar_Group group(app); + Query_Bar string_bar = {}; + string_bar.prompt = SCu8("String: "); + u8 string_buffer[KB(1)]; + string_bar.string.str = string_buffer; + string_bar.string_capacity = sizeof(string_buffer); + Query_Bar number_bar = {}; + number_bar.prompt = SCu8("Repeat Count: "); + u8 number_buffer[KB(1)]; + number_bar.string.str = number_buffer; + number_bar.string_capacity = sizeof(number_buffer); + + if (query_user_string(app, &string_bar)){ + if (string_bar.string.size > 0){ + if (query_user_number(app, &number_bar)){ + if (number_bar.string.size > 0){ + i32 repeats = (i32)string_to_integer(number_bar.string, 10); + repeats = clamp_top(repeats, 1000); + Scratch_Block scratch(app); + String_Const_u8 msg = push_stringf(scratch, "%.*s\n", string_expand(string_bar.string)); + for (i32 i = 0; i < repeats; i += 1){ + print_message(app, msg); + } + } + } + } + } +} + +// BOTTOM + diff --git a/custom/4coder_file_moving.h b/custom/4coder_file_moving.h index 9e5ea59f..e05fa4e0 100644 --- a/custom/4coder_file_moving.h +++ b/custom/4coder_file_moving.h @@ -17,10 +17,6 @@ #include #include -// -// API -// - // System commands static char SF_CMD[4096]; static i32 error_state = 0; @@ -43,15 +39,18 @@ if (prev_error != 0) error_state = 1; \ internal void fm_execute_in_dir(char *dir, char *str, char *args); // Init -internal Arena fm_init_system(); +enum{ + DetailLevel_Basics = 0, + DetailLevel_FileOperations = 1, + DetailLevel_Everything = 2, +}; +global i32 detail_level = 0; + +internal Arena fm_init_system(i32 detail_level); // Timing internal u64 fm_get_time(); -#define LLU_CAST(n) (long long unsigned int)(n) -#define BEGIN_TIME_SECTION() u64 start = fm_get_time() -#define END_TIME_SECTION(n) u64 total = fm_get_time() - start; printf("%-20s: %.2llu.%.6llu\n", (n), LLU_CAST(total/1000000), LLU_CAST(total%1000000)); - // Files and Folders Manipulation internal void fm_make_folder_if_missing(Arena *arena, char *dir); internal void fm_clear_folder(char *folder); @@ -183,6 +182,16 @@ fm__init_memory(void){ return(make_arena_malloc(MB(512), 8)); } +function b32 +fm__show_details_for_file_operations(void){ + return(detail_level >= DetailLevel_FileOperations); +} + +function b32 +fm__show_details_for_zip_output(void){ + return(detail_level >= DetailLevel_Everything); +} + // // Windows implementation // @@ -266,7 +275,8 @@ extern "C"{ global u64 perf_frequency; internal Arena -fm_init_system(void){ +fm_init_system(i32 det){ + detail_level = det; LARGE_INTEGER lint; if (QueryPerformanceFrequency(&lint)){ perf_frequency = lint.QuadPart; @@ -351,7 +361,9 @@ fm_make_folder_if_missing(Arena *arena, char *dir){ internal void fm_clear_folder(char *folder){ - fprintf(stdout, "clearing folder %s\n", folder); + if (fm__show_details_for_file_operations()){ + fprintf(stdout, "clearing folder %s\n", folder); + } fflush(stdout); systemf("del /S /Q /F %s\\* > nul & rmdir /S /Q %s > nul & mkdir %s > nul", folder, folder, folder); } @@ -363,14 +375,18 @@ fm_delete_file(char *file){ internal void fm_copy_file(char *file, char *newname){ - printf("copy %s to %s\n", file, newname); + if (fm__show_details_for_file_operations()){ + printf("copy %s to %s\n", file, newname); + } fflush(stdout); CopyFileA(file, newname, 0); } internal void fm_copy_all(char *source, char *folder){ - fprintf(stdout, "copy %s to %s\n", source, folder); + if (fm__show_details_for_file_operations()){ + fprintf(stdout, "copy %s to %s\n", source, folder); + } fflush(stdout); systemf("xcopy /s /e /y /q %s %s > nul", source, folder); } @@ -394,17 +410,27 @@ fm_write_file(char *file_name, char *data, u32 size){ internal void fm_zip(char *parent, char *folder, char *dest){ - printf("zipping %s\\%s to %s\n", parent, folder, dest); + if (fm__show_details_for_file_operations()){ + printf("zipping %s\\%s to %s\n", parent, folder, dest); + } fflush(stdout); char cdir[512]; fm_get_current_directory(cdir, sizeof(cdir)); + char *hide_output = " > nul >> nul"; + char *show_output = ""; + char *output_rule = hide_output; + if (fm__show_details_for_zip_output()){ + output_rule = show_output; + } + Temp_Dir temp = fm_pushdir(parent); - systemf("%s\\bin\\zip %s\\4ed_gobble.zip > nul", cdir, cdir); + systemf("%s\\bin\\zip %s\\4ed_gobble.zip%s", cdir, cdir, output_rule); fm_popdir(temp); - systemf("copy %s\\4ed_gobble.zip %s > nul & del %s\\4ed_gobble.zip > nul", cdir, dest, cdir); + systemf("copy %s\\4ed_gobble.zip %s%s & del %s\\4ed_gobble.zip%s", + cdir, dest, output_rule, cdir, output_rule); } // @@ -435,7 +461,8 @@ fm_popdir(Temp_Dir temp){ } internal Arena -fm_init_system(){ +fm_init_system(i32 det){ + detail_level = det; return(fm__init_memory()); } @@ -492,7 +519,9 @@ fm_make_folder_if_missing(Arena *arena, char *dir){ internal void fm_clear_folder(char *folder){ - fprintf(stdout, "clearing folder %s\n", folder); + if (fm__show_details_for_file_operations()){ + fprintf(stdout, "clearing folder %s\n", folder); + } fflush(stdout); systemf("rm -rf %s* > /dev/null", folder); } @@ -504,12 +533,19 @@ fm_delete_file(char *file){ internal void fm_copy_file(char *file, char *newname){ + if (fm__show_details_for_file_operations()){ + printf("copy %s to %s\n", file, newname); + } + fflush(stdout); systemf("cp %s %s", file, newname); } internal void fm_copy_all(char *source, char *folder){ - fprintf(stdout, "copy %s to %s\n", source, folder); + if (fm__show_details_for_file_operations()){ + fprintf(stdout, "copy %s to %s\n", source, folder); + } + fflush(stdout); systemf("cp -rf %s/* %s > /dev/null", source, folder); } @@ -525,9 +561,20 @@ fm_write_file(char *file_name, char *data, u32 size){ internal void fm_zip(char *parent, char *folder, char *file){ + if (fm__show_details_for_file_operations()){ + printf("zipping %s/%s to %s\n", parent, folder, file); + } + fflush(stdout); + + char *hide_output = " > nul 2> nul"; + char *show_output = ""; + char *output_rule = hide_output; + if (fm__show_details_for_zip_output()){ + output_rule = show_output; + } + Temp_Dir temp = fm_pushdir(parent); - printf("PARENT DIR: %s\n", parent); - systemf("zip -r %s %s", file, folder); + systemf("zip -r %s %s%s", file, folder, output_rule); fm_popdir(temp); } diff --git a/custom/4coder_helper.cpp b/custom/4coder_helper.cpp index 986397e2..203dccff 100644 --- a/custom/4coder_helper.cpp +++ b/custom/4coder_helper.cpp @@ -9,6 +9,30 @@ //////////////////////////////// +function i32 +get_command_id(Custom_Command_Function *func){ + i32 result = -1; + for (i32 i = 0; i < ArrayCount(fcoder_metacmd_table); i += 1){ + if (func == fcoder_metacmd_table[i].proc){ + result = i; + break; + } + } + return(result); +} + +function Command_Metadata* +get_command_metadata(Custom_Command_Function *func){ + Command_Metadata *result = 0; + i32 id = get_command_id(func); + if (id >= 0){ + result = &fcoder_metacmd_table[id]; + } + return(result); +} + +//////////////////////////////// + internal Token_Array get_token_array_from_buffer(Application_Links *app, Buffer_ID buffer){ Token_Array result = {}; @@ -70,16 +94,14 @@ character_predicate_from_function(Character_Predicate_Function *func){ for (i32 bit_index = 0; bit_index < 8; i += 1, bit_index += 1){ v[bit_index] = func((u8)i); } - predicate.b[byte_index] = ( - (v[0] << 0) | + predicate.b[byte_index] = ((v[0] << 0) | (v[1] << 1) | (v[2] << 2) | (v[3] << 3) | (v[4] << 4) | (v[5] << 5) | (v[6] << 6) | - (v[7] << 7) - ); + (v[7] << 7)); byte_index += 1; } return(predicate); @@ -612,318 +634,318 @@ boundary_token(Application_Links *app, Buffer_ID buffer, Side side, Scan_Directi }break; case Scan_Backward: - { - result = 0; + { + result = 0; if (tokens.count > 0){ - Token_Iterator_Array it = token_iterator_pos(0, &tokens, pos); - Token *token = token_it_read(&it); -if (token->kind == TokenBaseKind_Whitespace){ - token_it_dec_non_whitespace(&it); -token = token_it_read(&it); - } + Token_Iterator_Array it = token_iterator_pos(0, &tokens, pos); + Token *token = token_it_read(&it); + if (token->kind == TokenBaseKind_Whitespace){ + token_it_dec_non_whitespace(&it); + token = token_it_read(&it); + } if (token != 0){ - if (side == Side_Min){ - if (token->pos >= pos){ - token_it_dec_non_whitespace(&it); -token = token_it_read(&it); - } + if (side == Side_Min){ + if (token->pos >= pos){ + token_it_dec_non_whitespace(&it); + token = token_it_read(&it); + } result = token->pos; - } + } else{ - if (token->pos + token->size >= pos){ - token_it_dec_non_whitespace(&it); -token = token_it_read(&it); - } + if (token->pos + token->size >= pos){ + token_it_dec_non_whitespace(&it); + token = token_it_read(&it); + } result = token->pos + token->size; - } } } - }break; - } - } - return(result); + } + }break; + } + } + return(result); } - internal i64 +internal i64 boundary_line(Application_Links *app, Buffer_ID buffer, Side side, Scan_Direction direction, i64 pos){ - i64 line_number = get_line_number_from_pos(app, buffer, pos); - i64 new_pos = get_line_side_pos(app, buffer, line_number, side); - if (direction == Scan_Backward && new_pos >= pos){ - if (line_number > 1){ - new_pos = get_line_side_pos(app, buffer, line_number - 1, side); - } - else{ - new_pos = 0; - } - } - else if (direction == Scan_Forward && new_pos <= pos){ - new_pos = get_line_side_pos(app, buffer, line_number + 1, side); - if (new_pos <= pos){ - new_pos = (i32)buffer_get_size(app, buffer); - } + i64 line_number = get_line_number_from_pos(app, buffer, pos); + i64 new_pos = get_line_side_pos(app, buffer, line_number, side); + if (direction == Scan_Backward && new_pos >= pos){ + if (line_number > 1){ + new_pos = get_line_side_pos(app, buffer, line_number - 1, side); } + else{ + new_pos = 0; + } + } + else if (direction == Scan_Forward && new_pos <= pos){ + new_pos = get_line_side_pos(app, buffer, line_number + 1, side); + if (new_pos <= pos){ + new_pos = (i32)buffer_get_size(app, buffer); + } + } return(new_pos); } - - //////////////////////////////// + +//////////////////////////////// // TODO(allen): these need a little more rewrite internal void seek_string_forward(Application_Links *app, Buffer_ID buffer, i64 pos, i64 end, String_Const_u8 needle, i64 *result){ - if (end == 0){ - end = (i32)buffer_get_size(app, buffer); - } + if (end == 0){ + end = (i32)buffer_get_size(app, buffer); + } String_Match match = {}; -match.range.first = pos; - for (;;){ - match = buffer_seek_string(app, buffer, needle, Scan_Forward, (i32)match.range.first); - if (HasFlag(match.flags, StringMatch_CaseSensitive) || - match.buffer != buffer || match.range.first >= end) break; - } - if (match.range.first < end && match.buffer == buffer){ - *result = match.range.first; -} - else{ - *result = buffer_get_size(app, buffer); - } - } - - internal void -seek_string_backward(Application_Links *app, Buffer_ID buffer, i64 pos, i64 min, String_Const_u8 needle, i64 *result){ - String_Match match = {}; match.range.first = pos; - for (;;){ - match = buffer_seek_string(app, buffer, needle, Scan_Backward, match.range.first); - if (HasFlag(match.flags, StringMatch_CaseSensitive) || - match.buffer != buffer || match.range.first < min) break; - } - if (match.range.first >= min && match.buffer == buffer){ - *result = match.range.first; + for (;;){ + match = buffer_seek_string(app, buffer, needle, Scan_Forward, (i32)match.range.first); + if (HasFlag(match.flags, StringMatch_CaseSensitive) || + match.buffer != buffer || match.range.first >= end) break; + } + if (match.range.first < end && match.buffer == buffer){ + *result = match.range.first; + } + else{ + *result = buffer_get_size(app, buffer); + } } - else{ - *result = -1; - } - } - - internal void -seek_string_insensitive_forward(Application_Links *app, Buffer_ID buffer, i64 pos, i64 end, String_Const_u8 needle, i64 *result){ - if (end == 0){ - end = (i32)buffer_get_size(app, buffer); - } - String_Match match = buffer_seek_string(app, buffer, needle, Scan_Forward, pos); - if (match.range.first < end && match.buffer == buffer){ - *result = match.range.first; - } - else{ - *result = buffer_get_size(app, buffer); - } - } - internal void +internal void +seek_string_backward(Application_Links *app, Buffer_ID buffer, i64 pos, i64 min, String_Const_u8 needle, i64 *result){ + String_Match match = {}; + match.range.first = pos; + for (;;){ + match = buffer_seek_string(app, buffer, needle, Scan_Backward, match.range.first); + if (HasFlag(match.flags, StringMatch_CaseSensitive) || + match.buffer != buffer || match.range.first < min) break; + } + if (match.range.first >= min && match.buffer == buffer){ + *result = match.range.first; + } + else{ + *result = -1; + } +} + +internal void +seek_string_insensitive_forward(Application_Links *app, Buffer_ID buffer, i64 pos, i64 end, String_Const_u8 needle, i64 *result){ + if (end == 0){ + end = (i32)buffer_get_size(app, buffer); + } + String_Match match = buffer_seek_string(app, buffer, needle, Scan_Forward, pos); + if (match.range.first < end && match.buffer == buffer){ + *result = match.range.first; + } + else{ + *result = buffer_get_size(app, buffer); + } +} + +internal void seek_string_insensitive_backward(Application_Links *app, Buffer_ID buffer, i64 pos, i64 min, String_Const_u8 needle, i64 *result){ - String_Match match = buffer_seek_string(app, buffer, needle, Scan_Backward, pos); - if (match.range.first >= min && match.buffer == buffer){ - *result = match.range.first; - } - else{ - *result = -1; + String_Match match = buffer_seek_string(app, buffer, needle, Scan_Backward, pos); + if (match.range.first >= min && match.buffer == buffer){ + *result = match.range.first; } + else{ + *result = -1; } - - internal void - seek_string(Application_Links *app, Buffer_ID buffer_id, i64 pos, i64 end, i64 min, String_Const_u8 str, i64 *result, Buffer_Seek_String_Flags flags){ - switch (flags & 3){ - case 0: - { - seek_string_forward(app, buffer_id, pos, end, str, result); - }break; +} + +internal void +seek_string(Application_Links *app, Buffer_ID buffer_id, i64 pos, i64 end, i64 min, String_Const_u8 str, i64 *result, Buffer_Seek_String_Flags flags){ + switch (flags & 3){ + case 0: + { + seek_string_forward(app, buffer_id, pos, end, str, result); + }break; case BufferSeekString_Backward: - { - seek_string_backward(app, buffer_id, pos, min, str, result); -}break; - - case BufferSeekString_CaseInsensitive: { - seek_string_insensitive_forward(app, buffer_id, pos, end, str, result); - }break; - - case BufferSeekString_Backward|BufferSeekString_CaseInsensitive: + seek_string_backward(app, buffer_id, pos, min, str, result); + }break; + + case BufferSeekString_CaseInsensitive: { - seek_string_insensitive_backward(app, buffer_id, pos, min, str, result); - }break; - } - } - - //////////////////////////////// - + seek_string_insensitive_forward(app, buffer_id, pos, end, str, result); + }break; + + case BufferSeekString_Backward|BufferSeekString_CaseInsensitive: + { + seek_string_insensitive_backward(app, buffer_id, pos, min, str, result); + }break; + } +} + +//////////////////////////////// + internal Range_i64 get_line_range_from_pos_range(Application_Links *app, Buffer_ID buffer, Range_i64 pos_range){ - Range_i64 line_range = {}; - line_range.first = get_line_number_from_pos(app, buffer, pos_range.first); - if (line_range.first != 0){ - line_range.end = get_line_number_from_pos(app, buffer, pos_range.one_past_last); -if (line_range.end == 0){ - line_range.first = 0; - } - } - return(line_range); - } - - // NOTE(allen): The end of the returned range does not include the terminating newline character of + Range_i64 line_range = {}; + line_range.first = get_line_number_from_pos(app, buffer, pos_range.first); + if (line_range.first != 0){ + line_range.end = get_line_number_from_pos(app, buffer, pos_range.one_past_last); + if (line_range.end == 0){ + line_range.first = 0; + } + } + return(line_range); +} + +// NOTE(allen): The end of the returned range does not include the terminating newline character of // the last line. internal Range_i64 get_pos_range_from_line_range(Application_Links *app, Buffer_ID buffer, Range_i64 line_range){ - Range_i64 pos_range = {}; - if (is_valid_line_range(app, buffer, line_range)){ - pos_range.first = get_line_start_pos(app, buffer, line_range.first); -pos_range.one_past_last = get_line_end_pos(app, buffer, line_range.end); - } + Range_i64 pos_range = {}; + if (is_valid_line_range(app, buffer, line_range)){ + pos_range.first = get_line_start_pos(app, buffer, line_range.first); + pos_range.one_past_last = get_line_end_pos(app, buffer, line_range.end); + } return(pos_range); +} + +internal Range_i64 +enclose_boundary(Application_Links *app, Buffer_ID buffer, Range_i64 range, + Boundary_Function *func){ + i64 new_min = func(app, buffer, Side_Min, Scan_Backward, range.min + 1); + i64 new_min_check = func(app, buffer, Side_Max, Scan_Backward, range.min + 1); + if (new_min_check <= new_min && new_min < range.min){ + range.min = new_min; } - - internal Range_i64 - enclose_boundary(Application_Links *app, Buffer_ID buffer, Range_i64 range, -Boundary_Function *func){ - i64 new_min = func(app, buffer, Side_Min, Scan_Backward, range.min + 1); - i64 new_min_check = func(app, buffer, Side_Max, Scan_Backward, range.min + 1); - if (new_min_check <= new_min && new_min < range.min){ - range.min = new_min; - } - i64 new_max = func(app, buffer, Side_Max, Scan_Forward, range.max - 1); - i64 new_max_check = func(app, buffer, Side_Min, Scan_Forward, range.max); - if (new_max_check >= new_max && new_max > range.max){ - range.max = new_max; - } - return(range); - } - - internal Range_i64 - left_enclose_boundary(Application_Links *app, Buffer_ID buffer, Range_i64 range, -Boundary_Function *func){ - i64 new_min = func(app, buffer, Side_Min, Scan_Backward, range.min + 1); - i64 new_min_check = func(app, buffer, Side_Max, Scan_Backward, range.min + 1); - if (new_min_check <= new_min && new_min < range.min){ - range.min = new_min; - } - return(range); - } - - internal Range_i64 - right_enclose_boundary(Application_Links *app, Buffer_ID buffer, Range_i64 range, -Boundary_Function *func){ - i64 new_max = func(app, buffer, Side_Max, Scan_Forward, range.max - 1); - i64 new_max_check = func(app, buffer, Side_Min, Scan_Forward, range.max - 1); -if (new_max_check >= new_max && new_max > range.max){ - range.max = new_max; - } - return(range); - } - - internal Range_i64 - enclose_non_whitespace(Application_Links *app, Buffer_ID buffer, Range_i64 range){ -return(enclose_boundary(app, buffer, range, boundary_non_whitespace)); - } - internal Range_i64 + i64 new_max = func(app, buffer, Side_Max, Scan_Forward, range.max - 1); + i64 new_max_check = func(app, buffer, Side_Min, Scan_Forward, range.max); + if (new_max_check >= new_max && new_max > range.max){ + range.max = new_max; + } + return(range); +} + +internal Range_i64 +left_enclose_boundary(Application_Links *app, Buffer_ID buffer, Range_i64 range, + Boundary_Function *func){ + i64 new_min = func(app, buffer, Side_Min, Scan_Backward, range.min + 1); + i64 new_min_check = func(app, buffer, Side_Max, Scan_Backward, range.min + 1); + if (new_min_check <= new_min && new_min < range.min){ + range.min = new_min; + } + return(range); +} + +internal Range_i64 +right_enclose_boundary(Application_Links *app, Buffer_ID buffer, Range_i64 range, + Boundary_Function *func){ + i64 new_max = func(app, buffer, Side_Max, Scan_Forward, range.max - 1); + i64 new_max_check = func(app, buffer, Side_Min, Scan_Forward, range.max - 1); + if (new_max_check >= new_max && new_max > range.max){ + range.max = new_max; + } + return(range); +} + +internal Range_i64 +enclose_non_whitespace(Application_Links *app, Buffer_ID buffer, Range_i64 range){ + return(enclose_boundary(app, buffer, range, boundary_non_whitespace)); +} +internal Range_i64 enclose_pos_non_whitespace(Application_Links *app, Buffer_ID buffer, i64 pos){ - return(enclose_boundary(app, buffer, Ii64(pos), boundary_non_whitespace)); + return(enclose_boundary(app, buffer, Ii64(pos), boundary_non_whitespace)); } internal Range_i64 - enclose_tokens(Application_Links *app, Buffer_ID buffer, Range_i64 range){ - return(enclose_boundary(app, buffer, range, boundary_token)); - } - internal Range_i64 - enclose_pos_tokens(Application_Links *app, Buffer_ID buffer, i64 pos){ -return(enclose_boundary(app, buffer, Ii64(pos), boundary_token)); - } - - internal Range_i64 - enclose_base10(Application_Links *app, Buffer_ID buffer, Range_i64 range){ - return(enclose_boundary(app, buffer, range, boundary_base10)); - } - internal Range_i64 - enclose_pos_base10(Application_Links *app, Buffer_ID buffer, i64 pos){ -return(enclose_boundary(app, buffer, Ii64(pos), boundary_base10)); - } - - internal Range_i64 - enclose_base16(Application_Links *app, Buffer_ID buffer, Range_i64 range){ - return(enclose_boundary(app, buffer, range, boundary_base16)); - } - internal Range_i64 - enclose_pos_base16(Application_Links *app, Buffer_ID buffer, i64 pos){ -return(enclose_boundary(app, buffer, Ii64(pos), boundary_base16)); - } - - internal Range_i64 - enclose_base10_colon(Application_Links *app, Buffer_ID buffer, Range_i64 range){ - return(enclose_boundary(app, buffer, range, boundary_base10_colon)); - } - internal Range_i64 - enclose_pos_base10_colon(Application_Links *app, Buffer_ID buffer, i64 pos){ - return(enclose_boundary(app, buffer, Ii64(pos), boundary_base10_colon)); +enclose_tokens(Application_Links *app, Buffer_ID buffer, Range_i64 range){ + return(enclose_boundary(app, buffer, range, boundary_token)); +} +internal Range_i64 +enclose_pos_tokens(Application_Links *app, Buffer_ID buffer, i64 pos){ + return(enclose_boundary(app, buffer, Ii64(pos), boundary_token)); } internal Range_i64 - enclose_alpha_numeric(Application_Links *app, Buffer_ID buffer, Range_i64 range){ - return(enclose_boundary(app, buffer, range, boundary_alpha_numeric)); - } - internal Range_i64 - enclose_pos_alpha_numeric(Application_Links *app, Buffer_ID buffer, i64 pos){ - return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric)); +enclose_base10(Application_Links *app, Buffer_ID buffer, Range_i64 range){ + return(enclose_boundary(app, buffer, range, boundary_base10)); +} +internal Range_i64 +enclose_pos_base10(Application_Links *app, Buffer_ID buffer, i64 pos){ + return(enclose_boundary(app, buffer, Ii64(pos), boundary_base10)); } internal Range_i64 - enclose_alpha_numeric_unicode(Application_Links *app, Buffer_ID buffer, Range_i64 range){ - return(enclose_boundary(app, buffer, range, boundary_alpha_numeric_unicode)); +enclose_base16(Application_Links *app, Buffer_ID buffer, Range_i64 range){ + return(enclose_boundary(app, buffer, range, boundary_base16)); } - internal Range_i64 - enclose_pos_alpha_numeric_unicode(Application_Links *app, Buffer_ID buffer, i64 pos){ - return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric_unicode)); - } - - internal Range_i64 - enclose_alpha_numeric_underscore(Application_Links *app, Buffer_ID buffer, Range_i64 range){ - return(enclose_boundary(app, buffer, range, boundary_alpha_numeric_underscore)); - } - internal Range_i64 - enclose_pos_alpha_numeric_underscore(Application_Links *app, Buffer_ID buffer, i64 pos){ - return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric_underscore)); - } - internal Range_i64 - right_enclose_alpha_numeric_underscore(Application_Links *app, Buffer_ID buffer, - Range_i64 range){ - return(right_enclose_boundary(app, buffer, range, boundary_alpha_numeric_underscore)); - } - +internal Range_i64 +enclose_pos_base16(Application_Links *app, Buffer_ID buffer, i64 pos){ + return(enclose_boundary(app, buffer, Ii64(pos), boundary_base16)); +} + +internal Range_i64 +enclose_base10_colon(Application_Links *app, Buffer_ID buffer, Range_i64 range){ + return(enclose_boundary(app, buffer, range, boundary_base10_colon)); +} +internal Range_i64 +enclose_pos_base10_colon(Application_Links *app, Buffer_ID buffer, i64 pos){ + return(enclose_boundary(app, buffer, Ii64(pos), boundary_base10_colon)); +} + +internal Range_i64 +enclose_alpha_numeric(Application_Links *app, Buffer_ID buffer, Range_i64 range){ + return(enclose_boundary(app, buffer, range, boundary_alpha_numeric)); +} +internal Range_i64 +enclose_pos_alpha_numeric(Application_Links *app, Buffer_ID buffer, i64 pos){ + return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric)); +} + +internal Range_i64 +enclose_alpha_numeric_unicode(Application_Links *app, Buffer_ID buffer, Range_i64 range){ + return(enclose_boundary(app, buffer, range, boundary_alpha_numeric_unicode)); +} +internal Range_i64 +enclose_pos_alpha_numeric_unicode(Application_Links *app, Buffer_ID buffer, i64 pos){ + return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric_unicode)); +} + +internal Range_i64 +enclose_alpha_numeric_underscore(Application_Links *app, Buffer_ID buffer, Range_i64 range){ + return(enclose_boundary(app, buffer, range, boundary_alpha_numeric_underscore)); +} +internal Range_i64 +enclose_pos_alpha_numeric_underscore(Application_Links *app, Buffer_ID buffer, i64 pos){ + return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric_underscore)); +} +internal Range_i64 +right_enclose_alpha_numeric_underscore(Application_Links *app, Buffer_ID buffer, + Range_i64 range){ + return(right_enclose_boundary(app, buffer, range, boundary_alpha_numeric_underscore)); +} + internal Range_i64 enclose_alpha_numeric_underscore_utf8(Application_Links *app, Buffer_ID buffer, Range_i64 range){ -return(enclose_boundary(app, buffer, range, boundary_alpha_numeric_underscore_utf8)); + return(enclose_boundary(app, buffer, range, boundary_alpha_numeric_underscore_utf8)); } internal Range_i64 - enclose_pos_alpha_numeric_underscore_utf8(Application_Links *app, Buffer_ID buffer, i64 pos){ -return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric_underscore_utf8)); - } - internal Range_i64 - right_enclose_alpha_numeric_underscore_utf8(Application_Links *app, Buffer_ID buffer, - Range_i64 range){ -return(right_enclose_boundary(app, buffer, range, boundary_alpha_numeric_underscore_utf8)); - } +enclose_pos_alpha_numeric_underscore_utf8(Application_Links *app, Buffer_ID buffer, i64 pos){ + return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric_underscore_utf8)); +} +internal Range_i64 +right_enclose_alpha_numeric_underscore_utf8(Application_Links *app, Buffer_ID buffer, + Range_i64 range){ + return(right_enclose_boundary(app, buffer, range, boundary_alpha_numeric_underscore_utf8)); +} - internal Range_i64 +internal Range_i64 enclose_alpha_numeric_camel(Application_Links *app, Buffer_ID buffer, Range_i64 range){ -return(enclose_boundary(app, buffer, range, boundary_alpha_numeric_camel)); + return(enclose_boundary(app, buffer, range, boundary_alpha_numeric_camel)); } internal Range_i64 enclose_pos_alpha_numeric_camel(Application_Links *app, Buffer_ID buffer, i64 pos){ -return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric_camel)); + return(enclose_boundary(app, buffer, Ii64(pos), boundary_alpha_numeric_camel)); } internal Range_i64 enclose_pos_inside_quotes(Application_Links *app, Buffer_ID buffer, i64 pos){ - return(enclose_boundary(app, buffer, Ii64(pos), boundary_inside_quotes)); + return(enclose_boundary(app, buffer, Ii64(pos), boundary_inside_quotes)); } internal Range_i64 @@ -932,1544 +954,1521 @@ enclose_whole_lines(Application_Links *app, Buffer_ID buffer, Range_i64 range){ } internal Range_i64 enclose_pos_whole_lines(Application_Links *app, Buffer_ID buffer, i64 pos){ - return(enclose_boundary(app, buffer, Ii64(pos), boundary_line)); - } - - //////////////////////////////// - - internal Range_i64 - get_snipe_range(Application_Links *app, Boundary_Function_List funcs, Buffer_ID buffer, i64 pos, Scan_Direction direction){ - Range_i64 result = {}; - i64 buffer_size = buffer_get_size(app, buffer); + return(enclose_boundary(app, buffer, Ii64(pos), boundary_line)); +} + +//////////////////////////////// + +internal Range_i64 +get_snipe_range(Application_Links *app, Boundary_Function_List funcs, Buffer_ID buffer, i64 pos, Scan_Direction direction){ + Range_i64 result = {}; + i64 buffer_size = buffer_get_size(app, buffer); i64 pos0 = pos; i64 pos1 = scan(app, funcs, buffer, direction, pos0); -if (0 <= pos1 && pos1 <= buffer_size){ -i64 pos2 = scan(app, funcs, buffer, flip_direction(direction), pos1); - if (0 <= pos2 && pos2 <= buffer_size){ -if (direction == Scan_Backward){ - pos2 = clamp_bot(pos2, pos0); - } -else{ - pos2 = clamp_top(pos2, pos0); - } - result = Ii64(pos1, pos2); - } - } - return(result); - } - - internal Range_i64 - get_snipe_range(Application_Links *app, Boundary_Function *func, Buffer_ID buffer, i64 pos, Scan_Direction direction){ - Scratch_Block scratch(app); - return(get_snipe_range(app, push_boundary_list(scratch, func), buffer, pos, direction)); + if (0 <= pos1 && pos1 <= buffer_size){ + i64 pos2 = scan(app, funcs, buffer, flip_direction(direction), pos1); + if (0 <= pos2 && pos2 <= buffer_size){ + if (direction == Scan_Backward){ + pos2 = clamp_bot(pos2, pos0); + } + else{ + pos2 = clamp_top(pos2, pos0); + } + result = Ii64(pos1, pos2); } - - //////////////////////////////// + } + return(result); +} + +internal Range_i64 +get_snipe_range(Application_Links *app, Boundary_Function *func, Buffer_ID buffer, i64 pos, Scan_Direction direction){ + Scratch_Block scratch(app); + return(get_snipe_range(app, push_boundary_list(scratch, func), buffer, pos, direction)); +} + +//////////////////////////////// internal String_Const_u8 push_buffer_range(Application_Links *app, Arena *arena, Buffer_ID buffer, Range_i64 range){ - String_Const_u8 result = {}; - i64 length = range_size(range); + String_Const_u8 result = {}; + i64 length = range_size(range); if (length > 0){ - Temp_Memory restore_point = begin_temp(arena); - u8 *memory = push_array(arena, u8, length); - if (buffer_read_range(app, buffer, range, memory)){ - result = SCu8(memory, length); - } - else{ - end_temp(restore_point); -} -} -return(result); + Temp_Memory restore_point = begin_temp(arena); + u8 *memory = push_array(arena, u8, length); + if (buffer_read_range(app, buffer, range, memory)){ + result = SCu8(memory, length); + } + else{ + end_temp(restore_point); + } + } + return(result); } internal String_Const_u8 - push_token_lexeme(Application_Links *app, Arena *arena, Buffer_ID buffer, Token *token){ - return(push_buffer_range(app, arena, buffer, Ii64(token))); - } - - internal String_Const_u8 - push_buffer_line(Application_Links *app, Arena *arena, Buffer_ID buffer, i64 line_number){ - return(push_buffer_range(app, arena, buffer, get_line_pos_range(app, buffer, line_number))); +push_token_lexeme(Application_Links *app, Arena *arena, Buffer_ID buffer, Token *token){ + return(push_buffer_range(app, arena, buffer, Ii64(token))); } internal String_Const_u8 - push_whole_buffer(Application_Links *app, Arena *arena, Buffer_ID buffer){ +push_buffer_line(Application_Links *app, Arena *arena, Buffer_ID buffer, i64 line_number){ + return(push_buffer_range(app, arena, buffer, get_line_pos_range(app, buffer, line_number))); +} + +internal String_Const_u8 +push_whole_buffer(Application_Links *app, Arena *arena, Buffer_ID buffer){ return(push_buffer_range(app, arena, buffer, buffer_range(app, buffer))); - } - - internal String_Const_u8 - push_view_range_string(Application_Links *app, Arena *arena, View_ID view){ - Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); - return(push_buffer_range(app, arena, buffer, get_view_range(app, view))); - } +} - internal String_Const_u8 - push_view_range_string(Application_Links *app, Arena *arena){ - View_ID view = get_active_view(app, Access_Always); -return(push_view_range_string(app, arena, view)); +internal String_Const_u8 +push_view_range_string(Application_Links *app, Arena *arena, View_ID view){ + Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); + return(push_buffer_range(app, arena, buffer, get_view_range(app, view))); +} + +internal String_Const_u8 +push_view_range_string(Application_Links *app, Arena *arena){ + View_ID view = get_active_view(app, Access_Always); + return(push_view_range_string(app, arena, view)); } internal String_Const_u8 push_enclose_range_at_pos(Application_Links *app, Arena *arena, Buffer_ID buffer, i64 pos, Enclose_Function *enclose){ - Range_i64 range = enclose(app, buffer, Ii64(pos)); + Range_i64 range = enclose(app, buffer, Ii64(pos)); return(push_buffer_range(app, arena, buffer, range)); - } +} //////////////////////////////// - - internal String_Const_u8 - token_it_lexeme(Application_Links *app, Arena *arena, Token_Iterator_Array *it){ - String_Const_u8 result = {}; - Token *token = token_it_read(it); -if (token != 0){ + +internal String_Const_u8 +token_it_lexeme(Application_Links *app, Arena *arena, Token_Iterator_Array *it){ + String_Const_u8 result = {}; + Token *token = token_it_read(it); + if (token != 0){ result = push_token_lexeme(app, arena, (Buffer_ID)it->user_id, token); - } -return(result); + } + return(result); } internal b32 token_it_check_and_get_lexeme(Application_Links *app, Arena *arena, Token_Iterator_Array *it, Token_Base_Kind kind, String_Const_u8 *lexeme_out){ - Token *token = token_it_read(it); + Token *token = token_it_read(it); b32 result = {}; if (token != 0 && token->kind == kind){ - result = true; - *lexeme_out = push_token_lexeme(app, arena, (Buffer_ID)it->user_id, token); + result = true; + *lexeme_out = push_token_lexeme(app, arena, (Buffer_ID)it->user_id, token); } -return(result); - } + return(result); +} - internal String_Const_u8 - token_it_lexeme(Application_Links *app, Arena *arena, Token_Iterator_List *it){ +internal String_Const_u8 +token_it_lexeme(Application_Links *app, Arena *arena, Token_Iterator_List *it){ String_Const_u8 result = {}; Token *token = token_it_read(it); -if (token != 0){ -result = push_token_lexeme(app, arena, (Buffer_ID)it->user_id, token); -} -return(result); + if (token != 0){ + result = push_token_lexeme(app, arena, (Buffer_ID)it->user_id, token); } - - internal b32 - token_it_check_and_get_lexeme(Application_Links *app, Arena *arena, Token_Iterator_List *it, Token_Base_Kind kind, String_Const_u8 *lexeme_out){ + return(result); +} + +internal b32 +token_it_check_and_get_lexeme(Application_Links *app, Arena *arena, Token_Iterator_List *it, Token_Base_Kind kind, String_Const_u8 *lexeme_out){ Token *token = token_it_read(it); b32 result = {}; if (token != 0 && token->kind == kind){ - result = true; - *lexeme_out = push_token_lexeme(app, arena, (Buffer_ID)it->user_id, token); - } - return(result); - } - - //////////////////////////////// - - internal b32 -buffer_has_name_with_star(Application_Links *app, Buffer_ID buffer){ - Scratch_Block scratch(app); -String_Const_u8 str = push_buffer_unique_name(app, scratch, buffer); - return(str.size > 0 && str.str[0] == '*'); + result = true; + *lexeme_out = push_token_lexeme(app, arena, (Buffer_ID)it->user_id, token); } - - internal u8 - buffer_get_char(Application_Links *app, Buffer_ID buffer_id, i64 pos){ - i64 buffer_size = buffer_get_size(app, buffer_id); - u8 result = ' '; - if (0 <= pos && pos < buffer_size){ + return(result); +} + +//////////////////////////////// + +internal b32 +buffer_has_name_with_star(Application_Links *app, Buffer_ID buffer){ + Scratch_Block scratch(app); + String_Const_u8 str = push_buffer_unique_name(app, scratch, buffer); + return(str.size > 0 && str.str[0] == '*'); +} + +internal u8 +buffer_get_char(Application_Links *app, Buffer_ID buffer_id, i64 pos){ + i64 buffer_size = buffer_get_size(app, buffer_id); + u8 result = ' '; + if (0 <= pos && pos < buffer_size){ buffer_read_range(app, buffer_id, Ii64(pos, pos + 1), &result); - } - return(result); + } + return(result); } internal b32 - line_is_valid_and_blank(Application_Links *app, Buffer_ID buffer, i64 line_number){ -b32 result = false; -if (is_valid_line(app, buffer, line_number)){ -Scratch_Block scratch(app); - String_Const_u8 line = push_buffer_line(app, scratch, buffer, line_number); - result = true; - for (u64 i = 0; i < line.size; i += 1){ - if (!character_is_whitespace(line.str[i])){ - result = false; - break; -} +line_is_valid_and_blank(Application_Links *app, Buffer_ID buffer, i64 line_number){ + b32 result = false; + if (is_valid_line(app, buffer, line_number)){ + Scratch_Block scratch(app); + String_Const_u8 line = push_buffer_line(app, scratch, buffer, line_number); + result = true; + for (u64 i = 0; i < line.size; i += 1){ + if (!character_is_whitespace(line.str[i])){ + result = false; + break; + } + } } - } - return(result); - } + return(result); +} - //////////////////////////////// - - internal i64 - get_pos_past_lead_whitespace_from_line_number(Application_Links *app, Buffer_ID buffer, i64 line_number){ +//////////////////////////////// + +internal i64 +get_pos_past_lead_whitespace_from_line_number(Application_Links *app, Buffer_ID buffer, i64 line_number){ Scratch_Block scratch(app); Range_i64 line_range = get_line_pos_range(app, buffer, line_number); -String_Const_u8 line = push_buffer_range(app, scratch, buffer, line_range); - i64 result = line_range.end; - for (u64 i = 0; i < line.size; i += 1){ - if (!character_is_whitespace(line.str[i])){ - result = line_range.start + i; -break; + String_Const_u8 line = push_buffer_range(app, scratch, buffer, line_range); + i64 result = line_range.end; + for (u64 i = 0; i < line.size; i += 1){ + if (!character_is_whitespace(line.str[i])){ + result = line_range.start + i; + break; } - } - return(result); - } - - internal i64 - get_pos_past_lead_whitespace(Application_Links *app, Buffer_ID buffer, i64 pos){ - i64 line_number = get_line_number_from_pos(app, buffer, pos); -i64 result = get_pos_past_lead_whitespace_from_line_number(app, buffer, line_number); -result = clamp_bot(pos, result); - return(result); - } - - internal void - move_past_lead_whitespace(Application_Links *app, View_ID view, Buffer_ID buffer){ - i64 pos = view_get_cursor_pos(app, view); - i64 new_pos = get_pos_past_lead_whitespace(app, buffer, pos); -view_set_cursor_and_preferred_x(app, view, seek_pos(new_pos)); - } - - internal void - move_past_lead_whitespace(Application_Links *app, View_ID view){ -Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); - move_past_lead_whitespace(app, view, buffer); } - -internal b32 -line_is_blank(Application_Links *app, Buffer_ID buffer, i64 line_number){ - Scratch_Block scratch(app); - String_Const_u8 line = push_buffer_line(app, scratch, buffer, line_number); - b32 is_blank = true; -for (u64 i = 0; i < line.size; i += 1){ - if (!character_is_whitespace(line.str[i])){ - is_blank = false; - break; - } - } - return(is_blank); - } - - internal i64 -get_line_number_of__whitespace_status_line(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 line_number_start, b32 get_blank_line){ -i64 line_count = buffer_get_line_count(app, buffer); - i64 line_number = line_number_start + direction; - for (;1 <= line_number && line_number <= line_count; line_number += direction){ -b32 is_blank = line_is_blank(app, buffer, line_number); -if (is_blank == get_blank_line){ - break; - } - } - line_number = clamp(1, line_number, line_count); - return(line_number); - } - - internal i64 - get_line_number_of_non_blank_line(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 line_number_start){ - return(get_line_number_of__whitespace_status_line(app, buffer, direction, line_number_start, false)); + return(result); } internal i64 - get_line_number_of_blank_line(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 line_number_start){ - return(get_line_number_of__whitespace_status_line(app, buffer, direction, line_number_start, true)); - } - - internal i64 - get_pos_of_blank_line(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 pos_start){ - i64 line_number_start = get_line_number_from_pos(app, buffer, pos_start); - i64 blank_line = get_line_number_of_blank_line(app, buffer, direction, line_number_start); - i64 pos = get_line_start_pos(app, buffer, blank_line); +get_pos_past_lead_whitespace(Application_Links *app, Buffer_ID buffer, i64 pos){ + i64 line_number = get_line_number_from_pos(app, buffer, pos); + i64 result = get_pos_past_lead_whitespace_from_line_number(app, buffer, line_number); + result = clamp_bot(pos, result); + return(result); +} + +internal void +move_past_lead_whitespace(Application_Links *app, View_ID view, Buffer_ID buffer){ + i64 pos = view_get_cursor_pos(app, view); + i64 new_pos = get_pos_past_lead_whitespace(app, buffer, pos); + view_set_cursor_and_preferred_x(app, view, seek_pos(new_pos)); +} + +internal void +move_past_lead_whitespace(Application_Links *app, View_ID view){ + Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); + move_past_lead_whitespace(app, view, buffer); +} + +internal b32 +line_is_blank(Application_Links *app, Buffer_ID buffer, i64 line_number){ + Scratch_Block scratch(app); + String_Const_u8 line = push_buffer_line(app, scratch, buffer, line_number); + b32 is_blank = true; + for (u64 i = 0; i < line.size; i += 1){ + if (!character_is_whitespace(line.str[i])){ + is_blank = false; + break; + } + } + return(is_blank); +} + +internal i64 +get_line_number_of__whitespace_status_line(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 line_number_start, b32 get_blank_line){ + i64 line_count = buffer_get_line_count(app, buffer); + i64 line_number = line_number_start + direction; + for (;1 <= line_number && line_number <= line_count; line_number += direction){ + b32 is_blank = line_is_blank(app, buffer, line_number); + if (is_blank == get_blank_line){ + break; + } + } + line_number = clamp(1, line_number, line_count); + return(line_number); +} + +internal i64 +get_line_number_of_non_blank_line(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 line_number_start){ + return(get_line_number_of__whitespace_status_line(app, buffer, direction, line_number_start, false)); +} + +internal i64 +get_line_number_of_blank_line(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 line_number_start){ + return(get_line_number_of__whitespace_status_line(app, buffer, direction, line_number_start, true)); +} + +internal i64 +get_pos_of_blank_line(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 pos_start){ + i64 line_number_start = get_line_number_from_pos(app, buffer, pos_start); + i64 blank_line = get_line_number_of_blank_line(app, buffer, direction, line_number_start); + i64 pos = get_line_start_pos(app, buffer, blank_line); return(pos); } - internal i64 - get_line_number_of_blank_line_grouped(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 line_number_start){ - i64 line_number = line_number_start; +internal i64 +get_line_number_of_blank_line_grouped(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 line_number_start){ + i64 line_number = line_number_start; if (line_is_blank(app, buffer, line_number)){ - line_number = get_line_number_of_non_blank_line(app, buffer, direction, line_number); - } + line_number = get_line_number_of_non_blank_line(app, buffer, direction, line_number); + } line_number = get_line_number_of_blank_line(app, buffer, direction, line_number); return(line_number); - } - - internal i64 - get_pos_of_blank_line_grouped(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 pos_start){ -i64 line_number_start = get_line_number_from_pos(app, buffer, pos_start); - i64 blank_line = get_line_number_of_blank_line_grouped(app, buffer, direction, line_number_start); - i64 pos = get_line_start_pos(app, buffer, blank_line); - return(pos); - } - - internal Indent_Info - get_indent_info_range(Application_Links *app, Buffer_ID buffer, Range_i64 range, i32 tab_width){ - Scratch_Block scratch(app); - String_Const_u8 s = push_buffer_range(app, scratch, buffer, range); +} - Indent_Info info = {}; -info.first_char_pos = range.end; +internal i64 +get_pos_of_blank_line_grouped(Application_Links *app, Buffer_ID buffer, Scan_Direction direction, i64 pos_start){ + i64 line_number_start = get_line_number_from_pos(app, buffer, pos_start); + i64 blank_line = get_line_number_of_blank_line_grouped(app, buffer, direction, line_number_start); + i64 pos = get_line_start_pos(app, buffer, blank_line); + return(pos); +} + +internal Indent_Info +get_indent_info_range(Application_Links *app, Buffer_ID buffer, Range_i64 range, i32 tab_width){ + Scratch_Block scratch(app); + String_Const_u8 s = push_buffer_range(app, scratch, buffer, range); + + Indent_Info info = {}; + info.first_char_pos = range.end; info.is_blank = true; info.all_space = true; - - for (u64 i = 0; i < s.size; i += 1){ - u8 c = s.str[i]; - if (!character_is_whitespace(c)){ - info.is_blank = false; - info.all_space = false; -info.first_char_pos = range.start + (i64)i; - break; + + for (u64 i = 0; i < s.size; i += 1){ + u8 c = s.str[i]; + if (!character_is_whitespace(c)){ + info.is_blank = false; + info.all_space = false; + info.first_char_pos = range.start + (i64)i; + break; + } + if (c == ' '){ + info.indent_pos += 1; + } + else{ + info.all_space = false; + } + if (c == '\t'){ + info.indent_pos += tab_width; + } } - if (c == ' '){ - info.indent_pos += 1; - } - else{ -info.all_space = false; -} -if (c == '\t'){ - info.indent_pos += tab_width; - } - } return(info); - } - - internal Indent_Info - get_indent_info_line_number_and_start(Application_Links *app, Buffer_ID buffer, i64 line_number, i64 line_start, i32 tab_width){ - i64 end = get_line_side_pos(app, buffer, line_number, Side_Max); -return(get_indent_info_range(app, buffer, Ii64(line_start, end), tab_width)); - } - - //////////////////////////////// - - internal History_Group - history_group_begin(Application_Links *app, Buffer_ID buffer){ - History_Group group = {}; - group.app = app; - group.buffer = buffer; - group.first = buffer_history_get_current_state_index(app, buffer); - group.first += 1; - return(group); - } - - internal void - history_group_end(History_Group group){ - History_Record_Index last = buffer_history_get_current_state_index(group.app, group.buffer); - if (group.first < last){ - buffer_history_merge_record_range(group.app, group.buffer, group.first, last, RecordMergeFlag_StateInRange_MoveStateForward); } + +internal Indent_Info +get_indent_info_line_number_and_start(Application_Links *app, Buffer_ID buffer, i64 line_number, i64 line_start, i32 tab_width){ + i64 end = get_line_side_pos(app, buffer, line_number, Side_Max); + return(get_indent_info_range(app, buffer, Ii64(line_start, end), tab_width)); +} + +//////////////////////////////// + +internal History_Group +history_group_begin(Application_Links *app, Buffer_ID buffer){ + History_Group group = {}; + group.app = app; + group.buffer = buffer; + group.first = buffer_history_get_current_state_index(app, buffer); + group.first += 1; + return(group); +} + +internal void +history_group_end(History_Group group){ + History_Record_Index last = buffer_history_get_current_state_index(group.app, group.buffer); + if (group.first < last){ + buffer_history_merge_record_range(group.app, group.buffer, group.first, last, RecordMergeFlag_StateInRange_MoveStateForward); + } } //////////////////////////////// internal void - replace_in_range(Application_Links *app, Buffer_ID buffer, Range_i64 range, String_Const_u8 needle, String_Const_u8 string){ +replace_in_range(Application_Links *app, Buffer_ID buffer, Range_i64 range, String_Const_u8 needle, String_Const_u8 string){ // TODO(allen): rewrite History_Group group = history_group_begin(app, buffer); i64 pos = range.min - 1; i64 new_pos = 0; - seek_string_forward(app, buffer, pos, range.end, needle, &new_pos); - i64 shift = replace_range_shift(needle.size, string.size); - for (; new_pos + (i64)needle.size <= range.end;){ - Range_i64 needle_range = Ii64(new_pos, new_pos + (i32)needle.size); - buffer_replace_range(app, buffer, needle_range, string); - range.end += shift; -pos = new_pos + (i32)string.size - 1; - seek_string_forward(app, buffer, pos, range.end, needle, &new_pos); - } - history_group_end(group); + seek_string_forward(app, buffer, pos, range.end, needle, &new_pos); + i64 shift = replace_range_shift(needle.size, string.size); + for (; new_pos + (i64)needle.size <= range.end;){ + Range_i64 needle_range = Ii64(new_pos, new_pos + (i32)needle.size); + buffer_replace_range(app, buffer, needle_range, string); + range.end += shift; + pos = new_pos + (i32)string.size - 1; + seek_string_forward(app, buffer, pos, range.end, needle, &new_pos); + } + history_group_end(group); } - - internal Range_i64 - swap_lines(Application_Links *app, Buffer_ID buffer, i64 line_1, i64 line_2){ -Range_i64 result = {}; -i64 line_count = buffer_get_line_count(app, buffer); - if (1 <= line_1 && line_2 <= line_count){ - Range_i64 range_1 = get_line_pos_range(app, buffer, line_1); - Range_i64 range_2 = get_line_pos_range(app, buffer, line_2); - - Scratch_Block scratch(app); - - String_Const_u8 text_1 = push_buffer_range(app, scratch, buffer, range_1); + +internal Range_i64 +swap_lines(Application_Links *app, Buffer_ID buffer, i64 line_1, i64 line_2){ + Range_i64 result = {}; + i64 line_count = buffer_get_line_count(app, buffer); + if (1 <= line_1 && line_2 <= line_count){ + Range_i64 range_1 = get_line_pos_range(app, buffer, line_1); + Range_i64 range_2 = get_line_pos_range(app, buffer, line_2); + + Scratch_Block scratch(app); + + String_Const_u8 text_1 = push_buffer_range(app, scratch, buffer, range_1); String_Const_u8 text_2 = push_buffer_range(app, scratch, buffer, range_2); History_Group group = history_group_begin(app, buffer); - buffer_replace_range(app, buffer, range_2, text_1); -buffer_replace_range(app, buffer, range_1, text_2); - history_group_end(group); - -i64 shift = replace_range_shift(range_1, text_2.size); - result.min = range_1.min; -result.max = range_2.min + shift; - } - return(result); -} - - internal i64 - move_line(Application_Links *app, Buffer_ID buffer, i64 line_number, Scan_Direction direction){ - i64 line_1 = 0; - i64 line_2 = 0; - if (direction == Scan_Forward){ - line_1 = line_number; -line_2 = line_number + 1; - } - else{ - line_1 = line_number - 1; - line_2 = line_number; - } - Range_i64 line_starts = swap_lines(app, buffer, line_1, line_2); - i64 result = 0; - if (line_starts.min < line_starts.max){ - if (direction == Scan_Forward){ - result = line_starts.max; - } - else{ - result = line_starts.min; - } - } - else{ - result = get_line_side_pos(app, buffer, line_number, Side_Min); - } - return(result); - } + buffer_replace_range(app, buffer, range_2, text_1); + buffer_replace_range(app, buffer, range_1, text_2); + history_group_end(group); - internal void - clear_buffer(Application_Links *app, Buffer_ID buffer){ - buffer_replace_range(app, buffer, buffer_range(app, buffer), string_u8_litexpr("")); - } - - //////////////////////////////// - - internal String_Match_List - find_all_matches_all_buffers(Application_Links *app, Arena *arena, String_Const_u8_Array match_patterns, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags){ - String_Match_List all_matches = {}; -for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); - buffer != 0; - buffer = get_buffer_next(app, buffer, Access_Always)){ -String_Match_List buffer_matches = {}; - for (i32 i = 0; i < match_patterns.count; i += 1){ - Range_i64 range = buffer_range(app, buffer); - String_Match_List pattern_matches = buffer_find_all_matches(app, arena, buffer, i, range, match_patterns.vals[i], - &character_predicate_alpha_numeric_underscore_utf8, Scan_Forward); - string_match_list_filter_flags(&pattern_matches, must_have_flags, must_not_have_flags); -if (pattern_matches.count > 0){ -if (buffer_matches.count == 0){ - buffer_matches = pattern_matches; - } - else{ -buffer_matches = string_match_list_merge_front_to_back(&buffer_matches, &pattern_matches); -} -} -} -all_matches = string_match_list_join(&all_matches, &buffer_matches); - } - return(all_matches); + i64 shift = replace_range_shift(range_1, text_2.size); + result.min = range_1.min; + result.max = range_2.min + shift; } - - internal String_Match_List - find_all_matches_all_buffers(Application_Links *app, Arena *arena, String_Const_u8 pattern, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags){ - String_Const_u8_Array array = {&pattern, 1}; - return(find_all_matches_all_buffers(app, arena, array, must_have_flags, must_not_have_flags)); - } + return(result); +} + +internal i64 +move_line(Application_Links *app, Buffer_ID buffer, i64 line_number, Scan_Direction direction){ + i64 line_1 = 0; + i64 line_2 = 0; + if (direction == Scan_Forward){ + line_1 = line_number; + line_2 = line_number + 1; + } + else{ + line_1 = line_number - 1; + line_2 = line_number; + } + Range_i64 line_starts = swap_lines(app, buffer, line_1, line_2); + i64 result = 0; + if (line_starts.min < line_starts.max){ + if (direction == Scan_Forward){ + result = line_starts.max; + } + else{ + result = line_starts.min; + } + } + else{ + result = get_line_side_pos(app, buffer, line_number, Side_Min); + } + return(result); +} + +internal void +clear_buffer(Application_Links *app, Buffer_ID buffer){ + buffer_replace_range(app, buffer, buffer_range(app, buffer), string_u8_litexpr("")); +} //////////////////////////////// - - internal b32 - is_modified(User_Input *input){ - return(is_modified(&input->event)); - } - - internal String_Const_u8 - to_writable(User_Input *in){ - return(to_writable(&in->event)); - } - - internal b32 - has_modifier(User_Input *in, Key_Code key_code){ - b32 result = false; - Input_Modifier_Set *mods = get_modifiers(&in->event); - if (mods != 0){ - result = has_modifier(mods, key_code); + +internal String_Match_List +find_all_matches_all_buffers(Application_Links *app, Arena *arena, String_Const_u8_Array match_patterns, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags){ + String_Match_List all_matches = {}; + for (Buffer_ID buffer = get_buffer_next(app, 0, Access_Always); + buffer != 0; + buffer = get_buffer_next(app, buffer, Access_Always)){ + String_Match_List buffer_matches = {}; + for (i32 i = 0; i < match_patterns.count; i += 1){ + Range_i64 range = buffer_range(app, buffer); + String_Match_List pattern_matches = buffer_find_all_matches(app, arena, buffer, i, range, match_patterns.vals[i], + &character_predicate_alpha_numeric_underscore_utf8, Scan_Forward); + string_match_list_filter_flags(&pattern_matches, must_have_flags, must_not_have_flags); + if (pattern_matches.count > 0){ + if (buffer_matches.count == 0){ + buffer_matches = pattern_matches; + } + else{ + buffer_matches = string_match_list_merge_front_to_back(&buffer_matches, &pattern_matches); + } + } } - return(result); - } - - internal b32 - match_key_code(User_Input *in, Key_Code key_code){ - return(match_key_code(&in->event, key_code)); + all_matches = string_match_list_join(&all_matches, &buffer_matches); } - + return(all_matches); +} + +internal String_Match_List +find_all_matches_all_buffers(Application_Links *app, Arena *arena, String_Const_u8 pattern, String_Match_Flag must_have_flags, String_Match_Flag must_not_have_flags){ + String_Const_u8_Array array = {&pattern, 1}; + return(find_all_matches_all_buffers(app, arena, array, must_have_flags, must_not_have_flags)); +} + +//////////////////////////////// + +internal b32 +is_modified(User_Input *input){ + return(is_modified(&input->event)); +} + +internal String_Const_u8 +to_writable(User_Input *in){ + return(to_writable(&in->event)); +} + +internal b32 +has_modifier(User_Input *in, Key_Code key_code){ + b32 result = false; + Input_Modifier_Set *mods = get_modifiers(&in->event); + if (mods != 0){ + result = has_modifier(mods, key_code); + } + return(result); +} + +internal b32 +match_key_code(User_Input *in, Key_Code key_code){ + return(match_key_code(&in->event, key_code)); +} + internal b32 match_core_code(User_Input *in, Key_Code core_code){ -return(match_core_code(&in->event, core_code)); + return(match_core_code(&in->event, core_code)); } internal String_Const_u8 backspace_utf8(String_Const_u8 string){ - if (string.size > 0){ -u64 i = string.size - 1; - for (; i > 0; --i){ - if (string.str[i] <= 0x7F || string.str[i] >= 0xC0){ - break; - } - } - string.size = i; + if (string.size > 0){ + u64 i = string.size - 1; + for (; i > 0; --i){ + if (string.str[i] <= 0x7F || string.str[i] >= 0xC0){ + break; + } + } + string.size = i; } return(string); - } - - //////////////////////////////// - -Query_Bar_Group::Query_Bar_Group(Application_Links *app){ - this->app = app; - this->view = get_active_view(app, Access_Always); -} - -Query_Bar_Group::Query_Bar_Group(Application_Links *app, View_ID view){ - this->app = app; - this->view = view; -} - -Query_Bar_Group::~Query_Bar_Group(){ -clear_all_query_bars(this->app, this->view); - } - - internal b32 - query_user_general(Application_Links *app, Query_Bar *bar, b32 force_number, String_Const_u8 init_string){ -// NOTE(allen|a3.4.4): It will not cause an *error* if we continue on after failing to. -// start a query bar, but it will be unusual behavior from the point of view of the - // user, if this command starts intercepting input even though no prompt is shown. -// This will only happen if you have a lot of bars open already or if the current view - // doesn't support query bars. - if (start_query_bar(app, bar, 0) == 0){ - return(false); - } - - if (init_string.size > 0){ - String_u8 string = Su8(bar->string.str, bar->string.size, bar->string_capacity); - string_append(&string, init_string); - bar->string.size = string.string.size; - } - - b32 success = true; - - for (;;){ - // NOTE(allen|a3.4.4): This call will block until the user does one of the input -// types specified in the flags. The first set of flags are inputs you'd like to - // intercept that you don't want to abort on. The second set are inputs that - // you'd like to cause the command to abort. If an event satisfies both flags, it -// is treated as an abort. - User_Input in = get_next_input(app, EventPropertyGroup_AnyKeyboardEvent, - EventProperty_Escape|EventProperty_MouseButton); - - // NOTE(allen|a3.4.4): The responsible thing to do on abort is to end the command - // without waiting on get_next_input again. -if (in.abort){ -success = false; - break; - } - - Scratch_Block scratch(app); - b32 good_insert = false; -String_Const_u8 insert_string = to_writable(&in); - if (insert_string.str != 0 && insert_string.size > 0){ - insert_string = string_replace(scratch, insert_string, - string_u8_litexpr("\n"), - string_u8_litexpr("")); - insert_string = string_replace(scratch, insert_string, - string_u8_litexpr("\t"), - string_u8_litexpr("")); - if (force_number){ -if (string_is_integer(insert_string, 10)){ - good_insert = true; - } - } - else{ - good_insert = true; - } -} - -// NOTE(allen|a3.4.4): All we have to do to update the query bar is edit our - // local Query_Bar struct! This is handy because it means our Query_Bar - // is always correct for typical use without extra work updating the bar. - if (in.event.kind == InputEventKind_KeyStroke && - (in.event.key.code == KeyCode_Return || in.event.key.code == KeyCode_Tab)){ - break; - } - else if (in.event.kind == InputEventKind_KeyStroke && - in.event.key.code == KeyCode_Backspace){ - bar->string = backspace_utf8(bar->string); - } - else if (good_insert){ - String_u8 string = Su8(bar->string.str, bar->string.size, bar->string_capacity); - string_append(&string, insert_string); - bar->string.size = string.string.size; - } - else{ - leave_current_input_unhandled(app); - } - } - - return(success); - } - - internal b32 - query_user_string(Application_Links *app, Query_Bar *bar){ - return(query_user_general(app, bar, false, string_u8_empty)); - } - - internal b32 - query_user_number(Application_Links *app, Query_Bar *bar){ -return(query_user_general(app, bar, true, string_u8_empty)); - } - - internal b32 - query_user_number(Application_Links *app, Query_Bar *bar, i32 x){ - Scratch_Block scratch(app); - String_Const_u8 string = push_u8_stringf(scratch, "%d", x); - return(query_user_general(app, bar, true, string)); - } - - //////////////////////////////// - - internal Buffer_Identifier - buffer_identifier(char *str, i32 len){ - Buffer_Identifier identifier; - identifier.name = str; - identifier.name_len = len; - identifier.id = 0; - return(identifier); - } - - internal Buffer_Identifier - buffer_identifier(String_Const_u8 str){ - return(buffer_identifier((char*)str.str, (i32)str.size)); - } - - internal Buffer_Identifier - buffer_identifier(Buffer_ID id){ - Buffer_Identifier identifier; - identifier.name = 0; -identifier.name_len = 0; -identifier.id = id; -return(identifier); - } - - internal Buffer_ID - buffer_identifier_to_id(Application_Links *app, Buffer_Identifier identifier){ -Buffer_ID id = 0; - if (identifier.id != 0){ -id = identifier.id; - } - else{ - String_Const_u8 name = SCu8(identifier.name, identifier.name_len); - id = get_buffer_by_name(app, name, Access_Always); - if (id == 0){ - id = get_buffer_by_file_name(app, name, Access_Always); - } - } - return(id); - } - - internal Buffer_ID - buffer_identifier_to_id_create_out_buffer(Application_Links *app, Buffer_Identifier buffer_id){ - Buffer_ID result = 0; - if (buffer_id.name != 0 && buffer_id.name_len > 0){ - String_Const_u8 buffer_name = SCu8(buffer_id.name, buffer_id.name_len); - Buffer_ID buffer_attach_id = get_buffer_by_name(app, buffer_name, Access_Always); - if (buffer_attach_id != 0){ - result = buffer_attach_id; - } -else{ -buffer_attach_id = create_buffer(app, buffer_name, BufferCreate_AlwaysNew|BufferCreate_NeverAttachToFile); -if (buffer_attach_id != 0){ -buffer_set_setting(app, buffer_attach_id, BufferSetting_ReadOnly, true); - buffer_set_setting(app, buffer_attach_id, BufferSetting_Unimportant, true); - result = buffer_attach_id; -} -} -} -else{ -result = buffer_id.id; - } - return(result); - } - - //////////////////////////////// - - function void -place_begin_and_end_on_own_lines(Application_Links *app, char *begin, char *end){ - View_ID view = get_active_view(app, Access_ReadWriteVisible); - Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); - - Range_i64 range = get_view_range(app, view); - Range_i64 lines = get_line_range_from_pos_range(app, buffer, range); - range = get_pos_range_from_line_range(app, buffer, lines); - -Scratch_Block scratch(app); - - b32 min_line_blank = line_is_valid_and_blank(app, buffer, lines.min); - b32 max_line_blank = line_is_valid_and_blank(app, buffer, lines.max); - - if ((lines.min < lines.max) || (!min_line_blank)){ - String_Const_u8 begin_str = {}; - String_Const_u8 end_str = {}; - - i64 min_adjustment = 0; - i64 max_adjustment = 0; - - if (min_line_blank){ - begin_str = push_u8_stringf(scratch, "\n%s", begin); - min_adjustment += 1; - } - else{ - begin_str = push_u8_stringf(scratch, "%s\n", begin); - } - if (max_line_blank){ -end_str = push_u8_stringf(scratch, "%s\n", end); - } - else{ - end_str = push_u8_stringf(scratch, "\n%s", end); - max_adjustment += 1; -} - -max_adjustment += begin_str.size; -Range_i64 new_pos = Ii64(range.min + min_adjustment, range.max + max_adjustment); - - History_Group group = history_group_begin(app, buffer); - buffer_replace_range(app, buffer, Ii64(range.min), begin_str); - buffer_replace_range(app, buffer, Ii64(range.max + begin_str.size), end_str); - history_group_end(group); - - set_view_range(app, view, new_pos); - } - else{ - String_Const_u8 str = push_u8_stringf(scratch, "%s\n\n%s", begin, end); - buffer_replace_range(app, buffer, range, str); - i64 center_pos = range.min + cstring_length(begin) + 1; - view_set_cursor_and_preferred_x(app, view, seek_pos(center_pos)); - view_set_mark(app, view, seek_pos(center_pos)); - } - } - - //////////////////////////////// - - function Face_ID - get_view_face_id(Application_Links *app, View_ID view){ - Buffer_ID buffer = view_get_buffer(app, view, Access_Always); - return(get_face_id(app, buffer)); - } - - function Face_Metrics - get_view_face_metrics(Application_Links *app, View_ID view){ - Face_ID face = get_view_face_id(app, view); - return(get_face_metrics(app, face)); - } - - function f32 - get_view_line_height(Application_Links *app, View_ID view){ - Face_Metrics metrics = get_view_face_metrics(app, view); - return(metrics.line_height); - } - -internal View_ID - open_view(Application_Links *app, View_ID view_location, View_Split_Position position){ - View_ID result = 0; - if (view_location != 0 && view_exists(app, view_location)){ - Panel_ID panel_id = view_get_panel(app, view_location); - if (panel_id != 0){ - Dimension split = (position == ViewSplit_Left || - position == ViewSplit_Right)?Dimension_X:Dimension_Y; - Side side = (position == ViewSplit_Left || - position == ViewSplit_Top)?Side_Min:Side_Max; - if (panel_split(app, panel_id, split)){ - Panel_ID new_panel_id = panel_get_child(app, panel_id, side); - if (new_panel_id != 0){ -View_ID new_view_id = panel_get_view(app, new_panel_id, - Access_Always); - if (new_view_id != 0){ - result = new_view_id; - } - } -} -} -} -return(result); -} - -internal View_ID -get_first_view_with_buffer(Application_Links *app, Buffer_ID buffer_id){ - View_ID result = {}; - if (buffer_id != 0){ -for (View_ID test = get_view_next(app, 0, Access_Always); -test != 0; - test = get_view_next(app, test, Access_Always)){ - Buffer_ID test_buffer = view_get_buffer(app, test, Access_Always); - if (test_buffer == buffer_id){ - result = test; - break; - } - } - } - return(result); - } - - internal b32 -open_file(Application_Links *app, Buffer_ID *buffer_out, String_Const_u8 file_name, b32 background, b32 never_new){ - b32 result = false; -Buffer_ID buffer = get_buffer_by_name(app, file_name, Access_ReadVisible); - b32 exists = buffer_exists(app, buffer); - if (!exists){ - Buffer_Create_Flag flags = 0; - if (background){ - flags |= BufferCreate_Background; - } - if (never_new){ - flags |= BufferCreate_NeverNew; - } - buffer = create_buffer(app, file_name, flags); - exists = buffer_exists(app, buffer); - } - if (exists){ - if (buffer_out != 0){ - *buffer_out = buffer; - } - result = true; - } - return(result); - } - -internal b32 -view_open_file(Application_Links *app, View_ID view, String_Const_u8 file_name, b32 never_new){ - b32 result = false; - if (view != 0){ - Buffer_ID buffer = 0; - if (open_file(app, &buffer, file_name, false, never_new)){ - view_set_buffer(app, view, buffer, 0); - result = true; - } -} - return(result); -} - -internal void -view_disable_highlight_range(Application_Links *app, View_ID view){ - Managed_Scope scope = view_get_managed_scope(app, view); - Managed_Object *highlight = scope_attachment(app, scope, view_highlight_range, Managed_Object); - if (*highlight != 0){ - managed_object_free(app, *highlight); - } - managed_scope_attachment_erase(app, scope, view_highlight_range); -managed_scope_attachment_erase(app, scope, view_highlight_buffer); - } - - internal void - view_set_highlight_range(Application_Links *app, View_ID view, Range_i64 range){ - view_disable_highlight_range(app, view); - - Buffer_ID buffer = view_get_buffer(app, view, Access_Always); - Managed_Scope scope = view_get_managed_scope(app, view); - Managed_Object *highlight = scope_attachment(app, scope, view_highlight_range, Managed_Object); - *highlight = alloc_buffer_markers_on_buffer(app, buffer, 2, &scope); -Marker markers[2] = {}; -markers[0].pos = range.min; - markers[1].pos = range.max; - managed_object_store_data(app, *highlight, 0, 2, markers); - Buffer_ID *highlight_buffer = scope_attachment(app, scope, view_highlight_buffer, Buffer_ID); - *highlight_buffer = buffer; -} - - function void - view_look_at_region(Application_Links *app, View_ID view, i64 major_pos, i64 minor_pos){ - Range_i64 range = Ii64(major_pos, minor_pos); - b32 bottom_major = false; - if (major_pos == range.max){ - bottom_major = true; -} - -Buffer_Cursor top = view_compute_cursor(app, view, seek_pos(range.min)); - if (top.line > 0){ - Buffer_Cursor bottom = view_compute_cursor(app, view, seek_pos(range.max)); - if (bottom.line > 0){ - Rect_f32 region = view_get_buffer_region(app, view); - f32 view_height = rect_height(region); -f32 skirt_height = view_height*.1f; - Range_f32 acceptable_y = If32(skirt_height, view_height*.9f); - - f32 target_height = view_line_y_difference(app, view, bottom.line + 1, top.line); - -f32 line_height = get_view_line_height(app, view); - if (target_height + 2*line_height > view_height){ - i64 major_line = bottom.line; - if (range.min == major_pos){ - major_line = top.line; - } - - Buffer_Scroll scroll = view_get_buffer_scroll(app, view); - scroll.target.line_number = major_line; - scroll.target.pixel_shift.y = -skirt_height; - view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); - } -else{ - Buffer_Scroll scroll = view_get_buffer_scroll(app, view); - Vec2_f32 top_p = view_relative_xy_of_pos(app, view, scroll.position.line_number, range.min); - top_p -= scroll.position.pixel_shift; -if (top_p.y < acceptable_y.min){ - scroll.target.line_number = top.line; - scroll.target.pixel_shift.y = -skirt_height; - view_set_buffer_scroll(app, view, scroll, SetBufferScroll_NoCursorChange); - } - else{ - Vec2_f32 bot_p = view_relative_xy_of_pos(app, view, scroll.position.line_number, range.max); - bot_p -= scroll.position.pixel_shift; - if (bot_p.y > acceptable_y.max){ - scroll.target.line_number = bottom.line; - scroll.target.pixel_shift.y = skirt_height - view_height; - view_set_buffer_scroll(app, view, scroll, SetBufferScroll_NoCursorChange); - } - } - } -} - } - } - - function void - view_look_at_region(Application_Links *app, View_ID view, Range_i64 range){ - view_look_at_region(app, view, range.min, range.max); - } - - //////////////////////////////// - - function Buffer_ID - get_buffer_next_looped(Application_Links *app, Buffer_ID buffer, Access_Flag access){ - buffer = get_buffer_next(app, buffer, access); - if (buffer == 0){ -buffer = get_buffer_next(app, 0, access); - } - return(buffer); - } - - //////////////////////////////// - - internal View_ID - get_next_view_looped_all_panels(Application_Links *app, View_ID view_id, Access_Flag access){ -view_id = get_view_next(app, view_id, access); - if (view_id == 0){ - view_id = get_view_next(app, 0, access); -} - return(view_id); - } - - internal View_ID - get_prev_view_looped_all_panels(Application_Links *app, View_ID view_id, Access_Flag access){ - view_id = get_view_prev(app, view_id, access); - if (view_id == 0){ - view_id = get_view_prev(app, 0, access); - } - return(view_id); - } - - //////////////////////////////// - - internal Buffer_Kill_Result - try_buffer_kill(Application_Links *app, Buffer_ID buffer, View_ID gui_view_id, Buffer_Kill_Flag flags){ - Buffer_Kill_Result result = buffer_kill(app, buffer, flags); - if (result == BufferKillResult_Dirty){ - if (do_buffer_kill_user_check(app, buffer, gui_view_id)){ - result = buffer_kill(app, buffer, BufferKill_AlwaysKill); -} - } - return(result); - } - - //////////////////////////////// - - internal String_Const_u8 -get_query_string(Application_Links *app, char *query_str, u8 *string_space, i32 space_size){ - Query_Bar_Group group(app); -Query_Bar bar = {}; -bar.prompt = SCu8((u8*)query_str); -bar.string = SCu8(string_space, (u64)0); -bar.string_capacity = space_size; -if (!query_user_string(app, &bar)){ - bar.string.size = 0; - } - return(bar.string); - } - -internal Token* - get_token_from_pos(Application_Links *app, Token_Array *array, u64 pos){ - Token *result = 0; - if (array->count > 0){ - i64 index = token_index_from_pos(array, pos); -result = array->tokens + index; -} -return(result); -} - -internal Token* -get_token_from_pos(Application_Links *app, Buffer_ID buffer, u64 pos){ - Token_Array array = get_token_array_from_buffer(app, buffer); -return(get_token_from_pos(app, &array, pos)); -} - -internal String_Const_u8 - push_token_or_word_under_pos(Application_Links *app, Arena *arena, Buffer_ID buffer, u64 pos){ - String_Const_u8 result = {}; -Token *token = get_token_from_pos(app, buffer, pos); -if (token != 0 && token->size > 0 && token->kind != TokenBaseKind_Whitespace){ - Range_i64 range = Ii64(token); - result = push_buffer_range(app, arena, buffer, range); - } - return(result); -} - - internal String_Const_u8 - push_token_or_word_under_active_cursor(Application_Links *app, Arena *arena){ - View_ID view = get_active_view(app, Access_Always); - Buffer_ID buffer = view_get_buffer(app, view, Access_Always); - i64 pos = view_get_cursor_pos(app, view); -return(push_token_or_word_under_pos(app, arena, buffer, pos)); - } - - //////////////////////////////// - - internal b32 -file_exists(Application_Links *app, String_Const_u8 file_name){ - Scratch_Block scratch(app); - File_Attributes attributes = system_quick_file_attributes(scratch, file_name); -return(attributes.last_write_time > 0); - } - - internal b32 - file_exists_and_is_file(Application_Links *app, String_Const_u8 file_name){ - Scratch_Block scratch(app); -File_Attributes attributes = system_quick_file_attributes(scratch, file_name); - return(attributes.last_write_time > 0 && !HasFlag(attributes.flags, FileAttribute_IsDirectory)); - } - - internal b32 - file_exists_and_is_folder(Application_Links *app, String_Const_u8 file_name){ - Scratch_Block scratch(app); -File_Attributes attributes = system_quick_file_attributes(scratch, file_name); - return(attributes.last_write_time > 0 && HasFlag(attributes.flags, FileAttribute_IsDirectory)); - } - -internal Data - dump_file_handle(Arena *arena, FILE *file){ -Data result = {}; - if (file != 0){ - fseek(file, 0, SEEK_END); - u64 size = ftell(file); - char *mem = push_array(arena, char, size); - if (mem != 0){ - fseek(file, 0, SEEK_SET); - fread(mem, 1, (size_t)size, file); - result = make_data(mem, size); - } - } - return(result); - } - -internal String_Const_u8 -push_file_search_up_path(Application_Links *app, Arena *arena, String_Const_u8 start_path, String_Const_u8 file_name){ -String_Const_u8 result = {}; -String_Const_u8 path = start_path; -for (;path.size > 0;){ - Temp_Memory temp = begin_temp(arena); - if (character_is_slash(string_get_character(path, path.size - 1))){ - path = string_chop(path, 1); - } - String_Const_u8 full_path = push_u8_stringf(arena, "%.*s/%.*s", - string_expand(path), -string_expand(file_name)); - if (file_exists(app, full_path)){ - result = full_path; - break; - } - path = string_remove_last_folder(path); - end_temp(temp); - } - return(result); - } - - internal FILE* - open_file_try_current_path_then_binary_path(Application_Links *app, char *file_name){ - FILE *file = fopen(file_name, "rb"); - if (file == 0){ -Scratch_Block scratch(app); - List_String_Const_u8 list = {}; - string_list_push(scratch, &list, system_get_path(scratch, SystemPath_Binary)); - string_list_push_overlap(scratch, &list, '/', SCu8(file_name)); - String_Const_u8 str = string_list_flatten(scratch, list, StringFill_NullTerminate); -file = fopen((char*)str.str, "rb"); -} -return(file); -} - -internal FILE* -open_file(Arena *scratch, String_Const_u8 name){ -Temp_Memory temp = begin_temp(scratch); - String_Const_u8 name_copy = push_string_copy(scratch, name); - FILE *file = fopen((char*)name_copy.str, "rb"); - end_temp(temp); - return(file); - } - - internal File_Name_Data - dump_file(Arena *arena, String_Const_u8 file_name){ -File_Name_Data result = {}; - FILE *file = open_file(arena, file_name); -if (file != 0){ - result.file_name = file_name; - result.data = dump_file_handle(arena, file); -fclose(file); - } -return(result); - } - - internal File_Name_Data - dump_file_search_up_path(Application_Links *app, Arena *arena, String_Const_u8 path, String_Const_u8 file_name){ - File_Name_Data result = {}; - String_Const_u8 full_path = push_file_search_up_path(app, arena, path, file_name); - if (full_path.size > 0){ - result = dump_file(arena, full_path); -} -return(result); -} - -internal void -sort_pairs_by_key__quick(Sort_Pair_i32 *pairs, i32 first, i32 one_past_last){ - i32 dif = one_past_last - first; - if (dif >= 2){ - i32 pivot = one_past_last - 1; - Sort_Pair_i32 pivot_pair = pairs[pivot]; - i32 j = first; - b32 interleave = false; - for (i32 i = first; i < pivot; i += 1){ - Sort_Pair_i32 pair = pairs[i]; - if (pair.key < pivot_pair.key){ - pairs[i] = pairs[j]; - pairs[j] = pair; - j += 1; -} - else if (pair.key == pivot_pair.key){ - if (interleave){ - pairs[i] = pairs[j]; - pairs[j] = pair; - j += 1; - } - interleave = !interleave; - } - } - pairs[pivot] = pairs[j]; - pairs[j] = pivot_pair; - sort_pairs_by_key__quick(pairs, first, j); - sort_pairs_by_key__quick(pairs, j + 1, one_past_last); - } - } - - internal void - sort_pairs_by_key(Sort_Pair_i32 *pairs, i32 count){ - sort_pairs_by_key__quick(pairs, 0, count); - } - - internal Range_i32_Array - get_ranges_of_duplicate_keys(Arena *arena, i32 *keys, i32 stride, i32 count){ - Range_i32_Array result = {}; - result.ranges = push_array(arena, Range_i32, count); -u8 *ptr = (u8*)keys; - i32 start_i = 0; - for (i32 i = 1; i <= count; i += 1){ - b32 is_end = false; - if (i == count){ - is_end = true; - } - else if (*(i32*)(ptr + i*stride) != *(i32*)(ptr + start_i*stride)){ - is_end = true; - } - if (is_end){ - Range_i32 *new_range = &result.ranges[result.count++]; - new_range->first = start_i; -new_range->one_past_last = i; - start_i = i; - } - } - pop_array(arena, Range_i32, count - result.count); - return(result); - } - - internal void - no_mark_snap_to_cursor(Application_Links *app, Managed_Scope view_scope){ - b32 *snap_to_cursor = scope_attachment(app, view_scope, view_snap_mark_to_cursor, b32); - *snap_to_cursor = false; - } - - internal void - no_mark_snap_to_cursor(Application_Links *app, View_ID view_id){ - Managed_Scope scope = view_get_managed_scope(app, view_id); - no_mark_snap_to_cursor(app, scope); - } - - internal void - no_mark_snap_to_cursor_if_shift(Application_Links *app, View_ID view_id){ - Scratch_Block scratch(app); - Input_Modifier_Set mods = system_get_keyboard_modifiers(scratch); - if (has_modifier(&mods, KeyCode_Shift)){ -no_mark_snap_to_cursor(app, view_id); - } - } - - internal b32 - view_has_highlighted_range(Application_Links *app, View_ID view){ -b32 result = false; - if (fcoder_mode == FCoderMode_NotepadLike){ - i64 pos = view_get_cursor_pos(app, view); -i64 mark = view_get_mark_pos(app, view); -result = (pos != mark); -} -return(result); -} - -internal b32 - if_view_has_highlighted_range_delete_range(Application_Links *app, View_ID view_id){ - b32 result = false; - if (view_has_highlighted_range(app, view_id)){ - Range_i64 range = get_view_range(app, view_id); - Buffer_ID buffer = view_get_buffer(app, view_id, Access_ReadWriteVisible); - buffer_replace_range(app, buffer, range, string_u8_litexpr("")); - result = true; - } - return(result); - } - - internal void - begin_notepad_mode(Application_Links *app){ - fcoder_mode = FCoderMode_NotepadLike; -for (View_ID view = get_view_next(app, 0, Access_Always); - view != 0; -view = get_view_next(app, view, Access_Always)){ - i64 pos = view_get_cursor_pos(app, view); - view_set_mark(app, view, seek_pos(pos)); -} } //////////////////////////////// - internal void +Query_Bar_Group::Query_Bar_Group(Application_Links *app){ + this->app = app; + this->view = get_active_view(app, Access_Always); +} + +Query_Bar_Group::Query_Bar_Group(Application_Links *app, View_ID view){ + this->app = app; + this->view = view; +} + +Query_Bar_Group::~Query_Bar_Group(){ + clear_all_query_bars(this->app, this->view); +} + +internal b32 +query_user_general(Application_Links *app, Query_Bar *bar, b32 force_number, String_Const_u8 init_string){ + if (start_query_bar(app, bar, 0) == 0){ + return(false); + } + + if (init_string.size > 0){ + String_u8 string = Su8(bar->string.str, bar->string.size, bar->string_capacity); + string_append(&string, init_string); + bar->string.size = string.string.size; + } + + b32 success = true; + for (;;){ + User_Input in = get_next_input(app, EventPropertyGroup_Any, + EventProperty_Escape|EventProperty_MouseButton); + if (in.abort){ + success = false; + break; + } + + Scratch_Block scratch(app); + b32 good_insert = false; + String_Const_u8 insert_string = to_writable(&in); + if (insert_string.str != 0 && insert_string.size > 0){ + insert_string = string_replace(scratch, insert_string, + string_u8_litexpr("\n"), + string_u8_litexpr("")); + insert_string = string_replace(scratch, insert_string, + string_u8_litexpr("\t"), + string_u8_litexpr("")); + if (force_number){ + if (string_is_integer(insert_string, 10)){ + good_insert = true; + } + } + else{ + good_insert = true; + } + } + + if (in.event.kind == InputEventKind_KeyStroke && + (in.event.key.code == KeyCode_Return || in.event.key.code == KeyCode_Tab)){ + break; + } + else if (in.event.kind == InputEventKind_KeyStroke && + in.event.key.code == KeyCode_Backspace){ + bar->string = backspace_utf8(bar->string); + } + else if (good_insert){ + String_u8 string = Su8(bar->string.str, bar->string.size, bar->string_capacity); + string_append(&string, insert_string); + bar->string.size = string.string.size; + } + else{ + // NOTE(allen): is the user trying to execute another command? + View_ID view = get_this_ctx_view(app, Access_Always); + View_Context ctx = view_current_context(app, view); + Mapping *mapping = ctx.mapping; + Command_Map *map = mapping_get_map(mapping, ctx.map_id); + Command_Binding binding = map_get_binding_recursive(mapping, map, &in.event); + if (binding.custom != 0){ + Command_Metadata *metadata = get_command_metadata(binding.custom); + if (metadata != 0){ + if (metadata->is_ui){ + view_enqueue_command_function(app, view, binding.custom); + break; + } + } + binding.custom(app); + } + else{ + leave_current_input_unhandled(app); + } + } + } + + return(success); +} + +internal b32 +query_user_string(Application_Links *app, Query_Bar *bar){ + return(query_user_general(app, bar, false, string_u8_empty)); +} + +internal b32 +query_user_number(Application_Links *app, Query_Bar *bar){ + return(query_user_general(app, bar, true, string_u8_empty)); +} + +internal b32 +query_user_number(Application_Links *app, Query_Bar *bar, i32 x){ + Scratch_Block scratch(app); + String_Const_u8 string = push_u8_stringf(scratch, "%d", x); + return(query_user_general(app, bar, true, string)); +} + +//////////////////////////////// + +internal Buffer_Identifier +buffer_identifier(char *str, i32 len){ + Buffer_Identifier identifier; + identifier.name = str; + identifier.name_len = len; + identifier.id = 0; + return(identifier); +} + +internal Buffer_Identifier +buffer_identifier(String_Const_u8 str){ + return(buffer_identifier((char*)str.str, (i32)str.size)); +} + +internal Buffer_Identifier +buffer_identifier(Buffer_ID id){ + Buffer_Identifier identifier; + identifier.name = 0; + identifier.name_len = 0; + identifier.id = id; + return(identifier); +} + +internal Buffer_ID +buffer_identifier_to_id(Application_Links *app, Buffer_Identifier identifier){ + Buffer_ID id = 0; + if (identifier.id != 0){ + id = identifier.id; + } + else{ + String_Const_u8 name = SCu8(identifier.name, identifier.name_len); + id = get_buffer_by_name(app, name, Access_Always); + if (id == 0){ + id = get_buffer_by_file_name(app, name, Access_Always); + } + } + return(id); +} + +internal Buffer_ID +buffer_identifier_to_id_create_out_buffer(Application_Links *app, Buffer_Identifier buffer_id){ + Buffer_ID result = 0; + if (buffer_id.name != 0 && buffer_id.name_len > 0){ + String_Const_u8 buffer_name = SCu8(buffer_id.name, buffer_id.name_len); + Buffer_ID buffer_attach_id = get_buffer_by_name(app, buffer_name, Access_Always); + if (buffer_attach_id != 0){ + result = buffer_attach_id; + } + else{ + buffer_attach_id = create_buffer(app, buffer_name, BufferCreate_AlwaysNew|BufferCreate_NeverAttachToFile); + if (buffer_attach_id != 0){ + buffer_set_setting(app, buffer_attach_id, BufferSetting_ReadOnly, true); + buffer_set_setting(app, buffer_attach_id, BufferSetting_Unimportant, true); + result = buffer_attach_id; + } + } + } + else{ + result = buffer_id.id; + } + return(result); +} + +//////////////////////////////// + +function void +place_begin_and_end_on_own_lines(Application_Links *app, char *begin, char *end){ + View_ID view = get_active_view(app, Access_ReadWriteVisible); + Buffer_ID buffer = view_get_buffer(app, view, Access_ReadWriteVisible); + + Range_i64 range = get_view_range(app, view); + Range_i64 lines = get_line_range_from_pos_range(app, buffer, range); + range = get_pos_range_from_line_range(app, buffer, lines); + + Scratch_Block scratch(app); + + b32 min_line_blank = line_is_valid_and_blank(app, buffer, lines.min); + b32 max_line_blank = line_is_valid_and_blank(app, buffer, lines.max); + + if ((lines.min < lines.max) || (!min_line_blank)){ + String_Const_u8 begin_str = {}; + String_Const_u8 end_str = {}; + + i64 min_adjustment = 0; + i64 max_adjustment = 0; + + if (min_line_blank){ + begin_str = push_u8_stringf(scratch, "\n%s", begin); + min_adjustment += 1; + } + else{ + begin_str = push_u8_stringf(scratch, "%s\n", begin); + } + if (max_line_blank){ + end_str = push_u8_stringf(scratch, "%s\n", end); + } + else{ + end_str = push_u8_stringf(scratch, "\n%s", end); + max_adjustment += 1; + } + + max_adjustment += begin_str.size; + Range_i64 new_pos = Ii64(range.min + min_adjustment, range.max + max_adjustment); + + History_Group group = history_group_begin(app, buffer); + buffer_replace_range(app, buffer, Ii64(range.min), begin_str); + buffer_replace_range(app, buffer, Ii64(range.max + begin_str.size), end_str); + history_group_end(group); + + set_view_range(app, view, new_pos); + } + else{ + String_Const_u8 str = push_u8_stringf(scratch, "%s\n\n%s", begin, end); + buffer_replace_range(app, buffer, range, str); + i64 center_pos = range.min + cstring_length(begin) + 1; + view_set_cursor_and_preferred_x(app, view, seek_pos(center_pos)); + view_set_mark(app, view, seek_pos(center_pos)); + } +} + +//////////////////////////////// + +function Face_ID +get_view_face_id(Application_Links *app, View_ID view){ + Buffer_ID buffer = view_get_buffer(app, view, Access_Always); + return(get_face_id(app, buffer)); +} + +function Face_Metrics +get_view_face_metrics(Application_Links *app, View_ID view){ + Face_ID face = get_view_face_id(app, view); + return(get_face_metrics(app, face)); +} + +function f32 +get_view_line_height(Application_Links *app, View_ID view){ + Face_Metrics metrics = get_view_face_metrics(app, view); + return(metrics.line_height); +} + +internal View_ID +open_view(Application_Links *app, View_ID view_location, View_Split_Position position){ + View_ID result = 0; + if (view_location != 0 && view_exists(app, view_location)){ + Panel_ID panel_id = view_get_panel(app, view_location); + if (panel_id != 0){ + Dimension split = (position == ViewSplit_Left || + position == ViewSplit_Right)?Dimension_X:Dimension_Y; + Side side = (position == ViewSplit_Left || + position == ViewSplit_Top)?Side_Min:Side_Max; + if (panel_split(app, panel_id, split)){ + Panel_ID new_panel_id = panel_get_child(app, panel_id, side); + if (new_panel_id != 0){ + View_ID new_view_id = panel_get_view(app, new_panel_id, + Access_Always); + if (new_view_id != 0){ + result = new_view_id; + } + } + } + } + } + return(result); +} + +internal View_ID +get_first_view_with_buffer(Application_Links *app, Buffer_ID buffer_id){ + View_ID result = {}; + if (buffer_id != 0){ + for (View_ID test = get_view_next(app, 0, Access_Always); + test != 0; + test = get_view_next(app, test, Access_Always)){ + Buffer_ID test_buffer = view_get_buffer(app, test, Access_Always); + if (test_buffer == buffer_id){ + result = test; + break; + } + } + } + return(result); +} + +internal b32 +open_file(Application_Links *app, Buffer_ID *buffer_out, String_Const_u8 file_name, b32 background, b32 never_new){ + b32 result = false; + Buffer_ID buffer = get_buffer_by_name(app, file_name, Access_ReadVisible); + b32 exists = buffer_exists(app, buffer); + if (!exists){ + Buffer_Create_Flag flags = 0; + if (background){ + flags |= BufferCreate_Background; + } + if (never_new){ + flags |= BufferCreate_NeverNew; + } + buffer = create_buffer(app, file_name, flags); + exists = buffer_exists(app, buffer); + } + if (exists){ + if (buffer_out != 0){ + *buffer_out = buffer; + } + result = true; + } + return(result); +} + +internal b32 +view_open_file(Application_Links *app, View_ID view, String_Const_u8 file_name, b32 never_new){ + b32 result = false; + if (view != 0){ + Buffer_ID buffer = 0; + if (open_file(app, &buffer, file_name, false, never_new)){ + view_set_buffer(app, view, buffer, 0); + result = true; + } + } + return(result); +} + +internal void +view_disable_highlight_range(Application_Links *app, View_ID view){ + Managed_Scope scope = view_get_managed_scope(app, view); + Managed_Object *highlight = scope_attachment(app, scope, view_highlight_range, Managed_Object); + if (*highlight != 0){ + managed_object_free(app, *highlight); + } + managed_scope_attachment_erase(app, scope, view_highlight_range); + managed_scope_attachment_erase(app, scope, view_highlight_buffer); +} + +internal void +view_set_highlight_range(Application_Links *app, View_ID view, Range_i64 range){ + view_disable_highlight_range(app, view); + + Buffer_ID buffer = view_get_buffer(app, view, Access_Always); + Managed_Scope scope = view_get_managed_scope(app, view); + Managed_Object *highlight = scope_attachment(app, scope, view_highlight_range, Managed_Object); + *highlight = alloc_buffer_markers_on_buffer(app, buffer, 2, &scope); + Marker markers[2] = {}; + markers[0].pos = range.min; + markers[1].pos = range.max; + managed_object_store_data(app, *highlight, 0, 2, markers); + Buffer_ID *highlight_buffer = scope_attachment(app, scope, view_highlight_buffer, Buffer_ID); + *highlight_buffer = buffer; +} + +function void +view_look_at_region(Application_Links *app, View_ID view, i64 major_pos, i64 minor_pos){ + Range_i64 range = Ii64(major_pos, minor_pos); + b32 bottom_major = false; + if (major_pos == range.max){ + bottom_major = true; + } + + Buffer_Cursor top = view_compute_cursor(app, view, seek_pos(range.min)); + if (top.line > 0){ + Buffer_Cursor bottom = view_compute_cursor(app, view, seek_pos(range.max)); + if (bottom.line > 0){ + Rect_f32 region = view_get_buffer_region(app, view); + f32 view_height = rect_height(region); + f32 skirt_height = view_height*.1f; + Range_f32 acceptable_y = If32(skirt_height, view_height*.9f); + + f32 target_height = view_line_y_difference(app, view, bottom.line + 1, top.line); + + f32 line_height = get_view_line_height(app, view); + if (target_height + 2*line_height > view_height){ + i64 major_line = bottom.line; + if (range.min == major_pos){ + major_line = top.line; + } + + Buffer_Scroll scroll = view_get_buffer_scroll(app, view); + scroll.target.line_number = major_line; + scroll.target.pixel_shift.y = -skirt_height; + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_SnapCursorIntoView); + } + else{ + Buffer_Scroll scroll = view_get_buffer_scroll(app, view); + Vec2_f32 top_p = view_relative_xy_of_pos(app, view, scroll.position.line_number, range.min); + top_p -= scroll.position.pixel_shift; + if (top_p.y < acceptable_y.min){ + scroll.target.line_number = top.line; + scroll.target.pixel_shift.y = -skirt_height; + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_NoCursorChange); + } + else{ + Vec2_f32 bot_p = view_relative_xy_of_pos(app, view, scroll.position.line_number, range.max); + bot_p -= scroll.position.pixel_shift; + if (bot_p.y > acceptable_y.max){ + scroll.target.line_number = bottom.line; + scroll.target.pixel_shift.y = skirt_height - view_height; + view_set_buffer_scroll(app, view, scroll, SetBufferScroll_NoCursorChange); + } + } + } + } + } +} + +function void +view_look_at_region(Application_Links *app, View_ID view, Range_i64 range){ + view_look_at_region(app, view, range.min, range.max); +} + +//////////////////////////////// + +function Buffer_ID +get_buffer_next_looped(Application_Links *app, Buffer_ID buffer, Access_Flag access){ + buffer = get_buffer_next(app, buffer, access); + if (buffer == 0){ + buffer = get_buffer_next(app, 0, access); + } + return(buffer); +} + +//////////////////////////////// + +internal View_ID +get_next_view_looped_all_panels(Application_Links *app, View_ID view_id, Access_Flag access){ + view_id = get_view_next(app, view_id, access); + if (view_id == 0){ + view_id = get_view_next(app, 0, access); + } + return(view_id); +} + +internal View_ID +get_prev_view_looped_all_panels(Application_Links *app, View_ID view_id, Access_Flag access){ + view_id = get_view_prev(app, view_id, access); + if (view_id == 0){ + view_id = get_view_prev(app, 0, access); + } + return(view_id); +} + +//////////////////////////////// + +internal Buffer_Kill_Result +try_buffer_kill(Application_Links *app, Buffer_ID buffer, View_ID gui_view_id, Buffer_Kill_Flag flags){ + Buffer_Kill_Result result = buffer_kill(app, buffer, flags); + if (result == BufferKillResult_Dirty){ + if (do_buffer_kill_user_check(app, buffer, gui_view_id)){ + result = buffer_kill(app, buffer, BufferKill_AlwaysKill); + } + } + return(result); +} + +//////////////////////////////// + +internal String_Const_u8 +get_query_string(Application_Links *app, char *query_str, u8 *string_space, i32 space_size){ + Query_Bar_Group group(app); + Query_Bar bar = {}; + bar.prompt = SCu8((u8*)query_str); + bar.string = SCu8(string_space, (u64)0); + bar.string_capacity = space_size; + if (!query_user_string(app, &bar)){ + bar.string.size = 0; + } + return(bar.string); +} + +internal Token* +get_token_from_pos(Application_Links *app, Token_Array *array, u64 pos){ + Token *result = 0; + if (array->count > 0){ + i64 index = token_index_from_pos(array, pos); + result = array->tokens + index; + } + return(result); +} + +internal Token* +get_token_from_pos(Application_Links *app, Buffer_ID buffer, u64 pos){ + Token_Array array = get_token_array_from_buffer(app, buffer); + return(get_token_from_pos(app, &array, pos)); +} + +internal String_Const_u8 +push_token_or_word_under_pos(Application_Links *app, Arena *arena, Buffer_ID buffer, u64 pos){ + String_Const_u8 result = {}; + Token *token = get_token_from_pos(app, buffer, pos); + if (token != 0 && token->size > 0 && token->kind != TokenBaseKind_Whitespace){ + Range_i64 range = Ii64(token); + result = push_buffer_range(app, arena, buffer, range); + } + return(result); +} + +internal String_Const_u8 +push_token_or_word_under_active_cursor(Application_Links *app, Arena *arena){ + View_ID view = get_active_view(app, Access_Always); + Buffer_ID buffer = view_get_buffer(app, view, Access_Always); + i64 pos = view_get_cursor_pos(app, view); + return(push_token_or_word_under_pos(app, arena, buffer, pos)); +} + +//////////////////////////////// + +internal b32 +file_exists(Application_Links *app, String_Const_u8 file_name){ + Scratch_Block scratch(app); + File_Attributes attributes = system_quick_file_attributes(scratch, file_name); + return(attributes.last_write_time > 0); +} + +internal b32 +file_exists_and_is_file(Application_Links *app, String_Const_u8 file_name){ + Scratch_Block scratch(app); + File_Attributes attributes = system_quick_file_attributes(scratch, file_name); + return(attributes.last_write_time > 0 && !HasFlag(attributes.flags, FileAttribute_IsDirectory)); +} + +internal b32 +file_exists_and_is_folder(Application_Links *app, String_Const_u8 file_name){ + Scratch_Block scratch(app); + File_Attributes attributes = system_quick_file_attributes(scratch, file_name); + return(attributes.last_write_time > 0 && HasFlag(attributes.flags, FileAttribute_IsDirectory)); +} + +internal Data +dump_file_handle(Arena *arena, FILE *file){ + Data result = {}; + if (file != 0){ + fseek(file, 0, SEEK_END); + u64 size = ftell(file); + char *mem = push_array(arena, char, size); + if (mem != 0){ + fseek(file, 0, SEEK_SET); + fread(mem, 1, (size_t)size, file); + result = make_data(mem, size); + } + } + return(result); +} + +internal String_Const_u8 +push_file_search_up_path(Application_Links *app, Arena *arena, String_Const_u8 start_path, String_Const_u8 file_name){ + String_Const_u8 result = {}; + String_Const_u8 path = start_path; + for (;path.size > 0;){ + Temp_Memory temp = begin_temp(arena); + if (character_is_slash(string_get_character(path, path.size - 1))){ + path = string_chop(path, 1); + } + String_Const_u8 full_path = push_u8_stringf(arena, "%.*s/%.*s", + string_expand(path), + string_expand(file_name)); + if (file_exists(app, full_path)){ + result = full_path; + break; + } + path = string_remove_last_folder(path); + end_temp(temp); + } + return(result); +} + +internal FILE* +open_file_try_current_path_then_binary_path(Application_Links *app, char *file_name){ + FILE *file = fopen(file_name, "rb"); + if (file == 0){ + Scratch_Block scratch(app); + List_String_Const_u8 list = {}; + string_list_push(scratch, &list, system_get_path(scratch, SystemPath_Binary)); + string_list_push_overlap(scratch, &list, '/', SCu8(file_name)); + String_Const_u8 str = string_list_flatten(scratch, list, StringFill_NullTerminate); + file = fopen((char*)str.str, "rb"); + } + return(file); +} + +internal FILE* +open_file(Arena *scratch, String_Const_u8 name){ + Temp_Memory temp = begin_temp(scratch); + String_Const_u8 name_copy = push_string_copy(scratch, name); + FILE *file = fopen((char*)name_copy.str, "rb"); + end_temp(temp); + return(file); +} + +internal File_Name_Data +dump_file(Arena *arena, String_Const_u8 file_name){ + File_Name_Data result = {}; + FILE *file = open_file(arena, file_name); + if (file != 0){ + result.file_name = file_name; + result.data = dump_file_handle(arena, file); + fclose(file); + } + return(result); +} + +internal File_Name_Data +dump_file_search_up_path(Application_Links *app, Arena *arena, String_Const_u8 path, String_Const_u8 file_name){ + File_Name_Data result = {}; + String_Const_u8 full_path = push_file_search_up_path(app, arena, path, file_name); + if (full_path.size > 0){ + result = dump_file(arena, full_path); + } + return(result); +} + +internal void +sort_pairs_by_key__quick(Sort_Pair_i32 *pairs, i32 first, i32 one_past_last){ + i32 dif = one_past_last - first; + if (dif >= 2){ + i32 pivot = one_past_last - 1; + Sort_Pair_i32 pivot_pair = pairs[pivot]; + i32 j = first; + b32 interleave = false; + for (i32 i = first; i < pivot; i += 1){ + Sort_Pair_i32 pair = pairs[i]; + if (pair.key < pivot_pair.key){ + pairs[i] = pairs[j]; + pairs[j] = pair; + j += 1; + } + else if (pair.key == pivot_pair.key){ + if (interleave){ + pairs[i] = pairs[j]; + pairs[j] = pair; + j += 1; + } + interleave = !interleave; + } + } + pairs[pivot] = pairs[j]; + pairs[j] = pivot_pair; + sort_pairs_by_key__quick(pairs, first, j); + sort_pairs_by_key__quick(pairs, j + 1, one_past_last); + } +} + +internal void +sort_pairs_by_key(Sort_Pair_i32 *pairs, i32 count){ + sort_pairs_by_key__quick(pairs, 0, count); +} + +internal Range_i32_Array +get_ranges_of_duplicate_keys(Arena *arena, i32 *keys, i32 stride, i32 count){ + Range_i32_Array result = {}; + result.ranges = push_array(arena, Range_i32, count); + u8 *ptr = (u8*)keys; + i32 start_i = 0; + for (i32 i = 1; i <= count; i += 1){ + b32 is_end = false; + if (i == count){ + is_end = true; + } + else if (*(i32*)(ptr + i*stride) != *(i32*)(ptr + start_i*stride)){ + is_end = true; + } + if (is_end){ + Range_i32 *new_range = &result.ranges[result.count++]; + new_range->first = start_i; + new_range->one_past_last = i; + start_i = i; + } + } + pop_array(arena, Range_i32, count - result.count); + return(result); +} + +internal void +no_mark_snap_to_cursor(Application_Links *app, Managed_Scope view_scope){ + b32 *snap_to_cursor = scope_attachment(app, view_scope, view_snap_mark_to_cursor, b32); + *snap_to_cursor = false; +} + +internal void +no_mark_snap_to_cursor(Application_Links *app, View_ID view_id){ + Managed_Scope scope = view_get_managed_scope(app, view_id); + no_mark_snap_to_cursor(app, scope); +} + +internal void +no_mark_snap_to_cursor_if_shift(Application_Links *app, View_ID view_id){ + Scratch_Block scratch(app); + Input_Modifier_Set mods = system_get_keyboard_modifiers(scratch); + if (has_modifier(&mods, KeyCode_Shift)){ + no_mark_snap_to_cursor(app, view_id); + } +} + +internal b32 +view_has_highlighted_range(Application_Links *app, View_ID view){ + b32 result = false; + if (fcoder_mode == FCoderMode_NotepadLike){ + i64 pos = view_get_cursor_pos(app, view); + i64 mark = view_get_mark_pos(app, view); + result = (pos != mark); + } + return(result); +} + +internal b32 +if_view_has_highlighted_range_delete_range(Application_Links *app, View_ID view_id){ + b32 result = false; + if (view_has_highlighted_range(app, view_id)){ + Range_i64 range = get_view_range(app, view_id); + Buffer_ID buffer = view_get_buffer(app, view_id, Access_ReadWriteVisible); + buffer_replace_range(app, buffer, range, string_u8_litexpr("")); + result = true; + } + return(result); +} + +internal void +begin_notepad_mode(Application_Links *app){ + fcoder_mode = FCoderMode_NotepadLike; + for (View_ID view = get_view_next(app, 0, Access_Always); + view != 0; + view = get_view_next(app, view, Access_Always)){ + i64 pos = view_get_cursor_pos(app, view); + view_set_mark(app, view, seek_pos(pos)); + } +} + +//////////////////////////////// + +internal void seek_pos_of_textual_line(Application_Links *app, Side side){ - View_ID view = get_active_view(app, Access_ReadVisible); + View_ID view = get_active_view(app, Access_ReadVisible); Buffer_ID buffer = view_get_buffer(app, view, Access_ReadVisible); i64 pos = view_get_cursor_pos(app, view); -i64 new_pos = get_line_side_pos_from_pos(app, buffer, pos, side); + i64 new_pos = get_line_side_pos_from_pos(app, buffer, pos, side); view_set_cursor_and_preferred_x(app, view, seek_pos(new_pos)); - no_mark_snap_to_cursor_if_shift(app, view); - } + no_mark_snap_to_cursor_if_shift(app, view); +} internal void seek_pos_of_visual_line(Application_Links *app, Side side){ - View_ID view = get_active_view(app, Access_ReadVisible); + View_ID view = get_active_view(app, Access_ReadVisible); i64 pos = view_get_cursor_pos(app, view); Buffer_Cursor cursor = view_compute_cursor(app, view, seek_pos(pos)); - Vec2_f32 p = view_relative_xy_of_pos(app, view, cursor.line, pos); - p.x = (side == Side_Min)?(0.f):(max_f32); -i64 new_pos = view_pos_at_relative_xy(app, view, cursor.line, p); - view_set_cursor_and_preferred_x(app, view, seek_pos(new_pos)); - no_mark_snap_to_cursor_if_shift(app, view); - } - - CUSTOM_COMMAND_SIG(seek_beginning_of_textual_line) - CUSTOM_DOC("Seeks the cursor to the beginning of the line across all text.") + Vec2_f32 p = view_relative_xy_of_pos(app, view, cursor.line, pos); + p.x = (side == Side_Min)?(0.f):(max_f32); + i64 new_pos = view_pos_at_relative_xy(app, view, cursor.line, p); + view_set_cursor_and_preferred_x(app, view, seek_pos(new_pos)); + no_mark_snap_to_cursor_if_shift(app, view); +} + +CUSTOM_COMMAND_SIG(seek_beginning_of_textual_line) +CUSTOM_DOC("Seeks the cursor to the beginning of the line across all text.") { seek_pos_of_textual_line(app, Side_Min); - } +} - CUSTOM_COMMAND_SIG(seek_end_of_textual_line) +CUSTOM_COMMAND_SIG(seek_end_of_textual_line) CUSTOM_DOC("Seeks the cursor to the end of the line across all text.") - { - seek_pos_of_textual_line(app, Side_Max); - } - - CUSTOM_COMMAND_SIG(seek_beginning_of_line) - CUSTOM_DOC("Seeks the cursor to the beginning of the visual line.") +{ + seek_pos_of_textual_line(app, Side_Max); +} + +CUSTOM_COMMAND_SIG(seek_beginning_of_line) +CUSTOM_DOC("Seeks the cursor to the beginning of the visual line.") { seek_pos_of_visual_line(app, Side_Min); - } - - CUSTOM_COMMAND_SIG(seek_end_of_line) - CUSTOM_DOC("Seeks the cursor to the end of the visual line.") - { - seek_pos_of_visual_line(app, Side_Max); - } - - CUSTOM_COMMAND_SIG(goto_beginning_of_file) - CUSTOM_DOC("Sets the cursor to the beginning of the file.") +} + +CUSTOM_COMMAND_SIG(seek_end_of_line) +CUSTOM_DOC("Seeks the cursor to the end of the visual line.") { -View_ID view = get_active_view(app, Access_ReadVisible); -view_set_cursor_and_preferred_x(app, view, seek_pos(0)); + seek_pos_of_visual_line(app, Side_Max); +} + +CUSTOM_COMMAND_SIG(goto_beginning_of_file) +CUSTOM_DOC("Sets the cursor to the beginning of the file.") +{ + View_ID view = get_active_view(app, Access_ReadVisible); + view_set_cursor_and_preferred_x(app, view, seek_pos(0)); no_mark_snap_to_cursor_if_shift(app, view); - } - - CUSTOM_COMMAND_SIG(goto_end_of_file) - CUSTOM_DOC("Sets the cursor to the end of the file.") - { - View_ID view = get_active_view(app, Access_ReadVisible); - Buffer_ID buffer_id = view_get_buffer(app, view, Access_ReadVisible); - i32 size = (i32)buffer_get_size(app, buffer_id); - view_set_cursor_and_preferred_x(app, view, seek_pos(size)); -no_mark_snap_to_cursor_if_shift(app, view); - } - - //////////////////////////////// - - internal b32 -view_set_split(Application_Links *app, View_ID view, View_Split_Kind kind, f32 t){ - b32 result = false; - if (view != 0){ - Panel_ID panel_id = view_get_panel(app, view); - if (panel_id != 0){ - Panel_ID parent_panel_id = panel_get_parent(app, panel_id); -if (parent_panel_id != 0){ - Panel_ID min_child_id = panel_get_child(app, parent_panel_id, Side_Min); - if (min_child_id != 0){ - b32 panel_is_min = (min_child_id == panel_id); -Panel_Split_Kind panel_kind = ((kind == ViewSplitKind_Ratio)? - (panel_is_min?PanelSplitKind_Ratio_Min:PanelSplitKind_Ratio_Max): -(panel_is_min?PanelSplitKind_FixedPixels_Min:PanelSplitKind_FixedPixels_Max)); - result = panel_set_split(app, parent_panel_id, panel_kind, t); - } } + +CUSTOM_COMMAND_SIG(goto_end_of_file) +CUSTOM_DOC("Sets the cursor to the end of the file.") +{ + View_ID view = get_active_view(app, Access_ReadVisible); + Buffer_ID buffer_id = view_get_buffer(app, view, Access_ReadVisible); + i32 size = (i32)buffer_get_size(app, buffer_id); + view_set_cursor_and_preferred_x(app, view, seek_pos(size)); + no_mark_snap_to_cursor_if_shift(app, view); } -} -return(result); - } + +//////////////////////////////// internal b32 - view_set_split_proportion(Application_Links *app, View_ID view, f32 t){ -return(view_set_split(app, view, ViewSplitKind_Ratio, t)); +view_set_split(Application_Links *app, View_ID view, View_Split_Kind kind, f32 t){ + b32 result = false; + if (view != 0){ + Panel_ID panel_id = view_get_panel(app, view); + if (panel_id != 0){ + Panel_ID parent_panel_id = panel_get_parent(app, panel_id); + if (parent_panel_id != 0){ + Panel_ID min_child_id = panel_get_child(app, parent_panel_id, Side_Min); + if (min_child_id != 0){ + b32 panel_is_min = (min_child_id == panel_id); + Panel_Split_Kind panel_kind = ((kind == ViewSplitKind_Ratio)? + (panel_is_min?PanelSplitKind_Ratio_Min:PanelSplitKind_Ratio_Max): + (panel_is_min?PanelSplitKind_FixedPixels_Min:PanelSplitKind_FixedPixels_Max)); + result = panel_set_split(app, parent_panel_id, panel_kind, t); + } + } + } } - - internal b32 + return(result); +} + +internal b32 +view_set_split_proportion(Application_Links *app, View_ID view, f32 t){ + return(view_set_split(app, view, ViewSplitKind_Ratio, t)); +} + +internal b32 view_set_split_pixel_size(Application_Links *app, View_ID view, i32 t){ return(view_set_split(app, view, ViewSplitKind_FixedPixels, (f32)t)); - } - - //////////////////////////////// +} + +//////////////////////////////// internal Record_Info get_single_record(Application_Links *app, Buffer_ID buffer_id, History_Record_Index index){ -Record_Info record = buffer_history_get_record_info(app, buffer_id, index); - if (record.error == RecordError_NoError && record.kind == RecordKind_Group){ - record = buffer_history_get_group_sub_record(app, buffer_id, index, record.group_count - 1); + Record_Info record = buffer_history_get_record_info(app, buffer_id, index); + if (record.error == RecordError_NoError && record.kind == RecordKind_Group){ + record = buffer_history_get_group_sub_record(app, buffer_id, index, record.group_count - 1); } return(record); - } - - //////////////////////////////// - - function Nest_Delimiter_Kind - get_nest_delimiter_kind(Token_Base_Kind kind, Find_Nest_Flag flags){ +} + +//////////////////////////////// + +function Nest_Delimiter_Kind +get_nest_delimiter_kind(Token_Base_Kind kind, Find_Nest_Flag flags){ Nest_Delimiter_Kind result = NestDelim_None; switch (kind){ - case TokenBaseKind_ScopeOpen: - { - if (HasFlag(flags, FindNest_Scope)){ - result = NestDelim_Open; + case TokenBaseKind_ScopeOpen: + { + if (HasFlag(flags, FindNest_Scope)){ + result = NestDelim_Open; + } + }break; + case TokenBaseKind_ScopeClose: + { + if (HasFlag(flags, FindNest_Scope)){ + result = NestDelim_Close; + } + }break; + case TokenBaseKind_ParentheticalOpen: + { + if (HasFlag(flags, FindNest_Paren)){ + result = NestDelim_Open; + } + }break; + case TokenBaseKind_ParentheticalClose: + { + if (HasFlag(flags, FindNest_Paren)){ + result = NestDelim_Close; + } + }break; } - }break; -case TokenBaseKind_ScopeClose: -{ -if (HasFlag(flags, FindNest_Scope)){ -result = NestDelim_Close; -} -}break; -case TokenBaseKind_ParentheticalOpen: -{ -if (HasFlag(flags, FindNest_Paren)){ -result = NestDelim_Open; -} -}break; -case TokenBaseKind_ParentheticalClose: -{ -if (HasFlag(flags, FindNest_Paren)){ -result = NestDelim_Close; -} -}break; -} -return(result); + return(result); } function b32 find_nest_side(Application_Links *app, Buffer_ID buffer, i64 pos, -Find_Nest_Flag flags, Scan_Direction scan, Nest_Delimiter_Kind delim, -Range_i64 *out){ -b32 result = false; - - b32 balanced = HasFlag(flags, FindNest_Balanced); + Find_Nest_Flag flags, Scan_Direction scan, Nest_Delimiter_Kind delim, + Range_i64 *out){ + b32 result = false; + + b32 balanced = HasFlag(flags, FindNest_Balanced); if (balanced){ - if ((delim == NestDelim_Open && scan == Scan_Forward) || - (delim == NestDelim_Close && scan == Scan_Backward)){ - balanced = false; + if ((delim == NestDelim_Open && scan == Scan_Forward) || + (delim == NestDelim_Close && scan == Scan_Backward)){ + balanced = false; + } } -} Managed_Scope scope = buffer_get_managed_scope(app, buffer); Token_Array *tokens = scope_attachment(app, scope, attachment_tokens, Token_Array); -if (tokens != 0 && tokens->count > 0){ -Token_Iterator_Array it = token_iterator_pos(0, tokens, pos); -i32 level = 0; -for (;;){ -Token *token = token_it_read(&it); -Nest_Delimiter_Kind token_delim = get_nest_delimiter_kind(token->kind, flags); - -if (level == 0 && token_delim == delim){ -*out = Ii64_size(token->pos, token->size); -result = true; -break; -} - -if (balanced && token_delim != NestDelim_None){ -level += (token_delim == delim)?-1:1; -} - -b32 good = false; -if (scan == Scan_Forward){ -good = token_it_inc(&it); - } -else{ -good = token_it_dec(&it); - } -if (!good){ - break; - } - } - } - - return(result); -} - - function b32 -find_nest_side(Application_Links *app, Buffer_ID buffer, i64 pos, -Find_Nest_Flag flags, Scan_Direction scan, Nest_Delimiter_Kind delim, - i64 *out){ -Range_i64 range = {}; - b32 result = find_nest_side(app, buffer, pos, flags, scan, delim, &range); -if (result){ - if (HasFlag(flags, FindNest_EndOfToken)){ - *out = range.end; - } - else{ - *out = range.start; - } - } - return(result); - } - - function b32 - find_surrounding_nest(Application_Links *app, Buffer_ID buffer, i64 pos, - Find_Nest_Flag flags, Range_i64 *out){ -b32 result = false; - Range_i64 range = {}; - if (find_nest_side(app, buffer, pos - 1, flags|FindNest_Balanced, -Scan_Backward, NestDelim_Open, &range.start) && - find_nest_side(app, buffer, pos, flags|FindNest_Balanced|FindNest_EndOfToken, - Scan_Forward, NestDelim_Close, &range.end)){ - *out = range; - result = true; - } - return(result); - } - - function void - select_scope(Application_Links *app, View_ID view, Range_i64 range){ - view_set_cursor_and_preferred_x(app, view, seek_pos(range.first)); - view_set_mark(app, view, seek_pos(range.end)); - view_look_at_region(app, view, range.first, range.end); - no_mark_snap_to_cursor(app, view); - } - - //////////////////////////////// - - function Line_Ending_Kind -guess_line_ending_kind_from_buffer(Application_Links *app, Buffer_ID buffer){ - u64 size = buffer_get_size(app, buffer); - size = clamp_top(size, KB(8)); - Scratch_Block scratch(app); - String_Const_u8 string = push_buffer_range(app, scratch, buffer, Ii64(0, size)); - return(string_guess_line_ending_kind(string)); - } - - //////////////////////////////// - - function i32 - get_command_id(Custom_Command_Function *func){ - i32 result = -1; - for (i32 i = 0; i < ArrayCount(fcoder_metacmd_table); i += 1){ - if (func == fcoder_metacmd_table[i].proc){ -result = i; - break; - } - } - return(result); + if (tokens != 0 && tokens->count > 0){ + Token_Iterator_Array it = token_iterator_pos(0, tokens, pos); + i32 level = 0; + for (;;){ + Token *token = token_it_read(&it); + Nest_Delimiter_Kind token_delim = get_nest_delimiter_kind(token->kind, flags); + + if (level == 0 && token_delim == delim){ + *out = Ii64_size(token->pos, token->size); + result = true; + break; } - function Command_Metadata* - get_command_metadata(Custom_Command_Function *func){ -Command_Metadata *result = 0; - i32 id = get_command_id(func); - if (id >= 0){ - result = &fcoder_metacmd_table[id]; - } - return(result); - } - - //////////////////////////////// - - // TODO(allen): REWRITE THIS EXACTLY HOW YOU WANT IT --- start --- - - internal Child_Process_Set_Target_Flags - flags_system_command(Command_Line_Interface_Flag flags){ - Child_Process_Set_Target_Flags set_buffer_flags = 0; - if (!HasFlag(flags, CLI_OverlapWithConflict)){ - set_buffer_flags |= ChildProcessSet_FailIfBufferAlreadyAttachedToAProcess; - } -if (HasFlag(flags, CLI_CursorAtEnd)){ - set_buffer_flags |= ChildProcessSet_CursorAtEnd; -} -return(set_buffer_flags); + if (balanced && token_delim != NestDelim_None){ + level += (token_delim == delim)?-1:1; + } + + b32 good = false; + if (scan == Scan_Forward){ + good = token_it_inc(&it); + } + else{ + good = token_it_dec(&it); + } + if (!good){ + break; + } + } } - internal b32 - set_buffer_system_command(Application_Links *app, Child_Process_ID process, Buffer_ID buffer, Command_Line_Interface_Flag flags){ - b32 result = false; -Child_Process_Set_Target_Flags set_buffer_flags = flags_system_command(flags); - if (child_process_set_target_buffer(app, process, buffer, set_buffer_flags)){ - clear_buffer(app, buffer); - if (HasFlag(flags, CLI_SendEndSignal)){ - buffer_send_end_signal(app, buffer); - } -result = true; + return(result); } -return(result); + +function b32 +find_nest_side(Application_Links *app, Buffer_ID buffer, i64 pos, + Find_Nest_Flag flags, Scan_Direction scan, Nest_Delimiter_Kind delim, + i64 *out){ + Range_i64 range = {}; + b32 result = find_nest_side(app, buffer, pos, flags, scan, delim, &range); + if (result){ + if (HasFlag(flags, FindNest_EndOfToken)){ + *out = range.end; + } + else{ + *out = range.start; + } + } + return(result); +} + +function b32 +find_surrounding_nest(Application_Links *app, Buffer_ID buffer, i64 pos, + Find_Nest_Flag flags, Range_i64 *out){ + b32 result = false; + Range_i64 range = {}; + if (find_nest_side(app, buffer, pos - 1, flags|FindNest_Balanced, + Scan_Backward, NestDelim_Open, &range.start) && + find_nest_side(app, buffer, pos, flags|FindNest_Balanced|FindNest_EndOfToken, + Scan_Forward, NestDelim_Close, &range.end)){ + *out = range; + result = true; + } + return(result); +} + +function void +select_scope(Application_Links *app, View_ID view, Range_i64 range){ + view_set_cursor_and_preferred_x(app, view, seek_pos(range.first)); + view_set_mark(app, view, seek_pos(range.end)); + view_look_at_region(app, view, range.first, range.end); + no_mark_snap_to_cursor(app, view); +} + +//////////////////////////////// + +function Line_Ending_Kind +guess_line_ending_kind_from_buffer(Application_Links *app, Buffer_ID buffer){ + u64 size = buffer_get_size(app, buffer); + size = clamp_top(size, KB(8)); + Scratch_Block scratch(app); + String_Const_u8 string = push_buffer_range(app, scratch, buffer, Ii64(0, size)); + return(string_guess_line_ending_kind(string)); +} + +//////////////////////////////// + +// TODO(allen): REWRITE THIS EXACTLY HOW YOU WANT IT --- start --- + +internal Child_Process_Set_Target_Flags +flags_system_command(Command_Line_Interface_Flag flags){ + Child_Process_Set_Target_Flags set_buffer_flags = 0; + if (!HasFlag(flags, CLI_OverlapWithConflict)){ + set_buffer_flags |= ChildProcessSet_FailIfBufferAlreadyAttachedToAProcess; + } + if (HasFlag(flags, CLI_CursorAtEnd)){ + set_buffer_flags |= ChildProcessSet_CursorAtEnd; + } + return(set_buffer_flags); +} + +internal b32 +set_buffer_system_command(Application_Links *app, Child_Process_ID process, Buffer_ID buffer, Command_Line_Interface_Flag flags){ + b32 result = false; + Child_Process_Set_Target_Flags set_buffer_flags = flags_system_command(flags); + if (child_process_set_target_buffer(app, process, buffer, set_buffer_flags)){ + clear_buffer(app, buffer); + if (HasFlag(flags, CLI_SendEndSignal)){ + buffer_send_end_signal(app, buffer); + } + result = true; + } + return(result); } internal b32 exec_system_command(Application_Links *app, View_ID view, Buffer_Identifier buffer_id, - String_Const_u8 path, String_Const_u8 command, Command_Line_Interface_Flag flags){ + String_Const_u8 path, String_Const_u8 command, Command_Line_Interface_Flag flags){ b32 result = false; -Child_Process_ID child_process_id = create_child_process(app, path, command); - if (child_process_id != 0){ -result = true; -Buffer_ID buffer_attach_id = buffer_identifier_to_id_create_out_buffer(app, buffer_id); - if (buffer_attach_id != 0){ - if (set_buffer_system_command(app, child_process_id, buffer_attach_id, flags)){ - if (view != 0){ - view_set_buffer(app, view, buffer_attach_id, 0); - view_set_cursor(app, view, seek_pos(0)); - } - } - } - } - return(result); - } + Child_Process_ID child_process_id = create_child_process(app, path, command); + if (child_process_id != 0){ + result = true; + Buffer_ID buffer_attach_id = buffer_identifier_to_id_create_out_buffer(app, buffer_id); + if (buffer_attach_id != 0){ + if (set_buffer_system_command(app, child_process_id, buffer_attach_id, flags)){ + if (view != 0){ + view_set_buffer(app, view, buffer_attach_id, 0); + view_set_cursor(app, view, seek_pos(0)); + } + } + } + } + return(result); +} - // TODO(allen): --- end --- +// TODO(allen): --- end --- // BOTTOM diff --git a/custom/4coder_jump_lister.cpp b/custom/4coder_jump_lister.cpp index 5803d00c..06f72d11 100644 --- a/custom/4coder_jump_lister.cpp +++ b/custom/4coder_jump_lister.cpp @@ -10,9 +10,9 @@ get_jump_index_from_user(Application_Links *app, Marker_List *list, Jump_Lister_Result result = {}; if (list != 0){ Scratch_Block scratch(app); - Lister *lister = begin_lister(app, scratch); + Lister_Block lister(app, scratch); lister_set_query(lister, query); - lister->handlers = lister_get_default_handlers(); + lister_set_default_handlers(lister); Buffer_ID list_buffer = list->buffer_id; diff --git a/custom/4coder_lister_base.cpp b/custom/4coder_lister_base.cpp index 4d398875..f2344e2a 100644 --- a/custom/4coder_lister_base.cpp +++ b/custom/4coder_lister_base.cpp @@ -38,11 +38,27 @@ lister_get_top_level_layout(Rect_f32 rect, f32 text_field_height){ //////////////////////////////// -Lister *global_lister_state[16] = {}; +function Lister* +view_get_lister(Application_Links *app, View_ID view){ + Managed_Scope scope = view_get_managed_scope(app, view); + Lister **ptr = scope_attachment(app, scope, view_lister_loc, Lister*); + Lister *result = 0; + if (ptr != 0){ + result = *ptr; + } + return(result); +} function Lister* -view_get_lister(View_ID view){ - return(global_lister_state[view - 1]); +view_set_lister(Application_Links *app, View_ID view, Lister *lister){ + Managed_Scope scope = view_get_managed_scope(app, view); + Lister **ptr = scope_attachment(app, scope, view_lister_loc, Lister*); + Lister *result = 0; + if (ptr != 0){ + result = *ptr; + *ptr = lister; + } + return(result); } function void @@ -57,19 +73,36 @@ lister_set_map(Lister *lister, Mapping *mapping, Command_Map_ID map){ lister->map = mapping_get_map(mapping, map); } -function Lister* +function Lister_Prev_Current begin_lister(Application_Links *app, Arena *arena){ + Lister_Prev_Current result = {}; Lister *lister = push_array_zero(arena, Lister, 1); lister->arena = arena; lister->query = Su8(lister->query_space, 0, sizeof(lister->query_space)); lister->text_field = Su8(lister->text_field_space, 0, sizeof(lister->text_field_space)); lister->key_string = Su8(lister->key_string_space, 0, sizeof(lister->key_string_space)); View_ID view = get_this_ctx_view(app, Access_Always); - global_lister_state[view - 1] = lister; + result.prev = view_set_lister(app, view, lister); + result.current = lister; lister->restore_all_point = begin_temp(lister->arena); View_Context ctx = view_current_context(app, view); lister_set_map(lister, ctx.mapping, ctx.map_id); - return(lister); + return(result); +} + +Lister_Block::Lister_Block(Application_Links *a, Arena *arena){ + Lister_Prev_Current new_lister = begin_lister(a, arena); + this->app = a; + this->lister = new_lister; +} + +Lister_Block::~Lister_Block(){ + View_ID view = get_this_ctx_view(app, Access_Always); + view_set_lister(this->app, view, this->lister.prev); +} + +Lister_Block::operator Lister *(){ + return(this->lister.current); } function void @@ -132,6 +165,11 @@ lister_append_key(Lister *lister, char *string){ lister_append_string(SCu8(string), &lister->key_string); } +function void +lister_set_handlers(Lister *lister, Lister_Handlers *handlers){ + block_copy_struct(&lister->handlers, handlers); +} + function void lister_zero_scroll(Lister *lister){ block_zero_struct(&lister->scroll); @@ -141,7 +179,7 @@ function void lister_render(Application_Links *app, Frame_Info frame_info, View_ID view){ Scratch_Block scratch(app); - Lister *lister = view_get_lister(view); + Lister *lister = view_get_lister(app, view); if (lister == 0){ return; } @@ -721,7 +759,7 @@ function Lister_Activation_Code lister__write_string__default(Application_Links *app){ Lister_Activation_Code result = ListerActivation_Continue; View_ID view = get_active_view(app, Access_Always); - Lister *lister = view_get_lister(view); + Lister *lister = view_get_lister(app, view); if (lister != 0){ User_Input in = get_current_input(app); String_Const_u8 string = to_writable(&in); @@ -739,7 +777,7 @@ lister__write_string__default(Application_Links *app){ function void lister__backspace_text_field__default(Application_Links *app){ View_ID view = get_active_view(app, Access_Always); - Lister *lister = view_get_lister(view); + Lister *lister = view_get_lister(app, view); if (lister != 0){ lister->text_field.string = backspace_utf8(lister->text_field.string); lister->key_string.string = backspace_utf8(lister->key_string.string); @@ -775,15 +813,21 @@ lister_get_default_handlers(void){ return(handlers); } +function void +lister_set_default_handlers(Lister *lister){ + Lister_Handlers handlers = lister_get_default_handlers(); + lister_set_handlers(lister, &handlers); +} + //////////////////////////////// function Lister_Result run_lister_with_refresh_handler(Application_Links *app, Arena *arena, String_Const_u8 query, Lister_Handlers handlers){ Lister_Result result = {}; if (handlers.refresh != 0){ - Lister *lister = begin_lister(app, arena); + Lister_Block lister(app, arena); lister_set_query(lister, query); - lister->handlers = handlers; + lister_set_handlers(lister, &handlers); handlers.refresh(app, lister); result = run_lister(app, lister); } @@ -865,7 +909,7 @@ function Lister_Activation_Code lister__key_stroke__choice_list(Application_Links *app){ Lister_Activation_Code result = ListerActivation_Continue; View_ID view = get_active_view(app, Access_Always); - Lister *lister = view_get_lister(view); + Lister *lister = view_get_lister(app, view); if (lister != 0){ User_Input in = get_current_input(app); if (in.event.kind == InputEventKind_KeyStroke){ @@ -894,7 +938,7 @@ function Lister_Choice* get_choice_from_user(Application_Links *app, String_Const_u8 query, Lister_Choice_List list){ Scratch_Block scratch(app); - Lister *lister = begin_lister(app, scratch); + Lister_Block lister(app, scratch); for (Lister_Choice *choice = list.first; choice != 0; choice = choice->next){ @@ -907,8 +951,7 @@ get_choice_from_user(Application_Links *app, String_Const_u8 query, Lister_Handlers handlers = {}; handlers.navigate = lister__navigate__default; handlers.key_stroke = lister__key_stroke__choice_list; - lister->handlers = handlers; - lister->handlers.refresh = 0; + lister_set_handlers(lister, &handlers); Lister_Result l_result = run_lister(app, lister); Lister_Choice *result = 0; diff --git a/custom/4coder_lister_base.h b/custom/4coder_lister_base.h index aa6fae80..52300483 100644 --- a/custom/4coder_lister_base.h +++ b/custom/4coder_lister_base.h @@ -92,6 +92,19 @@ struct Lister{ Lister_Result out; }; +struct Lister_Prev_Current{ + Lister *prev; + Lister *current; +}; + +struct Lister_Block{ + Application_Links *app; + Lister_Prev_Current lister; + Lister_Block(Application_Links *app, Arena *arena); + ~Lister_Block(); + operator Lister *(); +}; + struct Lister_Prealloced_String{ String_Const_u8 string; }; diff --git a/custom/4coder_lists.cpp b/custom/4coder_lists.cpp index 26595d4b..c88e2451 100644 --- a/custom/4coder_lists.cpp +++ b/custom/4coder_lists.cpp @@ -132,9 +132,9 @@ get_command_from_user(Application_Links *app, String_Const_u8 query, i32 *comman } Scratch_Block scratch(app, Scratch_Share); - Lister *lister = begin_lister(app, scratch); + Lister_Block lister(app, scratch); lister_set_query(lister, query); - lister->handlers = lister_get_default_handlers(); + lister_set_default_handlers(lister); for (i32 i = 0; i < command_id_count; i += 1){ i32 j = i; @@ -206,9 +206,9 @@ get_color_table_from_user(Application_Links *app, String_Const_u8 query, Color_T } Scratch_Block scratch(app, Scratch_Share); - Lister *lister = begin_lister(app, scratch); + Lister_Block lister(app, scratch); lister_set_query(lister, query); - lister->handlers = lister_get_default_handlers(); + lister_set_default_handlers(lister); lister_add_item(lister, string_u8_litexpr("4coder"), string_u8_litexpr(""), (void*)&default_color_table, 0); @@ -240,7 +240,7 @@ function Lister_Activation_Code lister__write_character__file_path(Application_Links *app){ Lister_Activation_Code result = ListerActivation_Continue; View_ID view = get_this_ctx_view(app, Access_Always); - Lister *lister = view_get_lister(view); + Lister *lister = view_get_lister(app, view); if (lister != 0){ User_Input in = get_current_input(app); String_Const_u8 string = to_writable(&in); @@ -265,7 +265,7 @@ lister__write_character__file_path(Application_Links *app){ function void lister__backspace_text_field__file_path(Application_Links *app){ View_ID view = get_this_ctx_view(app, Access_Always); - Lister *lister = view_get_lister(view); + Lister *lister = view_get_lister(app, view); if (lister != 0){ if (lister->text_field.size > 0){ char last_char = lister->text_field.str[lister->text_field.size - 1]; diff --git a/custom/4coder_project_commands.cpp b/custom/4coder_project_commands.cpp index bb1f5460..3a54cbe0 100644 --- a/custom/4coder_project_commands.cpp +++ b/custom/4coder_project_commands.cpp @@ -1261,9 +1261,9 @@ get_project_command_from_user(Application_Links *app, Project *project, Project_Command_Lister_Result result = {}; if (project != 0){ Scratch_Block scratch(app); - Lister *lister = begin_lister(app, scratch); + Lister_Block lister(app, scratch); lister_set_query(lister, query); - lister->handlers = lister_get_default_handlers(); + lister_set_default_handlers(lister); Project_Command *proj_cmd = project->command_array.commands; i32 count = project->command_array.count; diff --git a/custom/4coder_types.h b/custom/4coder_types.h index e979bd8c..0898ad28 100644 --- a/custom/4coder_types.h +++ b/custom/4coder_types.h @@ -638,6 +638,7 @@ typedef i32 Hook_ID; enum{ HookID_Tick, HookID_RenderCaller, + HookID_WholeScreenRenderCaller, HookID_DeltaRule, HookID_BufferViewerUpdate, HookID_ViewEventHandler, @@ -695,6 +696,9 @@ typedef void Tick_Function(Application_Links *app, Frame_Info frame_info); api(custom) typedef void Render_Caller_Function(Application_Links *app, Frame_Info frame_info, View_ID view); +api(custom) +typedef void Whole_Screen_Render_Caller_Function(Application_Links *app, Frame_Info frame_info); + api(custom) typedef u32 Layout_Item_Flag; enum{ diff --git a/custom/bin/build_metadata.sh b/custom/bin/build_metadata.sh old mode 100644 new mode 100755 diff --git a/custom/bin/build_one_time.sh b/custom/bin/build_one_time.sh new file mode 100755 index 00000000..724c34f0 --- /dev/null +++ b/custom/bin/build_one_time.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# If any command errors, stop the script +set -e + +# Set up directories +ORIGINAL=$PWD +ME="$(readlink -f "$0")" +LOCATION="$(dirname "$ME")" +cd $LOCATION +cd .. +CUSTOM_ROOT=$PWD +cd $ORIGINAL + +target=$1 +if [ -z "$target" ] +then + echo error: no input file + exit 1 +fi + +full_target=$target +if [[ ${target:0:1} != "/" ]]; +then +full_target="$PWD/$target" +fi + +dst=$2 +if [[ $dst == "" ]]; +then +dst=. +fi + +debug=-g + +opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -Wno-missing-declarations -Wno-logical-op-parentheses -g -DOS_LINUX=1 -DOS_WINDOWS=0 -DOS_MAC=0" + +pushd $dst +g++ -I"$CUSTOM_ROOT" $opts $full_target -o one_time +popd + + diff --git a/custom/bin/buildsuper_x64-linux.sh b/custom/bin/buildsuper_x64-linux.sh old mode 100644 new mode 100755 index 988b4c43..d175b40a --- a/custom/bin/buildsuper_x64-linux.sh +++ b/custom/bin/buildsuper_x64-linux.sh @@ -13,14 +13,17 @@ SOURCE="$1" if [ -z "$SOURCE" ]; then SOURCE="$(readlink -f "$CODE_HOME/4coder_default_bindings.cpp")" fi +echo SOURCE = $SOURCE -opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -Wno-writable-strings -g -DOS_LINUX=1 -DOS_WINDOWS=0 -DOS_MAC=1" +opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -Wno-missing-declarations -Wno-logical-op-parentheses -g -DOS_LINUX=1 -DOS_WINDOWS=0 -DOS_MAC=0" arch=-m64 +debug=-g + preproc_file=4coder_command_metadata.i meta_macros="-DMETA_PASS" -g++ -I"$CODE_HOME" $meta_macros $arch $opts $debug -std=gnu++0x "$SOURCE" -E -o $preproc_file -g++ -I"$CODE_HOME" $opts $debug -std=gnu++0x "$CODE_HOME/4coder_metadata_generator.cpp" -o "$CODE_HOME/metadata_generator" +g++ -I"$CODE_HOME" $meta_macros $arch $opts $debug -std=c++11 "$SOURCE" -E -o $preproc_file +g++ -I"$CODE_HOME" $opts $debug -std=c++11 "$CODE_HOME/4coder_metadata_generator.cpp" -o "$CODE_HOME/metadata_generator" "$CODE_HOME/metadata_generator" -R "$CODE_HOME" "$PWD/$preproc_file" g++ -I"$CODE_HOME" $arch $opts $debug -std=gnu++0x "$SOURCE" -shared -o custom_4coder.so -fPIC diff --git a/custom/bin/buildsuper_x64-mac.sh b/custom/bin/buildsuper_x64-mac.sh index f18a1466..02aefcb2 100755 --- a/custom/bin/buildsuper_x64-mac.sh +++ b/custom/bin/buildsuper_x64-mac.sh @@ -18,10 +18,12 @@ fi opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -Wno-missing-declarations -Wno-logical-op-parentheses -g -DOS_MAC=1 -DOS_WINDOWS=0 -DOS_LINUX=0" arch=-m64 +debug=-g + preproc_file=4coder_command_metadata.i meta_macros="-DMETA_PASS" -clang++ -I"$CODE_HOME" $meta_macros $arch $opts $debug -std=gnu++0x "$SOURCE" -E -o $preproc_file -clang++ -I"$CODE_HOME" $opts $debug -std=gnu++0x "$CODE_HOME/4coder_metadata_generator.cpp" -o "$CODE_HOME/metadata_generator" +clang++ -I"$CODE_HOME" $meta_macros $arch $opts $debug -std=c++11 "$SOURCE" -E -o $preproc_file +clang++ -I"$CODE_HOME" $opts $debug -std=c++11 "$CODE_HOME/4coder_metadata_generator.cpp" -o "$CODE_HOME/metadata_generator" "$CODE_HOME/metadata_generator" -R "$CODE_HOME" "$PWD/$preproc_file" clang++ -I"$CODE_HOME" $arch $opts $debug -std=c++11 "$SOURCE" -shared -o custom_4coder.so -fPIC diff --git a/custom/bin/buildsuper_x86-linux.sh b/custom/bin/buildsuper_x86-linux.sh old mode 100644 new mode 100755 index 18d247aa..f635aebf --- a/custom/bin/buildsuper_x86-linux.sh +++ b/custom/bin/buildsuper_x86-linux.sh @@ -1,52 +1,33 @@ #!/bin/bash -# Store the real CWD -REAL_PWD="$PWD" +# If any command errors, stop the script +set -e -# Find the code home folder -TARGET_FILE="$0" -cd `dirname $TARGET_FILE` -TARGET_FILE=`basename $TARGET_FILE` -while [ -L "$TARGET_FILE" ] -do - TARGET_FILE=`readlink $TARGET_FILE` - cd `dirname $TARGET_FILE` - TARGET_FILE=`basename $TARGET_FILE` -done -PHYS_DIR=`pwd -P` -SCRIPT_FILE=$PHYS_DIR/$TARGET_FILE -code_home=$(dirname "$SCRIPT_FILE") +# Store the real CWD +ME="$(readlink -f "$0")" +LOCATION="$(dirname "$ME")" +CODE_HOME="$(dirname "$LOCATION")" # Find the most reasonable candidate build file SOURCE="$1" if [ -z "$SOURCE" ]; then - SOURCE="$code_home/4coder_default_bindings.cpp" + SOURCE="$(readlink -f "$CODE_HOME/4coder_default_bindings.cpp")" fi -TARGET_FILE="$SOURCE" -cd `dirname $TARGET_FILE` -TARGET_FILE=`basename $TARGET_FILE` -while [ -L "$TARGET_FILE" ] -do - TARGET_FILE=`readlink $TARGET_FILE` - cd `dirname $TARGET_FILE` - TARGET_FILE=`basename $TARGET_FILE` -done -PHYS_DIR=`pwd -P` -SOURCE=$PHYS_DIR/$TARGET_FILE - -opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -Wno-writable-strings -g -DOS_LINUX=1 -DOS_WINDOWS=0 -DOS_MAC=1" +opts="-Wno-write-strings -Wno-null-dereference -Wno-comment -Wno-switch -Wno-missing-declarations -Wno-logical-op-parentheses -g -DOS_LINUX=1 -DOS_WINDOWS=0 -DOS_MAC=0" arch=-m32 -cd "$REAL_PWD" +debug=-g + preproc_file=4coder_command_metadata.i meta_macros="-DMETA_PASS" -g++ -I"$code_home" $meta_macros $arch $opts $debug -std=gnu++0x "$SOURCE" -E -o $preproc_file -g++ -I"$code_home" $opts $debug -std=gnu++0x "$code_home/4coder_metadata_generator.cpp" -o metadata_generator -./metadata_generator -R "$code_home" "$PWD/$preproc_file" +g++ -I"$CODE_HOME" $meta_macros $arch $opts $debug -std=c++11 "$SOURCE" -E -o $preproc_file +g++ -I"$CODE_HOME" $opts $debug -std=c++11 "$CODE_HOME/4coder_metadata_generator.cpp" -o "$CODE_HOME/metadata_generator" +"$CODE_HOME/metadata_generator" -R "$CODE_HOME" "$PWD/$preproc_file" -g++ -I"$code_home" $arch $opts $debug -std=gnu++0x "$SOURCE" -shared -o custom_4coder.so -fPIC +g++ -I"$CODE_HOME" $arch $opts $debug -std=gnu++0x "$SOURCE" -shared -o custom_4coder.so -fPIC -rm metadata_generator +rm "$CODE_HOME/metadata_generator" rm $preproc_file + diff --git a/custom/bin/detect_os.sh b/custom/bin/detect_os.sh old mode 100644 new mode 100755 diff --git a/custom/generated/4coder_event_codes.h b/custom/generated/4coder_event_codes.h index 633caf07..f94d29e7 100644 --- a/custom/generated/4coder_event_codes.h +++ b/custom/generated/4coder_event_codes.h @@ -1,212 +1,318 @@ enum{ - KeyCode_A = 1, - KeyCode_B = 2, - KeyCode_C = 3, - KeyCode_D = 4, - KeyCode_E = 5, - KeyCode_F = 6, - KeyCode_G = 7, - KeyCode_H = 8, - KeyCode_I = 9, - KeyCode_J = 10, - KeyCode_K = 11, - KeyCode_L = 12, - KeyCode_M = 13, - KeyCode_N = 14, - KeyCode_O = 15, - KeyCode_P = 16, - KeyCode_Q = 17, - KeyCode_R = 18, - KeyCode_S = 19, - KeyCode_T = 20, - KeyCode_U = 21, - KeyCode_V = 22, - KeyCode_W = 23, - KeyCode_X = 24, - KeyCode_Y = 25, - KeyCode_Z = 26, - KeyCode_0 = 27, - KeyCode_1 = 28, - KeyCode_2 = 29, - KeyCode_3 = 30, - KeyCode_4 = 31, - KeyCode_5 = 32, - KeyCode_6 = 33, - KeyCode_7 = 34, - KeyCode_8 = 35, - KeyCode_9 = 36, - KeyCode_Space = 37, - KeyCode_Tick = 38, - KeyCode_Minus = 39, - KeyCode_Equal = 40, - KeyCode_LeftBracket = 41, - KeyCode_RightBracket = 42, - KeyCode_Semicolon = 43, - KeyCode_Quote = 44, - KeyCode_Comma = 45, - KeyCode_Period = 46, - KeyCode_ForwardSlash = 47, - KeyCode_BackwardSlash = 48, - KeyCode_Tab = 49, - KeyCode_Escape = 50, - KeyCode_Pause = 51, - KeyCode_Up = 52, - KeyCode_Down = 53, - KeyCode_Left = 54, - KeyCode_Right = 55, - KeyCode_Backspace = 56, - KeyCode_Return = 57, - KeyCode_Delete = 58, - KeyCode_Insert = 59, - KeyCode_Home = 60, - KeyCode_End = 61, - KeyCode_PageUp = 62, - KeyCode_PageDown = 63, - KeyCode_CapsLock = 64, - KeyCode_NumLock = 65, - KeyCode_ScrollLock = 66, - KeyCode_Menu = 67, - KeyCode_Shift = 68, - KeyCode_Control = 69, - KeyCode_Alt = 70, - KeyCode_Command = 71, - KeyCode_F1 = 72, - KeyCode_F2 = 73, - KeyCode_F3 = 74, - KeyCode_F4 = 75, - KeyCode_F5 = 76, - KeyCode_F6 = 77, - KeyCode_F7 = 78, - KeyCode_F8 = 79, - KeyCode_F9 = 80, - KeyCode_F10 = 81, - KeyCode_F11 = 82, - KeyCode_F12 = 83, - KeyCode_F13 = 84, - KeyCode_F14 = 85, - KeyCode_F15 = 86, - KeyCode_F16 = 87, - KeyCode_COUNT = 88, +KeyCode_A = 1, +KeyCode_B = 2, +KeyCode_C = 3, +KeyCode_D = 4, +KeyCode_E = 5, +KeyCode_F = 6, +KeyCode_G = 7, +KeyCode_H = 8, +KeyCode_I = 9, +KeyCode_J = 10, +KeyCode_K = 11, +KeyCode_L = 12, +KeyCode_M = 13, +KeyCode_N = 14, +KeyCode_O = 15, +KeyCode_P = 16, +KeyCode_Q = 17, +KeyCode_R = 18, +KeyCode_S = 19, +KeyCode_T = 20, +KeyCode_U = 21, +KeyCode_V = 22, +KeyCode_W = 23, +KeyCode_X = 24, +KeyCode_Y = 25, +KeyCode_Z = 26, +KeyCode_0 = 27, +KeyCode_1 = 28, +KeyCode_2 = 29, +KeyCode_3 = 30, +KeyCode_4 = 31, +KeyCode_5 = 32, +KeyCode_6 = 33, +KeyCode_7 = 34, +KeyCode_8 = 35, +KeyCode_9 = 36, +KeyCode_Space = 37, +KeyCode_Tick = 38, +KeyCode_Minus = 39, +KeyCode_Equal = 40, +KeyCode_LeftBracket = 41, +KeyCode_RightBracket = 42, +KeyCode_Semicolon = 43, +KeyCode_Quote = 44, +KeyCode_Comma = 45, +KeyCode_Period = 46, +KeyCode_ForwardSlash = 47, +KeyCode_BackwardSlash = 48, +KeyCode_Tab = 49, +KeyCode_Escape = 50, +KeyCode_Pause = 51, +KeyCode_Up = 52, +KeyCode_Down = 53, +KeyCode_Left = 54, +KeyCode_Right = 55, +KeyCode_Backspace = 56, +KeyCode_Return = 57, +KeyCode_Delete = 58, +KeyCode_Insert = 59, +KeyCode_Home = 60, +KeyCode_End = 61, +KeyCode_PageUp = 62, +KeyCode_PageDown = 63, +KeyCode_CapsLock = 64, +KeyCode_NumLock = 65, +KeyCode_ScrollLock = 66, +KeyCode_Menu = 67, +KeyCode_Shift = 68, +KeyCode_Control = 69, +KeyCode_Alt = 70, +KeyCode_Command = 71, +KeyCode_F1 = 72, +KeyCode_F2 = 73, +KeyCode_F3 = 74, +KeyCode_F4 = 75, +KeyCode_F5 = 76, +KeyCode_F6 = 77, +KeyCode_F7 = 78, +KeyCode_F8 = 79, +KeyCode_F9 = 80, +KeyCode_F10 = 81, +KeyCode_F11 = 82, +KeyCode_F12 = 83, +KeyCode_F13 = 84, +KeyCode_F14 = 85, +KeyCode_F15 = 86, +KeyCode_F16 = 87, +KeyCode_F17 = 88, +KeyCode_F18 = 89, +KeyCode_F19 = 90, +KeyCode_F20 = 91, +KeyCode_F21 = 92, +KeyCode_F22 = 93, +KeyCode_F23 = 94, +KeyCode_F24 = 95, +KeyCode_NumPad0 = 96, +KeyCode_NumPad1 = 97, +KeyCode_NumPad2 = 98, +KeyCode_NumPad3 = 99, +KeyCode_NumPad4 = 100, +KeyCode_NumPad5 = 101, +KeyCode_NumPad6 = 102, +KeyCode_NumPad7 = 103, +KeyCode_NumPad8 = 104, +KeyCode_NumPad9 = 105, +KeyCode_NumPadStar = 106, +KeyCode_NumPadPlus = 107, +KeyCode_NumPadMinus = 108, +KeyCode_NumPadDot = 109, +KeyCode_NumPadSlash = 110, +KeyCode_Ex0 = 111, +KeyCode_Ex1 = 112, +KeyCode_Ex2 = 113, +KeyCode_Ex3 = 114, +KeyCode_Ex4 = 115, +KeyCode_Ex5 = 116, +KeyCode_Ex6 = 117, +KeyCode_Ex7 = 118, +KeyCode_Ex8 = 119, +KeyCode_Ex9 = 120, +KeyCode_Ex10 = 121, +KeyCode_Ex11 = 122, +KeyCode_Ex12 = 123, +KeyCode_Ex13 = 124, +KeyCode_Ex14 = 125, +KeyCode_Ex15 = 126, +KeyCode_Ex16 = 127, +KeyCode_Ex17 = 128, +KeyCode_Ex18 = 129, +KeyCode_Ex19 = 130, +KeyCode_Ex20 = 131, +KeyCode_Ex21 = 132, +KeyCode_Ex22 = 133, +KeyCode_Ex23 = 134, +KeyCode_Ex24 = 135, +KeyCode_Ex25 = 136, +KeyCode_Ex26 = 137, +KeyCode_Ex27 = 138, +KeyCode_Ex28 = 139, +KeyCode_Ex29 = 140, +KeyCode_COUNT = 141, }; global char* key_code_name[KeyCode_COUNT] = { - "None", - "A", - "B", - "C", - "D", - "E", - "F", - "G", - "H", - "I", - "J", - "K", - "L", - "M", - "N", - "O", - "P", - "Q", - "R", - "S", - "T", - "U", - "V", - "W", - "X", - "Y", - "Z", - "0", - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "Space", - "Tick", - "Minus", - "Equal", - "LeftBracket", - "RightBracket", - "Semicolon", - "Quote", - "Comma", - "Period", - "ForwardSlash", - "BackwardSlash", - "Tab", - "Escape", - "Pause", - "Up", - "Down", - "Left", - "Right", - "Backspace", - "Return", - "Delete", - "Insert", - "Home", - "End", - "PageUp", - "PageDown", - "CapsLock", - "NumLock", - "ScrollLock", - "Menu", - "Shift", - "Control", - "Alt", - "Command", - "F1", - "F2", - "F3", - "F4", - "F5", - "F6", - "F7", - "F8", - "F9", - "F10", - "F11", - "F12", - "F13", - "F14", - "F15", - "F16", +"None", +"A", +"B", +"C", +"D", +"E", +"F", +"G", +"H", +"I", +"J", +"K", +"L", +"M", +"N", +"O", +"P", +"Q", +"R", +"S", +"T", +"U", +"V", +"W", +"X", +"Y", +"Z", +"0", +"1", +"2", +"3", +"4", +"5", +"6", +"7", +"8", +"9", +"Space", +"Tick", +"Minus", +"Equal", +"LeftBracket", +"RightBracket", +"Semicolon", +"Quote", +"Comma", +"Period", +"ForwardSlash", +"BackwardSlash", +"Tab", +"Escape", +"Pause", +"Up", +"Down", +"Left", +"Right", +"Backspace", +"Return", +"Delete", +"Insert", +"Home", +"End", +"PageUp", +"PageDown", +"CapsLock", +"NumLock", +"ScrollLock", +"Menu", +"Shift", +"Control", +"Alt", +"Command", +"F1", +"F2", +"F3", +"F4", +"F5", +"F6", +"F7", +"F8", +"F9", +"F10", +"F11", +"F12", +"F13", +"F14", +"F15", +"F16", +"F17", +"F18", +"F19", +"F20", +"F21", +"F22", +"F23", +"F24", +"NumPad0", +"NumPad1", +"NumPad2", +"NumPad3", +"NumPad4", +"NumPad5", +"NumPad6", +"NumPad7", +"NumPad8", +"NumPad9", +"NumPadStar", +"NumPadPlus", +"NumPadMinus", +"NumPadDot", +"NumPadSlash", +"Ex0", +"Ex1", +"Ex2", +"Ex3", +"Ex4", +"Ex5", +"Ex6", +"Ex7", +"Ex8", +"Ex9", +"Ex10", +"Ex11", +"Ex12", +"Ex13", +"Ex14", +"Ex15", +"Ex16", +"Ex17", +"Ex18", +"Ex19", +"Ex20", +"Ex21", +"Ex22", +"Ex23", +"Ex24", +"Ex25", +"Ex26", +"Ex27", +"Ex28", +"Ex29", }; enum{ - MouseCode_Left = 1, - MouseCode_Middle = 2, - MouseCode_Right = 3, - MouseCode_COUNT = 4, +MouseCode_Left = 1, +MouseCode_Middle = 2, +MouseCode_Right = 3, +MouseCode_COUNT = 4, }; global char* mouse_code_name[MouseCode_COUNT] = { - "None", - "Left", - "Middle", - "Right", +"None", +"Left", +"Middle", +"Right", }; enum{ - CoreCode_Startup = 1, - CoreCode_Animate = 2, - CoreCode_ClickActivateView = 3, - CoreCode_ClickDeactivateView = 4, - CoreCode_TryExit = 5, - CoreCode_FileExternallyModified = 6, - CoreCode_NewClipboardContents = 7, - CoreCode_COUNT = 8, +CoreCode_Startup = 1, +CoreCode_Animate = 2, +CoreCode_ClickActivateView = 3, +CoreCode_ClickDeactivateView = 4, +CoreCode_TryExit = 5, +CoreCode_FileExternallyModified = 6, +CoreCode_NewClipboardContents = 7, +CoreCode_COUNT = 8, }; global char* core_code_name[CoreCode_COUNT] = { - "None", - "Startup", - "Animate", - "ClickActivateView", - "ClickDeactivateView", - "TryExit", - "FileExternallyModified", - "NewClipboardContents", +"None", +"Startup", +"Animate", +"ClickActivateView", +"ClickDeactivateView", +"TryExit", +"FileExternallyModified", +"NewClipboardContents", }; diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index 33fa492a..fc706980 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -2,7 +2,7 @@ #define command_id(c) (fcoder_metacmd_ID_##c) #define command_metadata(c) (&fcoder_metacmd_table[command_id(c)]) #define command_metadata_by_id(id) (&fcoder_metacmd_table[id]) -#define command_one_past_last_id 238 +#define command_one_past_last_id 242 #if defined(CUSTOM_COMMAND_SIG) #define PROC_LINKS(x,y) x #else @@ -53,6 +53,9 @@ CUSTOM_COMMAND_SIG(delete_current_scope); CUSTOM_COMMAND_SIG(delete_file_query); CUSTOM_COMMAND_SIG(delete_line); CUSTOM_COMMAND_SIG(delete_range); +CUSTOM_COMMAND_SIG(display_key_codes); +CUSTOM_COMMAND_SIG(display_text_input); +CUSTOM_COMMAND_SIG(double_backspace); CUSTOM_COMMAND_SIG(duplicate_line); CUSTOM_COMMAND_SIG(execute_any_cli); CUSTOM_COMMAND_SIG(execute_previous_cli); @@ -158,6 +161,7 @@ CUSTOM_COMMAND_SIG(paste_and_indent); CUSTOM_COMMAND_SIG(paste_next); CUSTOM_COMMAND_SIG(paste_next_and_indent); CUSTOM_COMMAND_SIG(place_in_scope); +CUSTOM_COMMAND_SIG(play_with_a_counter); CUSTOM_COMMAND_SIG(profile_clear); CUSTOM_COMMAND_SIG(profile_disable); CUSTOM_COMMAND_SIG(profile_enable); @@ -212,9 +216,9 @@ CUSTOM_COMMAND_SIG(show_the_log_graph); CUSTOM_COMMAND_SIG(snipe_backward_whitespace_or_token_boundary); CUSTOM_COMMAND_SIG(snipe_forward_whitespace_or_token_boundary); CUSTOM_COMMAND_SIG(snippet_lister); +CUSTOM_COMMAND_SIG(string_repeat); CUSTOM_COMMAND_SIG(suppress_mouse); CUSTOM_COMMAND_SIG(swap_panels); -CUSTOM_COMMAND_SIG(test_double_backspace); CUSTOM_COMMAND_SIG(theme_lister); CUSTOM_COMMAND_SIG(to_lowercase); CUSTOM_COMMAND_SIG(to_uppercase); @@ -259,73 +263,76 @@ char *source_name; i32 source_name_len; i32 line_number; }; -static Command_Metadata fcoder_metacmd_table[238] = { +static Command_Metadata fcoder_metacmd_table[242] = { { PROC_LINKS(allow_mouse, 0), false, "allow_mouse", 11, "Shows the mouse and causes all mouse input to be processed normally.", 68, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 409 }, { PROC_LINKS(auto_indent_line_at_cursor, 0), false, "auto_indent_line_at_cursor", 26, "Auto-indents the line on which the cursor sits.", 47, "W:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 413 }, { PROC_LINKS(auto_indent_range, 0), false, "auto_indent_range", 17, "Auto-indents the range between the cursor and the mark.", 55, "W:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 423 }, { PROC_LINKS(auto_indent_whole_file, 0), false, "auto_indent_whole_file", 22, "Audo-indents the entire current buffer.", 39, "W:\\4ed\\code\\custom\\4coder_auto_indent.cpp", 41, 404 }, -{ PROC_LINKS(backspace_alpha_numeric_boundary, 0), false, "backspace_alpha_numeric_boundary", 32, "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 165 }, +{ PROC_LINKS(backspace_alpha_numeric_boundary, 0), false, "backspace_alpha_numeric_boundary", 32, "Delete characters between the cursor position and the first alphanumeric boundary to the left.", 94, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 154 }, { PROC_LINKS(backspace_char, 0), false, "backspace_char", 14, "Deletes the character to the left of the cursor.", 48, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 96 }, -{ PROC_LINKS(basic_change_active_panel, 0), false, "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 658 }, +{ PROC_LINKS(basic_change_active_panel, 0), false, "basic_change_active_panel", 25, "Change the currently active panel, moving to the panel with the next highest view_id. Will not skipe the build panel if it is open.", 132, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 647 }, { PROC_LINKS(begin_clipboard_collection_mode, 0), true, "begin_clipboard_collection_mode", 31, "Allows the user to copy multiple strings from other applications before switching to 4coder and pasting them all.", 113, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 68 }, { PROC_LINKS(build_in_build_panel, 0), false, "build_in_build_panel", 20, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*. Puts the *compilation* buffer in a panel at the footer of the current view.", 230, "W:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 159 }, { PROC_LINKS(build_search, 0), false, "build_search", 12, "Looks for a build.bat, build.sh, or makefile in the current and parent directories. Runs the first that it finds and prints the output to *compilation*.", 153, "W:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 122 }, -{ PROC_LINKS(center_view, 0), false, "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 208 }, +{ PROC_LINKS(center_view, 0), false, "center_view", 11, "Centers the view vertically on the line on which the cursor sits.", 65, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 197 }, { PROC_LINKS(change_active_panel, 0), false, "change_active_panel", 19, "Change the currently active panel, moving to the panel with the next highest view_id.", 85, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 284 }, { PROC_LINKS(change_active_panel_backwards, 0), false, "change_active_panel_backwards", 29, "Change the currently active panel, moving to the panel with the next lowest view_id.", 84, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 290 }, { PROC_LINKS(change_to_build_panel, 0), false, "change_to_build_panel", 21, "If the special build panel is open, makes the build panel the active panel.", 75, "W:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 180 }, -{ PROC_LINKS(clean_all_lines, 0), false, "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 647 }, +{ PROC_LINKS(clean_all_lines, 0), false, "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 636 }, { PROC_LINKS(clear_all_themes, 0), false, "clear_all_themes", 16, "Clear the theme list", 20, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 480 }, { PROC_LINKS(clear_clipboard, 0), false, "clear_clipboard", 15, "Clears the history of the clipboard", 35, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 216 }, -{ PROC_LINKS(click_set_cursor, 0), false, "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 244 }, -{ PROC_LINKS(click_set_cursor_and_mark, 0), false, "click_set_cursor_and_mark", 25, "Sets the cursor position and mark to the mouse position.", 56, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 234 }, -{ PROC_LINKS(click_set_cursor_if_lbutton, 0), false, "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 254 }, -{ PROC_LINKS(click_set_mark, 0), false, "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 266 }, +{ PROC_LINKS(click_set_cursor, 0), false, "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 233 }, +{ PROC_LINKS(click_set_cursor_and_mark, 0), false, "click_set_cursor_and_mark", 25, "Sets the cursor position and mark to the mouse position.", 56, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 223 }, +{ PROC_LINKS(click_set_cursor_if_lbutton, 0), false, "click_set_cursor_if_lbutton", 27, "If the mouse left button is pressed, sets the cursor position to the mouse position.", 84, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 243 }, +{ PROC_LINKS(click_set_mark, 0), false, "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 255 }, { PROC_LINKS(clipboard_record_clip, 0), false, "clipboard_record_clip", 21, "In response to a new clipboard contents events, saves the new clip onto the clipboard history", 93, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 7 }, { PROC_LINKS(close_all_code, 0), false, "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 843 }, { PROC_LINKS(close_build_panel, 0), false, "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "W:\\4ed\\code\\custom\\4coder_build_commands.cpp", 44, 174 }, -{ PROC_LINKS(close_panel, 0), false, "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 666 }, +{ PROC_LINKS(close_panel, 0), false, "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 655 }, { PROC_LINKS(command_documentation, 0), true, "command_documentation", 21, "Prompts the user to select a command then loads a doc buffer for that item", 74, "W:\\4ed\\code\\custom\\4coder_docs.cpp", 34, 190 }, { PROC_LINKS(command_lister, 0), true, "command_lister", 14, "Opens an interactive list of all registered commands.", 53, "W:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 761 }, { PROC_LINKS(comment_line, 0), false, "comment_line", 12, "Insert '//' at the beginning of the line after leading whitespace.", 66, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 125 }, { PROC_LINKS(comment_line_toggle, 0), false, "comment_line_toggle", 19, "Turns uncommented lines into commented lines and vice versa for comments starting with '//'.", 92, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 149 }, { PROC_LINKS(copy, 0), false, "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 107 }, -{ PROC_LINKS(cursor_mark_swap, 0), false, "cursor_mark_swap", 16, "Swaps the position of the cursor and the mark.", 46, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 135 }, +{ PROC_LINKS(cursor_mark_swap, 0), false, "cursor_mark_swap", 16, "Swaps the position of the cursor and the mark.", 46, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 124 }, { PROC_LINKS(custom_api_documentation, 0), true, "custom_api_documentation", 24, "Prompts the user to select a Custom API item then loads a doc buffer for that item", 82, "W:\\4ed\\code\\custom\\4coder_docs.cpp", 34, 175 }, { PROC_LINKS(cut, 0), false, "cut", 3, "Cut the text in the range from the cursor to the mark onto the clipboard.", 73, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 116 }, -{ PROC_LINKS(decrease_face_size, 0), false, "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 749 }, -{ PROC_LINKS(default_file_externally_modified, 0), false, "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1891 }, +{ PROC_LINKS(decrease_face_size, 0), false, "decrease_face_size", 18, "Decrease the size of the face used by the current buffer.", 57, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 738 }, +{ PROC_LINKS(default_file_externally_modified, 0), false, "default_file_externally_modified", 32, "Notes the external modification of attached files by printing a message.", 72, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1897 }, { PROC_LINKS(default_startup, 0), false, "default_startup", 15, "Default command for responding to a startup event", 49, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 7 }, { PROC_LINKS(default_try_exit, 0), false, "default_try_exit", 16, "Default command for responding to a try-exit event", 50, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 23 }, { PROC_LINKS(default_view_input_handler, 0), false, "default_view_input_handler", 26, "Input consumption loop for default view behavior", 48, "W:\\4ed\\code\\custom\\4coder_default_hooks.cpp", 43, 51 }, -{ PROC_LINKS(delete_alpha_numeric_boundary, 0), false, "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 173 }, +{ PROC_LINKS(delete_alpha_numeric_boundary, 0), false, "delete_alpha_numeric_boundary", 29, "Delete characters between the cursor position and the first alphanumeric boundary to the right.", 95, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 162 }, { PROC_LINKS(delete_char, 0), false, "delete_char", 11, "Deletes the character to the right of the cursor.", 49, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 79 }, { PROC_LINKS(delete_current_scope, 0), false, "delete_current_scope", 20, "Deletes the braces surrounding the currently selected scope. Leaves the contents within the scope.", 99, "W:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 112 }, -{ PROC_LINKS(delete_file_query, 0), false, "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1317 }, -{ PROC_LINKS(delete_line, 0), false, "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1489 }, -{ PROC_LINKS(delete_range, 0), false, "delete_range", 12, "Deletes the text in the range between the cursor and the mark.", 62, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 145 }, -{ PROC_LINKS(duplicate_line, 0), false, "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1475 }, +{ PROC_LINKS(delete_file_query, 0), false, "delete_file_query", 17, "Deletes the file of the current buffer if 4coder has the appropriate access rights. Will ask the user for confirmation first.", 125, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1323 }, +{ PROC_LINKS(delete_line, 0), false, "delete_line", 11, "Delete the line the on which the cursor sits.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1495 }, +{ PROC_LINKS(delete_range, 0), false, "delete_range", 12, "Deletes the text in the range between the cursor and the mark.", 62, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 134 }, +{ PROC_LINKS(display_key_codes, 0), false, "display_key_codes", 17, "Example of input handling loop", 30, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 90 }, +{ PROC_LINKS(display_text_input, 0), false, "display_text_input", 18, "Example of to_writable and leave_current_input_unhandled", 56, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 134 }, +{ PROC_LINKS(double_backspace, 0), false, "double_backspace", 16, "Example of history group helpers", 32, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 10 }, +{ PROC_LINKS(duplicate_line, 0), false, "duplicate_line", 14, "Create a copy of the line on which the cursor sits.", 51, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1481 }, { PROC_LINKS(execute_any_cli, 0), false, "execute_any_cli", 15, "Queries for an output buffer name and system command, runs the system command as a CLI and prints the output to the specified buffer.", 133, "W:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 22 }, { PROC_LINKS(execute_previous_cli, 0), false, "execute_previous_cli", 20, "If the command execute_any_cli has already been used, this will execute a CLI reusing the most recent buffer name and command.", 126, "W:\\4ed\\code\\custom\\4coder_cli_command.cpp", 41, 7 }, -{ PROC_LINKS(exit_4coder, 0), false, "exit_4coder", 11, "Attempts to close 4coder.", 25, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 836 }, -{ PROC_LINKS(goto_beginning_of_file, 0), false, "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2201 }, -{ PROC_LINKS(goto_end_of_file, 0), false, "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2209 }, +{ PROC_LINKS(exit_4coder, 0), false, "exit_4coder", 11, "Attempts to close 4coder.", 25, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 825 }, +{ PROC_LINKS(goto_beginning_of_file, 0), false, "goto_beginning_of_file", 22, "Sets the cursor to the beginning of the file.", 45, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2224 }, +{ PROC_LINKS(goto_end_of_file, 0), false, "goto_end_of_file", 16, "Sets the cursor to the end of the file.", 39, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2232 }, { PROC_LINKS(goto_first_jump, 0), false, "goto_first_jump", 15, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer.", 95, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 525 }, { PROC_LINKS(goto_first_jump_same_panel_sticky, 0), false, "goto_first_jump_same_panel_sticky", 33, "If a buffer containing jump locations has been locked in, goes to the first jump in the buffer and views the buffer in the panel where the jump list was.", 153, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 542 }, { PROC_LINKS(goto_jump_at_cursor, 0), false, "goto_jump_at_cursor", 19, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in another view and changes the active panel to the view containing the jump.", 187, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 348 }, { PROC_LINKS(goto_jump_at_cursor_same_panel, 0), false, "goto_jump_at_cursor_same_panel", 30, "If the cursor is found to be on a jump location, parses the jump location and brings up the file and position in this view, losing the compilation output or jump list.", 167, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 375 }, -{ PROC_LINKS(goto_line, 0), false, "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 844 }, +{ PROC_LINKS(goto_line, 0), false, "goto_line", 9, "Queries the user for a number, and jumps the cursor to the corresponding line.", 78, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 833 }, { PROC_LINKS(goto_next_jump, 0), false, "goto_next_jump", 14, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, skipping sub jump locations.", 123, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 464 }, { PROC_LINKS(goto_next_jump_no_skips, 0), false, "goto_next_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the next jump in the buffer, and does not skip sub jump locations.", 132, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 494 }, { PROC_LINKS(goto_prev_jump, 0), false, "goto_prev_jump", 14, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, skipping sub jump locations.", 127, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 481 }, { PROC_LINKS(goto_prev_jump_no_skips, 0), false, "goto_prev_jump_no_skips", 23, "If a buffer containing jump locations has been locked in, goes to the previous jump in the buffer, and does not skip sub jump locations.", 136, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 511 }, -{ PROC_LINKS(hide_filebar, 0), false, "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 696 }, -{ PROC_LINKS(hide_scrollbar, 0), false, "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 682 }, +{ PROC_LINKS(hide_filebar, 0), false, "hide_filebar", 12, "Sets the current view to hide it's filebar.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 685 }, +{ PROC_LINKS(hide_scrollbar, 0), false, "hide_scrollbar", 14, "Sets the current view to hide it's scrollbar.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 671 }, { PROC_LINKS(hms_demo_tutorial, 0), false, "hms_demo_tutorial", 17, "Tutorial for built in 4coder bindings and features.", 51, "W:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 869 }, { PROC_LINKS(if0_off, 0), false, "if0_off", 7, "Surround the range between the cursor and mark with an '#if 0' and an '#endif'", 78, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 70 }, { PROC_LINKS(if_read_only_goto_position, 0), false, "if_read_only_goto_position", 26, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 564 }, { PROC_LINKS(if_read_only_goto_position_same_panel, 0), false, "if_read_only_goto_position_same_panel", 37, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "W:\\4ed\\code\\custom\\4coder_jump_sticky.cpp", 41, 581 }, -{ PROC_LINKS(increase_face_size, 0), false, "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 738 }, +{ PROC_LINKS(increase_face_size, 0), false, "increase_face_size", 18, "Increase the size of the face used by the current buffer.", 57, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 727 }, { PROC_LINKS(interactive_kill_buffer, 0), true, "interactive_kill_buffer", 23, "Interactively kill an open buffer.", 34, "W:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 520 }, { PROC_LINKS(interactive_new, 0), true, "interactive_new", 15, "Interactively creates a new file.", 33, "W:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 661 }, { PROC_LINKS(interactive_open, 0), true, "interactive_open", 16, "Interactively opens a file.", 27, "W:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 715 }, @@ -335,9 +342,9 @@ static Command_Metadata fcoder_metacmd_table[238] = { { PROC_LINKS(keyboard_macro_finish_recording, 0), false, "keyboard_macro_finish_recording", 31, "Stop macro recording, do nothing if macro recording is not already started", 74, "W:\\4ed\\code\\custom\\4coder_keyboard_macro.cpp", 44, 54 }, { PROC_LINKS(keyboard_macro_replay, 0), false, "keyboard_macro_replay", 21, "Replay the most recently recorded keyboard macro", 48, "W:\\4ed\\code\\custom\\4coder_keyboard_macro.cpp", 44, 77 }, { PROC_LINKS(keyboard_macro_start_recording, 0), false, "keyboard_macro_start_recording", 30, "Start macro recording, do nothing if macro recording is already started", 71, "W:\\4ed\\code\\custom\\4coder_keyboard_macro.cpp", 44, 41 }, -{ PROC_LINKS(kill_buffer, 0), false, "kill_buffer", 11, "Kills the current buffer.", 25, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1635 }, +{ PROC_LINKS(kill_buffer, 0), false, "kill_buffer", 11, "Kills the current buffer.", 25, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1641 }, { PROC_LINKS(kill_tutorial, 0), false, "kill_tutorial", 13, "If there is an active tutorial, kill it.", 40, "W:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 9 }, -{ PROC_LINKS(left_adjust_view, 0), false, "left_adjust_view", 16, "Sets the left size of the view near the x position of the cursor.", 65, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 222 }, +{ PROC_LINKS(left_adjust_view, 0), false, "left_adjust_view", 16, "Sets the left size of the view near the x position of the cursor.", 65, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 211 }, { PROC_LINKS(list_all_functions_all_buffers, 0), false, "list_all_functions_all_buffers", 30, "Creates a jump list of lines from all buffers that appear to define or declare functions.", 89, "W:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 295 }, { PROC_LINKS(list_all_functions_all_buffers_lister, 0), true, "list_all_functions_all_buffers_lister", 37, "Creates a lister of locations that look like function definitions and declarations all buffers.", 95, "W:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 301 }, { PROC_LINKS(list_all_functions_current_buffer, 0), false, "list_all_functions_current_buffer", 33, "Creates a jump list of lines of the current buffer that appear to define or declare functions.", 94, "W:\\4ed\\code\\custom\\4coder_function_list.cpp", 43, 267 }, @@ -356,59 +363,60 @@ static Command_Metadata fcoder_metacmd_table[238] = { { PROC_LINKS(load_theme_current_buffer, 0), false, "load_theme_current_buffer", 25, "Parse the current buffer as a theme file and add the theme to the theme list. If the buffer has a .4coder postfix in it's name, it is removed when the name is saved.", 165, "W:\\4ed\\code\\custom\\4coder_config.cpp", 36, 1627 }, { PROC_LINKS(load_themes_default_folder, 0), false, "load_themes_default_folder", 26, "Loads all the theme files in the default theme folder.", 54, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 457 }, { PROC_LINKS(load_themes_hot_directory, 0), false, "load_themes_hot_directory", 25, "Loads all the theme files in the current hot directory.", 55, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 469 }, -{ PROC_LINKS(make_directory_query, 0), false, "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1429 }, +{ PROC_LINKS(make_directory_query, 0), false, "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1435 }, { PROC_LINKS(miblo_decrement_basic, 0), false, "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "W:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 44 }, { PROC_LINKS(miblo_decrement_time_stamp, 0), false, "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "W:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 237 }, { PROC_LINKS(miblo_decrement_time_stamp_minute, 0), false, "miblo_decrement_time_stamp_minute", 33, "Decrement a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "W:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 249 }, { PROC_LINKS(miblo_increment_basic, 0), false, "miblo_increment_basic", 21, "Increment an integer under the cursor by one.", 45, "W:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 29 }, { PROC_LINKS(miblo_increment_time_stamp, 0), false, "miblo_increment_time_stamp", 26, "Increment a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "W:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 231 }, { PROC_LINKS(miblo_increment_time_stamp_minute, 0), false, "miblo_increment_time_stamp_minute", 33, "Increment a time stamp under the cursor by one minute. (format [m]m:ss or h:mm:ss", 81, "W:\\4ed\\code\\custom\\4coder_miblo_numbers.cpp", 43, 243 }, -{ PROC_LINKS(mouse_wheel_change_face_size, 0), false, "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 791 }, -{ PROC_LINKS(mouse_wheel_scroll, 0), false, "mouse_wheel_scroll", 18, "Reads the scroll wheel value from the mouse state and scrolls accordingly.", 74, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 276 }, -{ PROC_LINKS(move_down, 0), false, "move_down", 9, "Moves the cursor down one line.", 31, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 347 }, -{ PROC_LINKS(move_down_10, 0), false, "move_down_10", 12, "Moves the cursor down ten lines.", 32, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 359 }, -{ PROC_LINKS(move_down_textual, 0), false, "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 365 }, -{ PROC_LINKS(move_down_to_blank_line, 0), false, "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 418 }, -{ PROC_LINKS(move_down_to_blank_line_end, 0), false, "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 442 }, -{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), false, "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 430 }, -{ PROC_LINKS(move_left, 0), false, "move_left", 9, "Moves the cursor one character to the left.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 448 }, -{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), false, "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 525 }, -{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), false, "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 539 }, -{ PROC_LINKS(move_left_token_boundary, 0), false, "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 497 }, -{ PROC_LINKS(move_left_whitespace_boundary, 0), false, "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 482 }, -{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), false, "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 511 }, -{ PROC_LINKS(move_line_down, 0), false, "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1469 }, -{ PROC_LINKS(move_line_up, 0), false, "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1463 }, -{ PROC_LINKS(move_right, 0), false, "move_right", 10, "Moves the cursor one character to the right.", 44, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 456 }, -{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), false, "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 518 }, -{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), false, "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 532 }, -{ PROC_LINKS(move_right_token_boundary, 0), false, "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 490 }, -{ PROC_LINKS(move_right_whitespace_boundary, 0), false, "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 474 }, -{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), false, "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 504 }, -{ PROC_LINKS(move_up, 0), false, "move_up", 7, "Moves the cursor up one line.", 29, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 341 }, -{ PROC_LINKS(move_up_10, 0), false, "move_up_10", 10, "Moves the cursor up ten lines.", 30, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 353 }, -{ PROC_LINKS(move_up_to_blank_line, 0), false, "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 412 }, -{ PROC_LINKS(move_up_to_blank_line_end, 0), false, "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 436 }, -{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), false, "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 424 }, +{ PROC_LINKS(mouse_wheel_change_face_size, 0), false, "mouse_wheel_change_face_size", 28, "Reads the state of the mouse wheel and uses it to either increase or decrease the face size.", 92, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 780 }, +{ PROC_LINKS(mouse_wheel_scroll, 0), false, "mouse_wheel_scroll", 18, "Reads the scroll wheel value from the mouse state and scrolls accordingly.", 74, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 265 }, +{ PROC_LINKS(move_down, 0), false, "move_down", 9, "Moves the cursor down one line.", 31, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 336 }, +{ PROC_LINKS(move_down_10, 0), false, "move_down_10", 12, "Moves the cursor down ten lines.", 32, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 348 }, +{ PROC_LINKS(move_down_textual, 0), false, "move_down_textual", 17, "Moves down to the next line of actual text, regardless of line wrapping.", 72, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 354 }, +{ PROC_LINKS(move_down_to_blank_line, 0), false, "move_down_to_blank_line", 23, "Seeks the cursor down to the next blank line.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 407 }, +{ PROC_LINKS(move_down_to_blank_line_end, 0), false, "move_down_to_blank_line_end", 27, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 431 }, +{ PROC_LINKS(move_down_to_blank_line_skip_whitespace, 0), false, "move_down_to_blank_line_skip_whitespace", 39, "Seeks the cursor down to the next blank line and places it at the end of the line.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 419 }, +{ PROC_LINKS(move_left, 0), false, "move_left", 9, "Moves the cursor one character to the left.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 437 }, +{ PROC_LINKS(move_left_alpha_numeric_boundary, 0), false, "move_left_alpha_numeric_boundary", 32, "Seek left for boundary between alphanumeric characters and non-alphanumeric characters.", 87, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 514 }, +{ PROC_LINKS(move_left_alpha_numeric_or_camel_boundary, 0), false, "move_left_alpha_numeric_or_camel_boundary", 41, "Seek left for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 106, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 528 }, +{ PROC_LINKS(move_left_token_boundary, 0), false, "move_left_token_boundary", 24, "Seek left for the next beginning of a token.", 44, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 486 }, +{ PROC_LINKS(move_left_whitespace_boundary, 0), false, "move_left_whitespace_boundary", 29, "Seek left for the next boundary between whitespace and non-whitespace.", 70, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 471 }, +{ PROC_LINKS(move_left_whitespace_or_token_boundary, 0), false, "move_left_whitespace_or_token_boundary", 38, "Seek left for the next end of a token or boundary between whitespace and non-whitespace.", 88, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 500 }, +{ PROC_LINKS(move_line_down, 0), false, "move_line_down", 14, "Swaps the line under the cursor with the line below it, and moves the cursor down with it.", 90, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1475 }, +{ PROC_LINKS(move_line_up, 0), false, "move_line_up", 12, "Swaps the line under the cursor with the line above it, and moves the cursor up with it.", 88, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1469 }, +{ PROC_LINKS(move_right, 0), false, "move_right", 10, "Moves the cursor one character to the right.", 44, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 445 }, +{ PROC_LINKS(move_right_alpha_numeric_boundary, 0), false, "move_right_alpha_numeric_boundary", 33, "Seek right for boundary between alphanumeric characters and non-alphanumeric characters.", 88, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 507 }, +{ PROC_LINKS(move_right_alpha_numeric_or_camel_boundary, 0), false, "move_right_alpha_numeric_or_camel_boundary", 42, "Seek right for boundary between alphanumeric characters or camel case word and non-alphanumeric characters.", 107, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 521 }, +{ PROC_LINKS(move_right_token_boundary, 0), false, "move_right_token_boundary", 25, "Seek right for the next end of a token.", 39, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 479 }, +{ PROC_LINKS(move_right_whitespace_boundary, 0), false, "move_right_whitespace_boundary", 30, "Seek right for the next boundary between whitespace and non-whitespace.", 71, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 463 }, +{ PROC_LINKS(move_right_whitespace_or_token_boundary, 0), false, "move_right_whitespace_or_token_boundary", 39, "Seek right for the next end of a token or boundary between whitespace and non-whitespace.", 89, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 493 }, +{ PROC_LINKS(move_up, 0), false, "move_up", 7, "Moves the cursor up one line.", 29, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 330 }, +{ PROC_LINKS(move_up_10, 0), false, "move_up_10", 10, "Moves the cursor up ten lines.", 30, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 342 }, +{ PROC_LINKS(move_up_to_blank_line, 0), false, "move_up_to_blank_line", 21, "Seeks the cursor up to the next blank line.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 401 }, +{ PROC_LINKS(move_up_to_blank_line_end, 0), false, "move_up_to_blank_line_end", 25, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 425 }, +{ PROC_LINKS(move_up_to_blank_line_skip_whitespace, 0), false, "move_up_to_blank_line_skip_whitespace", 37, "Seeks the cursor up to the next blank line and places it at the end of the line.", 80, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 413 }, { PROC_LINKS(multi_paste_interactive, 0), false, "multi_paste_interactive", 23, "Paste multiple lines from the clipboard history, controlled with arrow keys", 75, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 364 }, { PROC_LINKS(multi_paste_interactive_quick, 0), false, "multi_paste_interactive_quick", 29, "Paste multiple lines from the clipboard history, controlled by inputing the number of lines to paste", 100, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 373 }, { PROC_LINKS(open_all_code, 0), false, "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 849 }, { PROC_LINKS(open_all_code_recursive, 0), false, "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 855 }, -{ PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1554 }, -{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1885 }, +{ PROC_LINKS(open_file_in_quotes, 0), false, "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1560 }, +{ PROC_LINKS(open_in_other, 0), false, "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1891 }, { PROC_LINKS(open_long_braces, 0), false, "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 46 }, { PROC_LINKS(open_long_braces_break, 0), false, "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 62 }, { PROC_LINKS(open_long_braces_semicolon, 0), false, "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 54 }, -{ PROC_LINKS(open_matching_file_cpp, 0), false, "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1586 }, +{ PROC_LINKS(open_matching_file_cpp, 0), false, "open_matching_file_cpp", 22, "If the current file is a *.cpp or *.h, attempts to open the corresponding *.h or *.cpp file in the other view.", 110, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1592 }, { PROC_LINKS(open_panel_hsplit, 0), false, "open_panel_hsplit", 17, "Create a new panel by horizontally splitting the active panel.", 62, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 310 }, { PROC_LINKS(open_panel_vsplit, 0), false, "open_panel_vsplit", 17, "Create a new panel by vertically splitting the active panel.", 60, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 300 }, -{ PROC_LINKS(page_down, 0), false, "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 383 }, -{ PROC_LINKS(page_up, 0), false, "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 375 }, +{ PROC_LINKS(page_down, 0), false, "page_down", 9, "Scrolls the view down one view height and moves the cursor down one view height.", 80, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 372 }, +{ PROC_LINKS(page_up, 0), false, "page_up", 7, "Scrolls the view up one view height and moves the cursor up one view height.", 76, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 364 }, { PROC_LINKS(paste, 0), false, "paste", 5, "At the cursor, insert the text at the top of the clipboard.", 59, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 127 }, { PROC_LINKS(paste_and_indent, 0), false, "paste_and_indent", 16, "Paste from the top of clipboard and run auto-indent on the newly pasted text.", 77, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 202 }, { PROC_LINKS(paste_next, 0), false, "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 161 }, { PROC_LINKS(paste_next_and_indent, 0), false, "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "W:\\4ed\\code\\custom\\4coder_clipboard.cpp", 39, 209 }, { PROC_LINKS(place_in_scope, 0), false, "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "W:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 106 }, +{ PROC_LINKS(play_with_a_counter, 0), false, "play_with_a_counter", 19, "Example of query bar", 20, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 29 }, { PROC_LINKS(profile_clear, 0), false, "profile_clear", 13, "Clear all profiling information from 4coder's self profiler.", 60, "W:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 226 }, { PROC_LINKS(profile_disable, 0), false, "profile_disable", 15, "Prevent 4coder's self profiler from gathering new profiling information.", 72, "W:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 219 }, { PROC_LINKS(profile_enable, 0), false, "profile_enable", 14, "Allow 4coder's self profiler to gather new profiling information.", 65, "W:\\4ed\\code\\custom\\4coder_profile.cpp", 37, 212 }, @@ -416,28 +424,28 @@ static Command_Metadata fcoder_metacmd_table[238] = { { PROC_LINKS(project_command_lister, 0), false, "project_command_lister", 22, "Open a lister of all commands in the currently loaded project.", 62, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1290 }, { PROC_LINKS(project_fkey_command, 0), false, "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 871 }, { PROC_LINKS(project_go_to_root_directory, 0), false, "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 897 }, -{ PROC_LINKS(query_replace, 0), false, "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1245 }, -{ PROC_LINKS(query_replace_identifier, 0), false, "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1266 }, -{ PROC_LINKS(query_replace_selection, 0), false, "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1282 }, -{ PROC_LINKS(redo, 0), false, "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1724 }, -{ PROC_LINKS(redo_all_buffers, 0), false, "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1809 }, -{ PROC_LINKS(rename_file_query, 0), false, "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1394 }, -{ PROC_LINKS(reopen, 0), false, "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1653 }, -{ PROC_LINKS(replace_in_all_buffers, 0), false, "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1155 }, -{ PROC_LINKS(replace_in_buffer, 0), false, "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1146 }, -{ PROC_LINKS(replace_in_range, 0), false, "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1137 }, -{ PROC_LINKS(reverse_search, 0), false, "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1078 }, -{ PROC_LINKS(reverse_search_identifier, 0), false, "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1090 }, -{ PROC_LINKS(save, 0), false, "save", 4, "Saves the current buffer.", 25, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1643 }, +{ PROC_LINKS(query_replace, 0), false, "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1251 }, +{ PROC_LINKS(query_replace_identifier, 0), false, "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1272 }, +{ PROC_LINKS(query_replace_selection, 0), false, "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1288 }, +{ PROC_LINKS(redo, 0), false, "redo", 4, "Advances forwards through the undo history of the current buffer.", 65, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1730 }, +{ PROC_LINKS(redo_all_buffers, 0), false, "redo_all_buffers", 16, "Advances forward through the undo history in the buffer containing the most recent regular edit.", 96, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1815 }, +{ PROC_LINKS(rename_file_query, 0), false, "rename_file_query", 17, "Queries the user for a new name and renames the file of the current buffer, altering the buffer's name too.", 107, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1400 }, +{ PROC_LINKS(reopen, 0), false, "reopen", 6, "Reopen the current buffer from the hard drive.", 46, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1659 }, +{ PROC_LINKS(replace_in_all_buffers, 0), false, "replace_in_all_buffers", 22, "Queries the user for a needle and string. Replaces all occurences of needle with string in all editable buffers.", 112, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1161 }, +{ PROC_LINKS(replace_in_buffer, 0), false, "replace_in_buffer", 17, "Queries the user for a needle and string. Replaces all occurences of needle with string in the active buffer.", 109, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1152 }, +{ PROC_LINKS(replace_in_range, 0), false, "replace_in_range", 16, "Queries the user for a needle and string. Replaces all occurences of needle with string in the range between cursor and the mark in the active buffer.", 150, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1143 }, +{ PROC_LINKS(reverse_search, 0), false, "reverse_search", 14, "Begins an incremental search up through the current buffer for a user specified string.", 87, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1084 }, +{ PROC_LINKS(reverse_search_identifier, 0), false, "reverse_search_identifier", 25, "Begins an incremental search up through the current buffer for the word or token under the cursor.", 98, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1096 }, +{ PROC_LINKS(save, 0), false, "save", 4, "Saves the current buffer.", 25, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1649 }, { PROC_LINKS(save_all_dirty_buffers, 0), false, "save_all_dirty_buffers", 22, "Saves all buffers marked dirty (showing the '*' indicator).", 59, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 382 }, -{ PROC_LINKS(save_to_query, 0), false, "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1361 }, -{ PROC_LINKS(search, 0), false, "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1072 }, -{ PROC_LINKS(search_identifier, 0), false, "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1084 }, -{ PROC_LINKS(seek_beginning_of_line, 0), false, "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2189 }, -{ PROC_LINKS(seek_beginning_of_textual_line, 0), false, "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2177 }, -{ PROC_LINKS(seek_end_of_line, 0), false, "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2195 }, -{ PROC_LINKS(seek_end_of_textual_line, 0), false, "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2183 }, -{ PROC_LINKS(select_all, 0), false, "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 548 }, +{ PROC_LINKS(save_to_query, 0), false, "save_to_query", 13, "Queries the user for a file name and saves the contents of the current buffer, altering the buffer's name too.", 110, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1367 }, +{ PROC_LINKS(search, 0), false, "search", 6, "Begins an incremental search down through the current buffer for a user specified string.", 89, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1078 }, +{ PROC_LINKS(search_identifier, 0), false, "search_identifier", 17, "Begins an incremental search down through the current buffer for the word or token under the cursor.", 100, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1090 }, +{ PROC_LINKS(seek_beginning_of_line, 0), false, "seek_beginning_of_line", 22, "Seeks the cursor to the beginning of the visual line.", 53, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2212 }, +{ PROC_LINKS(seek_beginning_of_textual_line, 0), false, "seek_beginning_of_textual_line", 30, "Seeks the cursor to the beginning of the line across all text.", 62, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2200 }, +{ PROC_LINKS(seek_end_of_line, 0), false, "seek_end_of_line", 16, "Seeks the cursor to the end of the visual line.", 47, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2218 }, +{ PROC_LINKS(seek_end_of_textual_line, 0), false, "seek_end_of_textual_line", 24, "Seeks the cursor to the end of the line across all text.", 56, "W:\\4ed\\code\\custom\\4coder_helper.cpp", 36, 2206 }, +{ PROC_LINKS(select_all, 0), false, "select_all", 10, "Puts the cursor at the top of the file, and the mark at the bottom of the file.", 79, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 537 }, { PROC_LINKS(select_next_scope_absolute, 0), false, "select_next_scope_absolute", 26, "Finds the first scope started by '{' after the cursor and puts the cursor and mark on the '{' and '}'.", 102, "W:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 57 }, { PROC_LINKS(select_next_scope_after_current, 0), false, "select_next_scope_after_current", 31, "If a scope is selected, find first scope that starts after the selected scope. Otherwise find the first scope that starts after the cursor.", 139, "W:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 66 }, { PROC_LINKS(select_prev_scope_absolute, 0), false, "select_prev_scope_absolute", 26, "Finds the first scope started by '{' before the cursor and puts the cursor and mark on the '{' and '}'.", 103, "W:\\4ed\\code\\custom\\4coder_scope_commands.cpp", 44, 82 }, @@ -448,44 +456,44 @@ static Command_Metadata fcoder_metacmd_table[238] = { { PROC_LINKS(set_eol_mode_to_binary, 0), false, "set_eol_mode_to_binary", 22, "Puts the buffer in bin line ending mode.", 40, "W:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 112 }, { PROC_LINKS(set_eol_mode_to_crlf, 0), false, "set_eol_mode_to_crlf", 20, "Puts the buffer in crlf line ending mode.", 41, "W:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 86 }, { PROC_LINKS(set_eol_mode_to_lf, 0), false, "set_eol_mode_to_lf", 18, "Puts the buffer in lf line ending mode.", 39, "W:\\4ed\\code\\custom\\4coder_eol.cpp", 33, 99 }, -{ PROC_LINKS(set_face_size, 0), false, "set_face_size", 13, "Set face size of the face used by the current buffer.", 53, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 718 }, -{ PROC_LINKS(set_face_size_this_buffer, 0), false, "set_face_size_this_buffer", 25, "Set face size of the face used by the current buffer; if any other buffers are using the same face a new face is created so that only this buffer is effected", 157, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 760 }, -{ PROC_LINKS(set_mark, 0), false, "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 126 }, +{ PROC_LINKS(set_face_size, 0), false, "set_face_size", 13, "Set face size of the face used by the current buffer.", 53, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 707 }, +{ PROC_LINKS(set_face_size_this_buffer, 0), false, "set_face_size_this_buffer", 25, "Set face size of the face used by the current buffer; if any other buffers are using the same face a new face is created so that only this buffer is effected", 157, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 749 }, +{ PROC_LINKS(set_mark, 0), false, "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 115 }, { PROC_LINKS(set_mode_to_notepad_like, 0), false, "set_mode_to_notepad_like", 24, "Sets the edit mode to Notepad like.", 35, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 427 }, { PROC_LINKS(set_mode_to_original, 0), false, "set_mode_to_original", 20, "Sets the edit mode to 4coder original.", 38, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 421 }, { PROC_LINKS(setup_build_bat, 0), false, "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1238 }, { PROC_LINKS(setup_build_bat_and_sh, 0), false, "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1250 }, { PROC_LINKS(setup_build_sh, 0), false, "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1244 }, { PROC_LINKS(setup_new_project, 0), false, "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "W:\\4ed\\code\\custom\\4coder_project_commands.cpp", 46, 1231 }, -{ PROC_LINKS(show_filebar, 0), false, "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 689 }, -{ PROC_LINKS(show_scrollbar, 0), false, "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 675 }, +{ PROC_LINKS(show_filebar, 0), false, "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 678 }, +{ PROC_LINKS(show_scrollbar, 0), false, "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 664 }, { PROC_LINKS(show_the_log_graph, 0), true, "show_the_log_graph", 18, "Parses *log* and displays the 'log graph' UI", 44, "W:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 994 }, -{ PROC_LINKS(snipe_backward_whitespace_or_token_boundary, 0), false, "snipe_backward_whitespace_or_token_boundary", 43, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 190 }, -{ PROC_LINKS(snipe_forward_whitespace_or_token_boundary, 0), false, "snipe_forward_whitespace_or_token_boundary", 42, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 198 }, +{ PROC_LINKS(snipe_backward_whitespace_or_token_boundary, 0), false, "snipe_backward_whitespace_or_token_boundary", 43, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 179 }, +{ PROC_LINKS(snipe_forward_whitespace_or_token_boundary, 0), false, "snipe_forward_whitespace_or_token_boundary", 42, "Delete a single, whole token on or to the right of the cursor and post it to the clipboard.", 91, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 187 }, { PROC_LINKS(snippet_lister, 0), true, "snippet_lister", 14, "Opens a snippet lister for inserting whole pre-written snippets of text.", 72, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 237 }, +{ PROC_LINKS(string_repeat, 0), false, "string_repeat", 13, "Example of query_user_string and query_user_number", 50, "W:\\4ed\\code\\custom\\4coder_examples.cpp", 38, 176 }, { PROC_LINKS(suppress_mouse, 0), false, "suppress_mouse", 14, "Hides the mouse and causes all mosue input (clicks, position, wheel) to be ignored.", 83, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 403 }, -{ PROC_LINKS(swap_panels, 0), false, "swap_panels", 11, "Swaps the active panel with it's sibling.", 41, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1611 }, -{ PROC_LINKS(test_double_backspace, 0), false, "test_double_backspace", 21, "Made for testing purposes (I should have deleted this if you are reading it let me know)", 88, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 115 }, +{ PROC_LINKS(swap_panels, 0), false, "swap_panels", 11, "Swaps the active panel with it's sibling.", 41, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1617 }, { PROC_LINKS(theme_lister, 0), true, "theme_lister", 12, "Opens an interactive list of all registered themes.", 51, "W:\\4ed\\code\\custom\\4coder_lists.cpp", 35, 785 }, -{ PROC_LINKS(to_lowercase, 0), false, "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 574 }, -{ PROC_LINKS(to_uppercase, 0), false, "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 561 }, -{ PROC_LINKS(toggle_filebar, 0), false, "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 703 }, -{ PROC_LINKS(toggle_fps_meter, 0), false, "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 712 }, +{ PROC_LINKS(to_lowercase, 0), false, "to_lowercase", 12, "Converts all ascii text in the range between the cursor and the mark to lowercase.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 563 }, +{ PROC_LINKS(to_uppercase, 0), false, "to_uppercase", 12, "Converts all ascii text in the range between the cursor and the mark to uppercase.", 82, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 550 }, +{ PROC_LINKS(toggle_filebar, 0), false, "toggle_filebar", 14, "Toggles the visibility status of the current view's filebar.", 60, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 692 }, +{ PROC_LINKS(toggle_fps_meter, 0), false, "toggle_fps_meter", 16, "Toggles the visibility of the FPS performance meter", 51, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 701 }, { PROC_LINKS(toggle_fullscreen, 0), false, "toggle_fullscreen", 17, "Toggle fullscreen mode on or off. The change(s) do not take effect until the next frame.", 89, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 451 }, { PROC_LINKS(toggle_highlight_enclosing_scopes, 0), false, "toggle_highlight_enclosing_scopes", 33, "In code files scopes surrounding the cursor are highlighted with distinguishing colors.", 87, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 439 }, { PROC_LINKS(toggle_highlight_line_at_cursor, 0), false, "toggle_highlight_line_at_cursor", 31, "Toggles the line highlight at the cursor.", 41, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 433 }, -{ PROC_LINKS(toggle_line_numbers, 0), false, "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 817 }, -{ PROC_LINKS(toggle_line_wrap, 0), false, "toggle_line_wrap", 16, "Toggles the line wrap setting on this buffer.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 823 }, +{ PROC_LINKS(toggle_line_numbers, 0), false, "toggle_line_numbers", 19, "Toggles the left margin line numbers.", 37, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 806 }, +{ PROC_LINKS(toggle_line_wrap, 0), false, "toggle_line_wrap", 16, "Toggles the line wrap setting on this buffer.", 45, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 812 }, { PROC_LINKS(toggle_mouse, 0), false, "toggle_mouse", 12, "Toggles the mouse suppression mode, see suppress_mouse and allow_mouse.", 71, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 415 }, { PROC_LINKS(toggle_paren_matching_helper, 0), false, "toggle_paren_matching_helper", 28, "In code files matching parentheses pairs are colored with distinguishing colors.", 80, "W:\\4ed\\code\\custom\\4coder_default_framework.cpp", 47, 445 }, -{ PROC_LINKS(toggle_show_whitespace, 0), false, "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 808 }, -{ PROC_LINKS(toggle_virtual_whitespace, 0), false, "toggle_virtual_whitespace", 25, "Toggles virtual whitespace for all files.", 41, "W:\\4ed\\code\\custom\\4coder_code_index.cpp", 40, 1175 }, +{ PROC_LINKS(toggle_show_whitespace, 0), false, "toggle_show_whitespace", 22, "Toggles the current buffer's whitespace visibility status.", 58, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 797 }, +{ PROC_LINKS(toggle_virtual_whitespace, 0), false, "toggle_virtual_whitespace", 25, "Toggles virtual whitespace for all files.", 41, "W:\\4ed\\code\\custom\\4coder_code_index.cpp", 40, 1176 }, { PROC_LINKS(tutorial_maximize, 0), false, "tutorial_maximize", 17, "Expand the tutorial window", 26, "W:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 20 }, { PROC_LINKS(tutorial_minimize, 0), false, "tutorial_minimize", 17, "Shrink the tutorial window", 26, "W:\\4ed\\code\\custom\\4coder_tutorial.cpp", 38, 34 }, { PROC_LINKS(uncomment_line, 0), false, "uncomment_line", 14, "If present, delete '//' at the beginning of the line after leading whitespace.", 78, "W:\\4ed\\code\\custom\\4coder_combined_write_commands.cpp", 53, 137 }, -{ PROC_LINKS(undo, 0), false, "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1711 }, -{ PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1738 }, -{ PROC_LINKS(view_buffer_other_panel, 0), false, "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1599 }, +{ PROC_LINKS(undo, 0), false, "undo", 4, "Advances backwards through the undo history of the current buffer.", 66, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1717 }, +{ PROC_LINKS(undo_all_buffers, 0), false, "undo_all_buffers", 16, "Advances backward through the undo history in the buffer containing the most recent regular edit.", 97, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1744 }, +{ PROC_LINKS(view_buffer_other_panel, 0), false, "view_buffer_other_panel", 23, "Set the other non-active panel to view the buffer that the active panel views, and switch to that panel.", 104, "W:\\4ed\\code\\custom\\4coder_base_commands.cpp", 43, 1605 }, { PROC_LINKS(view_jump_list_with_lister, 0), false, "view_jump_list_with_lister", 26, "When executed on a buffer with jumps, creates a persistent lister for all the jumps", 83, "W:\\4ed\\code\\custom\\4coder_jump_lister.cpp", 41, 59 }, { PROC_LINKS(word_complete, 0), false, "word_complete", 13, "Iteratively tries completing the word to the left of the cursor with other words in open buffers that have the same prefix string.", 130, "W:\\4ed\\code\\custom\\4coder_search.cpp", 36, 395 }, { PROC_LINKS(word_complete_drop_down, 0), false, "word_complete_drop_down", 23, "Word complete with drop down menu.", 34, "W:\\4ed\\code\\custom\\4coder_search.cpp", 36, 642 }, @@ -543,198 +551,202 @@ static i32 fcoder_metacmd_ID_delete_current_scope = 40; static i32 fcoder_metacmd_ID_delete_file_query = 41; static i32 fcoder_metacmd_ID_delete_line = 42; static i32 fcoder_metacmd_ID_delete_range = 43; -static i32 fcoder_metacmd_ID_duplicate_line = 44; -static i32 fcoder_metacmd_ID_execute_any_cli = 45; -static i32 fcoder_metacmd_ID_execute_previous_cli = 46; -static i32 fcoder_metacmd_ID_exit_4coder = 47; -static i32 fcoder_metacmd_ID_goto_beginning_of_file = 48; -static i32 fcoder_metacmd_ID_goto_end_of_file = 49; -static i32 fcoder_metacmd_ID_goto_first_jump = 50; -static i32 fcoder_metacmd_ID_goto_first_jump_same_panel_sticky = 51; -static i32 fcoder_metacmd_ID_goto_jump_at_cursor = 52; -static i32 fcoder_metacmd_ID_goto_jump_at_cursor_same_panel = 53; -static i32 fcoder_metacmd_ID_goto_line = 54; -static i32 fcoder_metacmd_ID_goto_next_jump = 55; -static i32 fcoder_metacmd_ID_goto_next_jump_no_skips = 56; -static i32 fcoder_metacmd_ID_goto_prev_jump = 57; -static i32 fcoder_metacmd_ID_goto_prev_jump_no_skips = 58; -static i32 fcoder_metacmd_ID_hide_filebar = 59; -static i32 fcoder_metacmd_ID_hide_scrollbar = 60; -static i32 fcoder_metacmd_ID_hms_demo_tutorial = 61; -static i32 fcoder_metacmd_ID_if0_off = 62; -static i32 fcoder_metacmd_ID_if_read_only_goto_position = 63; -static i32 fcoder_metacmd_ID_if_read_only_goto_position_same_panel = 64; -static i32 fcoder_metacmd_ID_increase_face_size = 65; -static i32 fcoder_metacmd_ID_interactive_kill_buffer = 66; -static i32 fcoder_metacmd_ID_interactive_new = 67; -static i32 fcoder_metacmd_ID_interactive_open = 68; -static i32 fcoder_metacmd_ID_interactive_open_or_new = 69; -static i32 fcoder_metacmd_ID_interactive_switch_buffer = 70; -static i32 fcoder_metacmd_ID_jump_to_definition = 71; -static i32 fcoder_metacmd_ID_keyboard_macro_finish_recording = 72; -static i32 fcoder_metacmd_ID_keyboard_macro_replay = 73; -static i32 fcoder_metacmd_ID_keyboard_macro_start_recording = 74; -static i32 fcoder_metacmd_ID_kill_buffer = 75; -static i32 fcoder_metacmd_ID_kill_tutorial = 76; -static i32 fcoder_metacmd_ID_left_adjust_view = 77; -static i32 fcoder_metacmd_ID_list_all_functions_all_buffers = 78; -static i32 fcoder_metacmd_ID_list_all_functions_all_buffers_lister = 79; -static i32 fcoder_metacmd_ID_list_all_functions_current_buffer = 80; -static i32 fcoder_metacmd_ID_list_all_functions_current_buffer_lister = 81; -static i32 fcoder_metacmd_ID_list_all_locations = 82; -static i32 fcoder_metacmd_ID_list_all_locations_case_insensitive = 83; -static i32 fcoder_metacmd_ID_list_all_locations_of_identifier = 84; -static i32 fcoder_metacmd_ID_list_all_locations_of_identifier_case_insensitive = 85; -static i32 fcoder_metacmd_ID_list_all_locations_of_selection = 86; -static i32 fcoder_metacmd_ID_list_all_locations_of_selection_case_insensitive = 87; -static i32 fcoder_metacmd_ID_list_all_locations_of_type_definition = 88; -static i32 fcoder_metacmd_ID_list_all_locations_of_type_definition_of_identifier = 89; -static i32 fcoder_metacmd_ID_list_all_substring_locations = 90; -static i32 fcoder_metacmd_ID_list_all_substring_locations_case_insensitive = 91; -static i32 fcoder_metacmd_ID_load_project = 92; -static i32 fcoder_metacmd_ID_load_theme_current_buffer = 93; -static i32 fcoder_metacmd_ID_load_themes_default_folder = 94; -static i32 fcoder_metacmd_ID_load_themes_hot_directory = 95; -static i32 fcoder_metacmd_ID_make_directory_query = 96; -static i32 fcoder_metacmd_ID_miblo_decrement_basic = 97; -static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp = 98; -static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 99; -static i32 fcoder_metacmd_ID_miblo_increment_basic = 100; -static i32 fcoder_metacmd_ID_miblo_increment_time_stamp = 101; -static i32 fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 102; -static i32 fcoder_metacmd_ID_mouse_wheel_change_face_size = 103; -static i32 fcoder_metacmd_ID_mouse_wheel_scroll = 104; -static i32 fcoder_metacmd_ID_move_down = 105; -static i32 fcoder_metacmd_ID_move_down_10 = 106; -static i32 fcoder_metacmd_ID_move_down_textual = 107; -static i32 fcoder_metacmd_ID_move_down_to_blank_line = 108; -static i32 fcoder_metacmd_ID_move_down_to_blank_line_end = 109; -static i32 fcoder_metacmd_ID_move_down_to_blank_line_skip_whitespace = 110; -static i32 fcoder_metacmd_ID_move_left = 111; -static i32 fcoder_metacmd_ID_move_left_alpha_numeric_boundary = 112; -static i32 fcoder_metacmd_ID_move_left_alpha_numeric_or_camel_boundary = 113; -static i32 fcoder_metacmd_ID_move_left_token_boundary = 114; -static i32 fcoder_metacmd_ID_move_left_whitespace_boundary = 115; -static i32 fcoder_metacmd_ID_move_left_whitespace_or_token_boundary = 116; -static i32 fcoder_metacmd_ID_move_line_down = 117; -static i32 fcoder_metacmd_ID_move_line_up = 118; -static i32 fcoder_metacmd_ID_move_right = 119; -static i32 fcoder_metacmd_ID_move_right_alpha_numeric_boundary = 120; -static i32 fcoder_metacmd_ID_move_right_alpha_numeric_or_camel_boundary = 121; -static i32 fcoder_metacmd_ID_move_right_token_boundary = 122; -static i32 fcoder_metacmd_ID_move_right_whitespace_boundary = 123; -static i32 fcoder_metacmd_ID_move_right_whitespace_or_token_boundary = 124; -static i32 fcoder_metacmd_ID_move_up = 125; -static i32 fcoder_metacmd_ID_move_up_10 = 126; -static i32 fcoder_metacmd_ID_move_up_to_blank_line = 127; -static i32 fcoder_metacmd_ID_move_up_to_blank_line_end = 128; -static i32 fcoder_metacmd_ID_move_up_to_blank_line_skip_whitespace = 129; -static i32 fcoder_metacmd_ID_multi_paste_interactive = 130; -static i32 fcoder_metacmd_ID_multi_paste_interactive_quick = 131; -static i32 fcoder_metacmd_ID_open_all_code = 132; -static i32 fcoder_metacmd_ID_open_all_code_recursive = 133; -static i32 fcoder_metacmd_ID_open_file_in_quotes = 134; -static i32 fcoder_metacmd_ID_open_in_other = 135; -static i32 fcoder_metacmd_ID_open_long_braces = 136; -static i32 fcoder_metacmd_ID_open_long_braces_break = 137; -static i32 fcoder_metacmd_ID_open_long_braces_semicolon = 138; -static i32 fcoder_metacmd_ID_open_matching_file_cpp = 139; -static i32 fcoder_metacmd_ID_open_panel_hsplit = 140; -static i32 fcoder_metacmd_ID_open_panel_vsplit = 141; -static i32 fcoder_metacmd_ID_page_down = 142; -static i32 fcoder_metacmd_ID_page_up = 143; -static i32 fcoder_metacmd_ID_paste = 144; -static i32 fcoder_metacmd_ID_paste_and_indent = 145; -static i32 fcoder_metacmd_ID_paste_next = 146; -static i32 fcoder_metacmd_ID_paste_next_and_indent = 147; -static i32 fcoder_metacmd_ID_place_in_scope = 148; -static i32 fcoder_metacmd_ID_profile_clear = 149; -static i32 fcoder_metacmd_ID_profile_disable = 150; -static i32 fcoder_metacmd_ID_profile_enable = 151; -static i32 fcoder_metacmd_ID_profile_inspect = 152; -static i32 fcoder_metacmd_ID_project_command_lister = 153; -static i32 fcoder_metacmd_ID_project_fkey_command = 154; -static i32 fcoder_metacmd_ID_project_go_to_root_directory = 155; -static i32 fcoder_metacmd_ID_query_replace = 156; -static i32 fcoder_metacmd_ID_query_replace_identifier = 157; -static i32 fcoder_metacmd_ID_query_replace_selection = 158; -static i32 fcoder_metacmd_ID_redo = 159; -static i32 fcoder_metacmd_ID_redo_all_buffers = 160; -static i32 fcoder_metacmd_ID_rename_file_query = 161; -static i32 fcoder_metacmd_ID_reopen = 162; -static i32 fcoder_metacmd_ID_replace_in_all_buffers = 163; -static i32 fcoder_metacmd_ID_replace_in_buffer = 164; -static i32 fcoder_metacmd_ID_replace_in_range = 165; -static i32 fcoder_metacmd_ID_reverse_search = 166; -static i32 fcoder_metacmd_ID_reverse_search_identifier = 167; -static i32 fcoder_metacmd_ID_save = 168; -static i32 fcoder_metacmd_ID_save_all_dirty_buffers = 169; -static i32 fcoder_metacmd_ID_save_to_query = 170; -static i32 fcoder_metacmd_ID_search = 171; -static i32 fcoder_metacmd_ID_search_identifier = 172; -static i32 fcoder_metacmd_ID_seek_beginning_of_line = 173; -static i32 fcoder_metacmd_ID_seek_beginning_of_textual_line = 174; -static i32 fcoder_metacmd_ID_seek_end_of_line = 175; -static i32 fcoder_metacmd_ID_seek_end_of_textual_line = 176; -static i32 fcoder_metacmd_ID_select_all = 177; -static i32 fcoder_metacmd_ID_select_next_scope_absolute = 178; -static i32 fcoder_metacmd_ID_select_next_scope_after_current = 179; -static i32 fcoder_metacmd_ID_select_prev_scope_absolute = 180; -static i32 fcoder_metacmd_ID_select_prev_top_most_scope = 181; -static i32 fcoder_metacmd_ID_select_surrounding_scope = 182; -static i32 fcoder_metacmd_ID_select_surrounding_scope_maximal = 183; -static i32 fcoder_metacmd_ID_set_eol_mode_from_contents = 184; -static i32 fcoder_metacmd_ID_set_eol_mode_to_binary = 185; -static i32 fcoder_metacmd_ID_set_eol_mode_to_crlf = 186; -static i32 fcoder_metacmd_ID_set_eol_mode_to_lf = 187; -static i32 fcoder_metacmd_ID_set_face_size = 188; -static i32 fcoder_metacmd_ID_set_face_size_this_buffer = 189; -static i32 fcoder_metacmd_ID_set_mark = 190; -static i32 fcoder_metacmd_ID_set_mode_to_notepad_like = 191; -static i32 fcoder_metacmd_ID_set_mode_to_original = 192; -static i32 fcoder_metacmd_ID_setup_build_bat = 193; -static i32 fcoder_metacmd_ID_setup_build_bat_and_sh = 194; -static i32 fcoder_metacmd_ID_setup_build_sh = 195; -static i32 fcoder_metacmd_ID_setup_new_project = 196; -static i32 fcoder_metacmd_ID_show_filebar = 197; -static i32 fcoder_metacmd_ID_show_scrollbar = 198; -static i32 fcoder_metacmd_ID_show_the_log_graph = 199; -static i32 fcoder_metacmd_ID_snipe_backward_whitespace_or_token_boundary = 200; -static i32 fcoder_metacmd_ID_snipe_forward_whitespace_or_token_boundary = 201; -static i32 fcoder_metacmd_ID_snippet_lister = 202; -static i32 fcoder_metacmd_ID_suppress_mouse = 203; -static i32 fcoder_metacmd_ID_swap_panels = 204; -static i32 fcoder_metacmd_ID_test_double_backspace = 205; -static i32 fcoder_metacmd_ID_theme_lister = 206; -static i32 fcoder_metacmd_ID_to_lowercase = 207; -static i32 fcoder_metacmd_ID_to_uppercase = 208; -static i32 fcoder_metacmd_ID_toggle_filebar = 209; -static i32 fcoder_metacmd_ID_toggle_fps_meter = 210; -static i32 fcoder_metacmd_ID_toggle_fullscreen = 211; -static i32 fcoder_metacmd_ID_toggle_highlight_enclosing_scopes = 212; -static i32 fcoder_metacmd_ID_toggle_highlight_line_at_cursor = 213; -static i32 fcoder_metacmd_ID_toggle_line_numbers = 214; -static i32 fcoder_metacmd_ID_toggle_line_wrap = 215; -static i32 fcoder_metacmd_ID_toggle_mouse = 216; -static i32 fcoder_metacmd_ID_toggle_paren_matching_helper = 217; -static i32 fcoder_metacmd_ID_toggle_show_whitespace = 218; -static i32 fcoder_metacmd_ID_toggle_virtual_whitespace = 219; -static i32 fcoder_metacmd_ID_tutorial_maximize = 220; -static i32 fcoder_metacmd_ID_tutorial_minimize = 221; -static i32 fcoder_metacmd_ID_uncomment_line = 222; -static i32 fcoder_metacmd_ID_undo = 223; -static i32 fcoder_metacmd_ID_undo_all_buffers = 224; -static i32 fcoder_metacmd_ID_view_buffer_other_panel = 225; -static i32 fcoder_metacmd_ID_view_jump_list_with_lister = 226; -static i32 fcoder_metacmd_ID_word_complete = 227; -static i32 fcoder_metacmd_ID_word_complete_drop_down = 228; -static i32 fcoder_metacmd_ID_write_block = 229; -static i32 fcoder_metacmd_ID_write_hack = 230; -static i32 fcoder_metacmd_ID_write_note = 231; -static i32 fcoder_metacmd_ID_write_space = 232; -static i32 fcoder_metacmd_ID_write_text_and_auto_indent = 233; -static i32 fcoder_metacmd_ID_write_text_input = 234; -static i32 fcoder_metacmd_ID_write_todo = 235; -static i32 fcoder_metacmd_ID_write_underscore = 236; -static i32 fcoder_metacmd_ID_write_zero_struct = 237; +static i32 fcoder_metacmd_ID_display_key_codes = 44; +static i32 fcoder_metacmd_ID_display_text_input = 45; +static i32 fcoder_metacmd_ID_double_backspace = 46; +static i32 fcoder_metacmd_ID_duplicate_line = 47; +static i32 fcoder_metacmd_ID_execute_any_cli = 48; +static i32 fcoder_metacmd_ID_execute_previous_cli = 49; +static i32 fcoder_metacmd_ID_exit_4coder = 50; +static i32 fcoder_metacmd_ID_goto_beginning_of_file = 51; +static i32 fcoder_metacmd_ID_goto_end_of_file = 52; +static i32 fcoder_metacmd_ID_goto_first_jump = 53; +static i32 fcoder_metacmd_ID_goto_first_jump_same_panel_sticky = 54; +static i32 fcoder_metacmd_ID_goto_jump_at_cursor = 55; +static i32 fcoder_metacmd_ID_goto_jump_at_cursor_same_panel = 56; +static i32 fcoder_metacmd_ID_goto_line = 57; +static i32 fcoder_metacmd_ID_goto_next_jump = 58; +static i32 fcoder_metacmd_ID_goto_next_jump_no_skips = 59; +static i32 fcoder_metacmd_ID_goto_prev_jump = 60; +static i32 fcoder_metacmd_ID_goto_prev_jump_no_skips = 61; +static i32 fcoder_metacmd_ID_hide_filebar = 62; +static i32 fcoder_metacmd_ID_hide_scrollbar = 63; +static i32 fcoder_metacmd_ID_hms_demo_tutorial = 64; +static i32 fcoder_metacmd_ID_if0_off = 65; +static i32 fcoder_metacmd_ID_if_read_only_goto_position = 66; +static i32 fcoder_metacmd_ID_if_read_only_goto_position_same_panel = 67; +static i32 fcoder_metacmd_ID_increase_face_size = 68; +static i32 fcoder_metacmd_ID_interactive_kill_buffer = 69; +static i32 fcoder_metacmd_ID_interactive_new = 70; +static i32 fcoder_metacmd_ID_interactive_open = 71; +static i32 fcoder_metacmd_ID_interactive_open_or_new = 72; +static i32 fcoder_metacmd_ID_interactive_switch_buffer = 73; +static i32 fcoder_metacmd_ID_jump_to_definition = 74; +static i32 fcoder_metacmd_ID_keyboard_macro_finish_recording = 75; +static i32 fcoder_metacmd_ID_keyboard_macro_replay = 76; +static i32 fcoder_metacmd_ID_keyboard_macro_start_recording = 77; +static i32 fcoder_metacmd_ID_kill_buffer = 78; +static i32 fcoder_metacmd_ID_kill_tutorial = 79; +static i32 fcoder_metacmd_ID_left_adjust_view = 80; +static i32 fcoder_metacmd_ID_list_all_functions_all_buffers = 81; +static i32 fcoder_metacmd_ID_list_all_functions_all_buffers_lister = 82; +static i32 fcoder_metacmd_ID_list_all_functions_current_buffer = 83; +static i32 fcoder_metacmd_ID_list_all_functions_current_buffer_lister = 84; +static i32 fcoder_metacmd_ID_list_all_locations = 85; +static i32 fcoder_metacmd_ID_list_all_locations_case_insensitive = 86; +static i32 fcoder_metacmd_ID_list_all_locations_of_identifier = 87; +static i32 fcoder_metacmd_ID_list_all_locations_of_identifier_case_insensitive = 88; +static i32 fcoder_metacmd_ID_list_all_locations_of_selection = 89; +static i32 fcoder_metacmd_ID_list_all_locations_of_selection_case_insensitive = 90; +static i32 fcoder_metacmd_ID_list_all_locations_of_type_definition = 91; +static i32 fcoder_metacmd_ID_list_all_locations_of_type_definition_of_identifier = 92; +static i32 fcoder_metacmd_ID_list_all_substring_locations = 93; +static i32 fcoder_metacmd_ID_list_all_substring_locations_case_insensitive = 94; +static i32 fcoder_metacmd_ID_load_project = 95; +static i32 fcoder_metacmd_ID_load_theme_current_buffer = 96; +static i32 fcoder_metacmd_ID_load_themes_default_folder = 97; +static i32 fcoder_metacmd_ID_load_themes_hot_directory = 98; +static i32 fcoder_metacmd_ID_make_directory_query = 99; +static i32 fcoder_metacmd_ID_miblo_decrement_basic = 100; +static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp = 101; +static i32 fcoder_metacmd_ID_miblo_decrement_time_stamp_minute = 102; +static i32 fcoder_metacmd_ID_miblo_increment_basic = 103; +static i32 fcoder_metacmd_ID_miblo_increment_time_stamp = 104; +static i32 fcoder_metacmd_ID_miblo_increment_time_stamp_minute = 105; +static i32 fcoder_metacmd_ID_mouse_wheel_change_face_size = 106; +static i32 fcoder_metacmd_ID_mouse_wheel_scroll = 107; +static i32 fcoder_metacmd_ID_move_down = 108; +static i32 fcoder_metacmd_ID_move_down_10 = 109; +static i32 fcoder_metacmd_ID_move_down_textual = 110; +static i32 fcoder_metacmd_ID_move_down_to_blank_line = 111; +static i32 fcoder_metacmd_ID_move_down_to_blank_line_end = 112; +static i32 fcoder_metacmd_ID_move_down_to_blank_line_skip_whitespace = 113; +static i32 fcoder_metacmd_ID_move_left = 114; +static i32 fcoder_metacmd_ID_move_left_alpha_numeric_boundary = 115; +static i32 fcoder_metacmd_ID_move_left_alpha_numeric_or_camel_boundary = 116; +static i32 fcoder_metacmd_ID_move_left_token_boundary = 117; +static i32 fcoder_metacmd_ID_move_left_whitespace_boundary = 118; +static i32 fcoder_metacmd_ID_move_left_whitespace_or_token_boundary = 119; +static i32 fcoder_metacmd_ID_move_line_down = 120; +static i32 fcoder_metacmd_ID_move_line_up = 121; +static i32 fcoder_metacmd_ID_move_right = 122; +static i32 fcoder_metacmd_ID_move_right_alpha_numeric_boundary = 123; +static i32 fcoder_metacmd_ID_move_right_alpha_numeric_or_camel_boundary = 124; +static i32 fcoder_metacmd_ID_move_right_token_boundary = 125; +static i32 fcoder_metacmd_ID_move_right_whitespace_boundary = 126; +static i32 fcoder_metacmd_ID_move_right_whitespace_or_token_boundary = 127; +static i32 fcoder_metacmd_ID_move_up = 128; +static i32 fcoder_metacmd_ID_move_up_10 = 129; +static i32 fcoder_metacmd_ID_move_up_to_blank_line = 130; +static i32 fcoder_metacmd_ID_move_up_to_blank_line_end = 131; +static i32 fcoder_metacmd_ID_move_up_to_blank_line_skip_whitespace = 132; +static i32 fcoder_metacmd_ID_multi_paste_interactive = 133; +static i32 fcoder_metacmd_ID_multi_paste_interactive_quick = 134; +static i32 fcoder_metacmd_ID_open_all_code = 135; +static i32 fcoder_metacmd_ID_open_all_code_recursive = 136; +static i32 fcoder_metacmd_ID_open_file_in_quotes = 137; +static i32 fcoder_metacmd_ID_open_in_other = 138; +static i32 fcoder_metacmd_ID_open_long_braces = 139; +static i32 fcoder_metacmd_ID_open_long_braces_break = 140; +static i32 fcoder_metacmd_ID_open_long_braces_semicolon = 141; +static i32 fcoder_metacmd_ID_open_matching_file_cpp = 142; +static i32 fcoder_metacmd_ID_open_panel_hsplit = 143; +static i32 fcoder_metacmd_ID_open_panel_vsplit = 144; +static i32 fcoder_metacmd_ID_page_down = 145; +static i32 fcoder_metacmd_ID_page_up = 146; +static i32 fcoder_metacmd_ID_paste = 147; +static i32 fcoder_metacmd_ID_paste_and_indent = 148; +static i32 fcoder_metacmd_ID_paste_next = 149; +static i32 fcoder_metacmd_ID_paste_next_and_indent = 150; +static i32 fcoder_metacmd_ID_place_in_scope = 151; +static i32 fcoder_metacmd_ID_play_with_a_counter = 152; +static i32 fcoder_metacmd_ID_profile_clear = 153; +static i32 fcoder_metacmd_ID_profile_disable = 154; +static i32 fcoder_metacmd_ID_profile_enable = 155; +static i32 fcoder_metacmd_ID_profile_inspect = 156; +static i32 fcoder_metacmd_ID_project_command_lister = 157; +static i32 fcoder_metacmd_ID_project_fkey_command = 158; +static i32 fcoder_metacmd_ID_project_go_to_root_directory = 159; +static i32 fcoder_metacmd_ID_query_replace = 160; +static i32 fcoder_metacmd_ID_query_replace_identifier = 161; +static i32 fcoder_metacmd_ID_query_replace_selection = 162; +static i32 fcoder_metacmd_ID_redo = 163; +static i32 fcoder_metacmd_ID_redo_all_buffers = 164; +static i32 fcoder_metacmd_ID_rename_file_query = 165; +static i32 fcoder_metacmd_ID_reopen = 166; +static i32 fcoder_metacmd_ID_replace_in_all_buffers = 167; +static i32 fcoder_metacmd_ID_replace_in_buffer = 168; +static i32 fcoder_metacmd_ID_replace_in_range = 169; +static i32 fcoder_metacmd_ID_reverse_search = 170; +static i32 fcoder_metacmd_ID_reverse_search_identifier = 171; +static i32 fcoder_metacmd_ID_save = 172; +static i32 fcoder_metacmd_ID_save_all_dirty_buffers = 173; +static i32 fcoder_metacmd_ID_save_to_query = 174; +static i32 fcoder_metacmd_ID_search = 175; +static i32 fcoder_metacmd_ID_search_identifier = 176; +static i32 fcoder_metacmd_ID_seek_beginning_of_line = 177; +static i32 fcoder_metacmd_ID_seek_beginning_of_textual_line = 178; +static i32 fcoder_metacmd_ID_seek_end_of_line = 179; +static i32 fcoder_metacmd_ID_seek_end_of_textual_line = 180; +static i32 fcoder_metacmd_ID_select_all = 181; +static i32 fcoder_metacmd_ID_select_next_scope_absolute = 182; +static i32 fcoder_metacmd_ID_select_next_scope_after_current = 183; +static i32 fcoder_metacmd_ID_select_prev_scope_absolute = 184; +static i32 fcoder_metacmd_ID_select_prev_top_most_scope = 185; +static i32 fcoder_metacmd_ID_select_surrounding_scope = 186; +static i32 fcoder_metacmd_ID_select_surrounding_scope_maximal = 187; +static i32 fcoder_metacmd_ID_set_eol_mode_from_contents = 188; +static i32 fcoder_metacmd_ID_set_eol_mode_to_binary = 189; +static i32 fcoder_metacmd_ID_set_eol_mode_to_crlf = 190; +static i32 fcoder_metacmd_ID_set_eol_mode_to_lf = 191; +static i32 fcoder_metacmd_ID_set_face_size = 192; +static i32 fcoder_metacmd_ID_set_face_size_this_buffer = 193; +static i32 fcoder_metacmd_ID_set_mark = 194; +static i32 fcoder_metacmd_ID_set_mode_to_notepad_like = 195; +static i32 fcoder_metacmd_ID_set_mode_to_original = 196; +static i32 fcoder_metacmd_ID_setup_build_bat = 197; +static i32 fcoder_metacmd_ID_setup_build_bat_and_sh = 198; +static i32 fcoder_metacmd_ID_setup_build_sh = 199; +static i32 fcoder_metacmd_ID_setup_new_project = 200; +static i32 fcoder_metacmd_ID_show_filebar = 201; +static i32 fcoder_metacmd_ID_show_scrollbar = 202; +static i32 fcoder_metacmd_ID_show_the_log_graph = 203; +static i32 fcoder_metacmd_ID_snipe_backward_whitespace_or_token_boundary = 204; +static i32 fcoder_metacmd_ID_snipe_forward_whitespace_or_token_boundary = 205; +static i32 fcoder_metacmd_ID_snippet_lister = 206; +static i32 fcoder_metacmd_ID_string_repeat = 207; +static i32 fcoder_metacmd_ID_suppress_mouse = 208; +static i32 fcoder_metacmd_ID_swap_panels = 209; +static i32 fcoder_metacmd_ID_theme_lister = 210; +static i32 fcoder_metacmd_ID_to_lowercase = 211; +static i32 fcoder_metacmd_ID_to_uppercase = 212; +static i32 fcoder_metacmd_ID_toggle_filebar = 213; +static i32 fcoder_metacmd_ID_toggle_fps_meter = 214; +static i32 fcoder_metacmd_ID_toggle_fullscreen = 215; +static i32 fcoder_metacmd_ID_toggle_highlight_enclosing_scopes = 216; +static i32 fcoder_metacmd_ID_toggle_highlight_line_at_cursor = 217; +static i32 fcoder_metacmd_ID_toggle_line_numbers = 218; +static i32 fcoder_metacmd_ID_toggle_line_wrap = 219; +static i32 fcoder_metacmd_ID_toggle_mouse = 220; +static i32 fcoder_metacmd_ID_toggle_paren_matching_helper = 221; +static i32 fcoder_metacmd_ID_toggle_show_whitespace = 222; +static i32 fcoder_metacmd_ID_toggle_virtual_whitespace = 223; +static i32 fcoder_metacmd_ID_tutorial_maximize = 224; +static i32 fcoder_metacmd_ID_tutorial_minimize = 225; +static i32 fcoder_metacmd_ID_uncomment_line = 226; +static i32 fcoder_metacmd_ID_undo = 227; +static i32 fcoder_metacmd_ID_undo_all_buffers = 228; +static i32 fcoder_metacmd_ID_view_buffer_other_panel = 229; +static i32 fcoder_metacmd_ID_view_jump_list_with_lister = 230; +static i32 fcoder_metacmd_ID_word_complete = 231; +static i32 fcoder_metacmd_ID_word_complete_drop_down = 232; +static i32 fcoder_metacmd_ID_write_block = 233; +static i32 fcoder_metacmd_ID_write_hack = 234; +static i32 fcoder_metacmd_ID_write_note = 235; +static i32 fcoder_metacmd_ID_write_space = 236; +static i32 fcoder_metacmd_ID_write_text_and_auto_indent = 237; +static i32 fcoder_metacmd_ID_write_text_input = 238; +static i32 fcoder_metacmd_ID_write_todo = 239; +static i32 fcoder_metacmd_ID_write_underscore = 240; +static i32 fcoder_metacmd_ID_write_zero_struct = 241; #endif diff --git a/custom/generated/managed_id_metadata.cpp b/custom/generated/managed_id_metadata.cpp index c0df4ce7..aa675593 100644 --- a/custom/generated/managed_id_metadata.cpp +++ b/custom/generated/managed_id_metadata.cpp @@ -48,6 +48,7 @@ view_highlight_range = managed_id_declare(app, string_u8_litexpr("attachment"), view_highlight_buffer = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("view_highlight_buffer")); view_render_hook = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("view_render_hook")); view_word_complete_menu = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("view_word_complete_menu")); +view_lister_loc = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("view_lister_loc")); buffer_map_id = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("buffer_map_id")); buffer_eol_setting = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("buffer_eol_setting")); buffer_lex_task = managed_id_declare(app, string_u8_litexpr("attachment"), string_u8_litexpr("buffer_lex_task")); diff --git a/opengl/4ed_opengl_defines.h b/opengl/4ed_opengl_defines.h index 2fec0704..03de2224 100644 --- a/opengl/4ed_opengl_defines.h +++ b/opengl/4ed_opengl_defines.h @@ -210,22 +210,20 @@ typedef char GLchar; typedef short GLshort; typedef signed char GLbyte; typedef unsigned short GLushort; + +#if !OS_LINUX typedef ptrdiff_t GLsizeiptr; typedef ptrdiff_t GLintptr; +#endif typedef void GL_Debug_Function(GLenum src, GLenum type, GLuint id, GLenum severity, GLsizei length, -#ifdef OS_LINUX const GLchar* message, - const void *user_data -#else - GLchar *message, - void *user_data -#endif - ); + const void *user_data); + typedef GL_Debug_Function *GLDEBUGPROC; #endif diff --git a/opengl/4ed_opengl_funcs.h b/opengl/4ed_opengl_funcs.h index 12d2e74e..4c2e65d8 100644 --- a/opengl/4ed_opengl_funcs.h +++ b/opengl/4ed_opengl_funcs.h @@ -13,19 +13,21 @@ #include "4ed_opengl_funcs.h" */ +#if OS_WINDOWS || OS_LINUX GL_FUNC(glDebugMessageControl, void, (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)) GL_FUNC(glDebugMessageCallback, void, (GLDEBUGPROC callback, const void *userParam)) -#ifndef OS_LINUX +GL_FUNC(glGenVertexArrays, void, (GLsizei n, GLuint *arrays)) +GL_FUNC(glBindVertexArray, void, (GLuint array)) + +GL_FUNC(glDeleteVertexArrays, void, (GLsizei n, const GLuint *arrays)) + +#if !OS_LINUX GL_FUNC(glTexImage3D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels)) GL_FUNC(glTexSubImage3D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels)) GL_FUNC(glActiveTexture, void, (GLenum texture)) #endif -GL_FUNC(glGenVertexArrays, void, (GLsizei n, GLuint *arrays)) -GL_FUNC(glBindVertexArray, void, (GLuint array)) -GL_FUNC(glDeleteVertexArrays, void, (GLsizei n, const GLuint *arrays)) - GL_FUNC(glGenBuffers, void, (GLsizei n, GLuint *buffers)) GL_FUNC(glBindBuffer, void, (GLenum target, GLuint buffer)) GL_FUNC(glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage)) @@ -54,6 +56,7 @@ GL_FUNC(glDisableVertexAttribArray, void, (GLuint index)) GL_FUNC(glEnableVertexAttribArray, void, (GLuint index)) GL_FUNC(glVertexAttribPointer, void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer)) + GL_FUNC(glVertexAttribIPointer, void, (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)) GL_FUNC(glUniform1f, void, (GLint location, GLfloat v0)) @@ -87,6 +90,18 @@ GL_FUNC(glBlitFramebuffer, void, (GLint srcX0, GLint srcY0, GLint srcX1, GLint s GL_FUNC(glTexImage2DMultisample, void, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations)) +#elif OS_MAC + +GL_FUNC(glDebugMessageControl, void, (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)) +GL_FUNC(glDebugMessageCallback, void, (GLDEBUGPROC callback, const void *userParam)) + +GL_FUNC(glGenVertexArrays, void, (GLsizei n, GLuint *arrays)) +GL_FUNC(glBindVertexArray, void, (GLuint array)) + +GL_FUNC(glVertexAttribIPointer, void, (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)) + +#endif + #undef GL_FUNC // BOTTOM diff --git a/opengl/4ed_opengl_render.cpp b/opengl/4ed_opengl_render.cpp index fd05dfcb..0713539d 100644 --- a/opengl/4ed_opengl_render.cpp +++ b/opengl/4ed_opengl_render.cpp @@ -54,11 +54,7 @@ gl__fill_texture(Texture_Kind texture_kind, u32 texture, Vec3_i32 p, Vec3_i32 di } internal void -#ifdef OS_LINUX gl__error_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char *message, const void *userParam){ -#else -gl__error_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, char *message, void *userParam){ -#endif switch (id){ case 131218: { @@ -72,70 +68,70 @@ gl__error_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsiz } } -char *gl__header = R"foo(#version 150 -)foo"; +char *gl__header = R"foo(#version 130 + )foo"; char *gl__vertex = R"foo( -uniform vec2 view_t; -uniform mat2x2 view_m; -in vec2 vertex_p; -in vec3 vertex_t; -in uint vertex_c; -in float vertex_ht; -smooth out vec4 fragment_color; -smooth out vec3 uvw; -smooth out vec2 xy; -smooth out vec2 adjusted_half_dim; -smooth out float half_thickness; -void main(void) -{ -gl_Position = vec4(view_m*(vertex_p - view_t), 0.0, 1.0); - fragment_color.b = (float((vertex_c )&0xFFu))/255.0; -fragment_color.g = (float((vertex_c>> 8u)&0xFFu))/255.0; -fragment_color.r = (float((vertex_c>>16u)&0xFFu))/255.0; -fragment_color.a = (float((vertex_c>>24u)&0xFFu))/255.0; -uvw = vertex_t; -vec2 center = vertex_t.xy; -vec2 half_dim = abs(vertex_p - center); -adjusted_half_dim = half_dim - vertex_t.zz + vec2(0.5, 0.5); -half_thickness = vertex_ht; -xy = vertex_p; -} -)foo"; + uniform vec2 view_t; + uniform mat2x2 view_m; + in vec2 vertex_p; + in vec3 vertex_t; + in uint vertex_c; + in float vertex_ht; + smooth out vec4 fragment_color; + smooth out vec3 uvw; + smooth out vec2 xy; + smooth out vec2 adjusted_half_dim; + smooth out float half_thickness; + void main(void) + { + gl_Position = vec4(view_m*(vertex_p - view_t), 0.0, 1.0); + fragment_color.b = (float((vertex_c )&0xFFu))/255.0; + fragment_color.g = (float((vertex_c>> 8u)&0xFFu))/255.0; + fragment_color.r = (float((vertex_c>>16u)&0xFFu))/255.0; + fragment_color.a = (float((vertex_c>>24u)&0xFFu))/255.0; + uvw = vertex_t; + vec2 center = vertex_t.xy; + vec2 half_dim = abs(vertex_p - center); + adjusted_half_dim = half_dim - vertex_t.zz + vec2(0.5, 0.5); + half_thickness = vertex_ht; + xy = vertex_p; + } + )foo"; char *gl__fragment = R"foo( -smooth in vec4 fragment_color; -smooth in vec3 uvw; -smooth in vec2 xy; -smooth in vec2 adjusted_half_dim; -smooth in float half_thickness; -uniform sampler2DArray sampler; -out vec4 out_color; - -float rectangle_sd(vec2 p, vec2 b){ -vec2 d = abs(p) - b; -return(length(max(d, vec2(0.0, 0.0))) + min(max(d.x, d.y), 0.0)); -} - -void main(void) -{ -float has_thickness = (step(0.49, half_thickness)); -float does_not_have_thickness = 1.0 - has_thickness; - -float sample_value = texture(sampler, uvw).r; -sample_value *= does_not_have_thickness; - -vec2 center = uvw.xy; -float roundness = uvw.z; -float sd = rectangle_sd(xy - center, adjusted_half_dim); -sd = sd - roundness; -sd = abs(sd + half_thickness) - half_thickness; -float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd); -shape_value *= has_thickness; - -out_color = vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value)); -} -)foo"; + smooth in vec4 fragment_color; + smooth in vec3 uvw; + smooth in vec2 xy; + smooth in vec2 adjusted_half_dim; + smooth in float half_thickness; + uniform sampler2DArray sampler; + out vec4 out_color; + + float rectangle_sd(vec2 p, vec2 b){ + vec2 d = abs(p) - b; + return(length(max(d, vec2(0.0, 0.0))) + min(max(d.x, d.y), 0.0)); + } + + void main(void) + { + float has_thickness = (step(0.49, half_thickness)); + float does_not_have_thickness = 1.0 - has_thickness; + + float sample_value = texture(sampler, uvw).r; + sample_value *= does_not_have_thickness; + + vec2 center = uvw.xy; + float roundness = uvw.z; + float sd = rectangle_sd(xy - center, adjusted_half_dim); + sd = sd - roundness; + sd = abs(sd + half_thickness) - half_thickness; + float shape_value = 1.0 - smoothstep(-1.0, 0.0, sd); + shape_value *= has_thickness; + + out_color = vec4(fragment_color.xyz, fragment_color.a*(sample_value + shape_value)); + } + )foo"; #define AttributeList(X) \ X(vertex_p) \ @@ -154,7 +150,7 @@ struct GL_Program{ AttributeList(GetAttributeLocation) #undef GetAttributeLocation #define GetUniformLocation(N) i32 N; - UniformList(GetUniformLocation) + UniformList(GetUniformLocation) #undef GetUniformLocation }; @@ -205,9 +201,9 @@ gl__make_program(char *header, char *vertex, char *fragment){ AttributeList(GetAttributeLocation) #undef GetAttributeLocation #define GetUniformLocation(N) result.N = glGetUniformLocation(program, #N); - UniformList(GetUniformLocation) + UniformList(GetUniformLocation) #undef GetUniformLocation - return(result); + return(result); } #define GLOffsetStruct(p,m) ((void*)(OffsetOfMemberStruct(p,m))) @@ -294,9 +290,9 @@ gl_render(Render_Target *t){ group = group->next){ Rect_i32 box = Ri32(group->clip_box); - Rect_i32 scissor_box = { - box.x0, height - box.y1, box.x1 - box.x0, box.y1 - box.y0, - }; + Rect_i32 scissor_box = { + box.x0, height - box.y1, box.x1 - box.x0, box.y1 - box.y0, + }; scissor_box.x0 = clamp_bot(0, scissor_box.x0); scissor_box.y0 = clamp_bot(0, scissor_box.y0); scissor_box.x1 = clamp_bot(0, scissor_box.x1); diff --git a/platform_linux/linux_4ed.cpp b/platform_linux/linux_4ed.cpp index 66444b7f..13e8f4bc 100644 --- a/platform_linux/linux_4ed.cpp +++ b/platform_linux/linux_4ed.cpp @@ -11,8 +11,8 @@ // TOP #define FPS 60 -#define frame_useconds (1000000 / FPS) -#define frame_nseconds (UINT64_C(1000000000) / FPS) +#define frame_useconds (Million(1) / FPS) +#define frame_nseconds (Billion(1) / FPS) #define SLASH '/' #define DLL "so" @@ -101,18 +101,18 @@ #include #ifdef INSO_DEBUG - #define LINUX_FN_DEBUG(fmt, ...) do { \ - fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__);\ - } while (0) +#define LINUX_FN_DEBUG(fmt, ...) do { \ +fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__);\ +} while (0) // I want to see a message - #undef AssertBreak - #define AssertBreak(m) ({\ - fprintf(stderr, "\n** ASSERTION FAILURE: %s:%d: %s\n\n", __FILE__, __LINE__, #m);\ - *((volatile u64*)0) = 0xba771e70ad5;\ - }) +#undef AssertBreak +#define AssertBreak(m) ({\ +fprintf(stderr, "\n** ASSERTION FAILURE: %s:%d: %s\n\n", __FILE__, __LINE__, #m);\ +*((volatile u64*)0) = 0xba771e70ad5;\ +}) #else - #define LINUX_FN_DEBUG(...) +#define LINUX_FN_DEBUG(...) #endif //////////////////////////// @@ -150,46 +150,45 @@ struct Linux_Memory_Tracker_Node { struct Linux_Vars { Thread_Context tctx; Arena *frame_arena; - + Display* dpy; Window win; - + b32 has_xfixes; int xfixes_selection_event; XIM xim; XIC xic; FcConfig* fontconfig; XkbDescPtr xkb; - + Linux_Input_Chunk input; int xkb_event; int xkb_group; // active keyboard layout (0-3) - + int epoll; int step_timer_fd; u64 last_step_time; - b32 step_pending; - + XCursor xcursors[APP_MOUSE_CURSOR_COUNT]; Application_Mouse_Cursor cursor; XCursor hidden_cursor; i32 cursor_show; i32 prev_cursor_show; - + Node free_linux_objects; Node timer_objects; - + System_Mutex global_frame_mutex; pthread_mutex_t memory_tracker_mutex; Linux_Memory_Tracker_Node* memory_tracker_head; Linux_Memory_Tracker_Node* memory_tracker_tail; int memory_tracker_count; - + Arena* clipboard_arena; String_Const_u8 clipboard_contents; b32 received_new_clipboard; b32 clipboard_catch_all; - + Atom atom_TARGETS; Atom atom_CLIPBOARD; Atom atom_UTF8_STRING; @@ -267,19 +266,19 @@ handle_to_object(Plat_Handle ph){ internal Linux_Object* linux_alloc_object(Linux_Object_Kind kind){ Linux_Object* result = NULL; - + if (linuxvars.free_linux_objects.next != &linuxvars.free_linux_objects) { result = CastFromMember(Linux_Object, node, linuxvars.free_linux_objects.next); } - + if (result == NULL) { i32 count = 512; - + Linux_Object* objects = (Linux_Object*)system_memory_allocate( - sizeof(Linux_Object) * count, - file_name_line_number_lit_u8 - ); - + sizeof(Linux_Object) * count, + file_name_line_number_lit_u8 + ); + objects[0].node.prev = &linuxvars.free_linux_objects; linuxvars.free_linux_objects.next = &objects[0].node; for (i32 i = 1; i < count; ++i) { @@ -288,10 +287,10 @@ linux_alloc_object(Linux_Object_Kind kind){ } objects[count - 1].node.next = &linuxvars.free_linux_objects; linuxvars.free_linux_objects.prev = &objects[count - 1].node; - + result = CastFromMember(Linux_Object, node, linuxvars.free_linux_objects.next); } - + Assert(result != 0); dll_remove(&result->node); block_zero_struct(result); @@ -313,12 +312,12 @@ internal int linux_compare_file_infos(File_Info** a, File_Info** b) { b32 a_hidden = (*a)->file_name.str[0] == '.'; b32 b_hidden = (*b)->file_name.str[0] == '.'; - + // hidden files lower in list if(a_hidden != b_hidden) { return a_hidden - b_hidden; } - + // push_stringf seems to null terminate return strcoll((char*)(*a)->file_name.str, (char*)(*b)->file_name.str); } @@ -336,8 +335,8 @@ linux_system_get_file_list_filter(const struct dirent *dirent) { } internal u64 -linux_ns_from_timespec(const struct timespec timespec) { - return timespec.tv_nsec + UINT64_C(1000000000) * timespec.tv_sec; +linux_us_from_timespec(const struct timespec timespec) { + return timespec.tv_nsec/Thousand(1) + Million(1) * timespec.tv_sec; } internal File_Attribute_Flag @@ -351,29 +350,28 @@ internal File_Attributes linux_file_attributes_from_struct_stat(struct stat* file_stat) { File_Attributes result = {}; result.size = file_stat->st_size; - result.last_write_time = linux_ns_from_timespec(file_stat->st_mtim); + result.last_write_time = linux_us_from_timespec(file_stat->st_mtim); result.flags = linux_convert_file_attribute_flags(file_stat->st_mode); - return result; + return(result); } internal void linux_schedule_step(){ - if(!__sync_bool_compare_and_swap(&linuxvars.step_pending, 0, 1)) { - return; - } - u64 now = system_now_time(); u64 diff = (now - linuxvars.last_step_time); - + struct itimerspec its = {}; - - if(diff >= frame_nseconds) { + timerfd_gettime(linuxvars.step_timer_fd, &its); + + if (diff > frame_useconds) { its.it_value.tv_nsec = 1; + timerfd_settime(linuxvars.step_timer_fd, 0, &its, NULL); } else { - its.it_value.tv_nsec = frame_nseconds - diff; + if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0){ + its.it_value.tv_nsec = (frame_useconds - diff) * 1000UL; + timerfd_settime(linuxvars.step_timer_fd, 0, &its, NULL); + } } - - timerfd_settime(linuxvars.step_timer_fd, 0, &its, NULL); } enum wm_state_mode { @@ -385,7 +383,7 @@ enum wm_state_mode { internal void linux_set_wm_state(Atom one, Atom two, enum wm_state_mode mode){ //NOTE(inso): this will only work after the window has been mapped - + XEvent e = {}; e.xany.type = ClientMessage; e.xclient.message_type = linuxvars.atom__NET_WM_STATE; @@ -395,7 +393,7 @@ linux_set_wm_state(Atom one, Atom two, enum wm_state_mode mode){ e.xclient.data.l[1] = one; e.xclient.data.l[2] = two; e.xclient.data.l[3] = 1L; - + XSendEvent(linuxvars.dpy, RootWindow(linuxvars.dpy, 0), 0, SubstructureNotifyMask | SubstructureRedirectMask, &e); @@ -419,71 +417,71 @@ linux_get_xsettings_dpi(Display* dpy, int screen){ u16 name_len; char name[0]; }; - + struct XSettings { u8 byte_order; u8 pad[3]; u32 serial; u32 num_settings; }; - + enum { XSettingsTypeInt, XSettingsTypeString, XSettingsTypeColor }; - + int dpi = -1; unsigned char* prop = NULL; char sel_buffer[64]; struct XSettings* xs; const char* p; - + snprintf(sel_buffer, sizeof(sel_buffer), "_XSETTINGS_S%d", screen); - + Atom XSET_SEL = XInternAtom(dpy, sel_buffer, True); Atom XSET_SET = XInternAtom(dpy, "_XSETTINGS_SETTINGS", True); - + if (XSET_SEL == None || XSET_SET == None){ //LOG("XSETTINGS unavailable.\n"); return(dpi); } - + Window xset_win = XGetSelectionOwner(dpy, XSET_SEL); if (xset_win == None){ // TODO(inso): listen for the ClientMessage about it becoming available? - // there's not much point atm if DPI scaling is only done at startup + // there's not much point atm if DPI scaling is only done at startup goto out; } - + { Atom type; int fmt; unsigned long pad, num; - + if (XGetWindowProperty(dpy, xset_win, XSET_SET, 0, 1024, False, XSET_SET, &type, &fmt, &num, &pad, &prop) != Success){ //LOG("XSETTINGS: GetWindowProperty failed.\n"); goto out; } - + if (fmt != 8){ //LOG("XSETTINGS: Wrong format.\n"); goto out; } } - + xs = (struct XSettings*)prop; p = (char*)(xs + 1); - + if (xs->byte_order != 0){ //LOG("FIXME: XSETTINGS not host byte order?\n"); goto out; } - + for (int i = 0; i < xs->num_settings; ++i){ struct XSettingHeader* h = (struct XSettingHeader*)p; - + p += sizeof(struct XSettingHeader); p += h->name_len; p += ((4 - (h->name_len & 3)) & 3); p += 4; // serial - + switch (h->type){ case XSettingsTypeInt: { if (strncmp(h->name, "Xft/DPI", h->name_len) == 0){ @@ -492,30 +490,30 @@ linux_get_xsettings_dpi(Display* dpy, int screen){ } p += 4; } break; - + case XSettingsTypeString: { u32 len = *(u32*)p; p += 4; p += len; p += ((4 - (len & 3)) & 3); } break; - + case XSettingsTypeColor: { p += 8; } break; - + default: { //LOG("XSETTINGS: Got invalid type...\n"); goto out; } break; } } - + out: - if (prop){ - XFree(prop); - } - + if (prop){ + XFree(prop); + } + return dpi; } @@ -536,6 +534,12 @@ linux_set_icon(Display* d, Window w){ #include "linux_error_box.cpp" +function void +os_popup_error(char *title, char *message){ + system_error_box(message); + exit(1); +} + //////////////////////////// #include "linux_4ed_functions.cpp" @@ -563,15 +567,15 @@ graphics_fill_texture_sig(){ internal Face_Description linux_find_font(Face_Description* desc) { Face_Description result = *desc; - + char* name = strndupa((char*)desc->font.file_name.str, desc->font.file_name.size); - + double size; const char* style; { Face_Load_Parameters* p = &desc->parameters; size = p->pt_size; - + if(p->bold && p->italic) { style = "Bold Italic"; } else if(p->bold) { @@ -582,59 +586,58 @@ linux_find_font(Face_Description* desc) { style = "Regular"; } } - - FcPattern *pattern = FcPatternBuild( - 0, - FC_POSTSCRIPT_NAME, FcTypeString, name, - FC_SIZE, FcTypeDouble, size, - FC_FONTFORMAT, FcTypeString, "TrueType", - FC_STYLE, FcTypeString, (FcChar8*)style, - NULL); - + + FcPattern *pattern = FcPatternBuild(0, + FC_POSTSCRIPT_NAME, FcTypeString, name, + FC_SIZE, FcTypeDouble, size, + FC_FONTFORMAT, FcTypeString, "TrueType", + FC_STYLE, FcTypeString, (FcChar8*)style, + NULL); + if(!pattern) { return result; } - + if (FcConfigSubstitute(linuxvars.fontconfig, pattern, FcMatchPattern)){ FcDefaultSubstitute(pattern); - + FcResult res; FcPattern *font = FcFontMatch(linuxvars.fontconfig, pattern, &res); if (!font){ return result; } - + FcChar8 *filename = 0; FcPatternGetString(font, FC_FILE, 0, &filename); if(filename) { LINUX_FN_DEBUG("FONTCONFIG FILENAME = %s\n", filename); result.font.file_name = push_u8_stringf(linuxvars.frame_arena, "%s", filename); } - + FcPatternDestroy(font); } - + FcPatternDestroy(pattern); - + return result; } internal font_make_face_sig() { - + Face* result = ft__font_make_face(arena, description, scale_factor); - + // if it failed to load the font directly, try via fontconfig. if(!result) { Face_Description desc2 = {}; desc2.parameters = description->parameters; desc2.font.file_name = string_front_of_path(description->font.file_name); - + printf("FONT %.*s\n", string_expand(desc2.font.file_name)); desc2 = linux_find_font(&desc2); result = ft__font_make_face(arena, &desc2, scale_factor); } - + if(!result) { // is this fatal? 4ed.cpp:277 (caller) does not check for null. String_Const_u8 s = description->font.file_name; @@ -642,7 +645,7 @@ font_make_face_sig() { snprintf(msg, sizeof(msg), "Unable to load font: %.*s", (int)s.size, s.str); system_error_box(msg); } - + return(result); } @@ -651,17 +654,17 @@ font_make_face_sig() { internal b32 glx_init(void) { int glx_maj, glx_min; - + if(!glXQueryVersion(linuxvars.dpy, &glx_maj, &glx_min)) { return false; } - + return glx_maj > 1 || (glx_maj == 1 && glx_min >= 3); } internal b32 glx_get_config(GLXFBConfig* fb_config, XVisualInfo* vi) { - + static const int attrs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, @@ -676,24 +679,24 @@ glx_get_config(GLXFBConfig* fb_config, XVisualInfo* vi) { GLX_DOUBLEBUFFER , True, None }; - + int conf_count = 0; GLXFBConfig* conf_list = glXChooseFBConfig(linuxvars.dpy, DefaultScreen(linuxvars.dpy), attrs, &conf_count); if(!conf_count || conf_count <= 0) { return false; } - + *fb_config = *conf_list; XFree(conf_list); - + XVisualInfo* xvi = glXGetVisualFromFBConfig(linuxvars.dpy, *fb_config); if(!xvi) { return false; } - + *vi = *xvi; XFree(xvi); - + return true; } @@ -714,19 +717,19 @@ typedef int (glXSwapIntervalSGI_Function) (int interval); internal b32 glx_create_context(GLXFBConfig fb_config){ const char *glx_exts = glXQueryExtensionsString(linuxvars.dpy, DefaultScreen(linuxvars.dpy)); - + glXCreateContextAttribsARB_Function *glXCreateContextAttribsARB = 0; glXSwapIntervalEXT_Function *glXSwapIntervalEXT = 0; glXSwapIntervalMESA_Function *glXSwapIntervalMESA = 0; glXGetSwapIntervalMESA_Function *glXGetSwapIntervalMESA = 0; glXSwapIntervalSGI_Function *glXSwapIntervalSGI = 0; - + #define GLXLOAD(f) f = (f##_Function*) glXGetProcAddressARB((const GLubyte*) #f); GLXLOAD(glXCreateContextAttribsARB); - + GLXContext ctx = NULL; int (*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(&glx_error_handler); - + if (glXCreateContextAttribsARB == NULL){ //LOG("glXCreateContextAttribsARB() not found, using old-style GLX context\n" ); ctx = glXCreateNewContext(linuxvars.dpy, fb_config, GLX_RGBA_TYPE, 0, True); @@ -735,37 +738,37 @@ glx_create_context(GLXFBConfig fb_config){ GLX_CONTEXT_MAJOR_VERSION_ARB, 2, GLX_CONTEXT_MINOR_VERSION_ARB, 1, GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, -#if defined(FRED_INTERNAL) +#if GL_DEBUG_MODE GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_DEBUG_BIT_ARB, #endif None }; - + //LOG("Creating GL 2.1 context... "); ctx = glXCreateContextAttribsARB(linuxvars.dpy, fb_config, 0, True, context_attribs); } - + XSync(linuxvars.dpy, False); if(glx_ctx_error || !ctx) { return false; } - + XSync(linuxvars.dpy, False); XSetErrorHandler(old_handler); - + //b32 direct = glXIsDirect(linuxvars.dpy, ctx); - + //LOG("Making context current\n"); glXMakeCurrent(linuxvars.dpy, linuxvars.win, ctx); - + //glx_enable_vsync(); - + // NOTE(allen): Load gl functions #define GL_FUNC(f,R,P) GLXLOAD(f) #include "opengl/4ed_opengl_funcs.h" - + #undef GLXLOAD - + return true; } @@ -773,17 +776,17 @@ glx_create_context(GLXFBConfig fb_config){ internal void linux_x11_init(int argc, char** argv, Plat_Settings* settings) { - + Display* dpy = XOpenDisplay(0); if (!dpy){ fprintf(stderr, "FATAL: Cannot open X11 Display!\n"); exit(1); } - + linuxvars.dpy = dpy; - + #define LOAD_ATOM(x) linuxvars.atom_##x = XInternAtom(linuxvars.dpy, #x, False); - + LOAD_ATOM(TARGETS); LOAD_ATOM(CLIPBOARD); LOAD_ATOM(UTF8_STRING); @@ -796,140 +799,140 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { LOAD_ATOM(_NET_WM_WINDOW_TYPE_NORMAL); LOAD_ATOM(_NET_WM_PID); LOAD_ATOM(WM_DELETE_WINDOW); - + #undef LOAD_ATOM - + if (!glx_init()){ system_error_box("Your XServer's GLX version is too old. GLX 1.3+ is required."); } - + GLXFBConfig fb_config; XVisualInfo vi; if (!glx_get_config(&fb_config, &vi)){ system_error_box("Could not get a matching GLX FBConfig. Check your OpenGL drivers are installed correctly."); } - + // TODO: window size #define WINDOW_W_DEFAULT 800 #define WINDOW_H_DEFAULT 600 int w = WINDOW_W_DEFAULT; int h = WINDOW_H_DEFAULT; - + // TEMP render_target.width = w; render_target.height = h; - + XSetWindowAttributes swa = {}; swa.backing_store = WhenMapped; swa.event_mask = StructureNotifyMask; swa.bit_gravity = NorthWestGravity; swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi.screen), vi.visual, AllocNone); - + u32 CWflags = CWBackingStore|CWBitGravity|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask; linuxvars.win = XCreateWindow(dpy, RootWindow(dpy, vi.screen), 0, 0, w, h, 0, vi.depth, InputOutput, vi.visual, CWflags, &swa); - + if (!linuxvars.win){ system_error_box("XCreateWindow failed. Make sure your display is set up correctly."); } - + //NOTE(inso): Set the window's type to normal XChangeProperty(linuxvars.dpy, linuxvars.win, linuxvars.atom__NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char*)&linuxvars.atom__NET_WM_WINDOW_TYPE_NORMAL, 1); - + //NOTE(inso): window managers want the PID as a window property for some reason. pid_t pid = getpid(); XChangeProperty(linuxvars.dpy, linuxvars.win, linuxvars.atom__NET_WM_PID, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&pid, 1); - + //NOTE(inso): set wm properties XStoreName(linuxvars.dpy, linuxvars.win, WINDOW_NAME); - + XSizeHints *sz_hints = XAllocSizeHints(); XWMHints *wm_hints = XAllocWMHints(); XClassHint *cl_hints = XAllocClassHint(); - + sz_hints->flags = PMinSize | PMaxSize | PWinGravity; - + sz_hints->min_width = 50; sz_hints->min_height = 50; - + sz_hints->max_width = sz_hints->max_height = (1UL << 16UL); sz_hints->win_gravity = NorthWestGravity; - + if (settings->set_window_pos){ sz_hints->flags |= USPosition; sz_hints->x = settings->window_x; sz_hints->y = settings->window_y; } - + wm_hints->flags |= InputHint | StateHint; wm_hints->input = True; wm_hints->initial_state = NormalState; - + cl_hints->res_name = "4coder"; cl_hints->res_class = "4coder"; - + char* win_name_list[] = { WINDOW_NAME }; XTextProperty win_name; XStringListToTextProperty(win_name_list, 1, &win_name); - + XSetWMProperties(linuxvars.dpy, linuxvars.win, &win_name, NULL, argv, argc, sz_hints, wm_hints, cl_hints); - + XFree(win_name.value); XFree(sz_hints); XFree(wm_hints); XFree(cl_hints); - + linux_set_icon(linuxvars.dpy, linuxvars.win); - + // NOTE(inso): make the window visible XMapWindow(linuxvars.dpy, linuxvars.win); - + if(!glx_create_context(fb_config)) { system_error_box("Unable to create GLX context."); } - + XRaiseWindow(linuxvars.dpy, linuxvars.win); - + if (settings->set_window_pos){ XMoveWindow(linuxvars.dpy, linuxvars.win, settings->window_x, settings->window_y); } - + if (settings->maximize_window){ linux_set_wm_state(linuxvars.atom__NET_WM_STATE_MAXIMIZED_HORZ, linuxvars.atom__NET_WM_STATE_MAXIMIZED_VERT, WM_STATE_ADD); } else if (settings->fullscreen_window){ linux_set_wm_state(linuxvars.atom__NET_WM_STATE_FULLSCREEN, 0, WM_STATE_ADD); } - + XSync(linuxvars.dpy, False); - + Atom wm_protos[] = { linuxvars.atom_WM_DELETE_WINDOW, linuxvars.atom__NET_WM_PING }; - + XSetWMProtocols(linuxvars.dpy, linuxvars.win, wm_protos, 2); - + // XFixes extension for clipboard notification. { int xfixes_version_unused, xfixes_err_unused; Bool has_xfixes = XQueryExtension(linuxvars.dpy, "XFIXES", &xfixes_version_unused, &linuxvars.xfixes_selection_event, &xfixes_err_unused); linuxvars.has_xfixes = (has_xfixes == True); - + // request notifications for CLIPBOARD updates. if(has_xfixes) { XFixesSelectSelectionInput(linuxvars.dpy, linuxvars.win, linuxvars.atom_CLIPBOARD, XFixesSetSelectionOwnerNotifyMask); } } - + // Input handling init - + setlocale(LC_ALL, ""); XSetLocaleModifiers(""); b32 locale_supported = XSupportsLocale(); - + if (!locale_supported){ setlocale(LC_ALL, "C"); } - + linuxvars.xim = XOpenIM(dpy, 0, 0, 0); if (!linuxvars.xim){ // NOTE(inso): Try falling back to the internal XIM implementation that @@ -937,16 +940,16 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { XSetLocaleModifiers("@im=none"); linuxvars.xim = XOpenIM(dpy, 0, 0, 0); } - + // If it still isn't there we're screwed. if (!linuxvars.xim){ system_error_box("Could not initialize X Input."); } - + XIMStyles *styles = NULL; const XIMStyle style_want = (XIMPreeditNothing | XIMStatusNothing); b32 found_style = false; - + if (!XGetIMValues(linuxvars.xim, XNQueryInputStyle, &styles, NULL) && styles){ for (i32 i = 0; i < styles->count_styles; ++i){ XIMStyle style = styles->supported_styles[i]; @@ -956,28 +959,28 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { } } } - + if(!found_style) { system_error_box("Could not find supported X Input style."); } - + XFree(styles); - + linuxvars.xic = XCreateIC(linuxvars.xim, XNInputStyle, style_want, XNClientWindow, linuxvars.win, XNFocusWindow, linuxvars.win, NULL); - + if(!linuxvars.xic) { system_error_box("Error creating X Input context."); } - + int xim_event_mask; if (XGetICValues(linuxvars.xic, XNFilterEvents, &xim_event_mask, NULL)){ xim_event_mask = 0; } - + u32 event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask @@ -987,24 +990,24 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { | StructureNotifyMask | ExposureMask | VisibilityChangeMask | xim_event_mask; - + XSelectInput(linuxvars.dpy, linuxvars.win, event_mask); - + // init XKB keyboard extension - + if(!XkbQueryExtension(linuxvars.dpy, 0, &linuxvars.xkb_event, 0, 0, 0)) { system_error_box("XKB Extension not available."); } - + XkbSelectEvents(linuxvars.dpy, XkbUseCoreKbd, XkbAllEventsMask, XkbAllEventsMask); linuxvars.xkb = XkbGetKeyboard(linuxvars.dpy, XkbAllComponentsMask, XkbUseCoreKbd); if(!linuxvars.xkb) { system_error_box("Error getting XKB keyboard details."); } - + // closer to windows behaviour (holding key doesn't generate release events) XkbSetDetectableAutoRepeat(linuxvars.dpy, True, NULL); - + XCursor cursors[APP_MOUSE_CURSOR_COUNT] = { None, None, @@ -1013,15 +1016,15 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) { XCreateFontCursor(linuxvars.dpy, XC_sb_v_double_arrow) }; block_copy(linuxvars.xcursors, cursors, sizeof(cursors)); - + // sneaky invisible cursor { char data = 0; XColor c = {}; Pixmap p = XCreateBitmapFromData(linuxvars.dpy, linuxvars.win, &data, 1, 1); - + linuxvars.hidden_cursor = XCreatePixmapCursor(linuxvars.dpy, p, p, &c, &c, 0, 0); - + XFreePixmap(linuxvars.dpy, p); } } @@ -1030,9 +1033,9 @@ global Key_Code keycode_lookup_table[255]; internal void linux_keycode_init(Display* dpy){ - + block_zero_array(keycode_lookup_table); - + // Find these keys by physical position, and map to QWERTY KeyCodes #define K(k) glue(KeyCode_, k) static const u8 positional_keys[] = { @@ -1042,27 +1045,27 @@ linux_keycode_init(Display* dpy){ K(Z), K(X), K(C), K(V), K(B), K(N), K(M), K(Comma), K(Period), K(ForwardSlash), 0, 0 }; #undef K - + // XKB gives the alphanumeric keys names like AE01 -> E is the row (from B-E), 01 is the column (01-12). // to get key names in .ps file: setxkbmap -print | xkbcomp - - | xkbprint -label name - out.ps - + static const int ncols = 12; static const int nrows = 4; - + for(int i = XkbMinLegalKeyCode; i <= XkbMaxLegalKeyCode; ++i) { const char* name = linuxvars.xkb->names->keys[i].name; - + if(name[0] == 'A' && name[1] >= 'B' && name[1] <= 'E') { int row = (nrows - 1) - (name[1] - 'B'); int col = (name[2] - '0') * 10 + (name[3] - '0') - 1; - + if(row >= 0 && row < nrows && col >= 0 && col < ncols) { keycode_lookup_table[i] = positional_keys[row * ncols + col]; } } - + // a few special cases: - + else if(memcmp(name, "TLDE", XkbKeyNameLength) == 0) { keycode_lookup_table[i] = KeyCode_Tick; } else if(memcmp(name, "BKSL", XkbKeyNameLength) == 0) { @@ -1074,12 +1077,12 @@ linux_keycode_init(Display* dpy){ // keycode_lookup_table[i] = } } - + // Find the rest by their key label struct SymCode { KeySym sym; Key_Code code; }; - SymCode sym_table[100]; + SymCode sym_table[108]; SymCode* p = sym_table; - + *p++ = { XK_space, KeyCode_Space }; *p++ = { XK_Tab, KeyCode_Tab }; *p++ = { XK_Escape, KeyCode_Escape }; @@ -1108,22 +1111,22 @@ linux_keycode_init(Display* dpy){ *p++ = { XK_Alt_R, KeyCode_Alt }; *p++ = { XK_Super_L, KeyCode_Command }; *p++ = { XK_Super_R, KeyCode_Command }; - - for(Key_Code k = KeyCode_F1; k <= KeyCode_F16; ++k) { + + for (Key_Code k = KeyCode_F1; k <= KeyCode_F24; ++k){ *p++ = { XK_F1 + (k - KeyCode_F1), k }; } - + const int table_size = p - sym_table; Assert(table_size < ArrayCount(sym_table)); - + for(int i = XkbMinLegalKeyCode; i <= XkbMaxLegalKeyCode; ++i) { KeySym sym = NoSymbol; - + // lookup key in current layout with no modifiers held (0) if(!XkbTranslateKeyCode(linuxvars.xkb, i, XkbBuildCoreState(0, linuxvars.xkb_group), NULL, &sym)) { continue; } - + for(int j = 0; j < table_size; ++j) { if(sym_table[j].sym == sym) { keycode_lookup_table[i] = sym_table[j].code; @@ -1137,20 +1140,20 @@ internal void linux_epoll_init(void) { struct epoll_event e = {}; e.events = EPOLLIN | EPOLLET; - + linuxvars.step_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); linuxvars.epoll = epoll_create(16); - + e.data.ptr = &epoll_tag_x11; epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, ConnectionNumber(linuxvars.dpy), &e); - + e.data.ptr = &epoll_tag_step_timer; epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, linuxvars.step_timer_fd, &e); } internal void linux_clipboard_send(XSelectionRequestEvent* req) { - + XSelectionEvent rsp = {}; rsp.type = SelectionNotify; rsp.requestor = req->requestor; @@ -1158,112 +1161,149 @@ linux_clipboard_send(XSelectionRequestEvent* req) { rsp.target = req->target; rsp.time = req->time; rsp.property = None; - + Atom formats[] = { linuxvars.atom_UTF8_STRING, XA_STRING, }; - + if(linuxvars.clipboard_contents.size == 0) { goto done; } - + if(req->selection != linuxvars.atom_CLIPBOARD || req->property == None) { goto done; } - + if (req->target == linuxvars.atom_TARGETS){ - + XChangeProperty( - req->display, - req->requestor, - req->property, - XA_ATOM, - 32, - PropModeReplace, - (u8*)formats, - ArrayCount(formats)); - + req->display, + req->requestor, + req->property, + XA_ATOM, + 32, + PropModeReplace, + (u8*)formats, + ArrayCount(formats)); + rsp.property = req->property; - + } else { - + int i; for(i = 0; i < ArrayCount(formats); ++i){ if (req->target == formats[i]){ break; } } - + if (i != ArrayCount(formats)){ XChangeProperty( - req->display, - req->requestor, - req->property, - req->target, - 8, - PropModeReplace, - linuxvars.clipboard_contents.str, - linuxvars.clipboard_contents.size - ); - + req->display, + req->requestor, + req->property, + req->target, + 8, + PropModeReplace, + linuxvars.clipboard_contents.str, + linuxvars.clipboard_contents.size + ); + rsp.property = req->property; } } - -done: + + done: XSendEvent(req->display, req->requestor, True, 0, (XEvent*)&rsp); } -internal void -linux_clipboard_recv(XSelectionEvent* ev) { - - if(ev->selection != linuxvars.atom_CLIPBOARD || - ev->target != linuxvars.atom_UTF8_STRING || - ev->property == None) { - return; - } - +internal String_Const_u8 +linux_clipboard_recv(Arena *arena){ Atom type; int fmt; unsigned long nitems; unsigned long bytes_left; u8 *data; - - int result = XGetWindowProperty( - linuxvars.dpy, - linuxvars.win, - linuxvars.atom_CLIPBOARD, - 0L, 0x20000000L, False, - linuxvars.atom_UTF8_STRING, - &type, &fmt, &nitems, - &bytes_left, &data); - + + int result = XGetWindowProperty(linuxvars.dpy, + linuxvars.win, + linuxvars.atom_CLIPBOARD, + 0L, 0x20000000L, False, + linuxvars.atom_UTF8_STRING, + &type, &fmt, &nitems, + &bytes_left, &data); + + String_Const_u8 clip = {}; if(result == Success && fmt == 8){ - linalloc_clear(linuxvars.clipboard_arena); - linuxvars.clipboard_contents = push_u8_stringf(linuxvars.clipboard_arena, "%.*s", nitems, data); - linuxvars.received_new_clipboard = true; + clip= push_string_copy(arena, SCu8(data, nitems)); XFree(data); XDeleteProperty(linuxvars.dpy, linuxvars.win, linuxvars.atom_CLIPBOARD); + } + + return(clip); +} + +internal void +linux_clipboard_recv(XSelectionEvent* ev) { + + if(ev->selection != linuxvars.atom_CLIPBOARD || + ev->target != linuxvars.atom_UTF8_STRING || + ev->property == None) { + return; + } + + Scratch_Block scratch(&linuxvars.tctx); + String_Const_u8 clip = linux_clipboard_recv(scratch); + if (clip.size > 0){ + linalloc_clear(linuxvars.clipboard_arena); + linuxvars.clipboard_contents = push_string_copy(linuxvars.clipboard_arena, clip); + linuxvars.received_new_clipboard = true; linux_schedule_step(); } } +internal +system_get_clipboard_sig(){ + // TODO(inso): index? + return(push_string_copy(arena, linuxvars.clipboard_contents)); +} + +internal void +system_post_clipboard(String_Const_u8 str, i32 index){ + // TODO(inso): index? + //LINUX_FN_DEBUG("%.*s", string_expand(str)); + linalloc_clear(linuxvars.clipboard_arena); + linuxvars.clipboard_contents = push_u8_stringf(linuxvars.clipboard_arena, "%.*s", str.size, str.str); + XSetSelectionOwner(linuxvars.dpy, linuxvars.atom_CLIPBOARD, linuxvars.win, CurrentTime); +} + +internal void +system_set_clipboard_catch_all(b32 enabled){ + LINUX_FN_DEBUG("%d", enabled); + linuxvars.clipboard_catch_all = !!enabled; +} + +internal b32 +system_get_clipboard_catch_all(void){ + return linuxvars.clipboard_catch_all; +} + internal String_Const_u8 linux_filter_text(Arena* arena, u8* buf, int len) { u8* const result = push_array(arena, u8, len); u8* outp = result; - + for(int i = 0; i < len; ++i) { u8 c = buf[i]; - + if(c == '\r') { *outp++ = '\n'; } else if(c > 127 || (' ' <= c && c <= '~') || c == '\t') { *outp++ = c; } } - + return SCu8(result, outp - result); } @@ -1271,47 +1311,47 @@ internal void linux_handle_x11_events() { static XEvent prev_event = {}; b32 should_step = false; - + while (XPending(linuxvars.dpy)) { XEvent event; XNextEvent(linuxvars.dpy, &event); - + if (XFilterEvent(&event, None) == True){ continue; } - + switch(event.type) { case KeyPress: { should_step = true; - + Input_Modifier_Set_Fixed* mods = &linuxvars.input.pers.modifiers; - + int state = event.xkey.state; set_modifier(mods, KeyCode_Shift, state & ShiftMask); set_modifier(mods, KeyCode_Control, state & ControlMask); set_modifier(mods, KeyCode_CapsLock, state & LockMask); set_modifier(mods, KeyCode_Alt, state & Mod1Mask); - + event.xkey.state &= ~(ControlMask); - + Status status; KeySym keysym = NoSymbol; u8 buf[256] = {}; - + int len = Xutf8LookupString(linuxvars.xic, &event.xkey, (char*)buf, sizeof(buf) - 1, &keysym, &status); - + if (status == XBufferOverflow){ Xutf8ResetIC(linuxvars.xic); XSetICFocus(linuxvars.xic); } - + if (keysym == XK_ISO_Left_Tab){ add_modifier(mods, KeyCode_Shift); } - + Key_Code key = keycode_lookup_table[(u8)event.xkey.keycode]; //printf("key %d = %s\n", event.xkey.keycode, key_code_name[key]); - + Input_Event* key_event = NULL; if(key) { add_modifier(mods, key); @@ -1320,7 +1360,7 @@ linux_handle_x11_events() { key_event->key.code = key; key_event->key.modifiers = copy_modifier_set(linuxvars.frame_arena, mods); } - + Input_Event* text_event = NULL; if(status == XLookupChars || status == XLookupBoth) { String_Const_u8 str = linux_filter_text(linuxvars.frame_arena, buf, len); @@ -1330,26 +1370,26 @@ linux_handle_x11_events() { text_event->text.string = str; } } - + if(key_event && text_event) { key_event->key.first_dependent_text = text_event; } - + } break; - + case KeyRelease: { should_step = true; - + Input_Modifier_Set_Fixed* mods = &linuxvars.input.pers.modifiers; - + int state = event.xkey.state; set_modifier(mods, KeyCode_Shift, state & ShiftMask); set_modifier(mods, KeyCode_Control, state & ControlMask); set_modifier(mods, KeyCode_CapsLock, state & LockMask); set_modifier(mods, KeyCode_Alt, state & Mod1Mask); - + Key_Code key = keycode_lookup_table[(u8)event.xkey.keycode]; - + Input_Event* key_event = NULL; if(key) { remove_modifier(mods, key); @@ -1359,149 +1399,147 @@ linux_handle_x11_events() { key_event->key.modifiers = copy_modifier_set(linuxvars.frame_arena, mods); } } break; - + case MotionNotify: { int x = clamp(0, event.xmotion.x, render_target.width - 1); int y = clamp(0, event.xmotion.y, render_target.height - 1); linuxvars.input.pers.mouse = { x, y }; should_step = true; } break; - + case ButtonPress: { should_step = true; switch(event.xbutton.button) { case Button1: { linuxvars.input.trans.mouse_l_press = true; linuxvars.input.pers.mouse_l = true; - + // NOTE(inso): improves selection dragging (especially in notepad-like mode). // we will still get mouse events when the pointer leaves the window if it's dragging. XGrabPointer( - linuxvars.dpy, - linuxvars.win, - True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, - None, None, CurrentTime); - + linuxvars.dpy, + linuxvars.win, + True, PointerMotionMask | ButtonPressMask | ButtonReleaseMask, + GrabModeAsync, GrabModeAsync, + None, None, CurrentTime); + } break; - + case Button3: { linuxvars.input.trans.mouse_r_press = true; linuxvars.input.pers.mouse_r = true; } break; - + case Button4: { linuxvars.input.trans.mouse_wheel = -100; } break; - + case Button5: { linuxvars.input.trans.mouse_wheel = +100; } break; } } break; - + case ButtonRelease: { should_step = true; switch(event.xbutton.button) { case Button1: { linuxvars.input.trans.mouse_l_release = true; linuxvars.input.pers.mouse_l = false; - + XUngrabPointer(linuxvars.dpy, CurrentTime); } break; - + case Button3: { linuxvars.input.trans.mouse_r_release = true; linuxvars.input.pers.mouse_r = false; } break; } } break; - + case FocusIn: case FocusOut: { linuxvars.input.pers.mouse_l = false; linuxvars.input.pers.mouse_r = false; block_zero_struct(&linuxvars.input.pers.modifiers); } break; - + case EnterNotify: { linuxvars.input.pers.mouse_out_of_window = 0; } break; - + case LeaveNotify: { linuxvars.input.pers.mouse_out_of_window = 1; } break; - + case ConfigureNotify: { i32 w = event.xconfigure.width; i32 h = event.xconfigure.height; - + if (w != render_target.width || h != render_target.height){ should_step = true; render_target.width = w; render_target.height = h; } } break; - + case ClientMessage: { Atom atom = event.xclient.data.l[0]; - + // Window X button clicked if(atom == linuxvars.atom_WM_DELETE_WINDOW) { should_step = true; linuxvars.input.trans.trying_to_kill = true; } - + // Notify WM that we're still responding (don't grey our window out). else if(atom == linuxvars.atom__NET_WM_PING) { event.xclient.window = DefaultRootWindow(linuxvars.dpy); - XSendEvent( - linuxvars.dpy, - event.xclient.window, - False, - SubstructureRedirectMask | SubstructureNotifyMask, - &event); + XSendEvent(linuxvars.dpy, + event.xclient.window, + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &event); } } break; - + case SelectionRequest: { linux_clipboard_send((XSelectionRequestEvent*)&event); } break; - + case SelectionNotify: { linux_clipboard_recv((XSelectionEvent*)&event); } break; - + case SelectionClear: { if(event.xselectionclear.selection == linuxvars.atom_CLIPBOARD) { linalloc_clear(linuxvars.clipboard_arena); block_zero_struct(&linuxvars.clipboard_contents); } } break; - + case Expose: case VisibilityNotify: { should_step = true; } break; - + default: { // clipboard update notification - ask for the new content - if (linuxvars.clipboard_catch_all && event.type == linuxvars.xfixes_selection_event) { + if (event.type == linuxvars.xfixes_selection_event) { XFixesSelectionNotifyEvent* sne = (XFixesSelectionNotifyEvent*)&event; if (sne->subtype == XFixesSelectionNotify && sne->owner != linuxvars.win){ - XConvertSelection( - linuxvars.dpy, - linuxvars.atom_CLIPBOARD, - linuxvars.atom_UTF8_STRING, - linuxvars.atom_CLIPBOARD, - linuxvars.win, - CurrentTime); + XConvertSelection(linuxvars.dpy, + linuxvars.atom_CLIPBOARD, + linuxvars.atom_UTF8_STRING, + linuxvars.atom_CLIPBOARD, + linuxvars.win, + CurrentTime); } } - + else if(event.type == linuxvars.xkb_event) { XkbEvent* kb = (XkbEvent*)&event; - + // Keyboard layout changed, refresh lookup table. if(kb->any.xkb_type == XkbStateNotify && kb->state.group != linuxvars.xkb_group) { linuxvars.xkb_group = kb->state.group; @@ -1512,7 +1550,7 @@ linux_handle_x11_events() { } break; } } - + if(should_step) { linux_schedule_step(); } @@ -1521,20 +1559,20 @@ linux_handle_x11_events() { internal b32 linux_epoll_process(struct epoll_event* events, int num_events) { b32 do_step = false; - + for (int i = 0; i < num_events; ++i){ struct epoll_event* ev = events + i; Epoll_Kind* tag = (Epoll_Kind*)ev->data.ptr; - + switch (*tag){ case EPOLL_X11: { linux_handle_x11_events(); } break; - + case EPOLL_X11_INTERNAL: { //XProcessInternalConnection(linuxvars.dpy, fd); } break; - + case EPOLL_STEP_TIMER: { u64 count; int ret; @@ -1543,11 +1581,11 @@ linux_epoll_process(struct epoll_event* events, int num_events) { } while (ret != -1 || errno != EAGAIN); do_step = true; } break; - + case EPOLL_CLI_PIPE: { linux_schedule_step(); } break; - + case EPOLL_USER_TIMER: { Linux_Object* obj = CastFromMember(Linux_Object, timer.epoll_tag, tag); close(obj->timer.fd); @@ -1556,51 +1594,51 @@ linux_epoll_process(struct epoll_event* events, int num_events) { } break; } } - + return do_step; } int main(int argc, char **argv){ - + pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&linuxvars.memory_tracker_mutex, &attr); - + // NOTE(allen): context setup { Base_Allocator* alloc = get_base_allocator_system(); thread_ctx_init(&linuxvars.tctx, ThreadKind_Main, alloc, alloc); } - + API_VTable_system system_vtable = {}; system_api_fill_vtable(&system_vtable); - + API_VTable_graphics graphics_vtable = {}; graphics_api_fill_vtable(&graphics_vtable); - + API_VTable_font font_vtable = {}; font_api_fill_vtable(&font_vtable); - + // NOTE(allen): memory linuxvars.frame_arena = reserve_arena(&linuxvars.tctx); linuxvars.clipboard_arena = reserve_arena(&linuxvars.tctx); render_target.arena = make_arena_system(KB(256)); - + linuxvars.fontconfig = FcInitLoadConfigAndFonts(); - + linuxvars.cursor_show = MouseCursorShow_Always; linuxvars.prev_cursor_show = MouseCursorShow_Always; - + dll_init_sentinel(&linuxvars.free_linux_objects); dll_init_sentinel(&linuxvars.timer_objects); - + //InitializeCriticalSection(&win32vars.thread_launch_mutex); //InitializeConditionVariable(&win32vars.thread_launch_cv); - - linuxvars.clipboard_catch_all = true; - + + linuxvars.clipboard_catch_all = false; + // NOTE(allen): load core System_Library core_library = {}; App_Functions app = {}; @@ -1609,7 +1647,7 @@ main(int argc, char **argv){ Scratch_Block scratch(&linuxvars.tctx, Scratch_Share); Path_Search_List search_list = {}; search_list_add_system_path(scratch, &search_list, SystemPath_Binary); - + String_Const_u8 core_path = get_full_path(scratch, &search_list, SCu8("4ed_app.so")); if (system_load_library(scratch, core_path, &core_library)){ get_funcs = (App_Get_Functions*)system_get_proc(core_library, "app_get_functions"); @@ -1626,20 +1664,20 @@ main(int argc, char **argv){ system_error_box(msg); } } - + // NOTE(allen): send system vtable to core app.load_vtables(&system_vtable, &font_vtable, &graphics_vtable); // get_logger calls log_init which is needed. app.get_logger(); //linuxvars.log_string = app.get_logger(); - + // NOTE(allen): init & command line parameters Plat_Settings plat_settings = {}; void *base_ptr = 0; { Scratch_Block scratch(&linuxvars.tctx, Scratch_Share); String_Const_u8 curdir = system_get_path(scratch, SystemPath_CurrentDirectory); - + char **files = 0; i32 *file_count = 0; base_ptr = app.read_command_line(&linuxvars.tctx, curdir, &plat_settings, &files, &file_count, argc, argv); @@ -1656,16 +1694,17 @@ main(int argc, char **argv){ *file_count = j; }*/ } - + // NOTE(allen): load custom layer System_Library custom_library = {}; Custom_API custom = {}; { char custom_not_found_msg[] = "Did not find a library for the custom layer."; - char custom_fail_version_msg[] = "Failed to load custom code due to missing version information or a version mismatch. Try rebuilding with buildsuper."; + char custom_fail_load_msg[] = "Failed to load custom code due to missing version information. Try rebuilding with buildsuper."; + char custom_fail_version_msg[] = "Failed to load custom code due to a version mismatch. Try rebuilding with buildsuper."; char custom_fail_init_apis[] = "Failed to load custom code due to missing 'init_apis' symbol. Try rebuilding with buildsuper"; - - Scratch_Block scratch(&linuxvars.tctx, Scratch_Share); + + Scratch_Block scratch(&linuxvars.tctx); String_Const_u8 default_file_name = string_u8_litexpr("custom_4coder.so"); Path_Search_List search_list = {}; search_list_add_system_path(scratch, &search_list, SystemPath_CurrentDirectory); @@ -1695,12 +1734,15 @@ main(int argc, char **argv){ has_library = true; } } - + if (!has_library){ system_error_box(custom_not_found_msg); } custom.get_version = (_Get_Version_Type*)system_get_proc(custom_library, "get_version"); - if (custom.get_version == 0 || custom.get_version(MAJOR, MINOR, PATCH) == 0){ + if (custom.get_version == 0){ + system_error_box(custom_fail_load_msg); + } + else if (custom.get_version(MAJOR, MINOR, PATCH) == 0){ system_error_box(custom_fail_version_msg); } custom.init_apis = (_Init_APIs_Type*)system_get_proc(custom_library, "init_apis"); @@ -1708,37 +1750,38 @@ main(int argc, char **argv){ system_error_box(custom_fail_init_apis); } } - + linux_x11_init(argc, argv, &plat_settings); linux_keycode_init(linuxvars.dpy); linux_epoll_init(); - + // app init { Scratch_Block scratch(&linuxvars.tctx, Scratch_Share); String_Const_u8 curdir = system_get_path(scratch, SystemPath_CurrentDirectory); app.init(&linuxvars.tctx, &render_target, base_ptr, curdir, custom); } - + linuxvars.global_frame_mutex = system_mutex_make(); system_mutex_acquire(linuxvars.global_frame_mutex); - + linux_schedule_step(); b32 first_step = true; - + u64 timer_start = system_now_time(); + for (;;) { - + if (XEventsQueued(linuxvars.dpy, QueuedAlready)){ linux_handle_x11_events(); } - + system_mutex_release(linuxvars.global_frame_mutex); - + struct epoll_event events[16]; int num_events = epoll_wait(linuxvars.epoll, events, ArrayCount(events), -1); - + system_mutex_acquire(linuxvars.global_frame_mutex); - + if (num_events == -1){ if (errno != EINTR){ perror("epoll_wait"); @@ -1746,31 +1789,31 @@ main(int argc, char **argv){ } continue; } - + if(!linux_epoll_process(events, num_events)) { continue; } - + linuxvars.last_step_time = system_now_time(); - + // NOTE(allen): Frame Clipboard Input // Request clipboard contents from X11 on first step, or every step if they don't have XFixes notification ability. if (first_step || (!linuxvars.has_xfixes && linuxvars.clipboard_catch_all)){ XConvertSelection(linuxvars.dpy, linuxvars.atom_CLIPBOARD, linuxvars.atom_UTF8_STRING, linuxvars.atom_CLIPBOARD, linuxvars.win, CurrentTime); } - + Application_Step_Input input = {}; - - if (linuxvars.received_new_clipboard){ + + if (linuxvars.received_new_clipboard && linuxvars.clipboard_catch_all){ input.clipboard = linuxvars.clipboard_contents; - linuxvars.received_new_clipboard = false; } - + linuxvars.received_new_clipboard = false; + input.first_step = first_step; input.dt = frame_useconds/1000000.f; // variable? input.events = linuxvars.input.trans.event_list; input.trying_to_kill = linuxvars.input.trans.trying_to_kill; - + input.mouse.out_of_window = linuxvars.input.pers.mouse_out_of_window; input.mouse.p = linuxvars.input.pers.mouse; input.mouse.l = linuxvars.input.pers.mouse_l; @@ -1780,23 +1823,23 @@ main(int argc, char **argv){ input.mouse.press_r = linuxvars.input.trans.mouse_r_press; input.mouse.release_r = linuxvars.input.trans.mouse_r_release; input.mouse.wheel = linuxvars.input.trans.mouse_wheel; - + // NOTE(allen): Application Core Update Application_Step_Result result = {}; if (app.step != 0){ result = app.step(&linuxvars.tctx, &render_target, base_ptr, &input); } - + // NOTE(allen): Finish the Loop if (result.perform_kill){ break; } - + // NOTE(NAME): Switch to New Title if (result.has_new_title){ XStoreName(linuxvars.dpy, linuxvars.win, result.title_string); } - + // NOTE(allen): Switch to New Cursor if (result.mouse_cursor_type != linuxvars.cursor && !linuxvars.input.pers.mouse_l){ XCursor c = linuxvars.xcursors[result.mouse_cursor_type]; @@ -1805,17 +1848,23 @@ main(int argc, char **argv){ } linuxvars.cursor = result.mouse_cursor_type; } - + gl_render(&render_target); glXSwapBuffers(linuxvars.dpy, linuxvars.win); - + + // TODO(allen): don't let the screen size change until HERE after the render + + // NOTE(allen): Schedule a step if necessary + if (result.animating){ + linux_schedule_step(); + } + first_step = false; - + linalloc_clear(linuxvars.frame_arena); block_zero_struct(&linuxvars.input.trans); - linuxvars.step_pending = false; } - + return 0; } diff --git a/platform_linux/linux_4ed_functions.cpp b/platform_linux/linux_4ed_functions.cpp index 2cebb4d0..040d503f 100644 --- a/platform_linux/linux_4ed_functions.cpp +++ b/platform_linux/linux_4ed_functions.cpp @@ -11,7 +11,7 @@ internal String_Const_u8 system_get_path(Arena* arena, System_Path_Code path_code){ String_Const_u8 result = {}; - + switch (path_code){ case SystemPath_CurrentDirectory: { // glibc extension: getcwd allocates its own memory if passed NULL @@ -19,70 +19,70 @@ system_get_path(Arena* arena, System_Path_Code path_code){ u64 working_dir_len = cstring_length(working_dir); u8 *out = push_array(arena, u8, working_dir_len + 1); block_copy(out, working_dir, working_dir_len); - + // NOTE: 4ed appears to expect a slash on the end. out[working_dir_len] = '/'; - + free(working_dir); result = SCu8(out, working_dir_len + 1); } break; - + case SystemPath_Binary: { // linux-specific: binary path symlinked at /proc/self/exe // PATH_MAX is probably good enough... // read the 'readlink' manpage for some comedy about it being 'broken by design'. - + char* buf = push_array(arena, char, PATH_MAX); ssize_t n = readlink("/proc/self/exe", buf, PATH_MAX); - + if(n == -1) { perror("readlink"); *buf = n = 0; } - + result = string_remove_last_folder(SCu8(buf, n)); } break; } - + return(result); } internal String_Const_u8 system_get_canonical(Arena* arena, String_Const_u8 name){ - + // first remove redundant ../, //, ./ parts - + const u8* input = (u8*) strndupa((char*)name.str, name.size); u8* output = push_array(arena, u8, name.size + 1); - + const u8* p = input; u8* q = output; - + while(*p) { - + // not a slash - copy char if(p[0] != '/') { *q++ = *p++; continue; } - + // two slashes in a row, skip one. if(p[1] == '/') { ++p; } else if(p[1] == '.') { - + // skip "/./" or trailing "/." if(p[2] == '/' || p[2] == '\0') { p += 2; } - + // if we encounter "/../" or trailing "/..", remove last directory instead else if(p[2] == '.' && (p[3] == '/' || p[3] == '\0')) { while(q > output && *--q != '/'){}; p += 3; } - + else { *q++ = *p++; } @@ -91,13 +91,13 @@ system_get_canonical(Arena* arena, String_Const_u8 name){ *q++ = *p++; } } - + #ifdef INSO_DEBUG if(name.size != q - output) { LINUX_FN_DEBUG("[%.*s] -> [%.*s]", (int)name.size, name.str, (int)(q - output), output); } #endif - + // TODO: use realpath at this point to resolve symlinks? return SCu8(output, q - output); } @@ -106,66 +106,73 @@ internal File_List system_get_file_list(Arena* arena, String_Const_u8 directory){ //LINUX_FN_DEBUG("%.*s", (int)directory.size, directory.str); File_List result = {}; - + char* path = strndupa((char*)directory.str, directory.size); int fd = open(path, O_RDONLY | O_DIRECTORY); if(fd == -1) { perror("open"); return result; } - + DIR* dir = fdopendir(fd); struct dirent* d; - + File_Info* head = NULL; File_Info** fip = &head; - + while((d = readdir(dir))) { const char* name = d->d_name; - + // ignore . and .. if(*name == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) { continue; } - + *fip = push_array(arena, File_Info, 1); (*fip)->file_name = push_u8_stringf(arena, "%.*s", d->d_reclen, name); - + struct stat st; - if(fstatat(fd, name, &st, 0) == -1){ + if (fstatat(fd, name, &st, 0) == -1){ perror("fstatat"); } - - (*fip)->attributes = linux_file_attributes_from_struct_stat(&st); + else{ + (*fip)->attributes = linux_file_attributes_from_struct_stat(&st); + } + fip = &(*fip)->next; result.count++; } closedir(dir); - + if(result.count > 0) { result.infos = fip = push_array(arena, File_Info*, result.count); - + for(File_Info* f = head; f; f = f->next) { *fip++ = f; } - + qsort(result.infos, result.count, sizeof(File_Info*), (__compar_fn_t)&linux_compare_file_infos); - + for(u32 i = 0; i < result.count - 1; ++i) { result.infos[i]->next = result.infos[i+1]; } result.infos[result.count-1]->next = NULL; } - + return result; } internal File_Attributes system_quick_file_attributes(Arena* scratch, String_Const_u8 file_name){ //LINUX_FN_DEBUG("%.*s", (int)file_name.size, file_name.str); + Temp_Memory_Block temp(scratch); + file_name = push_string_copy(scratch, file_name); + File_Attributes result = {}; struct stat file_stat; - stat((const char*)file_name.str, &file_stat); - return linux_file_attributes_from_struct_stat(&file_stat); + if (stat((const char*)file_name.str, &file_stat) == 0){ + result = linux_file_attributes_from_struct_stat(&file_stat); + } + return(result); } internal b32 @@ -182,9 +189,12 @@ system_load_handle(Arena* scratch, char* file_name, Plat_Handle* out){ internal File_Attributes system_load_attributes(Plat_Handle handle){ LINUX_FN_DEBUG(); + File_Attributes result = {}; struct stat file_stat; - fstat(*(int*)&handle, &file_stat); - return linux_file_attributes_from_struct_stat(&file_stat); + if (fstat(*(int*)&handle, &file_stat) == 0){ + result = linux_file_attributes_from_struct_stat(&file_stat); + } + return(result); } internal b32 @@ -209,23 +219,25 @@ internal File_Attributes system_save_file(Arena* scratch, char* file_name, String_Const_u8 data){ LINUX_FN_DEBUG("%s", file_name); File_Attributes result = {}; - + // TODO(inso): should probably put a \n on the end if it's a text file. - - int fd = open(file_name, O_WRONLY, O_CREAT); + + int fd = open(file_name, O_TRUNC|O_WRONLY|O_CREAT, 0666); if (fd != -1) { int bytes_written = write(fd, data.str, data.size); if (bytes_written == -1) { perror("write"); - } else if(bytes_written == data.size) { + } else if (bytes_written == data.size) { struct stat file_stat; - fstat(fd, &file_stat); - return linux_file_attributes_from_struct_stat(&file_stat); + if (fstat(fd, &file_stat) == 0){ + result = linux_file_attributes_from_struct_stat(&file_stat); + } } + close(fd); } else { perror("open"); } - + return result; } @@ -256,8 +268,8 @@ internal u64 system_now_time(void){ //LINUX_FN_DEBUG(); struct timespec time; - clock_gettime(CLOCK_MONOTONIC_RAW, &time); - return linux_ns_from_timespec(time); + clock_gettime(CLOCK_MONOTONIC, &time); + return linux_us_from_timespec(time); } internal Plat_Handle @@ -265,7 +277,7 @@ system_wake_up_timer_create(void){ LINUX_FN_DEBUG(); Linux_Object* object = linux_alloc_object(LinuxObjectKind_Timer); dll_insert(&linuxvars.timer_objects, &object->node); - + // NOTE(inso): timers created on-demand to avoid file-descriptor exhaustion. object->timer.fd = -1; } @@ -287,23 +299,23 @@ internal void system_wake_up_timer_set(Plat_Handle handle, u32 time_milliseconds){ //LINUX_FN_DEBUG("%u", time_milliseconds); Linux_Object* object = handle_to_object(handle); - + if (object->kind == LinuxObjectKind_Timer){ if(object->timer.fd == -1) { object->timer.fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); - + struct epoll_event ev; ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT; ev.data.ptr = &object->timer.epoll_tag; epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, object->timer.fd, &ev); } - + struct itimerspec it = {}; it.it_value.tv_sec = time_milliseconds / 1000; it.it_value.tv_nsec = (time_milliseconds % 1000) * UINT64_C(1000000); timerfd_settime(object->timer.fd, 0, &it, NULL); } - + } internal void @@ -323,33 +335,6 @@ system_sleep(u64 microseconds){ nanosleep(&requested, &remaining); } -internal String_Const_u8 -system_get_clipboard(Arena* arena, i32 index){ - // TODO(inso): index? - u8* ptr = push_array_write(arena, u8, linuxvars.clipboard_contents.size, linuxvars.clipboard_contents.str); - return SCu8(ptr, linuxvars.clipboard_contents.size); -} - -internal void -system_post_clipboard(String_Const_u8 str, i32 index){ - // TODO(inso): index? - //LINUX_FN_DEBUG("%.*s", string_expand(str)); - linalloc_clear(linuxvars.clipboard_arena); - linuxvars.clipboard_contents = push_u8_stringf(linuxvars.clipboard_arena, "%.*s", str.size, str.str); - XSetSelectionOwner(linuxvars.dpy, linuxvars.atom_CLIPBOARD, linuxvars.win, CurrentTime); -} - -internal void -system_set_clipboard_catch_all(b32 enabled){ - LINUX_FN_DEBUG("%d", enabled); - linuxvars.clipboard_catch_all = !!enabled; -} - -internal b32 -system_get_clipboard_catch_all(void){ - return linuxvars.clipboard_catch_all; -} - internal b32 system_cli_call(Arena* scratch, char* path, char* script, CLI_Handles* cli_out){ LINUX_FN_DEBUG("%s / %s", path, script); @@ -358,28 +343,28 @@ system_cli_call(Arena* scratch, char* path, char* script, CLI_Handles* cli_out){ perror("system_cli_call: pipe"); return 0; } - + pid_t child_pid = vfork(); if (child_pid == -1){ perror("system_cli_call: fork"); return 0; } - + enum { PIPE_FD_READ, PIPE_FD_WRITE }; - + // child if (child_pid == 0){ close(pipe_fds[PIPE_FD_READ]); dup2(pipe_fds[PIPE_FD_WRITE], STDOUT_FILENO); dup2(pipe_fds[PIPE_FD_WRITE], STDERR_FILENO); - + if (chdir(path) == -1){ perror("system_cli_call: chdir"); exit(1); } - + char* argv[] = { "sh", "-c", script, NULL }; - + if (execv("/bin/sh", argv) == -1){ perror("system_cli_call: execv"); } @@ -387,17 +372,17 @@ system_cli_call(Arena* scratch, char* path, char* script, CLI_Handles* cli_out){ } else{ close(pipe_fds[PIPE_FD_WRITE]); - + *(pid_t*)&cli_out->proc = child_pid; *(int*)&cli_out->out_read = pipe_fds[PIPE_FD_READ]; *(int*)&cli_out->out_write = pipe_fds[PIPE_FD_WRITE]; - + struct epoll_event e = {}; e.events = EPOLLIN | EPOLLET; e.data.ptr = &epoll_tag_cli_pipe; epoll_ctl(linuxvars.epoll, EPOLL_CTL_ADD, pipe_fds[PIPE_FD_READ], &e); } - + return(true); } @@ -411,16 +396,16 @@ internal b32 system_cli_update_step(CLI_Handles* cli, char* dest, u32 max, u32* amount){ LINUX_FN_DEBUG(); int pipe_read_fd = *(int*)&cli->out_read; - + fd_set fds; FD_ZERO(&fds); FD_SET(pipe_read_fd, &fds); - + struct timeval tv = {}; - + size_t space_left = max; char* ptr = dest; - + while (space_left > 0 && select(pipe_read_fd + 1, &fds, NULL, NULL, &tv) == 1){ ssize_t num = read(pipe_read_fd, ptr, space_left); if (num == -1){ @@ -433,7 +418,7 @@ system_cli_update_step(CLI_Handles* cli, char* dest, u32 max, u32* amount){ space_left -= num; } } - + *amount = (ptr - dest); return((ptr - dest) > 0); } @@ -443,16 +428,16 @@ system_cli_end_update(CLI_Handles* cli){ LINUX_FN_DEBUG(); pid_t pid = *(pid_t*)&cli->proc; b32 close_me = false; - + int status; if (pid && waitpid(pid, &status, WNOHANG) > 0){ cli->exit = WEXITSTATUS(status); - + close_me = true; close(*(int*)&cli->out_read); close(*(int*)&cli->out_write); } - + return(close_me); } @@ -484,28 +469,28 @@ internal System_Thread system_thread_launch(Thread_Function* proc, void* ptr){ LINUX_FN_DEBUG(); System_Thread result = {}; - + Linux_Object* thread_info = linux_alloc_object(LinuxObjectKind_Thread); thread_info->thread.proc = proc; thread_info->thread.ptr = ptr; - + pthread_attr_t thread_attr; pthread_attr_init(&thread_attr); int create_result = pthread_create( - &thread_info->thread.pthread, - &thread_attr, - linux_thread_proc_start, - thread_info); - + &thread_info->thread.pthread, + &thread_attr, + linux_thread_proc_start, + thread_info); + pthread_attr_destroy(&thread_attr); - + // TODO(andrew): Need to wait for thread to confirm it launched? if (create_result == 0) { - static_assert(sizeof(Linux_Object*) <= sizeof(System_Thread)); + static_assert(sizeof(Linux_Object*) <= sizeof(System_Thread), "Linux_Object doesn't fit inside System_Thread"); *(Linux_Object**)&result = thread_info; return result; } - + return result; } @@ -554,7 +539,10 @@ internal System_Mutex system_mutex_make(void){ System_Mutex result = {}; Linux_Object* object = linux_alloc_object(LinuxObjectKind_Mutex); - pthread_mutex_init(&object->mutex, NULL); + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&object->mutex, &attr); *(Linux_Object**)&result = object; //LINUX_FN_DEBUG("%p", object); return result; @@ -626,31 +614,31 @@ system_condition_variable_free(System_Condition_Variable cv){ internal void* system_memory_allocate(u64 size, String_Const_u8 location){ - - static_assert(MEMORY_PREFIX_SIZE >= sizeof(Memory_Annotation_Node)); + + static_assert(MEMORY_PREFIX_SIZE >= sizeof(Memory_Annotation_Node), "MEMORY_PREFIX_SIZE is not enough to contain Memory_Annotation_Node"); u64 adjusted_size = size + MEMORY_PREFIX_SIZE; - + Assert(adjusted_size > size); - + const int prot = PROT_READ | PROT_WRITE; const int flags = MAP_PRIVATE | MAP_ANONYMOUS; - + void* result = mmap(NULL, adjusted_size, prot, flags, -1, 0); - + if(result == MAP_FAILED) { perror("mmap"); return NULL; } - + Linux_Memory_Tracker_Node* node = (Linux_Memory_Tracker_Node*)result; node->location = location; node->size = size; - + pthread_mutex_lock(&linuxvars.memory_tracker_mutex); zdll_push_back(linuxvars.memory_tracker_head, linuxvars.memory_tracker_tail, node); linuxvars.memory_tracker_count++; pthread_mutex_unlock(&linuxvars.memory_tracker_mutex); - + return (u8*)result + MEMORY_PREFIX_SIZE; } @@ -669,12 +657,12 @@ internal void system_memory_free(void* ptr, u64 size){ u64 adjusted_size = size + MEMORY_PREFIX_SIZE; Linux_Memory_Tracker_Node* node = (Linux_Memory_Tracker_Node*)((u8*)ptr - MEMORY_PREFIX_SIZE); - + pthread_mutex_lock(&linuxvars.memory_tracker_mutex); zdll_remove(linuxvars.memory_tracker_head, linuxvars.memory_tracker_tail, node); linuxvars.memory_tracker_count--; pthread_mutex_unlock(&linuxvars.memory_tracker_mutex); - + if(munmap(node, adjusted_size) == -1) { perror("munmap"); } @@ -683,12 +671,12 @@ system_memory_free(void* ptr, u64 size){ internal Memory_Annotation system_memory_annotation(Arena* arena){ LINUX_FN_DEBUG(); - + Memory_Annotation result; Memory_Annotation_Node** ptr = &result.first; - + pthread_mutex_lock(&linuxvars.memory_tracker_mutex); - + for(Linux_Memory_Tracker_Node* node = linuxvars.memory_tracker_head; node; node = node->next) { *ptr = push_array(arena, Memory_Annotation_Node, 1); (*ptr)->location = node->location; @@ -697,25 +685,25 @@ system_memory_annotation(Arena* arena){ ptr = &(*ptr)->next; result.count++; } - + pthread_mutex_unlock(&linuxvars.memory_tracker_mutex); - + *ptr = NULL; result.last = CastFromMember(Memory_Annotation_Node, next, ptr); - + return result; } internal void system_show_mouse_cursor(i32 show){ LINUX_FN_DEBUG("%d", show); - + linuxvars.cursor_show = show; - + XDefineCursor( - linuxvars.dpy, - linuxvars.win, - show ? None : linuxvars.hidden_cursor); + linuxvars.dpy, + linuxvars.win, + show ? None : linuxvars.hidden_cursor); } internal b32 @@ -727,11 +715,11 @@ system_set_fullscreen(b32 full_screen){ internal b32 system_is_fullscreen(void){ b32 result = 0; - + // NOTE(inso): This will get the "true" state of fullscreen, // even if it was toggled outside of 4coder. // (e.g. super-F11 on some WMs sets fullscreen for any window/program) - + Atom type, *prop; unsigned long nitems, pad; int fmt; @@ -741,12 +729,12 @@ system_is_fullscreen(void){ 0, 32, False, XA_ATOM, &type, &fmt, &nitems, &pad, (unsigned char**)&prop); - + if(ret == Success && prop){ result = *prop == linuxvars.atom__NET_WM_STATE_FULLSCREEN; XFree((unsigned char*)prop); } - + return result; } diff --git a/platform_linux/linux_4ed_old.cpp b/platform_linux/linux_4ed_old.cpp index 6a050baf..d0cd237d 100644 --- a/platform_linux/linux_4ed_old.cpp +++ b/platform_linux/linux_4ed_old.cpp @@ -86,7 +86,7 @@ #define frame_useconds (1000000UL / FPS) #define LINUX_FN_DEBUG(fmt, ...) do { \ - /*LOGF("%s: " fmt "\n", __func__, ##__VA_ARGS__);*/ \ +/*LOGF("%s: " fmt "\n", __func__, ##__VA_ARGS__);*/ \ } while (0) // TODO(allen): Make an intrinsics header that uses the cracked OS to define a single set of intrinsic names. @@ -547,41 +547,41 @@ Sys_Font_Path(name, parameters){ Font_Path path = {}; FcPattern *pattern_regular = FcPatternBuild( - 0, - FC_POSTSCRIPT_NAME, FcTypeString, name, - FC_SIZE, FcTypeDouble, (double)parameters->pt_size, - FC_FONTFORMAT, FcTypeString, "TrueType", - FC_STYLE, FcTypeString, (FcChar8*)"Regular", - (void*)0); + 0, + FC_POSTSCRIPT_NAME, FcTypeString, name, + FC_SIZE, FcTypeDouble, (double)parameters->pt_size, + FC_FONTFORMAT, FcTypeString, "TrueType", + FC_STYLE, FcTypeString, (FcChar8*)"Regular", + (void*)0); FcPattern *pattern_styled = 0; if (parameters->italics || parameters->bold){ if (parameters->italics && !parameters->bold){ pattern_styled = FcPatternBuild( - 0, - FC_POSTSCRIPT_NAME, FcTypeString, name, - FC_SIZE, FcTypeDouble, (double)parameters->pt_size, - FC_FONTFORMAT, FcTypeString, "TrueType", - FC_STYLE, FcTypeString, (FcChar8*)"Italic", - (void*)0); + 0, + FC_POSTSCRIPT_NAME, FcTypeString, name, + FC_SIZE, FcTypeDouble, (double)parameters->pt_size, + FC_FONTFORMAT, FcTypeString, "TrueType", + FC_STYLE, FcTypeString, (FcChar8*)"Italic", + (void*)0); } else if (!parameters->italics && parameters->bold){ pattern_styled = FcPatternBuild( - 0, - FC_POSTSCRIPT_NAME, FcTypeString, name, - FC_SIZE, FcTypeDouble, (double)parameters->pt_size, - FC_FONTFORMAT, FcTypeString, "TrueType", - FC_STYLE, FcTypeString, (FcChar8*)"Bold", - (void*)0); + 0, + FC_POSTSCRIPT_NAME, FcTypeString, name, + FC_SIZE, FcTypeDouble, (double)parameters->pt_size, + FC_FONTFORMAT, FcTypeString, "TrueType", + FC_STYLE, FcTypeString, (FcChar8*)"Bold", + (void*)0); } else{ pattern_styled = FcPatternBuild( - 0, - FC_POSTSCRIPT_NAME, FcTypeString, name, - FC_SIZE, FcTypeDouble, (double)parameters->pt_size, - FC_FONTFORMAT, FcTypeString, "TrueType", - FC_STYLE, FcTypeString, (FcChar8*)"Bold Italic", - (void*)0); + 0, + FC_POSTSCRIPT_NAME, FcTypeString, name, + FC_SIZE, FcTypeDouble, (double)parameters->pt_size, + FC_FONTFORMAT, FcTypeString, "TrueType", + FC_STYLE, FcTypeString, (FcChar8*)"Bold Italic", + (void*)0); } } @@ -672,9 +672,9 @@ linux_get_loadable_fonts(Partition *part, Font_Setup_List *list){ } FcPattern* pat = FcPatternBuild( - 0, - FC_STYLE, FcTypeString, (FcChar8*)"Regular", - (void*)0); + 0, + FC_STYLE, FcTypeString, (FcChar8*)"Regular", + (void*)0); FcObjectSet* os = FcObjectSetBuild(FC_FAMILY, FC_FILE, (char*)0); FcFontSet* fs = FcFontList(fc_config, pat, os); if (fs != 0){ @@ -778,7 +778,7 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig *best_con if (glXCreateContextAttribsARB == 0){ //LOG("glXCreateContextAttribsARB() not found, using old-style GLX context\n" ); ctx = glXCreateNewContext( XDisplay, *best_config, GLX_RGBA_TYPE, 0, True ); - } + } else{ int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 2, @@ -926,7 +926,7 @@ ChooseGLXConfig(Display *XDisplay, int XScreenIndex) GLX_STENCIL_SIZE , 8, GLX_DOUBLEBUFFER , True, None - }; + }; int ConfigCount = 0; GLXFBConfig *Configs = glXChooseFBConfig(XDisplay, XScreenIndex, DesiredAttributes, &ConfigCount); @@ -1196,7 +1196,7 @@ LinuxGetXSettingsDPI(Display* dpy, int screen) Window xset_win = XGetSelectionOwner(dpy, XSET_SEL); if (xset_win == None){ // TODO(inso): listen for the ClientMessage about it becoming available? - // there's not much point atm if DPI scaling is only done at startup + // there's not much point atm if DPI scaling is only done at startup goto out; } @@ -1760,11 +1760,11 @@ linux_handle_x11_events(void) else if ((Atom)event.xclient.data.l[0] == linuxvars.atom__NET_WM_PING){ event.xclient.window = DefaultRootWindow(linuxvars.XDisplay); XSendEvent( - linuxvars.XDisplay, - event.xclient.window, - False, - SubstructureRedirectMask | SubstructureNotifyMask, - &event); + linuxvars.XDisplay, + event.xclient.window, + False, + SubstructureRedirectMask | SubstructureNotifyMask, + &event); } }break; @@ -1792,14 +1792,14 @@ linux_handle_x11_events(void) if (request.target == linuxvars.atom_TARGETS){ XChangeProperty( - request.display, - request.requestor, - request.property, - XA_ATOM, - 32, - PropModeReplace, - (u8*)atoms, - ArrayCount(atoms)); + request.display, + request.requestor, + request.property, + XA_ATOM, + 32, + PropModeReplace, + (u8*)atoms, + ArrayCount(atoms)); response.property = request.property; @@ -1814,15 +1814,15 @@ linux_handle_x11_events(void) if (found){ XChangeProperty( - request.display, - request.requestor, - request.property, - request.target, - 8, - PropModeReplace, - (u8*)linuxvars.clipboard_outgoing.str, - linuxvars.clipboard_outgoing.size - ); + request.display, + request.requestor, + request.property, + request.target, + 8, + PropModeReplace, + (u8*)linuxvars.clipboard_outgoing.str, + linuxvars.clipboard_outgoing.size + ); response.property = request.property; } @@ -1915,7 +1915,7 @@ main(int argc, char **argv){ memory_init(); // - // HACK(allen): + // HACK(allen): // Previously zipped stuff is here, it should be zipped in the new pattern now. // diff --git a/platform_linux/linux_error_box.cpp b/platform_linux/linux_error_box.cpp index f61aa3d6..531efebe 100644 --- a/platform_linux/linux_error_box.cpp +++ b/platform_linux/linux_error_box.cpp @@ -15,16 +15,16 @@ internal void system_error_box(char *msg, b32 shutdown = true){ fprintf(stderr, "Fatal Error: %s\n", msg); //LOGF("Fatal Error: %s\n", msg); - + Display *dpy = XOpenDisplay(0); if (!dpy){ exit(1); } - + const int num_cols = 50; int win_w = (num_cols + 10) * 9; int win_h = 140; - + { const char *start_p = msg, *space_p = NULL; for(const char* p = msg; *p; ++p){ @@ -36,86 +36,86 @@ system_error_box(char *msg, b32 shutdown = true){ } } } - + Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, win_w, win_h, 0, 0, 0x227A3B); XStoreName(dpy, w, "4coder Error"); - + XSizeHints* sh = XAllocSizeHints(); sh->flags = PMinSize; sh->min_width = win_w; sh->min_height = win_h; XSetWMNormalHints(dpy, w, sh); - + Atom type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); - + XChangeProperty(dpy, w, XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False), XA_ATOM, 32, PropModeReplace, (unsigned char*) &type, 1); - + Atom WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False); XSetWMProtocols(dpy, w, &WM_DELETE_WINDOW, 1); - + linux_set_icon(dpy, w); - + XMapRaised(dpy, w); XSync(dpy, False); - + XSelectInput(dpy, w, ExposureMask | StructureNotifyMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask); - + XFontStruct* font = XLoadQueryFont(dpy, "-*-fixed-bold-*-*-*-*-140-*-*-*-*-iso8859-1"); if (!font){ exit(1); } - + XGCValues gcv; gcv.foreground = WhitePixel(dpy, 0); gcv.line_width = 2; gcv.font = font->fid; - + GC gc1 = XCreateGC(dpy, w, GCForeground | GCFont | GCLineWidth, &gcv); gcv.foreground = BlackPixel(dpy, 0); GC gc2 = XCreateGC(dpy, w, GCForeground | GCFont | GCLineWidth, &gcv); - + int button_trigger = 0; int button_hi = 0; int redraw = 1; - + XEvent ev; while (1){ XNextEvent(dpy, &ev); - + if (ev.type == Expose) redraw = 1; - + if (ev.type == ConfigureNotify){ redraw = 1; win_w = ev.xconfigure.width; win_h = ev.xconfigure.height; } - + XRectangle button_rect = { (short)(win_w/2-40), (short)(win_h*0.8f), 80, 20 }; - + if (ev.type == MotionNotify){ int new_hi = (ev.xmotion.x > button_rect.x && ev.xmotion.y > button_rect.y && ev.xmotion.x < button_rect.x + button_rect.width && ev.xmotion.y < button_rect.y + button_rect.height); - + if (new_hi != button_hi){ button_hi = new_hi; redraw = 1; } } - + if (ev.type == KeyPress){ KeySym sym = XLookupKeysym(&ev.xkey, 0); if (sym == XK_Escape || sym == XK_Return){ exit(1); } } - + if (ev.type == ButtonPress && ev.xbutton.button == Button1){ if (button_hi) button_trigger = 1; redraw = 1; } - + if (ev.type == ButtonRelease && ev.xbutton.button == Button1){ if (button_trigger){ if (button_hi){ @@ -126,61 +126,61 @@ system_error_box(char *msg, b32 shutdown = true){ } redraw = 1; } - + if (ev.type == ClientMessage && ev.xclient.window == w && (Atom)ev.xclient.data.l[0] == WM_DELETE_WINDOW){ exit(1); } - + #define DRAW_STR(x, y, str, len) \ - XDrawString(dpy, w, gc2, (x)+1, (y)+1, (str), (len)); \ - XDrawString(dpy, w, gc1, (x) , (y) , (str), (len)) - +XDrawString(dpy, w, gc2, (x)+1, (y)+1, (str), (len)); \ +XDrawString(dpy, w, gc1, (x) , (y) , (str), (len)) + if (redraw){ redraw = 0; XClearWindow(dpy, w); - + const char* line_start = msg; const char* last_space = NULL; int y = 30; - + { const char title[] = "4coder - Fatal Error"; int width = XTextWidth(font, title, sizeof(title)-1); int x = (win_w/2) - (width/2); DRAW_STR(x, y, title, sizeof(title)-1); } - + y += 36; int width = XTextWidth(font, "x", 1) * num_cols; int x = (win_w/2) - (width/2); - + for(const char* p = line_start; *p; ++p){ if (*p == ' ') last_space = p; if (p - line_start > num_cols || *p == '\n' || !p[1]){ - + const char* new_line_start = last_space + 1; if (!last_space || *p == '\n' || !p[1]){ new_line_start = last_space = (p + !p[1]); } - + DRAW_STR(x, y, line_start, last_space - line_start); - + line_start = new_line_start; last_space = NULL; y += 18; } } - + XDrawRectangles(dpy, w, gc1, &button_rect, 1); if (button_hi || button_trigger){ XDrawRectangle(dpy, w, gc2, button_rect.x+1, button_rect.y+1, button_rect.width-2, button_rect.height-2); } - + DRAW_STR(button_rect.x + 20, button_rect.y + 15, "Drat!", 5); } } #undef DRAW_STR - + if (shutdown){ exit(1); } diff --git a/platform_mac/mac_4ed.mm b/platform_mac/mac_4ed.mm index 46997aff..97b45eff 100644 --- a/platform_mac/mac_4ed.mm +++ b/platform_mac/mac_4ed.mm @@ -94,8 +94,8 @@ struct Mac_Input_Chunk_Transient{ b8 mouse_r_press; b8 mouse_r_release; b8 out_of_window; - i8 mouse_wheel; b8 trying_to_kill; + i32 mouse_wheel; }; struct Mac_Input_Chunk_Persistent{ @@ -193,10 +193,9 @@ struct Mac_Vars { String_Const_u8 binary_path; - Arena *clipboard_arena; - String_Const_u8 clipboard_contents; u32 clipboard_change_count; b32 next_clipboard_is_self; + b32 clip_catch_all; Arena clip_post_arena; String_Const_u8 clip_post; @@ -530,39 +529,7 @@ mac_get_clipboard_change_count(void){ return(result); } -function b32 -mac_read_clipboard_contents(Arena *scratch){ - b32 result = false; - - Temp_Memory temp = begin_temp(scratch); - { - NSPasteboard *board = [NSPasteboard generalPasteboard]; - NSString *utf8_type = @"public.utf8-plain-text"; - NSArray *types_array = [NSArray arrayWithObjects:utf8_type, nil]; - NSString *has_string = [board availableTypeFromArray:types_array]; - if (has_string != nil){ - NSData *data = [board dataForType:utf8_type]; - if (data != nil){ - u32 copy_length = data.length; - if (copy_length > 0){ - Arena *clip_arena = mac_vars.clipboard_arena; - linalloc_clear(clip_arena); - - mac_vars.clipboard_contents = string_const_u8_push(clip_arena, copy_length); - [data getBytes:mac_vars.clipboard_contents.str - length:mac_vars.clipboard_contents.size]; - - result = true; - } - } - } - } - end_temp(temp); - - return(result); -} - -function void +internal void mac_post_clipboard(Arena *scratch, char *text, i32 len){ NSPasteboard *board = [NSPasteboard generalPasteboard]; @@ -583,6 +550,65 @@ mac_post_clipboard(Arena *scratch, char *text, i32 len){ //////////////////////////////// +internal +system_get_clipboard_sig(){ + String_Const_u8 result = {}; + u32 change_count = mac_get_clipboard_change_count(); + if (change_count != mac_vars.clipboard_change_count){ + if (mac_vars.next_clipboard_is_self){ + mac_vars.next_clipboard_is_self = false; + } else { + NSPasteboard *board = [NSPasteboard generalPasteboard]; + NSString *utf8_type = @"public.utf8-plain-text"; + NSArray *types_array = [NSArray arrayWithObjects:utf8_type, nil]; + NSString *has_string = [board availableTypeFromArray:types_array]; + if (has_string != nil){ + NSData *data = [board dataForType:utf8_type]; + if (data != nil){ + u32 copy_length = data.length; + if (copy_length > 0){ + result = string_const_u8_push(arena, copy_length); + [data getBytes:result.str length:result.size]; + } + } + } + } + mac_vars.clipboard_change_count = change_count; + } + return(result); +} + +internal +system_post_clipboard_sig(){ + Arena *arena = &mac_vars.clip_post_arena; + if (arena->base_allocator == 0){ + *arena = make_arena_system(); + } else{ + linalloc_clear(arena); + } + + mac_vars.clip_post.str = push_array(arena, u8, str.size + 1); + if (mac_vars.clip_post.str != 0){ + block_copy(mac_vars.clip_post.str, str.str, str.size); + mac_vars.clip_post.str[str.size] = 0; + mac_vars.clip_post.size = str.size; + } else{ + // NOTE(yuval): Failed to allocate buffer for clipboard post + } +} + +internal +system_set_clipboard_catch_all_sig(){ + mac_vars.clip_catch_all = enabled?true:false; +} + +internal +system_get_clipboard_catch_all_sig(){ + return(mac_vars.clip_catch_all); +} + +//////////////////////////////// + function void mac_toggle_fullscreen(void){ [mac_vars.window toggleFullScreen:nil]; @@ -712,31 +738,11 @@ mac_toggle_fullscreen(void){ } // NOTE(yuval): Frame clipboard input + Scratch_Block scratch(mac_vars.tctx); MacProfileScope("Frame Clipboard Input"){ - block_zero_struct(&mac_vars.clipboard_contents); - input.clipboard_changed = false; - - if (mac_vars.clipboard_change_count != 0){ - u32 change_count = mac_get_clipboard_change_count(); - if (change_count != mac_vars.clipboard_change_count){ - if (mac_vars.next_clipboard_is_self){ - mac_vars.next_clipboard_is_self = false; - } else{ - for (i32 r = 0; r < 4; ++r){ - Scratch_Block scratch(mac_vars.tctx, Scratch_Share); - - if (mac_read_clipboard_contents(scratch)){ - input.clipboard_changed = true; - break; - } - } - } - - mac_vars.clipboard_change_count = change_count; - } + if (mac_vars.clipboard_change_count != 0 && mac_vars.clip_catch_all){ + input.clipboard = system_get_clipboard(scratch, 0); } - - input.clipboard = mac_vars.clipboard_contents; } mac_vars.clip_post.size = 0; @@ -759,7 +765,6 @@ mac_toggle_fullscreen(void){ // NOTE(yuval): Post new clipboard content MacProfileScope("Post Clipboard"){ if (mac_vars.clip_post.size > 0){ - Scratch_Block scratch(mac_vars.tctx, Scratch_Share); mac_post_clipboard(scratch, (char*)mac_vars.clip_post.str, (i32)mac_vars.clip_post.size); } } @@ -979,17 +984,9 @@ mac_toggle_fullscreen(void){ } - (void)scrollWheel:(NSEvent *)event{ - float dx = event.scrollingDeltaX; - float dy = event.scrollingDeltaY; - - i8 wheel_delta = 0; - if (dy > 0){ - wheel_delta = -100; - } else if (dy < 0){ - wheel_delta = 100; - } - mac_vars.input_chunk.trans.mouse_wheel = wheel_delta; - + f32 dx = event.scrollingDeltaX; + f32 dy = event.scrollingDeltaY; + mac_vars.input_chunk.trans.mouse_wheel = (i32)(-dy); system_signal_step(0); } @@ -1326,16 +1323,11 @@ main(int arg_count, char **args){ // NOTE(yuval): Initialize clipboard { - mac_vars.clipboard_arena = reserve_arena(mac_vars.tctx); + Scratch_Block scratch(mac_vars.tctx); + mac_post_clipboard(scratch, "", 0); mac_vars.clipboard_change_count = mac_get_clipboard_change_count(); mac_vars.next_clipboard_is_self = false; - // NOTE(yuval): Read the current clipboard - { - Scratch_Block scratch(mac_vars.tctx, Scratch_Share); - mac_read_clipboard_contents(scratch); - } - // NOTE(yuval): Start the clipboard polling timer [NSTimer scheduledTimerWithTimeInterval: 0.5 target:mac_vars.view @@ -1368,7 +1360,7 @@ main(int arg_count, char **args){ Scratch_Block scratch(mac_vars.tctx, Scratch_Share); String_Const_u8 curdir = system_get_path(scratch, SystemPath_CurrentDirectory); curdir = string_mod_replace_character(curdir, '\\', '/'); - app.init(mac_vars.tctx, &target, mac_vars.base_ptr, mac_vars.clipboard_contents, curdir, custom); + app.init(mac_vars.tctx, &target, mac_vars.base_ptr, curdir, custom); } // diff --git a/platform_mac/mac_4ed_functions.mm b/platform_mac/mac_4ed_functions.mm index 135a8f10..3478dede 100644 --- a/platform_mac/mac_4ed_functions.mm +++ b/platform_mac/mac_4ed_functions.mm @@ -440,27 +440,6 @@ system_sleep_sig(){ //////////////////////////////// -function -system_post_clipboard_sig(){ - Arena *arena = &mac_vars.clip_post_arena; - if (arena->base_allocator == 0){ - *arena = make_arena_system(); - } else{ - linalloc_clear(arena); - } - - mac_vars.clip_post.str = push_array(arena, u8, str.size + 1); - if (mac_vars.clip_post.str != 0){ - block_copy(mac_vars.clip_post.str, str.str, str.size); - mac_vars.clip_post.str[str.size] = 0; - mac_vars.clip_post.size = str.size; - } else{ - // NOTE(yuval): Failed to allocate buffer for clipboard post - } -} - -//////////////////////////////// - function system_cli_call_sig(){ b32 result = false; diff --git a/platform_mac/mac_4ed_old.cpp b/platform_mac/mac_4ed_old.cpp deleted file mode 100644 index 81e7ffc3..00000000 --- a/platform_mac/mac_4ed_old.cpp +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 28.06.2017 - * - * Mac C++ layer for 4coder - * - */ - -// TOP - -#define IS_PLAT_LAYER - -#include "4coder_base_types.h" -#include "4coder_API/4coder_version.h" - -#include "4coder_lib/4coder_utf8.h" - -#if defined(FRED_SUPER) -# include "4coder_lib/4coder_arena.h" -# include "4coder_lib/4coder_arena.cpp" -# define FSTRING_IMPLEMENTATION -# include "4coder_lib/4coder_string.h" - -#include "4coder_keycode_extension.h" -# include "4coder_API/4coder_style.h" -# include "4coder_API/4coder_types.h" - -#else -# include "4coder_default_bindings.cpp" -#endif - -#include "osx_objective_c_to_cpp_links.h" - -#include "4ed_math.h" - -#include - -#include "4ed_font.h" -#include "4ed_system.h" -#include "4ed_render_target.h" -#include "4ed_render_format.h" -#include "4ed.h" -#include "4ed_linked_node_macros.h" - -#include "4ed_file_track.h" -#include "4ed_system_shared.h" - -#include "unix_4ed_headers.h" -#include - -#undef external -#undef internal -#include -#define external extern "C" -#define internal static -#include - -#include - -//////////////////////////////// - -#include "4ed_shared_thread_constants.h" -#include "unix_threading_wrapper.h" -#include "mac_semaphore_wrapper.h" - -// TODO(allen): Make an intrinsics header that uses the cracked OS to define a single set of intrinsic names. -#define InterlockedCompareExchange(dest, ex, comp) \ -__sync_val_compare_and_swap((dest), (comp), (ex)) - -//////////////////////////////// - -#define SLASH '/' -#define DLL "so" - -global System_Functions sysfunc; -#include "4ed_shared_library_constants.h" -#include "unix_library_wrapper.h" - -#include "4ed_standard_libraries.cpp" -#include "4ed_coroutine.cpp" -#include "4ed_font.cpp" - -//////////////////////////////// - -struct OSX_Vars{ - Application_Step_Input input; - String clipboard_contents; - b32 keep_running; - - b32 has_prev_time; - u64 prev_time_u; - - File_Track_System track; - void *track_table; - u32 track_table_size; - u32 track_node_size; -}; - -//////////////////////////////// - -OSX_Objective_C_Vars osx_objc; -OSX_Vars osxvars; -global Render_Target target; -global Application_Memory memory_vars; -global Plat_Settings plat_settings; - -global Libraries libraries; -global App_Functions app; -global Custom_API custom_api; - -global Coroutine_System_Auto_Alloc coroutines; - -//////////////////////////////// - -#include "mac_error_box.cpp" - -//////////////////////////////// - -internal -Sys_Get_4ed_Path_Sig(system_get_4ed_path){ - Partition *scratch = &shared_vars.scratch; - Temp_Memory temp = begin_temp_memory(scratch); - char *temp_buffer = push_array(scratch, char, capacity); - i32 size = 0; - u32 buf_size = capacity; - i32 status = _NSGetExecutablePath(temp_buffer, &buf_size); - buf_size = str_size(temp_buffer); - if (status == 0){ - ssize_t ln_len = readlink(temp_buffer, out, capacity); - if (ln_len != -1){ - out[ln_len] = 0; - String str = make_string_cap(out, ln_len, capacity); - remove_last_folder(&str); - terminate_with_null(&str); - size = str.size; - } - else{ - memcpy(out, temp_buffer, buf_size); - String str = make_string_cap(out, buf_size, capacity); - remove_last_folder(&str); - terminate_with_null(&str); - size = str.size; - } - } - end_temp_memory(temp); - return(size); -} - -//#include "mac_fd_check.cpp" -#include "unix_4ed_functions.cpp" - -internal -Sys_Now_Time_Sig(system_now_time){ - f64 t = osx_timer_seconds(); - u64 result = (u64)(t*1000000.f); - return(result); -} - -//////////////////////////////// - -void -osx_log(char *m, i32 l){ - system_log(m, l); -} - -//////////////////////////////// - -internal void -system_schedule_step(void){ - osx_schedule_step(); -} - -//////////////////////////////// - -#include "4ed_work_queues.cpp" - -//////////////////////////////// - -internal -Sys_Show_Mouse_Cursor_Sig(system_show_mouse_cursor){ - switch (show){ - case MouseCursorShow_Never: - { - osx_show_cursor(-1, 0); - }break; - - case MouseCursorShow_Always: - { - osx_show_cursor(1, 0); - }break; - } -} - -internal -Sys_Set_Fullscreen_Sig(system_set_fullscreen){ - osx_objc.do_toggle = (osx_objc.full_screen != full_screen); - return(true); -} - -internal -Sys_Is_Fullscreen_Sig(system_is_fullscreen){ - b32 result = (osx_objc.full_screen != osx_objc.do_toggle); - return(result); -} - -#include "4ed_coroutine_functions.cpp" - -#include "4ed_system_shared.cpp" - -// File Change Listeners - -internal b32 -handle_track_out_of_memory(i32 val){ - b32 result = false; - - switch (val){ - case FileTrack_OutOfTableMemory: - { - u32 new_table_size = osxvars.track_table_size*2; - void *new_table = system_memory_allocate(new_table_size); - move_track_system(&osxvars.track, &shared_vars.scratch, new_table, new_table_size); - system_memory_free(osxvars.track_table, osxvars.track_table_size); - osxvars.track_table_size = new_table_size; - osxvars.track_table = new_table; - }break; - - case FileTrack_OutOfListenerMemory: - { - osxvars.track_node_size *= 2; - void *node_expansion = system_memory_allocate(osxvars.track_node_size); - expand_track_system_listeners(&osxvars.track, &shared_vars.scratch, node_expansion, osxvars.track_node_size); - }break; - - default: result = true; break; - } - - return(result); -} - -internal -Sys_Add_Listener_Sig(system_add_listener){ - b32 result = false; - for (;;){ - i32 track_result = add_listener(&osxvars.track, &shared_vars.scratch, (u8*)filename); - if (handle_track_out_of_memory(track_result)){ - if (track_result == FileTrack_Good){ - result = true; - } - break; - } - } - return(result); -} - -internal -Sys_Remove_Listener_Sig(system_remove_listener){ - b32 result = false; - i32 track_result = remove_listener(&osxvars.track, &shared_vars.scratch, (u8*)filename); - if (track_result == FileTrack_Good){ - result = true; - } - return(result); -} - -internal -Sys_Get_File_Change_Sig(system_get_file_change){ - b32 result = false; - - i32 size = 0; - i32 get_result = get_change_event(&osxvars.track, &shared_vars.scratch, (u8*)buffer, max, &size); - - *required_size = size; - *mem_too_small = false; - if (get_result == FileTrack_Good){ - result = true; - } - else if (get_result == FileTrack_MemoryTooSmall){ - *mem_too_small = true; - result = true; - } - - return(result); -} - - -// -// Clipboard -// - -internal -Sys_Post_Clipboard_Sig(system_post_clipboard){ - char *string = str.str; - if (!terminate_with_null(&str)){ - if (osx_objc.clipboard_space_max <= str.size + 1){ - if (osx_objc.clipboard_space != 0){ - system_memory_free(osx_objc.clipboard_space, osx_objc.clipboard_space_max); - } - osx_objc.clipboard_space_max = l_round_up_u32(str.size*2 + 1, KB(4096)); - osx_objc.clipboard_space = (char*)system_memory_allocate(osx_objc.clipboard_space_max); - } - memcpy(osx_objc.clipboard_space, str.str, str.size); - osx_objc.clipboard_space[str.size] = 0; - string = osx_objc.clipboard_space; - } - osx_post_to_clipboard(string); -} - -// -// CLI -// - -// HACK(allen): ALMOST an exact duplicate from the Linux version. Just epoll doesn't port. deduplicate or switch to NSTask. -global i32 cli_count = 0; - -internal -Sys_CLI_Call_Sig(system_cli_call, path, script_name, cli_out){ - i32 pipe_fds[2]; - if (pipe(pipe_fds) == -1){ - - return 0; - } - - i32 child_pid = fork(); - if (child_pid == -1){ - - return 0; - } - - enum { PIPE_FD_READ, PIPE_FD_WRITE }; - - // child - if (child_pid == 0){ - close(pipe_fds[PIPE_FD_READ]); - dup2(pipe_fds[PIPE_FD_WRITE], STDOUT_FILENO); - dup2(pipe_fds[PIPE_FD_WRITE], STDERR_FILENO); - - if (chdir(path) == -1){ - - exit(1); - } - - char* argv[] = { - "sh", - "-c", - script_name, - 0 - }; - - if (execv("/bin/sh", argv) == -1){ - - } - exit(1); - } - else{ - close(pipe_fds[PIPE_FD_WRITE]); - - *(pid_t*)&cli_out->proc = child_pid; - *(int*)&cli_out->out_read = pipe_fds[PIPE_FD_READ]; - *(int*)&cli_out->out_write = pipe_fds[PIPE_FD_WRITE]; - - ++cli_count; - } - - return(true); -} - -internal -Sys_CLI_Begin_Update_Sig(system_cli_begin_update){ - // NOTE(inso): I don't think anything needs to be done here. -} - -internal -Sys_CLI_Update_Step_Sig(system_cli_update_step){ - i32 pipe_read_fd = *(i32*)&cli->out_read; - - fd_set fds; - FD_ZERO(&fds); - FD_SET(pipe_read_fd, &fds); - - struct timeval tv = {}; - - size_t space_left = max; - char* ptr = dest; - - while (space_left > 0 && select(pipe_read_fd + 1, &fds, NULL, NULL, &tv) == 1){ - ssize_t num = read(pipe_read_fd, ptr, space_left); - if (num == -1){ - - } else if (num == 0){ - // NOTE(inso): EOF - break; - } else { - ptr += num; - space_left -= num; - } - } - - *amount = (ptr - dest); - return((ptr - dest) > 0); -} - -internal -Sys_CLI_End_Update_Sig(system_cli_end_update){ - pid_t pid = *(pid_t*)&cli->proc; - b32 close_me = false; - - int status; - if (pid && waitpid(pid, &status, WNOHANG) > 0){ - close_me = true; - - cli->exit = WEXITSTATUS(status); - - close(*(int*)&cli->out_read); - close(*(int*)&cli->out_write); - - --cli_count; - } - - return(close_me); -} - -#include "4ed_font_provider_freetype.h" -global u32 system_font_method = SystemFontMethod_FilePath; -#include "4ed_font_provider_freetype.cpp" - -internal -Sys_Font_Path(name, parameters){ - b32 italic = (parameters != 0 && parameters->italics); - b32 bold = (parameters != 0 && parameters->bold); - i32 pt_size = 12; - if (parameters != 0){ - pt_size = parameters->pt_size; - } - - OSX_Font_Match match = osx_get_font_match(name, pt_size, italic, bold); - - Font_Path path = {}; - Partition *part = &shared_vars.font_scratch; - path.temp = begin_temp_memory(part); - - if (match.path != 0){ - i32 len = str_size(match.path); - char *buffer = push_array(part, char, len + 1); - if (buffer == 0){ - sysshared_partition_grow(part, l_round_up_i32(len + 1, KB(4))); - buffer = push_array(part, char, len + 1); - } - - if (buffer != 0){ - push_align(part, 8); - memcpy(buffer, match.path, len + 1); - path.len = len; - path.name = buffer; - } - } - - return(path); -} - -Sys_Font_Data_Not_Used; - -internal void -osx_get_loadable_fonts(Partition *part, Font_Setup_List *list){ - OSX_Loadable_Fonts fonts = osx_list_loadable_fonts(); - for (i32 i = 0; i < fonts.count; ++i){ - char *name = fonts.names[i]; - char *path = fonts.paths[i]; - - if (name == 0 || path == 0){ - continue; - } - - Temp_Memory reset= begin_temp_memory(part); - Font_Setup *setup = push_array(part, Font_Setup, 1); - - if (setup != 0){ - memset(setup, 0, sizeof(*setup)); - - i32 len = str_size(path); - if (len < sizeof(setup->stub.name)){ - i32 name_len = str_size(name); - if (name_len < sizeof(setup->name)){ - setup->stub.load_from_path = true; - memcpy(setup->stub.name, path, len + 1); - setup->stub.len = len; - setup->has_display_name = true; - setup->len = name_len; - memcpy(setup->name, name, name_len + 1); - sll_push(list->first, list->last, setup); - } - else{ - end_temp_memory(reset); - } - } - else{ - end_temp_memory(reset); - } - } - } - - free(fonts.names); -} - -#include -#include -#include "opengl/4ed_opengl_render.cpp" - -//////////////////////////////// - -#include "4ed_link_system_functions.cpp" -#include "4ed_shared_init_logic.cpp" - -external void* -osx_allocate(u64 size){ - void *result = system_memory_allocate(size); - return(result); -} - -external void -osx_free(void *ptr, u64 size){ - system_memory_free(ptr, size); -} - -external void -osx_resize(int width, int height){ - if (width > 0 && height > 0){ - osx_objc.width = width; - osx_objc.height = height; - - target.width = width; - target.height = height; - - osx_schedule_step(); - } -} - -internal void -osx_push_key(Key_Code code, Key_Code chr, Key_Code chr_nocaps, b8 *mods){ - i32 count = osxvars.input.keys.count; - - if (count < KEY_INPUT_BUFFER_SIZE){ - Key_Event_Data *data = osxvars.input.keys.keys; - - data[count].keycode = code; - data[count].character = chr; - data[count].character_no_caps_lock = chr_nocaps; - - memcpy(data[count].modifiers, mods, sizeof(*mods)*MDFR_INDEX_COUNT); - - osxvars.input.keys.count = count + 1; - } -} - -internal void -osx_mods_struct_to_array(OSX_Keyboard_Modifiers flags, b8 *mods){ - mods[MDFR_SHIFT_INDEX] = ((flags.shift) != 0); - mods[MDFR_CONTROL_INDEX] = ((flags.control) != 0); - mods[MDFR_ALT_INDEX] = ((flags.option) != 0); - mods[MDFR_COMMAND_INDEX] = ((flags.command) != 0); - mods[MDFR_CAPS_INDEX] = ((flags.caps) != 0); -} - -external void -osx_character_input(u32 code, OSX_Keyboard_Modifiers modifier_flags){ - Key_Code c = 0; - switch (code){ - // TODO(allen): Find the canonical list of these things. - case 0x007F: c = key_back; break; - case 0xF700: c = key_up; break; - case 0xF701: c = key_down; break; - case 0xF702: c = key_left; break; - case 0xF703: c = key_right; break; - case 0xF728: c = key_del; break; - case 0xF729: c = key_home; break; - case 0xF72B: c = key_end; break; - case 0xF72C: c = key_page_up; break; - case 0xF72D: c = key_page_down; break; - case 0x001B: c = key_esc; break; - - case 0xF704: c = key_f1; break; - case 0xF705: c = key_f2; break; - case 0xF706: c = key_f3; break; - case 0xF707: c = key_f4; break; - - case 0xF708: c = key_f5; break; - case 0xF709: c = key_f6; break; - case 0xF70A: c = key_f7; break; - case 0xF70B: c = key_f8; break; - - case 0xF70C: c = key_f9; break; - case 0xF70D: c = key_f10; break; - case 0xF70E: c = key_f11; break; - case 0xF70F: c = key_f12; break; - - case 0xF710: c = key_f13; break; - case 0xF711: c = key_f14; break; - case 0xF712: c = key_f15; break; - case 0xF713: c = key_f16; break; - } - - b8 mods[MDFR_INDEX_COUNT] = {}; - osx_mods_struct_to_array(modifier_flags, mods); - - if (c != 0){ - osx_push_key(c, 0, 0, mods); - } - else if (code != 0){ - if (code < 0xE000 || code > 0xF8FF){ - if (code == '\r'){ - code = '\n'; - } - Key_Code chr = code; - Key_Code nocaps = code; - if (modifier_flags.caps){ - if ('a' <= nocaps && nocaps <= 'z'){ - chr += 'A' - 'a'; - } - else if ('A' <= nocaps && nocaps <= 'Z'){ - chr += 'a' - 'A'; - } - } - osx_push_key(code, chr, nocaps, mods); - } - else{ - fprintf(stdout, "unhandled private code %x\n", code); - } - } - else{ - osx_push_key(0, 0, 0, mods); - } - - osx_schedule_step(); -} - -external void -osx_mouse(i32 mx, i32 my, u32 type){ - i32 new_x = mx; - i32 new_y = osx_objc.height - my; - if (new_x != osxvars.input.mouse.x || new_y != osxvars.input.mouse.y){ - osxvars.input.mouse.x = new_x; - osxvars.input.mouse.y = new_y; - osx_schedule_step(); - } - - if (type == MouseType_Press){ - osxvars.input.mouse.press_l = true; - osxvars.input.mouse.l = true; - osx_schedule_step(); - } - if (type == MouseType_Release){ - osxvars.input.mouse.release_l = true; - osxvars.input.mouse.l = false; - osx_schedule_step(); - } -} - -external void -osx_mouse_wheel(float dx, float dy){ - osxvars.input.mouse.wheel = - (int32_t)(dy); - osx_schedule_step(); -} - -external void -osx_try_to_close(void){ - osxvars.keep_running = false; - osx_schedule_step(); -} - -external void -osx_step(void){ - - Application_Step_Result result = {}; - - // NOTE(allen): Prepare the Frame Input - osxvars.input.dt = 1.f/60.f; - if (osxvars.has_prev_time){ - u64 time_u = system_now_time(); - u64 time_elapsed_u = time_u - osxvars.prev_time_u; - osxvars.input.dt = time_elapsed_u/1000000.f; - osxvars.prev_time_u = time_u; - } - else{ - osxvars.has_prev_time = true; - osxvars.prev_time_u = system_now_time(); - } - - // TODO(allen): CROSS REFERENCE WITH WINDOWS SPECIAL CODE "TIC898989" - Application_Step_Input frame_input = osxvars.input; - frame_input.trying_to_kill = !osxvars.keep_running; - OSX_Keyboard_Modifiers mods = osx_get_modifiers(); - osx_mods_struct_to_array(mods, frame_input.keys.modifiers); - - osxvars.input.first_step = false; - memset(&osxvars.input.keys, 0, sizeof(osxvars.input.keys)); - osxvars.input.mouse.press_l = false; - osxvars.input.mouse.release_l = false; - osxvars.input.mouse.press_r = false; - osxvars.input.mouse.release_r = false; - osxvars.input.mouse.wheel = 0; - - - // NOTE(allen): Frame Clipboard Input - if (osx_objc.has_clipboard_item){ - frame_input.clipboard = make_string(osx_objc.clipboard_data, (i32)osx_objc.clipboard_size); - } - else{ - frame_input.clipboard = null_string; - } - - // HACK(allen): Got this all messed up with respect to how everyone else (other OS layers) work - osx_objc.do_toggle = false; - osx_objc.full_screen = osx_is_fullscreen(); - - // HACK(allen): THIS SHIT IS FUCKED (happens on linux too) - b32 keep_running = osxvars.keep_running; - - // NOTE(allen): Application Core Update - target.buffer.pos = 0; - if (app.step != 0){ - result = app.step(&sysfunc, &target, &memory_vars, &frame_input); - } - else{ - //LOG("app.step == 0 -- skipping\n"); - } - - // NOTE(allen): Finish the Loop - if (result.perform_kill){ - osx_close_app(); - } - else if (!keep_running && !osxvars.keep_running){ - osxvars.keep_running = true; - } - - // NOTE(allen): Switch to New Title - if (result.has_new_title){ - osx_change_title(result.title_string); - } - - // NOTE(allen): Switch to New Cursor - osx_show_cursor(0, result.mouse_cursor_type); - - // NOTE(allen): Render - osx_begin_render(); - gl_render(&target, &shared_vars.pixel_scratch); - osx_end_render(); - - // NOTE(allen): Toggle Full Screen - if (osx_objc.do_toggle){ - osx_toggle_fullscreen(); - } - - // NOTE(allen): Schedule Another Step if Needed - if (result.animating || cli_count > 0){ - osx_schedule_step(); - } -} - -external void -osx_init(){ - // - // System Linkage - // - - link_system_code(); - - // - // Memory init - // - - memset(&target, 0, sizeof(target)); - memset(&memory_vars, 0, sizeof(memory_vars)); - memset(&plat_settings, 0, sizeof(plat_settings)); - - memset(&libraries, 0, sizeof(libraries)); - memset(&app, 0, sizeof(app)); - memset(&custom_api, 0, sizeof(custom_api)); - - memory_init(); - - osxvars.keep_running = true; - osxvars.input.first_step = true; - - // - // HACK(allen): - // Previously zipped stuff is here, it should be zipped in the new pattern now. - // - - init_shared_vars(); - - osxvars.track_table_size = KB(16); - osxvars.track_table = system_memory_allocate(osxvars.track_table_size); - - osxvars.track_node_size = KB(16); - void *track_nodes = system_memory_allocate(osxvars.track_node_size); - - i32 track_result = init_track_system(&osxvars.track, &shared_vars.scratch, - osxvars.track_table, osxvars.track_table_size, - track_nodes, osxvars.track_node_size); - - if (track_result != FileTrack_Good){ - exit(1); - } - - // - // Load Core Code - // - load_app_code(); - - // - // Read command line - // - read_command_line(osx_objc.argc, osx_objc.argv); - - // - // Load Custom Code - // -#if defined(FRED_SUPER) - load_custom_code(); -#else - DontCompile; -#endif - - // - // Threads - // - - work_system_init(); - - // - // Coroutines - // - - coroutines_init(); - - // - // Font System Init - // - - Partition *scratch = &shared_vars.scratch; - Temp_Memory temp = begin_temp_memory(scratch); - Font_Setup_List font_setup = system_font_get_local_stubs(scratch); - osx_get_loadable_fonts(scratch, &font_setup); - system_font_init(&sysfunc.font, plat_settings.font_size, plat_settings.use_hinting, font_setup); - end_temp_memory(temp); - - // - // App Init - // - - char cwd[4096]; - u32 size = sysfunc.get_current_path(cwd, sizeof(cwd)); - if (size == 0 || size >= sizeof(cwd)){ - system_error_box("Could not get current directory at launch."); - } - String curdir = make_string(cwd, size); - terminate_with_null(&curdir); - replace_char(&curdir, '\\', '/'); - - - - String clipboard_string = {}; - if (osx_objc.has_clipboard_item){ - clipboard_string = make_string(osx_objc.clipboard_data, osx_objc.clipboard_size); - } - - //LOG("Initializing application variables\n"); - app.init(&sysfunc, &target, &memory_vars, clipboard_string, curdir, custom_api); -} - -#include "mac_4ed_file_track.cpp" - -// BOTTOM - diff --git a/platform_mac/mac_4ed_old.m b/platform_mac/mac_4ed_old.m deleted file mode 100644 index fad0565e..00000000 --- a/platform_mac/mac_4ed_old.m +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 28.06.2017 - * - * Mac Objective C layer for 4coder - * - */ - -// TOP - -#define IS_OBJC_LAYER - -#include "4coder_base_types.h" - -#include "4coder_API/4coder_version.h" - -#include "4ed_cursor_codes.h" -#include "4ed_linked_node_macros.h" - -#undef global -#undef external -#define external - -#include "osx_objective_c_to_cpp_links.h" - -#include -#import -#import -#import -#import -#import - -#include -#include -#include -#include - -#include - -void -osx_post_to_clipboard(char *str){ - NSPasteboard *board = [NSPasteboard generalPasteboard]; - NSString *utf8_type = @"public.utf8-plain-text"; - NSArray *typesArray = [NSArray arrayWithObjects: utf8_type, nil]; - [board declareTypes:typesArray owner:nil]; - NSString *paste_string = [NSString stringWithUTF8String:str]; - [board setString:paste_string forType:utf8_type]; - osx_objc.just_posted_to_clipboard = true; -} - - -void -osx_error_dialogue(char *str){ - NSAlert *alert = [[NSAlert alloc] init]; - [alert addButtonWithTitle:@"OK"]; - NSString *text = [NSString stringWithUTF8String:str]; - [alert setMessageText:text]; - [alert setAlertStyle:NSCriticalAlertStyle]; - [alert runModal]; -} - -// -// Entry point, OpenGL window setup. -// - -@interface AppDelegate : NSObject -@end - -@interface My4coderView : NSOpenGLView{ - @public - //CVDisplayLinkRef displayLink; -} - -- (void)requestDisplay; -- (void)checkClipboard; -- (CVReturn)getFrame; -- (void)drawRect:(NSRect)bounds; -@end - -#define DISPLINK_SIG(n) CVReturn n(CVDisplayLinkRef link, const CVTimeStamp *now, const CVTimeStamp *output, CVOptionFlags flags_in, CVOptionFlags *flags_out, void *context) -static DISPLINK_SIG(osx_display_link); - -static OSX_Keyboard_Modifiers -osx_mods_nsevent_to_struct(NSEventModifierFlags flags){ - OSX_Keyboard_Modifiers mods = {}; - mods.shift = ((flags & NSEventModifierFlagShift) != 0); - mods.command = ((flags & NSEventModifierFlagCommand) != 0); - mods.control = ((flags & NSEventModifierFlagControl) != 0); - mods.option = ((flags & NSEventModifierFlagOption) != 0); - mods.caps = ((flags & NSEventModifierFlagCapsLock) != 0); - return(mods); -} - -@implementation My4coderView - -- (void)keyDown:(NSEvent *)event{ - NSString *real = [event charactersIgnoringModifiers]; - NSString *with_mods = [event characters]; - - b32 is_dead_key = false; - if (real && !with_mods){ - is_dead_key = true; - } - - OSX_Keyboard_Modifiers mods = osx_get_modifiers(); - - // TODO(allen): Not ideal solution, look for realer text - // input on Mac. This just makes sure we're getting good - // results for unmodified keys when cmnd and ctrl aren't down. - NSString *which = with_mods; - if (mods.command || mods.control){ - which = real; - } - - u32 length = which.length; - for (u32 i = 0; i < length; ++i){ - unichar c = [which characterAtIndex:i]; - osx_character_input(c, mods); - } -} - -- (void)mouseDown:(NSEvent*)event{ - NSPoint m = [event locationInWindow]; - osx_mouse(m.x, m.y, MouseType_Press); -} - -- (void)mouseDragged:(NSEvent*)event{ - NSPoint m = [event locationInWindow]; - osx_mouse(m.x, m.y, MouseType_Move); -} - -- (void)mouseMoved:(NSEvent*)event{ - NSPoint m = [event locationInWindow]; - osx_mouse(m.x, m.y, MouseType_Move); -} - -- (void)mouseUp:(NSEvent*)event{ - NSPoint m = [event locationInWindow]; - osx_mouse(m.x, m.y, MouseType_Release); -} - -- (void)scrollWheel:(NSEvent*)event{ - float dx = event.scrollingDeltaX; - float dy = event.scrollingDeltaY; - osx_mouse_wheel(dx, dy); -} - -- (BOOL)windowShouldClose:(NSWindow*)sender{ - osx_try_to_close(); - return(NO); -} - -- (void)requestDisplay{ - CGRect cg_rect = CGRectMake(0, 0, osx_objc.width, osx_objc.height); - NSRect rect = NSRectFromCGRect(cg_rect); - [self setNeedsDisplayInRect:rect]; -} - -static i32 did_update_for_clipboard = true; -- (void)checkClipboard{ - NSPasteboard *board = [NSPasteboard generalPasteboard]; - if (board.changeCount != osx_objc.prev_clipboard_change_count && did_update_for_clipboard){ - [self requestDisplay]; - did_update_for_clipboard = false; - } -} - -- (CVReturn)getFrame{ - did_update_for_clipboard = true; - - @autoreleasepool - { - if (osx_objc.running){ - osx_objc.has_clipboard_item = false; - NSPasteboard *board = [NSPasteboard generalPasteboard]; - if (board.changeCount != osx_objc.prev_clipboard_change_count){ - if (!osx_objc.just_posted_to_clipboard){ - NSString *utf8_type = @"public.utf8-plain-text"; - NSArray *array = [NSArray arrayWithObjects: utf8_type, nil]; - NSString *has_string = [board availableTypeFromArray:array]; - if (has_string != nil){ - NSData *data = [board dataForType: utf8_type]; - if (data != nil){ - u32 copy_length = data.length; - if (copy_length > 0){ - if (copy_length + 1 > osx_objc.clipboard_max){ - osx_free(osx_objc.clipboard_data, osx_objc.clipboard_max); - osx_objc.clipboard_max = l_round_up_u32(copy_length + 1, KB(4)); - osx_objc.clipboard_data = osx_allocate(osx_objc.clipboard_max); - } - - if (copy_length + 1 < osx_objc.clipboard_max){ - osx_objc.clipboard_size = copy_length; - [data - getBytes: osx_objc.clipboard_data - length: copy_length]; - ((char*)osx_objc.clipboard_data)[copy_length] = 0; - osx_objc.has_clipboard_item = true; - } - } - } - } - } - else{ - osx_objc.just_posted_to_clipboard = false; - } - osx_objc.prev_clipboard_change_count = board.changeCount; - } - - osx_step(); - } - } - return kCVReturnSuccess; -} - -- (void)reshape -{ - [super reshape]; - - NSRect rect = [self bounds]; - osx_resize(rect.size.width, rect.size.height); -} - -- (void)init_gl -{ - if (osx_objc.gl_is_initialized){ - return; - } - - [self setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - - NSOpenGLPixelFormatAttribute attrs[] = { - NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy, - NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFAAccelerated, - NSOpenGLPFADoubleBuffer, - 0 - }; - - NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; - if(format == nil){ - fprintf(stderr, "Error creating OpenGLPixelFormat\n"); - exit(1); - } - - NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil]; - - [self setPixelFormat:format]; - [self setOpenGLContext:context]; - - [context makeCurrentContext]; - - osx_objc.gl_is_initialized = true; -} - -- (id)init -{ - self = [super init]; - if(self == nil) - { - return nil; - } - - [self init_gl]; - return self; -} - -- (void)drawRect: (NSRect) bounds{ - [self getFrame]; -} - -- (void)awakeFromNib -{ - [self init_gl]; -} - -- (void)prepareOpenGL -{ - [super prepareOpenGL]; - - [[self openGLContext] makeCurrentContext]; - - GLint swapInt = 1; - [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; -} - -- (void)dealloc -{ - [super dealloc]; -} - -- (BOOL)acceptsFirstResponder -{ - return YES; -} - -- (BOOL)becomeFirstResponder -{ - return YES; -} - -- (BOOL)resignFirstResponder -{ - return YES; -} -@end - -@implementation AppDelegate -- (void)applicationDidFinishLaunching:(id)sender -{ -} -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)sender -{ - return YES; -} -- (void)applicationWillTerminate:(NSApplication*)sender -{ -} -@end - -////////////////// - -typedef struct File_Change_Node File_Change_Node; -struct File_Change_Node{ - File_Change_Node *next; - char *name; - i32 len; -}; - -typedef struct{ - File_Change_Node *first; - File_Change_Node *last; - volatile i64 lock; -} File_Change_Queue; - -static File_Change_Queue file_queue = {}; - -File_Change_Node* -file_change_node(char *name){ - i32 len = strlen(name); - void *block = malloc(len + 1 + sizeof(File_Change_Node)); - File_Change_Node *node = (File_Change_Node*)block; - memset(node, 0, sizeof(*node)); - node->name = (char*)(node + 1); - node->len = len; - memcpy(node->name, name, len + 1); - return(node); -} - -void -file_change_node_free(File_Change_Node *node){ - free(node); -} - -#define file_queue_lock() for(;;){i64 v=__sync_val_compare_and_swap(&file_queue.lock,0,1);if(v==0){break;}} - -#define file_queue_unlock() __sync_lock_test_and_set(&file_queue.lock, 0) - -void -file_watch_callback(ConstFSEventStreamRef stream, void *callbackInfo, size_t numEvents, void *evPaths, const FSEventStreamEventFlags *evFlags, const FSEventStreamEventId *evIds){ - char **paths = (char**)evPaths; - for (int i = 0; i < numEvents; ++i){ - File_Change_Node *node = file_change_node(paths[i]); - file_queue_lock(); - sll_push(file_queue.first, file_queue.last, node); - file_queue_unlock(); - } -} - -////////////////// - -typedef struct{ - FSEventStreamRef stream; -} File_Watching_Handle; - -File_Watching_Handle -schedule_file_watching(char *f){ - File_Watching_Handle handle = {}; - - CFStringRef arg = CFStringCreateWithCString(0, f, kCFStringEncodingUTF8); - - CFArrayRef paths = CFArrayCreate(0, (const void**)&arg, 1, 0); - - void *callbackInfo = 0; - CFAbsoluteTime latency = 2.0; - - handle.stream = FSEventStreamCreate(0, &file_watch_callback, 0, paths, kFSEventStreamEventIdSinceNow, latency, kFSEventStreamCreateFlagFileEvents); - - FSEventStreamScheduleWithRunLoop(handle.stream, CFRunLoopGetMain(), kCFRunLoopDefaultMode); - - if (!FSEventStreamStart(handle.stream)){ - fprintf(stdout, "BAD SCHED: %s\n", f); - } - - return(handle); -} - -void -unschedule_file_watching(File_Watching_Handle handle){ - FSEventStreamStop(handle.stream); - FSEventStreamInvalidate(handle.stream); - FSEventStreamRelease(handle.stream); -} - -typedef struct File_Table_Entry{ - u64 hash; - void *name; - i32 counter; - File_Watching_Handle handle; -} File_Table_Entry; - -typedef struct File_Change_Table{ - File_Table_Entry *table; - i32 count; - i32 size; -} File_Change_Table; - -static File_Change_Table file_change_table = {}; - -void* -osx_file_name_prefixed_length(char *name){ - i32 len = 0; - for (; name[len] != 0; ++len); - char *name_stored = (char*)malloc(4 + l_round_up_u32(len + 1, 4)); - *(i32*)name_stored = len; - memcpy(name_stored + 4, name, len); - name_stored[4 + len] = 0; - return(name_stored); -} - -b32 -osx_name_prefixed_match(void *a, void *b){ - b32 result = false; - i32 *len_a = (i32*)a; - i32 *len_b = (i32*)b; - if (*len_a == *len_b){ - char *str_a = (char*)(len_a + 1); - char *str_b = (char*)(len_b + 1); - if (strncmp(str_a, str_b, *len_a) == 0){ - result = true; - } - } - return(result); -} - -File_Table_Entry* -osx_file_listener_lookup_and_return_pointer(u64 hash, void *name){ - File_Table_Entry *result = 0; - i32 index = (i32)(hash % file_change_table.size); - i32 first_index = index; - - for (;;){ - File_Table_Entry *entry = &file_change_table.table[index]; - if (entry->hash == hash){ - if (osx_name_prefixed_match(name, entry->name)){ - result = entry; - break; - } - } - if (entry->name == 0){ - break; - } - - index = (index + 1)%file_change_table.size; - if (index == first_index){ - break; - } - } - - return(result); -} - -void -osx_file_listener_table_entry_erase(File_Table_Entry *entry){ - free(entry->name); - unschedule_file_watching(entry->handle); - memset(entry, 0, sizeof(*entry)); - entry->name = (void*)1; -} - -b32 -osx_file_listener_lookup_and_decrement(u64 hash, void *name){ - b32 found = false; - File_Table_Entry *entry = osx_file_listener_lookup_and_return_pointer(hash, name); - if (entry != 0){ - found = true; - --entry->counter; - if (entry->counter <= 0){ - osx_file_listener_table_entry_erase(entry); - } - } - return(found); -} - -b32 -osx_file_listener_hash(u64 hash, void *name, i32 counter, File_Watching_Handle **handle_address_out){ - b32 result = 0; - if (file_change_table.count*6 < file_change_table.size*5){ - i32 index = (i32)(hash % file_change_table.size); - i32 first_index = index; - - for (;;){ - File_Table_Entry *entry = &file_change_table.table[index]; - if (entry->name == 0 || entry->name == (void*)1){ - entry->hash = hash; - entry->name = name; - entry->counter = counter; - *handle_address_out = &entry->handle; - result = true; - ++file_change_table.count; - break; - } - - index = (index + 1)%file_change_table.size; - if (index == first_index){ - break; - } - } - - if (!result){ - //LOG("file change listener table error: could not find a free slot in the table\n"); - } - } - - return(result); -} - -void -osx_file_listener_grow_table(i32 size){ - if (file_change_table.size < size){ - File_Table_Entry *old_table = file_change_table.table; - i32 old_size = file_change_table.size; - - file_change_table.table = (File_Table_Entry*)osx_allocate(size*sizeof(File_Table_Entry)); - memset(file_change_table.table, 0, size*sizeof(File_Table_Entry)); - file_change_table.size = size; - - for (i32 i = 0; i < old_size; ++i){ - void *name = file_change_table.table[i].name; - if (name != 0 && name != (void*)1){ - File_Table_Entry *e = &file_change_table.table[i]; - File_Watching_Handle *handle_address = 0; - osx_file_listener_hash(e->hash, e->name, e->counter, &handle_address); - *handle_address = e->handle; - } - } - - if (old_table != 0){ - osx_free(old_table, old_size*sizeof(File_Table_Entry)); - } - } -} - -void -osx_file_listener_double_table(){ - osx_file_listener_grow_table(file_change_table.size*2); -} - -b32 -osx_file_listener_insert_or_increment_always(u64 hash, void *name, File_Watching_Handle **handle_address_out){ - b32 was_already_in_table = false; - File_Table_Entry *entry = osx_file_listener_lookup_and_return_pointer(hash, name); - if (entry != 0){ - ++entry->counter; - was_already_in_table = true; - } - else{ - b32 result = osx_file_listener_hash(hash, name, 1, handle_address_out); - if (!result){ - osx_file_listener_double_table(); - osx_file_listener_hash(hash, name, 1, handle_address_out); - } - } - return(was_already_in_table); -} - -u64 -osx_get_file_hash(void *name){ - u32 count = *(u32*)(name); - char *str = (char*)name + 4; - u64 hash = 0; - u64 state = count; - u64 inc = 1 + 2*count; - for (u32 i = 0; i <= count; ++i){ - u64 old_state = state; - state = state*6364136223846783005ULL + inc; - u32 xorshifted = ((old_state >> 18u) ^ old_state) >> 27u; - u32 rot = old_state >> 59u; - hash = (hash << 3) + (hash & 1) + ((xorshifted >> rot) | (xorshifted << ((-rot) & 31))); - if (i < count){ - inc = 1 + 2*(((inc - 1) << 7) | (u8)str[i]); - } - } - return(hash); -} - -void -osx_file_listener_init(void){ - osx_file_listener_grow_table(4096); -} - -void -osx_add_file_listener(char *dir_name){ - // TODO(allen): Decide what to do about these darn string mallocs. - void *name_stored = osx_file_name_prefixed_length(dir_name); - File_Watching_Handle *handle_address = 0; - b32 was_already_in_table = osx_file_listener_insert_or_increment_always(osx_get_file_hash(name_stored), name_stored, &handle_address); - if (was_already_in_table){ - free(name_stored); - } - else{ - *handle_address = schedule_file_watching(dir_name); - } -} - -void -osx_remove_file_listener(char *dir_name){ - void *name_stored = osx_file_name_prefixed_length(dir_name); - osx_file_listener_lookup_and_decrement(osx_get_file_hash(name_stored), name_stored); - free(name_stored); -} - -i32 -osx_get_file_change_event(char *buffer, i32 max, i32 *size){ - file_queue_lock(); - File_Change_Node *node = file_queue.first; - sll_pop(file_queue.first, file_queue.last); - file_queue_unlock(); - - i32 result = 0; - if (node != 0){ - if (node->len < max){ - result = 1; - memcpy(buffer, node->name, node->len); - *size = node->len; - } - else{ - result = -1; - // TODO(allen): Somehow save the node? - } - file_change_node_free(node); - } - - return(result); -} - -void -osx_show_cursor(i32 show, i32 cursor_type){ - local_persist b32 cursor_is_shown = 1; - if (show == 1){ - if (!cursor_is_shown){ - [NSCursor unhide]; - cursor_is_shown = true; - } - } - else if (show == -1){ - if (cursor_is_shown){ - [NSCursor hide]; - cursor_is_shown = false; - } - } - - if (cursor_type > 0){ - switch (cursor_type){ - case APP_MOUSE_CURSOR_ARROW: - { - [[NSCursor arrowCursor] set]; - }break; - - case APP_MOUSE_CURSOR_IBEAM: - { - [[NSCursor IBeamCursor] set]; - }break; - - case APP_MOUSE_CURSOR_LEFTRIGHT: - { - [[NSCursor resizeLeftRightCursor] set]; - }break; - - case APP_MOUSE_CURSOR_UPDOWN: - { - [[NSCursor resizeUpDownCursor] set]; - }break; - } - } -} - -My4coderView* view = 0; -NSWindow* window = 0; - -void -osx_begin_render(){ - CGLLockContext([[view openGLContext] CGLContextObj]); - [[view openGLContext] makeCurrentContext]; -} - -void -osx_end_render(){ - [[view openGLContext] flushBuffer]; - CGLUnlockContext([[view openGLContext] CGLContextObj]); -} - -void -osx_schedule_step(void){ - [NSTimer scheduledTimerWithTimeInterval: 0.0 - target: view - selector: @selector(requestDisplay) - userInfo: nil repeats:NO]; -} - -void -osx_toggle_fullscreen(void){ - [window toggleFullScreen:nil]; -} - -b32 -osx_is_fullscreen(void){ - b32 result = (([window styleMask] & NSFullScreenWindowMask) != 0); - return(result); -} - -void -osx_close_app(void){ - [NSApp terminate: nil]; -} - -f32 -osx_timer_seconds(void){ - f32 result = CACurrentMediaTime(); - return(result); -} - -NSFontManager *font_manager = 0; - -NSString *get_font_path(NSFont *font){ - CFStringRef name = (CFStringRef)[font fontName]; - CGFloat size = [font pointSize]; - CTFontDescriptorRef ref = CTFontDescriptorCreateWithNameAndSize(name, size); - CFURLRef url = CTFontDescriptorCopyAttribute(ref, kCTFontURLAttribute); - NSString *path = [(NSURL *)CFBridgingRelease(url) path]; - return(path); -} - -OSX_Font_Match -osx_get_font_match(char *name, i32 pt_size, b32 italic, b32 bold){ - if (font_manager == 0){ - font_manager = [NSFontManager sharedFontManager]; - } - - NSString *name_string = [NSString stringWithUTF8String:name]; - NSFontTraitMask trait_mask = 0; - if (italic){ - trait_mask = (trait_mask | NSItalicFontMask); - } - NSInteger weight = 5; - if (bold){ - weight = 9; - } - - b32 used_base_file = false; - NSFont *font = [font_manager - fontWithFamily: name_string - traits: trait_mask - weight: weight - size:(float)pt_size]; - - if (font == nil){ - font = [font_manager - fontWithFamily: name_string - traits: 0 - weight: 5 - size:(float)pt_size]; - used_base_file = true; - } - - OSX_Font_Match match = {}; - if (font != nil){ - NSString *path = get_font_path(font); - char *path_c = 0; - if (path != nil){ - path_c = (char*)[path UTF8String]; - } - if (path_c != 0){ - match.path = path_c; - match.used_base_file = used_base_file; - } - } - - return(match); -} - -OSX_Loadable_Fonts -osx_list_loadable_fonts(void){ - if (font_manager == 0){ - font_manager = [NSFontManager sharedFontManager]; - } - - NSArray *fonts = [font_manager availableFontFamilies]; - - OSX_Loadable_Fonts result = {}; - NSUInteger count_u = [fonts count]; - int count = (int)count_u; - - result.count = count; - - size_t memsize = count*2*sizeof(char*); - void *mem = malloc(memsize); - result.names = (char**)mem; - result.paths = result.names + count; - - for (int i = 0; i < count; ++i){ - NSString *font_n = fonts[i]; - char *font_n_c = (char*)[font_n UTF8String]; - NSFont *font = [font_manager - fontWithFamily:font_n - traits:NSUnboldFontMask|NSUnitalicFontMask - weight:5 - size:12]; - NSString *path = get_font_path(font); - char *path_c = 0; - if (path != nil){ - path_c = (char*)[path UTF8String]; - } - result.names[i] = font_n_c; - result.paths[i] = path_c; - } - - return(result); -} - -void -osx_change_title(char *str_c){ - NSString *str = [NSString stringWithUTF8String:str_c]; - [window setTitle:str]; -} - -OSX_Keyboard_Modifiers -osx_get_modifiers(void){ - return(osx_mods_nsevent_to_struct([NSEvent modifierFlags])); -} - -int -main(int argc, char **argv){ - memset(&osx_objc, 0, sizeof(osx_objc)); - - u32 clipboard_size = KB(16); - osx_objc.clipboard_data = osx_allocate(clipboard_size); - osx_objc.clipboard_max = clipboard_size; - osx_objc.argc = argc; - osx_objc.argv = argv; - - osx_file_listener_init(); - - @autoreleasepool{ - NSApplication *app = [NSApplication sharedApplication]; - [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; - - [app setDelegate:[[AppDelegate alloc] init]]; - NSRect screenRect = [[NSScreen mainScreen] frame]; - float w = 800.f; - float h = 600.f; - NSRect frame = NSMakeRect((screenRect.size.width - w) * 0.5, (screenRect.size.height - h) * 0.5, w, h); - - u32 flags = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; - window = [[NSWindow alloc] initWithContentRect:frame styleMask:flags backing:NSBackingStoreBuffered defer:NO]; - - [window setAcceptsMouseMovedEvents:YES]; - - view = [[My4coderView alloc] init]; - [view setFrame:[[window contentView] bounds]]; - [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; - - [[window contentView] addSubview:view]; - [window setMinSize:NSMakeSize(100, 100)]; - [window setTitle:@WINDOW_NAME]; - [window makeKeyAndOrderFront:nil]; - - [NSTimer scheduledTimerWithTimeInterval: 0.5 - target: view - selector: @selector(checkClipboard) - userInfo: nil repeats:YES]; - - osx_init(); - osx_objc.running = true; - - [NSApp run]; - } - - return(0); -} - -// BOTTOM - diff --git a/platform_mac/mac_4ed_opengl_funcs.h b/platform_mac/mac_4ed_opengl_funcs.h index 649847f9..3d603e67 100644 --- a/platform_mac/mac_4ed_opengl_funcs.h +++ b/platform_mac/mac_4ed_opengl_funcs.h @@ -6,6 +6,7 @@ #include "4ed_opengl_funcs.h" */ +// TODO(allen): eliminate this GL_FUNC(glDebugMessageControl, void, (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)) GL_FUNC(glDebugMessageCallback, void, (GLDEBUGPROC callback, const void *userParam)) diff --git a/platform_mac/osx_objective_c_to_cpp_links_old.h b/platform_mac/osx_objective_c_to_cpp_links_old.h deleted file mode 100644 index cdc74099..00000000 --- a/platform_mac/osx_objective_c_to_cpp_links_old.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Mr. 4th Dimention - Allen Webster - * - * 06.29.2017 - * - * Types and functions for communication between C++ and Objective-C layers. - * - */ - -// TOP - -#if !defined(OSX_OBJECTIVE_C_TO_CPP_LINKS_H) -#define OSX_OBJECTIVE_C_TO_CPP_LINKS_H - -#include - -#if 0 -#define DBG_POINT() fprintf(stdout, "%s\n", __FILE__ ":" LINE_STR ":") -#else -#define DBG_POINT() -#endif - -typedef enum OSX_Mouse_Event_Type{ - MouseType_Move, - MouseType_Press, - MouseType_Release, -} OSX_Mouse_Event_Type; - -typedef struct OSX_Keyboard_Modifiers{ - b32 shift; - b32 command; - b32 control; - b32 option; - b32 caps; -} OSX_Keyboard_Modifiers; - -typedef struct OSX_Objective_C_Vars{ - i32 width, height; - b32 gl_is_initialized; - b32 running; - u32 key_count; - u32 keys[8]; - - u32 prev_clipboard_change_count; - b32 has_clipboard_item; - void *clipboard_data; - u32 clipboard_size; - u32 clipboard_max; - b32 just_posted_to_clipboard; - - char *clipboard_space; - u64 clipboard_space_max; - - b32 full_screen; - b32 do_toggle; - - i32 argc; - char **argv; -} OSX_Objective_C_Vars; - -typedef struct OSX_Loadable_Fonts{ - char **names; - char **paths; - i32 count; -} OSX_Loadable_Fonts; - -typedef struct OSX_Font_Match{ - char *path; - b32 used_base_file; -} OSX_Font_Match; - -// In C++ layer. -extern OSX_Objective_C_Vars osx_objc; - -external void* -osx_allocate(u64 size); - -external void -osx_free(void *ptr, u64 size); - -external void -osx_resize(int width, int height); - -external void -osx_character_input(u32 code, OSX_Keyboard_Modifiers modifier_flags); - -external void -osx_mouse(i32 mx, i32 my, u32 type); - -external void -osx_mouse_wheel(float dx, float dy); - -external void -osx_try_to_close(void); - -external void -osx_step(); - -external void -osx_init(); - -external void -osx_log(char *m, i32 l); - -// In Objective-C layer. -external void -osx_post_to_clipboard(char *str); - -external void -osx_error_dialogue(char *str); - -external void -osx_add_file_listener(char *file_name); - -external void -osx_remove_file_listener(char *file_name); - -external i32 -osx_get_file_change_event(char *buffer, i32 max, i32 *size); - -external void -osx_show_cursor(i32 show_inc, i32 cursor_type); - -external void -osx_begin_render(void); - -external void -osx_end_render(void); - -external void -osx_schedule_step(void); - -external void -osx_toggle_fullscreen(void); - -external b32 -osx_is_fullscreen(void); - -external void -osx_close_app(void); - -external f32 -osx_timer_seconds(void); - -external OSX_Font_Match -osx_get_font_match(char *name, i32 pt_size, b32 italic, b32 bold); - -external OSX_Loadable_Fonts -osx_list_loadable_fonts(void); - -external void -osx_change_title(char *str); - -external OSX_Keyboard_Modifiers -osx_get_modifiers(void); - -#endif - -// BOTTOM - diff --git a/platform_unix/unix_4ed_functions.cpp b/platform_unix/unix_4ed_functions.cpp index d6fe65b7..693d6e15 100644 --- a/platform_unix/unix_4ed_functions.cpp +++ b/platform_unix/unix_4ed_functions.cpp @@ -9,6 +9,8 @@ // TOP +#error IS THIS STILL REAL? (February 27th 2020) + #if !defined(FD_CHECK) #define FD_CHECK() #endif diff --git a/platform_unix/unix_4ed_headers.h b/platform_unix/unix_4ed_headers.h index 7548359b..2a48e541 100644 --- a/platform_unix/unix_4ed_headers.h +++ b/platform_unix/unix_4ed_headers.h @@ -9,6 +9,8 @@ // TOP +#error IS THIS STILL REAL? (February 27th 2020) + #include #include #include diff --git a/platform_unix/unix_library_wrapper.h b/platform_unix/unix_library_wrapper.h index 0af75f92..b358ce34 100644 --- a/platform_unix/unix_library_wrapper.h +++ b/platform_unix/unix_library_wrapper.h @@ -9,6 +9,8 @@ // TOP +#error IS THIS STILL REAL? (February 27th 2020) + union Library{ void *lib; FixSize(LIBRARY_TYPE_SIZE); diff --git a/platform_unix/unix_threading_wrapper.h b/platform_unix/unix_threading_wrapper.h index a8d1afd9..15af8bd2 100644 --- a/platform_unix/unix_threading_wrapper.h +++ b/platform_unix/unix_threading_wrapper.h @@ -9,6 +9,8 @@ // TOP +#error IS THIS STILL REAL? (February 27th 2020) + #if !defined(MAC_THREADING_WRAPPER) #define MAC_THREADING_WRAPPER diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index cccda51a..34381474 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -718,8 +718,8 @@ win32_keycode_init(void){ keycode_lookup_table[VK_F6] = KeyCode_F6; keycode_lookup_table[VK_F7] = KeyCode_F7; keycode_lookup_table[VK_F8] = KeyCode_F8; - keycode_lookup_table[VK_F9] = KeyCode_F9; + keycode_lookup_table[VK_F9] = KeyCode_F9; keycode_lookup_table[VK_F10] = KeyCode_F10; keycode_lookup_table[VK_F11] = KeyCode_F11; keycode_lookup_table[VK_F12] = KeyCode_F12; @@ -727,6 +727,36 @@ win32_keycode_init(void){ keycode_lookup_table[VK_F14] = KeyCode_F14; keycode_lookup_table[VK_F15] = KeyCode_F15; keycode_lookup_table[VK_F16] = KeyCode_F16; + + keycode_lookup_table[VK_F17] = KeyCode_F17; + keycode_lookup_table[VK_F18] = KeyCode_F18; + keycode_lookup_table[VK_F19] = KeyCode_F19; + keycode_lookup_table[VK_F20] = KeyCode_F20; + keycode_lookup_table[VK_F21] = KeyCode_F21; + keycode_lookup_table[VK_F22] = KeyCode_F22; + keycode_lookup_table[VK_F23] = KeyCode_F23; + keycode_lookup_table[VK_F24] = KeyCode_F24; + + keycode_lookup_table[VK_NUMPAD0] = KeyCode_NumPad0; + keycode_lookup_table[VK_NUMPAD1] = KeyCode_NumPad1; + keycode_lookup_table[VK_NUMPAD2] = KeyCode_NumPad2; + keycode_lookup_table[VK_NUMPAD3] = KeyCode_NumPad3; + keycode_lookup_table[VK_NUMPAD4] = KeyCode_NumPad4; + keycode_lookup_table[VK_NUMPAD5] = KeyCode_NumPad5; + keycode_lookup_table[VK_NUMPAD6] = KeyCode_NumPad6; + keycode_lookup_table[VK_NUMPAD7] = KeyCode_NumPad7; + keycode_lookup_table[VK_NUMPAD8] = KeyCode_NumPad8; + keycode_lookup_table[VK_NUMPAD9] = KeyCode_NumPad9; + + keycode_lookup_table[VK_MULTIPLY] = KeyCode_NumPadStar; + keycode_lookup_table[VK_ADD] = KeyCode_NumPadPlus; + keycode_lookup_table[VK_SUBTRACT] = KeyCode_NumPadMinus; + keycode_lookup_table[VK_DECIMAL] = KeyCode_NumPadDot; + keycode_lookup_table[VK_DIVIDE] = KeyCode_NumPadSlash; + + for (i32 i = 0xDF; i < 0xFF; i += 1){ + keycode_lookup_table[i] = KeyCode_Ex0 + 1; + } } internal void @@ -1343,9 +1373,9 @@ win32_gl_create_window(HWND *wnd_out, HGLRC *context_out, DWORD style, RECT rect // NOTE(allen): Load wgl extensions #define LoadWGL(f,l) Stmnt((f) = (f##_Function*)wglGetProcAddress(#f); \ -(l) = (l) && win32_wgl_good((Void_Func*)(f));) - - b32 load_success = true; + (l) = (l) && win32_wgl_good((Void_Func*)(f));) + + b32 load_success = true; LoadWGL(wglCreateContextAttribsARB, load_success); LoadWGL(wglChoosePixelFormatARB, load_success); LoadWGL(wglGetExtensionsStringEXT, load_success); @@ -1443,7 +1473,6 @@ win32_gl_create_window(HWND *wnd_out, HGLRC *context_out, DWORD style, RECT rect goto fail_window_init; } -#if 1 i32 context_attrib_list[] = { /*0*/WGL_CONTEXT_MAJOR_VERSION_ARB, 3, /*2*/WGL_CONTEXT_MINOR_VERSION_ARB, 2, @@ -1455,15 +1484,6 @@ win32_gl_create_window(HWND *wnd_out, HGLRC *context_out, DWORD style, RECT rect /*6*/WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, /*8*/0 }; -#else - i32 context_attrib_list[] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, 2, - WGL_CONTEXT_MINOR_VERSION_ARB, 1, - WGL_CONTEXT_FLAGS_ARB, 0, - WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, - 0 - }; -#endif HGLRC context = wglCreateContextAttribsARB(dc, 0, context_attrib_list); if (context == 0){ diff --git a/project.4coder b/project.4coder index c5484349..d548b124 100644 --- a/project.4coder +++ b/project.4coder @@ -26,8 +26,8 @@ load_paths = { build_x64_win32 = "echo build: x64 & bin\\build.bat"; build_x86_win32 = "echo build: x86 & bin\\build.bat /DDEV_BUILD_X86"; -build_x64_linux = "echo build: x64 & bin/build.sh"; -build_x86_linux = "echo build: x86 & bin/build.sh -DDEV_BUILD_X86"; +build_x64_linux = "echo build: x64 & bin/build-linux.sh"; +build_x86_linux = "echo build: x86 & bin/build-linux.sh -DDEV_BUILD_X86"; build_x64_mac = "echo build: x64 & bin/build-mac.sh"; build_x86_mac = "echo build: x86 & bin/build-mac.sh -DDEV_BUILD_X86"; @@ -46,18 +46,20 @@ command_list = { { .name = "package", .out = "*compilation*", .footer_panel = false, .save_dirty_files = true, - .cmd = { {"echo package & bin\\package.bat", .os = "win" }, - {"echo package & bin/package.sh" , .os = "linux"}, - {"echo package & bin/package.sh" , .os = "mac" }, }, }, + .cmd = { {"echo package & bin\\package.bat" , .os = "win" }, + {"echo package & bin/package-linux.sh", .os = "linux"}, + {"echo package & bin/package-max.sh" , .os = "mac" }, }, }, { .name = "run one time", .out = "*run*", .footer_panel = false, .save_dirty_files = false, .cmd = { { "pushd ..\\build & one_time", .os = "win" }, - { "pushd ../build & one_time", .os = "mac" }, }, }, + { "cd ../build && ./one_time" , .os = "linux" }, + { "pushd ../build && ./one_time" , .os = "mac" }, }, }, { .name = "build custom api docs", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cmd = { { "custom\\bin\\build_one_time docs\\4ed_doc_custom_api_main.cpp ..\\build", .os = "win" }, + { "custom/bin/build_one_time.sh docs/4ed_doc_custom_api_main.cpp ../build", .os = "linux" }, { "custom/bin/build_one_time.sh docs/4ed_doc_custom_api_main.cpp ../build", .os = "mac" }, }, }, { .name = "build C++ lexer generator", @@ -90,7 +92,8 @@ command_list = { { .name = "build keycode generator", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, - .cmd = { { "custom\\bin\\build_one_time 4ed_generate_keycodes.cpp ..\\build", .os = "win" }, }, }, + .cmd = { { "custom\\bin\\build_one_time 4ed_generate_keycodes.cpp ..\\build", .os = "win" }, + { "custom/bin/build_one_time.sh 4ed_generate_keycodes.cpp ../build", .os = "linux" }, }, }, { .name = "build site render", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, diff --git a/ship_files/changes.txt b/ship_files/changes.txt index 18c6edad..ef1ccfd9 100644 --- a/ship_files/changes.txt +++ b/ship_files/changes.txt @@ -7,11 +7,14 @@ + in config.4coder the variable virtual_whitespace_regular_indent determines the number of space-widths to use as the regular indentation in a virtual whitespace layout + show whitespace mode implemented in 'default_render_buffer' + `set_face_size` and `set_face_size_this_buffer` commands + + `HookID_WholeScreenRenderCaller` hook runs once per frame after all views render + + Extended key codes list + Fix: tabs are measured with the correct amount of width for the user's settings + Fix: virtual whitespace toggling works when the config initially diabled virtual whitespace + Fix: never miss the most recent post to the clipboard on windows + Fix: command `load_theme_current_buffer` gaurds against destroying the active color palette when bad files are loaded + Fix: project deep copy routine copies strings in the whitelist and blacklist pattern arrays + + Fix: footer panel manipulation functions check if the view exists 4.1.3 + Unkillable buffer setting @@ -85,7 +88,7 @@ New in alpha 4.0.29: -Highlighting and marking API, supporting customizable line higlights, range highlights, cursors and marks -In config.4coder "use_line_highlight" enables the highlight at the cursor in the active view -In config.4coder "use_scope_highlight" enables background highlighting to distinguish scopes in code files --In config.4coder "use_paren_helper" enalbes distinct coloring for matching parentheses +-In config.4coder "use_paren_helper" enalbes distinct coloring for matching parentheses -In config.4coder "use_comment_keyword" enables special coloring for the strings 'TODO' and 'NOTE' anywhere they occur, in code or text -In config.4coder "mode" sets the editing mode "4coder" the default 4coder mode