diff --git a/4ed.cpp b/4ed.cpp index 99494ca4..858ce9aa 100644 --- a/4ed.cpp +++ b/4ed.cpp @@ -159,6 +159,7 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){ } Command_Map *map = mapping_get_or_make_map(&new_mapping, mapid); + map_set_parent(&new_mapping, map, mapid_global); if (unit->map_begin.replace){ map->real_beginning = unit; } @@ -197,7 +198,12 @@ interpret_binding_buffer(Models *models, void *buffer, i32 size){ case unit_inherit: { if (map_ptr != 0){ - map_set_parent(&new_mapping, map_ptr, unit->map_inherit.mapid); + if (unit->map_inherit.mapid == mapid_nomap){ + map_null_parent(map_ptr); + } + else{ + map_set_parent(&new_mapping, map_ptr, unit->map_inherit.mapid); + } } }break; @@ -581,14 +587,17 @@ force_abort_coroutine(Models *models, View *view){ init_query_set(&view->query_set); } -internal void +internal b32 launch_command_via_event(Models *models, View *view, Input_Event *event){ - block_copy_struct(&models->event, event); + b32 result = false; Command_Map_ID map = view_get_map(view); Command_Binding cmd_bind = map_get_binding_recursive(&models->mapping, map, event); if (cmd_bind.custom != 0){ + result = true; + block_copy_struct(&models->event, event); + Assert(models->command_coroutine == 0); Coroutine *command_coroutine = coroutine_create(&models->coroutines, command_caller); models->command_coroutine = command_coroutine; @@ -597,13 +606,19 @@ launch_command_via_event(Models *models, View *view, Input_Event *event){ cmd_in.models = models; cmd_in.bind = cmd_bind; + models->event_unhandled = false; models->command_coroutine = app_coroutine_run(models, Co_Command, models->command_coroutine, &cmd_in, models->command_coroutine_flags); + if (models->event_unhandled){ + result = false; + } models->prev_command = cmd_bind; if (match_core_code(event, CoreCode_Animate)){ models->animate_next_frame = true; } } + + return(result); } internal void @@ -964,8 +979,14 @@ App_Step_Sig(app_step){ for (Input_Event_Node *node = input_list.first; node != 0; node = node->next){ + b32 event_was_handled = false; Input_Event *event = &node->event; + if (event->kind == InputEventKind_TextInsert && + event->text.blocked){ + continue; + } + Panel *active_panel = layout_get_active_panel(layout); View *view = active_panel->view; Assert(view != 0); @@ -995,6 +1016,7 @@ App_Step_Sig(app_step){ { models->state = APP_STATE_RESIZING; models->resizing_intermediate_panel = divider_panel; + event_was_handled = true; }break; case EventConsume_ClickChangeView: @@ -1019,6 +1041,8 @@ App_Step_Sig(app_step){ // NOTE(allen): run activate command launch_command_via_core_event(models, view, CoreCode_ClickActivateView); + + event_was_handled = true; }break; case EventConsume_CustomCommand: @@ -1033,6 +1057,8 @@ App_Step_Sig(app_step){ Event_Property event_flags = get_event_properties(event); if ((get_flags & event_flags) != 0){ + event_was_handled = true; + Command_Map_ID map = view_get_map(view); Command_Binding cmd_bind = map_get_binding_recursive(&models->mapping, map, event); @@ -1040,7 +1066,12 @@ App_Step_Sig(app_step){ user_in.event = *event; user_in.command = cmd_bind.custom; user_in.abort = ((abort_flags & event_flags) != 0); + + models->event_unhandled = false; models->command_coroutine = app_coroutine_run(models, Co_Command, command_coroutine, &user_in, models->command_coroutine_flags); + if (models->event_unhandled){ + event_was_handled = false; + } if (!HasFlag(event_flags, EventProperty_Animate)){ models->animate_next_frame = true; @@ -1052,7 +1083,9 @@ App_Step_Sig(app_step){ } } else{ - launch_command_via_event(models, view, event); + if (launch_command_via_event(models, view, event)){ + event_was_handled = true; + } } }break; } @@ -1079,6 +1112,15 @@ App_Step_Sig(app_step){ } }break; } + + if (event_was_handled && event->kind == InputEventKind_KeyStroke){ + for (Input_Event *dependent_text = event->key.first_dependent_text; + dependent_text != 0; + dependent_text = dependent_text->text.next_text){ + Assert(dependent_text->kind == InputEventKind_TextInsert); + dependent_text->text.blocked = true; + } + } } // NOTE(allen): send panel size update diff --git a/4ed_api_implementation.cpp b/4ed_api_implementation.cpp index 3577b6ec..224296a5 100644 --- a/4ed_api_implementation.cpp +++ b/4ed_api_implementation.cpp @@ -2107,6 +2107,12 @@ set_command_input(Application_Links *app, Input_Event *event) models->event = *event; } +api(custom) function void +leave_command_input_unhandled(Application_Links *app){ + Models *models = (Models*)app->cmd_context; + models->event_unhandled = true; +} + api(custom) function Mouse_State get_mouse_state(Application_Links *app) { diff --git a/4ed_app_models.h b/4ed_app_models.h index 11ec4eb3..d2b6a42f 100644 --- a/4ed_app_models.h +++ b/4ed_app_models.h @@ -124,9 +124,10 @@ struct Models{ // Event Context Application_Step_Input *input; Input_Event event; + b8 event_unhandled; + b8 in_render_mode; Render_Target *target; - b32 in_render_mode; }; //////////////////////////////// diff --git a/4ed_command.cpp b/4ed_command.cpp index 7bcc9af8..def0ef89 100644 --- a/4ed_command.cpp +++ b/4ed_command.cpp @@ -104,7 +104,6 @@ mapping_release(Thread_Context *tctx, Mapping *mapping){ } } -#if 0 internal Command_Map* mapping_begin_new_map(Mapping *mapping){ Command_Map *map = mapping__alloc_map(mapping); @@ -115,7 +114,6 @@ mapping_begin_new_map(Mapping *mapping){ table_insert(&mapping->id_to_map, map->id, (u64)PtrAsInt(map)); return(map); } -#endif internal Command_Map* mapping_get_map(Mapping *mapping, Command_Map_ID id){ @@ -233,6 +231,11 @@ map_set_parent(Command_Map *map, Command_Map *parent){ } } +internal void +map_null_parent(Command_Map *map){ + map->parent = 0; +} + internal void map_set_binding_text_input(Command_Map *map, Custom_Command_Function *custom){ if (map != 0){ @@ -284,6 +287,12 @@ map_set_parent(Mapping *mapping, Command_Map *map, Command_Map_ID parent_id){ map_set_parent(map, parent); } +internal void +map_null_parent(Mapping *mapping, Command_Map_ID map_id){ + Command_Map *map = mapping_get_map(mapping, map_id); + map_null_parent(map); +} + internal void map_set_binding_text_input(Mapping *mapping, Command_Map_ID map_id, Custom_Command_Function *custom){ Command_Map *map = mapping_get_map(mapping, map_id); diff --git a/custom/4coder_events.cpp b/custom/4coder_events.cpp index 405f3fbb..d6142034 100644 --- a/custom/4coder_events.cpp +++ b/custom/4coder_events.cpp @@ -18,10 +18,6 @@ internal b32 is_modified(Input_Event *event){ b8 *mods = 0; switch (event->kind){ - case InputEventKind_TextInsert: - { - mods = event->text.modifiers.modifiers; - }break; case InputEventKind_KeyStroke: { mods = event->key.modifiers.modifiers; @@ -140,6 +136,14 @@ get_event_properties(Input_Event *event){ return(flags); } +internal Input_Event* +push_input_event(Arena *arena, Input_List *list){ + Input_Event_Node *node = push_array_zero(arena, Input_Event_Node, 1); + sll_queue_push(list->first, list->last, node); + list->count += 1; + return(&node->event); +} + internal Input_Event* push_input_event(Arena *arena, Input_List *list, Input_Event *event){ Input_Event_Node *node = push_array(arena, Input_Event_Node, 1); diff --git a/custom/4coder_events.h b/custom/4coder_events.h index b5c3017a..58d56076 100644 --- a/custom/4coder_events.h +++ b/custom/4coder_events.h @@ -46,11 +46,17 @@ struct Input_Event{ union{ struct{ String_Const_u8 string; - Key_Modifiers modifiers; + + // used internally + Input_Event *next_text; + b32 blocked; } text; struct{ Key_Code code; Key_Modifiers modifiers; + + // used internally + Input_Event *first_dependent_text; } key; struct{ Mouse_Code code; diff --git a/custom/4coder_jump_sticky.cpp b/custom/4coder_jump_sticky.cpp index 7c6f0182..283d3f64 100644 --- a/custom/4coder_jump_sticky.cpp +++ b/custom/4coder_jump_sticky.cpp @@ -571,6 +571,9 @@ CUSTOM_DOC("If the buffer in the active view is writable, inserts a character, o lock_jump_buffer(app, buffer); } } + else{ + leave_command_input_unhandled(app); + } } CUSTOM_COMMAND_SIG(if_read_only_goto_position_same_panel) @@ -585,6 +588,9 @@ CUSTOM_DOC("If the buffer in the active view is writable, inserts a character, o lock_jump_buffer(app, buffer); } } + else{ + leave_command_input_unhandled(app); + } } // diff --git a/custom/generated/command_metadata.h b/custom/generated/command_metadata.h index d30b83eb..22db7c2b 100644 --- a/custom/generated/command_metadata.h +++ b/custom/generated/command_metadata.h @@ -413,7 +413,7 @@ static Command_Metadata fcoder_metacmd_table[227] = { { PROC_LINKS(goto_first_jump, 0), "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, 523 }, { PROC_LINKS(goto_first_jump_same_panel_sticky, 0), "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, 540 }, { PROC_LINKS(if_read_only_goto_position, 0), "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, 562 }, -{ PROC_LINKS(if_read_only_goto_position_same_panel, 0), "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, 576 }, +{ PROC_LINKS(if_read_only_goto_position_same_panel, 0), "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, 579 }, { PROC_LINKS(view_jump_list_with_lister, 0), "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, 102 }, { PROC_LINKS(log_graph__escape, 0), "log_graph__escape", 17, "Ends the log grapher", 20, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 906 }, { PROC_LINKS(log_graph__scroll_wheel, 0), "log_graph__scroll_wheel", 23, "Scrolls the log graph", 21, "w:\\4ed\\code\\custom\\4coder_log_parser.cpp", 40, 915 }, diff --git a/custom/generated/custom_api.cpp b/custom/generated/custom_api.cpp index c10553cc..4ad18b1d 100644 --- a/custom/generated/custom_api.cpp +++ b/custom/generated/custom_api.cpp @@ -119,6 +119,7 @@ vtable->managed_object_load_data = managed_object_load_data; vtable->get_user_input = get_user_input; vtable->get_command_input = get_command_input; vtable->set_command_input = set_command_input; +vtable->leave_command_input_unhandled = leave_command_input_unhandled; vtable->get_mouse_state = get_mouse_state; vtable->get_active_query_bars = get_active_query_bars; vtable->start_query_bar = start_query_bar; @@ -293,6 +294,7 @@ managed_object_load_data = vtable->managed_object_load_data; get_user_input = vtable->get_user_input; get_command_input = vtable->get_command_input; set_command_input = vtable->set_command_input; +leave_command_input_unhandled = vtable->leave_command_input_unhandled; get_mouse_state = vtable->get_mouse_state; get_active_query_bars = vtable->get_active_query_bars; start_query_bar = vtable->start_query_bar; diff --git a/custom/generated/custom_api.h b/custom/generated/custom_api.h index c7342204..d9d8d32c 100644 --- a/custom/generated/custom_api.h +++ b/custom/generated/custom_api.h @@ -117,6 +117,7 @@ #define custom_get_user_input_sig() User_Input custom_get_user_input(Application_Links* app, Event_Property get_properties, Event_Property abort_properties) #define custom_get_command_input_sig() User_Input custom_get_command_input(Application_Links* app) #define custom_set_command_input_sig() void custom_set_command_input(Application_Links* app, Input_Event* event) +#define custom_leave_command_input_unhandled_sig() void custom_leave_command_input_unhandled(Application_Links* app) #define custom_get_mouse_state_sig() Mouse_State custom_get_mouse_state(Application_Links* app) #define custom_get_active_query_bars_sig() b32 custom_get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out) #define custom_start_query_bar_sig() b32 custom_start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags) @@ -287,6 +288,7 @@ typedef b32 custom_managed_object_load_data_type(Application_Links* app, Managed typedef User_Input custom_get_user_input_type(Application_Links* app, Event_Property get_properties, Event_Property abort_properties); typedef User_Input custom_get_command_input_type(Application_Links* app); typedef void custom_set_command_input_type(Application_Links* app, Input_Event* event); +typedef void custom_leave_command_input_unhandled_type(Application_Links* app); typedef Mouse_State custom_get_mouse_state_type(Application_Links* app); typedef b32 custom_get_active_query_bars_type(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out); typedef b32 custom_start_query_bar_type(Application_Links* app, Query_Bar* bar, u32 flags); @@ -458,6 +460,7 @@ custom_managed_object_load_data_type *managed_object_load_data; custom_get_user_input_type *get_user_input; custom_get_command_input_type *get_command_input; custom_set_command_input_type *set_command_input; +custom_leave_command_input_unhandled_type *leave_command_input_unhandled; custom_get_mouse_state_type *get_mouse_state; custom_get_active_query_bars_type *get_active_query_bars; custom_start_query_bar_type *start_query_bar; @@ -630,6 +633,7 @@ internal b32 managed_object_load_data(Application_Links* app, Managed_Object obj internal User_Input get_user_input(Application_Links* app, Event_Property get_properties, Event_Property abort_properties); internal User_Input get_command_input(Application_Links* app); internal void set_command_input(Application_Links* app, Input_Event* event); +internal void leave_command_input_unhandled(Application_Links* app); internal Mouse_State get_mouse_state(Application_Links* app); internal b32 get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out); internal b32 start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags); @@ -802,6 +806,7 @@ global custom_managed_object_load_data_type *managed_object_load_data = 0; global custom_get_user_input_type *get_user_input = 0; global custom_get_command_input_type *get_command_input = 0; global custom_set_command_input_type *set_command_input = 0; +global custom_leave_command_input_unhandled_type *leave_command_input_unhandled = 0; global custom_get_mouse_state_type *get_mouse_state = 0; global custom_get_active_query_bars_type *get_active_query_bars = 0; global custom_start_query_bar_type *start_query_bar = 0; diff --git a/custom/generated/custom_api_master_list.h b/custom/generated/custom_api_master_list.h index 1e577aec..12d21de3 100644 --- a/custom/generated/custom_api_master_list.h +++ b/custom/generated/custom_api_master_list.h @@ -117,6 +117,7 @@ api(custom) function b32 managed_object_load_data(Application_Links* app, Manage api(custom) function User_Input get_user_input(Application_Links* app, Event_Property get_properties, Event_Property abort_properties); api(custom) function User_Input get_command_input(Application_Links* app); api(custom) function void set_command_input(Application_Links* app, Input_Event* event); +api(custom) function void leave_command_input_unhandled(Application_Links* app); api(custom) function Mouse_State get_mouse_state(Application_Links* app); api(custom) function b32 get_active_query_bars(Application_Links* app, View_ID view_id, i32 max_result_count, Query_Bar_Ptr_Array* array_out); api(custom) function b32 start_query_bar(Application_Links* app, Query_Bar* bar, u32 flags); diff --git a/custom/generated/remapping.h b/custom/generated/remapping.h index 571b4c98..a062d10f 100644 --- a/custom/generated/remapping.h +++ b/custom/generated/remapping.h @@ -22,7 +22,6 @@ void fill_keys_default(Bind_Helper *context){ bind(context, KeyCode_X, MDFR_ALT, command_lister); bind(context, KeyCode_X, MDFR_ALT|MDFR_SHIFT, project_command_lister); bind(context, KeyCode_I, MDFR_CTRL|MDFR_SHIFT, list_all_functions_all_buffers_lister); - bind(context, KeyCode_F4, MDFR_ALT, exit_4coder); bind(context, KeyCode_F1, MDFR_NONE, project_fkey_command); bind(context, KeyCode_F2, MDFR_NONE, project_fkey_command); bind(context, KeyCode_F3, MDFR_NONE, project_fkey_command); @@ -39,6 +38,7 @@ void fill_keys_default(Bind_Helper *context){ bind(context, KeyCode_F14, MDFR_NONE, project_fkey_command); bind(context, KeyCode_F15, MDFR_NONE, project_fkey_command); bind(context, KeyCode_F16, MDFR_NONE, project_fkey_command); + bind(context, KeyCode_F4, MDFR_ALT, exit_4coder); //bind(context, KeyCodeExt_MouseWheel, MDFR_NONE, mouse_wheel_scroll); //bind(context, KeyCodeExt_MouseWheel, MDFR_CTRL, mouse_wheel_change_face_size); end_map(context); @@ -120,7 +120,6 @@ void fill_keys_default(Bind_Helper *context){ bind(context, KeyCode_Return, MDFR_NONE, if_read_only_goto_position); bind(context, KeyCode_Return, MDFR_SHIFT, if_read_only_goto_position_same_panel); bind(context, KeyCode_Period, MDFR_CTRL|MDFR_SHIFT, view_jump_list_with_lister); - bind(context, KeyCode_Space, MDFR_SHIFT, write_space); end_map(context); begin_map(context, default_code_map); inherit_map(context, mapid_file); diff --git a/platform_win32/win32_4ed.cpp b/platform_win32/win32_4ed.cpp index c58dd84c..ec7f4378 100644 --- a/platform_win32/win32_4ed.cpp +++ b/platform_win32/win32_4ed.cpp @@ -146,6 +146,8 @@ struct Win32_Vars{ Thread_Context *tctx; Arena *frame_arena; + Input_Event *active_key_stroke; + Input_Event *active_text_input; Win32_Input_Chunk input_chunk; b8 lctrl_lalt_is_altgr; b8 got_useful_event; @@ -999,42 +1001,69 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ Key_Code key = keycode_lookup_table[(u8)wParam]; if (key != 0){ Key_Modifiers modifiers = system_get_keyboard_modifiers(); - Input_Event event = {}; - event.kind = InputEventKind_KeyStroke; - event.key.code = key; - block_copy_struct(&event.key.modifiers, &modifiers); - push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list, &event); + Input_Event *event = push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list); + event->kind = InputEventKind_KeyStroke; + event->key.code = key; + block_copy_struct(&event->key.modifiers, &modifiers); + win32vars.active_key_stroke = event; win32vars.got_useful_event = true; } } + else{ + win32vars.active_key_stroke = 0; + win32vars.active_text_input = 0; + + win32vars.got_useful_event = true; + } }break; - case WM_CHAR: case WM_SYSCHAR: case WM_UNICHAR: + case WM_CHAR: { - u16 character = (u16)wParam; - - if (character == '\r'){ - character = '\n'; + u16 c = wParam & bitmask_16; + if (c == '\r'){ + c = '\n'; } - else if (character == '\t'){ - // Do nothing + if (c > 127 || (' ' <= c && c <= '~') || c == '\t' || c == '\n'){ + String_Const_u16 str_16 = SCu16(&c, 1); + String_Const_u8 str_8 = string_u8_from_string_u16(win32vars.frame_arena, str_16).string; + Input_Event *event = push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list); + event->kind = InputEventKind_TextInsert; + event->text.string = str_8; + event->text.next_text = 0; + event->text.blocked = false; + if (win32vars.active_text_input != 0){ + win32vars.active_text_input->text.next_text = event; + } + else if (win32vars.active_key_stroke != 0){ + win32vars.active_key_stroke->key.first_dependent_text = event; + } + win32vars.active_text_input = event; + + win32vars.got_useful_event = true; } - else if (character < 32 || character == 127){ - break; + }break; + + case WM_UNICHAR: + { + if (wParam == UNICODE_NOCHAR){ + result = true; + } + else{ + u32 c = (u32)wParam; + if (c == '\r'){ + c= '\n'; + } + if (c > 127 || (' ' <= c && c <= '~') || c == '\t' || c == '\n'){ + String_Const_u32 str_32 = SCu32(&c, 1); + String_Const_u8 str_8 = string_u8_from_string_u32(win32vars.frame_arena, str_32).string; + Input_Event event = {}; + event.kind = InputEventKind_TextInsert; + event.text.string = str_8; + push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list, &event); + win32vars.got_useful_event = true; + } } - - String_Const_u16 str_16 = SCu16(&character, 1); - String_Const_u8 str_8 = string_u8_from_string_u16(win32vars.frame_arena, str_16).string; - - Key_Modifiers modifiers = system_get_keyboard_modifiers(); - Input_Event event = {}; - event.kind = InputEventKind_TextInsert; - event.text.string = str_8; - block_copy_struct(&event.text.modifiers, &modifiers); - push_input_event(win32vars.frame_arena, &win32vars.input_chunk.trans.event_list, &event); - - win32vars.got_useful_event = true; }break; case WM_MOUSEMOVE: @@ -1096,6 +1125,8 @@ win32_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ win32vars.input_chunk.pers.control_keys[i] = false; } block_zero_struct(&win32vars.input_chunk.pers.controls); + win32vars.active_key_stroke = 0; + win32vars.active_text_input = 0; }break; case WM_SIZE: @@ -1659,6 +1690,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS for (;keep_running;){ linalloc_clear(win32vars.frame_arena); block_zero_struct(&win32vars.input_chunk.trans); + win32vars.active_key_stroke = 0; + win32vars.active_text_input = 0; // TODO(allen): Find a good way to wait on a pipe // without interfering with the reading process. @@ -1694,8 +1727,8 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdS } if (treat_normally){ - TranslateMessage(&msg); DispatchMessage(&msg); + TranslateMessage(&msg); } else{ Control_Keys *controls = &win32vars.input_chunk.pers.controls;