diff --git a/src/base/base_controller.h b/src/base/base_controller.h index e884d294..8cccfba0 100644 --- a/src/base/base_controller.h +++ b/src/base/base_controller.h @@ -139,6 +139,7 @@ Struct(ControllerEvent) b32 is_repeat; // ControllerEventKind_Text + u32 text_codepoint; u32 text_chars_count; u8 text_chars[4]; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 3fbe0590..33c21efc 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -261,19 +261,20 @@ void V_DrawPoint(Vec2 p, Vec4 srgb) //////////////////////////////////////////////////////////// //~ Text box -void V_ApplyTextBoxDelta(V_TextBoxState *tb, V_TextBoxDelta delta) +void V_ApplyTextboxDelta(V_TextboxState *tb, V_TextboxDelta delta) { - V_TextBoxDeltaNode tbd_node = { .delta = delta }; - V_ApplyTextBoxDeltas(tb, (V_TextBoxDeltaList) { .first = &tbd_node, .last = &tbd_node }); + V_TextboxDeltaNode tbd_node = { .delta = delta }; + V_ApplyTextboxDeltas(tb, (V_TextboxDeltaList) { .first = &tbd_node, .last = &tbd_node }); } -void V_ApplyTextBoxDeltas(V_TextBoxState *tb, V_TextBoxDeltaList deltas) +void V_ApplyTextboxDeltas(V_TextboxState *tb, V_TextboxDeltaList deltas) { - for (V_TextBoxDeltaNode *tbd_node = deltas.first; tbd_node; tbd_node = tbd_node->next) + TempArena scratch = BeginScratchNoConflict(); + for (V_TextboxDeltaNode *tbd_node = deltas.first; tbd_node; tbd_node = tbd_node->next) { - V_TextBoxDelta delta = tbd_node->delta; + V_TextboxDelta delta = tbd_node->delta; - // if (!(delta.flags & V_TextBoxDeltaFlag_DontUpdateCursor)) + // if (!(delta.flags & V_TextboxDeltaFlag_DontUpdateCursor)) // { // tb->start = ClampI64(delta.start, 0, tb->len); // tb->end = ClampI64(delta.end, 0, tb->len); @@ -284,60 +285,81 @@ void V_ApplyTextBoxDeltas(V_TextBoxState *tb, V_TextBoxDeltaList deltas) // Navigate { + b32 navigated = 0; + if (!(delta.flags & V_TextboxDeltaFlag_OnlyNavIfSelectionEmpty) || tb->start == tb->end) { - if (delta.flags & V_TextBoxDeltaFlag_NavDirect) + if (delta.flags & V_TextboxDeltaFlag_NavDirect) { - tb->start = delta.direct_start; - tb->end = delta.direct_end; + navigated = 1; + tb->start = ClampI64(delta.direct_start, 0, tb->len); + tb->end = ClampI64(delta.direct_end, 0, tb->len); } - if (delta.flags & V_TextBoxDeltaFlag_NavLeft) + if (delta.flags & V_TextboxDeltaFlag_NavLeft) { - if (delta.flags & V_TextBoxDeltaFlag_NavLine) + navigated = 1; + if (delta.flags & V_TextboxDeltaFlag_NavLine) { - // FIXME: Real line start + // TODO: Real line start tb->end = 0; } - else if (delta.flags & V_TextBoxDeltaFlag_NavWord) + else if (delta.flags & V_TextboxDeltaFlag_NavWord) { - for (i64 pos = ClampI64(tb->end - 1, 0, tb->len); pos >= 0; --pos) + if (tb->end > 0 && tb->text[tb->end - 1] == ' ') { - tb->end = pos - 1; - if (tb->text[pos] == ' ') + for (i64 pos = tb->end - 1; pos >= 0 && tb->text[pos] == ' '; --pos) { - break; + tb->end = pos; } } + for (i64 pos = tb->end - 1; pos >= 0 && tb->text[pos] != ' '; --pos) + { + tb->end = pos; + } } else { tb->end -= 1; + // Skip utf-8 continuations + // for (i64 pos = tb->end - 1; pos >= 0 && (tb->text[pos] & 0xC0) == 0x80; --pos) + // { + // tb->end = pos; + // } } } - if (delta.flags & V_TextBoxDeltaFlag_NavRight) + if (delta.flags & V_TextboxDeltaFlag_NavRight) { - if (delta.flags & V_TextBoxDeltaFlag_NavLine) + navigated = 1; + if (delta.flags & V_TextboxDeltaFlag_NavLine) { - // FIXME: Real line end + // TODO: Real line end tb->end = I64Max; } - else if (delta.flags & V_TextBoxDeltaFlag_NavWord) + else if (delta.flags & V_TextboxDeltaFlag_NavWord) { - for (i64 pos = ClampI64(tb->end + 1, 0, tb->len); pos < tb->len; ++pos) + if (tb->end < tb->len && tb->text[tb->end] == ' ') + { + for (i64 pos = tb->end; pos < tb->len && tb->text[pos] == ' '; ++pos) + { + tb->end = pos + 1; + } + } + for (i64 pos = tb->end; pos < tb->len && tb->text[pos] != ' '; ++pos) { tb->end = pos + 1; - if (tb->text[pos] == ' ') - { - break; - } } } else { tb->end += 1; + // Skip utf-8 continuations + // for (i64 pos = tb->end; pos < tb->len && (tb->text[pos] & 0xC0) == 0x80; ++pos) + // { + // tb->end = pos + 1; + // } } } } - if (!(delta.flags & V_TextBoxDeltaFlag_NavSelect)) + if (navigated && !(delta.flags & V_TextboxDeltaFlag_NavSelect)) { tb->start = tb->end; } @@ -345,60 +367,104 @@ void V_ApplyTextBoxDeltas(V_TextBoxState *tb, V_TextBoxDeltaList deltas) tb->end = ClampI64(tb->end, 0, tb->len); } - - - + if (delta.flags & V_TextboxDeltaFlag_InheritTextFromClipboard) + { + delta.text = PLT_GetClipboardText(scratch.arena); + } // Update text - if (delta.flags & V_TextBoxDeltaFlag_UpdateText) + if (delta.flags & V_TextboxDeltaFlag_UpdateText) { - RngI64 replace = Zi; - // Remove selected text { - replace = RNGI64(MinI64(tb->start, tb->end), MaxI64(tb->start, tb->end)); - if (replace.max > replace.min) + RngI64 remove = RNGI64(MinI64(tb->start, tb->end), MaxI64(tb->start, tb->end)); + if (remove.max > remove.min) { // FIXME: Truncate - i64 move_len = ClampI64(tb->len - replace.max, 0, countof(tb->text) - replace.max); - for (i64 src_pos = replace.max; src_pos < (replace.max + move_len); ++src_pos) + RngI64 move = RNGI64(remove.max, tb->len); + i64 move_stride = remove.max - remove.min; + for (i64 src_idx = move.min; src_idx < move.max; ++src_idx) { - i64 dst_pos = src_pos + move_len; - tb->text[dst_pos] = tb->text[src_pos]; + i64 dst_idx = src_idx - move_stride; + tb->text[dst_idx] = tb->text[src_idx]; } } - tb->len -= replace.max - replace.min; + + // FIXME + tb->len -= remove.max - remove.min; + tb->start = tb->end = remove.min; } + + + // Insert new text - if (delta.text.len > 0) { - i64 insert_len = ClampI64(delta.text.len, 0, countof(tb->text) - replace.min); - - // Make room // FIXME: Truncate - i64 move_len = ClampI64(tb->len - replace.min, 0, countof(tb->text) - replace.min); - for (i64 src_pos = replace.min; src_pos < (replace.min + move_len); ++src_pos) + i64 insert_pos = tb->end; + i64 insert_len = MinI64(delta.text.len, countof(tb->text) - insert_pos); + if (insert_len > 0) { - i64 dst_pos = src_pos + move_len; - tb->text[dst_pos] = tb->text[src_pos]; - } + RngI64 move_dst = Zi; + move_dst.min = insert_pos + insert_len; + move_dst.max = move_dst.min + (tb->len - insert_pos); + move_dst.min = ClampI64(move_dst.min, 0, countof(tb->text)); + move_dst.max = ClampI64(move_dst.max, move_dst.min, countof(tb->text)); - // Copy from delta - for (i64 src_pos = 0; src_pos < insert_len; ++src_pos) - { - i64 dst_pos = replace.min + src_pos; - tb->text[dst_pos] = delta.text.text[src_pos]; + i64 move_stride = insert_len; + + for (i64 dst_idx = move_dst.max - 1; dst_idx >= move_dst.min; --dst_idx) + { + i64 src_idx = dst_idx - move_stride; + tb->text[dst_idx] = tb->text[src_idx]; + } + + for (i64 src_idx = 0; src_idx < insert_len; ++src_idx) + { + i64 dst_idx = insert_pos + src_idx; + tb->text[dst_idx] = delta.text.text[src_idx]; + } } + tb->start = tb->end = insert_pos + insert_len; tb->len += insert_len; } - // FIXME: Expand selection on insert - // tb->start = ClampI64(tb->start, 0, tb->len); - // tb->end = ClampI64(tb->end, 0, tb->len); - tb->end = ClampI64(tb->end, 0, tb->len); - tb->start = tb->end; + + // // Insert new text + // if (delta.text.len > 0) + // { + // i64 insert_len = ClampI64(delta.text.len, 0, countof(tb->text) - replace.min); + + // // Make room + // // FIXME: Truncate + // i64 move_len = ClampI64(tb->len - replace.min, 0, countof(tb->text) - replace.min); + // for (i64 src_pos = replace.min; src_pos < (replace.min + move_len); ++src_pos) + // { + // i64 dst_pos = src_pos + move_len; + // tb->text[dst_pos] = tb->text[src_pos]; + // } + + // // Copy from delta + // for (i64 src_pos = 0; src_pos < insert_len; ++src_pos) + // { + // i64 dst_pos = replace.min + src_pos; + // tb->text[dst_pos] = delta.text.text[src_pos]; + // } + // tb->len += insert_len; + // } + + // tb->end = ClampI64(tb->end, 0, tb->len); + // tb->start = tb->end; + } + + if (delta.flags & V_TextboxDeltaFlag_CopySelectionToClipboard) + { + String selection = V_StringFromTextboxSelection(tb); + if (selection.len > 0) + { + PLT_SetClipboardText(selection); + } } @@ -412,7 +478,74 @@ void V_ApplyTextBoxDeltas(V_TextBoxState *tb, V_TextBoxDeltaList deltas) - // if (!(delta.flags & V_TextBoxDeltaFlag_DontUpdateText)) + + + + + // // Update text + // if (delta.flags & V_TextboxDeltaFlag_UpdateText) + // { + // RngI64 replace = Zi; + + // // Remove selected text + // { + // replace = RNGI64(MinI64(tb->start, tb->end), MaxI64(tb->start, tb->end)); + // if (replace.max > replace.min) + // { + // // FIXME: Truncate + // i64 move_len = ClampI64(tb->len - replace.max, 0, countof(tb->text) - replace.max); + // for (i64 src_pos = replace.max; src_pos < (replace.max + move_len); ++src_pos) + // { + // i64 dst_pos = src_pos + move_len; + // tb->text[dst_pos] = tb->text[src_pos]; + // } + // } + // tb->len -= replace.max - replace.min; + // } + + // // Insert new text + // if (delta.text.len > 0) + // { + // i64 insert_len = ClampI64(delta.text.len, 0, countof(tb->text) - replace.min); + + // // Make room + // // FIXME: Truncate + // i64 move_len = ClampI64(tb->len - replace.min, 0, countof(tb->text) - replace.min); + // for (i64 src_pos = replace.min; src_pos < (replace.min + move_len); ++src_pos) + // { + // i64 dst_pos = src_pos + move_len; + // tb->text[dst_pos] = tb->text[src_pos]; + // } + + // // Copy from delta + // for (i64 src_pos = 0; src_pos < insert_len; ++src_pos) + // { + // i64 dst_pos = replace.min + src_pos; + // tb->text[dst_pos] = delta.text.text[src_pos]; + // } + // tb->len += insert_len; + // } + + // // FIXME: Expand selection on insert + // // tb->start = ClampI64(tb->start, 0, tb->len); + // // tb->end = ClampI64(tb->end, 0, tb->len); + + // tb->end = ClampI64(tb->end, 0, tb->len); + // tb->start = tb->end; + // } + + + + + + + + + + + + + // if (!(delta.flags & V_TextboxDeltaFlag_DontUpdateText)) // { // RngI64 replace = Zi; @@ -458,13 +591,21 @@ void V_ApplyTextBoxDeltas(V_TextBoxState *tb, V_TextBoxDeltaList deltas) // } // } } + EndScratch(scratch); } -String V_StringFromTextBox(V_TextBoxState *tb) +String V_StringFromTextbox(V_TextboxState *tb) { return STRING(tb->len, tb->text); } +String V_StringFromTextboxSelection(V_TextboxState *tb) +{ + i64 min = MinI64(tb->start, tb->end); + i64 max = MaxI64(tb->start, tb->end); + return STRING(max - min, tb->text + min); +} + //////////////////////////////////////////////////////////// //~ Timeline helpers @@ -1011,7 +1152,7 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// //- Process controller events - V_TextBoxDeltaList text_input_deltas = Zi; + V_TextboxDeltaList text_input_deltas = Zi; frame->has_mouse_focus = UI_IsKeyNil(ui_frame->hot_box) || UI_MatchKey(ui_frame->hot_box, vis_box); frame->has_keyboard_focus = 1; @@ -1093,60 +1234,69 @@ void V_TickForever(WaveLaneCtx *lane) } else { - V_TextBoxDelta delta = Zi; + // Generate text input delta + V_TextboxDelta delta = Zi; { if (down && cev.button == Button_Left) { - delta.flags |= V_TextBoxDeltaFlag_NavLeft; + delta.flags |= V_TextboxDeltaFlag_NavLeft; } if (down && cev.button == Button_Right) { - delta.flags |= V_TextBoxDeltaFlag_NavRight; + delta.flags |= V_TextboxDeltaFlag_NavRight; } if (down && cev.button == Button_Home) { - delta.flags |= V_TextBoxDeltaFlag_NavLeft | V_TextBoxDeltaFlag_NavLine; + delta.flags |= V_TextboxDeltaFlag_NavLeft | V_TextboxDeltaFlag_NavLine; } if (down && cev.button == Button_End) { - delta.flags |= V_TextBoxDeltaFlag_NavRight | V_TextBoxDeltaFlag_NavLine; + delta.flags |= V_TextboxDeltaFlag_NavRight | V_TextboxDeltaFlag_NavLine; } if (down && cev.button == Button_A && frame->held_buttons[Button_Ctrl]) { - delta.flags |= V_TextBoxDeltaFlag_NavSelect | V_TextBoxDeltaFlag_NavDirect; + delta.flags |= V_TextboxDeltaFlag_NavSelect | V_TextboxDeltaFlag_NavDirect; delta.direct_start = 0; - delta.direct_end = I64Max; + delta.direct_end = V_MaxTextboxLen; } if (down && cev.button == Button_Backspace) { delta.text = Lit(""); - delta.flags |= V_TextBoxDeltaFlag_NavSelect | V_TextBoxDeltaFlag_NavLeft | V_TextBoxDeltaFlag_UpdateText; + delta.flags |= V_TextboxDeltaFlag_OnlyNavIfSelectionEmpty | V_TextboxDeltaFlag_NavSelect | V_TextboxDeltaFlag_NavLeft | V_TextboxDeltaFlag_UpdateText; } if (down && cev.button == Button_Delete) { delta.text = Lit(""); - delta.flags |= V_TextBoxDeltaFlag_NavSelect | V_TextBoxDeltaFlag_NavRight | V_TextBoxDeltaFlag_UpdateText; + delta.flags |= V_TextboxDeltaFlag_OnlyNavIfSelectionEmpty | V_TextboxDeltaFlag_NavSelect | V_TextboxDeltaFlag_NavRight | V_TextboxDeltaFlag_UpdateText; } - if (text.len > 0) + if (down && cev.button == Button_C && frame->held_buttons[Button_Ctrl]) { - delta.flags |= V_TextBoxDeltaFlag_UpdateText; + delta.flags |= V_TextboxDeltaFlag_CopySelectionToClipboard; + } + else if (down && cev.button == Button_V && frame->held_buttons[Button_Ctrl]) + { + delta.flags |= V_TextboxDeltaFlag_InheritTextFromClipboard | V_TextboxDeltaFlag_UpdateText; + } + else if (text.len > 0 && !MatchString(text, Lit("\n")) && !MatchString(text, Lit("\t")) && !MatchString(text, Lit("\r"))) + { + delta.flags |= V_TextboxDeltaFlag_UpdateText; delta.text = text; } if (delta.flags) { if (frame->held_buttons[Button_Shift]) { - delta.flags |= V_TextBoxDeltaFlag_NavSelect; + delta.flags |= V_TextboxDeltaFlag_NavSelect; } if (frame->held_buttons[Button_Ctrl]) { - delta.flags |= V_TextBoxDeltaFlag_NavWord; + delta.flags |= V_TextboxDeltaFlag_NavWord; } } } - if (delta.flags) + if (delta.flags != 0) { - V_TextBoxDeltaNode *tbd_node = PushStruct(frame->arena, V_TextBoxDeltaNode); + V_TextboxDeltaNode *tbd_node = PushStruct(frame->arena, V_TextboxDeltaNode); tbd_node->delta = delta; SllQueuePush(text_input_deltas.first, text_input_deltas.last, tbd_node); } @@ -4368,87 +4518,63 @@ void V_TickForever(WaveLaneCtx *lane) { UI_Key search_box = UI_KeyF("search box"); UI_BoxReport search_report = UI_ReportsFromKey(search_box).draw; - V_TextBoxState *search_state = &palette->search_state; + V_TextboxState *search_state = &palette->search_state; + + b32 has_focus = UI_MatchKey(search_box, prev_frame->keyboard_focus_box); + + // FIXME: Remove this + has_focus = 1; // if (search_report.m1.downs) - if (search_report.m1.downs || !UI_MatchKey(search_box, V.keyboard_focus_box)) + if (search_report.m1.downs) { - V.keyboard_focus_box = search_box; + has_focus = 1; V.text_input_ns = frame->time_ns; } - b32 has_focus = UI_MatchKey(search_box, V.keyboard_focus_box); if (search_report.is_hot) { WND_SetCursor(window_frame, WND_CursorKind_Text); } - if (has_focus && text_input_deltas.first) + if (has_focus) { - V_ApplyTextBoxDeltas(search_state, text_input_deltas); + frame->keyboard_focus_box = search_box; + if (text_input_deltas.first) + { + V.text_input_ns = frame->time_ns; + V_ApplyTextboxDeltas(search_state, text_input_deltas); + } } - // FIXME: Remove this - if (frame->held_buttons[Button_B] && !prev_frame->held_buttons[Button_B]) - { - V_TextBoxDelta delta = Zi; - // delta.kind = V_DeltaKind_ - delta.text = Lit("Hi"); - // delta.range = RNGI64(I64Max, I64Max); - - // delta.start = search_state->start; - // delta.end = search_state->end; - - // delta.start = 0; - // delta.end = 1; - - delta.flags |= V_TextBoxDeltaFlag_UpdateText; - - V_ApplyTextBoxDelta(search_state, delta); - } - - + // // FIXME: Remove this + // if (frame->held_buttons[Button_B] && !prev_frame->held_buttons[Button_B]) // { - // V_TextBoxDelta delta = Zi; + // V_TextboxDelta delta = Zi; + // // delta.kind = V_DeltaKind_ + // delta.text = Lit("Hi"); + // // delta.range = RNGI64(I64Max, I64Max); - // // FIXME: Remove this - // if (frame->held_buttons[Button_Left] && !prev_frame->held_buttons[Button_Left]) - // { - // delta.flags |= V_TextBoxDeltaFlag_NavLeft; - // } - // if (frame->held_buttons[Button_Right] && !prev_frame->held_buttons[Button_Right]) - // { - // delta.flags |= V_TextBoxDeltaFlag_NavRight; - // } + // // delta.start = search_state->start; + // // delta.end = search_state->end; - // if (delta.flags) - // { - // if (frame->held_buttons[Button_Shift]) - // { - // delta.flags |= V_TextBoxDeltaFlag_NavSelect; - // } - // if (frame->held_buttons[Button_Ctrl]) - // { - // delta.flags |= V_TextBoxDeltaFlag_NavWord; - // } - // V_ApplyTextBoxDelta(search_state, delta); - // V.text_input_ns = frame->time_ns; - // } + // // delta.start = 0; + // // delta.end = 1; + + // delta.flags |= V_TextboxDeltaFlag_UpdateText; + + // V_ApplyTextboxDelta(search_state, delta); // } - - - - - search_text = V_StringFromTextBox(search_state); + search_text = V_StringFromTextbox(search_state); is_searching = search_text.len != 0; diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index b41c9b26..9a3b5e8e 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -157,44 +157,47 @@ Struct(V_Notif) //////////////////////////////////////////////////////////// //~ Text box types -#define V_MaxTextBoxLen 1024 +#define V_MaxTextboxLen 1024 -Enum(V_TextBoxDeltaFlag) +Enum(V_TextboxDeltaFlag) { - V_TextBoxDeltaFlag_None = 0, - V_TextBoxDeltaFlag_UpdateText = (1 << 0), - V_TextBoxDeltaFlag_NavDirect = (1 << 1), - V_TextBoxDeltaFlag_NavLeft = (1 << 2), - V_TextBoxDeltaFlag_NavRight = (1 << 3), - V_TextBoxDeltaFlag_NavWord = (1 << 4), - V_TextBoxDeltaFlag_NavLine = (1 << 5), - V_TextBoxDeltaFlag_NavSelect = (1 << 6), + V_TextboxDeltaFlag_None = 0, + V_TextboxDeltaFlag_UpdateText = (1 << 0), + V_TextboxDeltaFlag_OnlyNavIfSelectionEmpty = (1 << 1), + V_TextboxDeltaFlag_CopySelectionToClipboard = (1 << 2), + V_TextboxDeltaFlag_InheritTextFromClipboard = (1 << 3), + V_TextboxDeltaFlag_NavDirect = (1 << 4), + V_TextboxDeltaFlag_NavLeft = (1 << 5), + V_TextboxDeltaFlag_NavRight = (1 << 6), + V_TextboxDeltaFlag_NavWord = (1 << 7), + V_TextboxDeltaFlag_NavLine = (1 << 8), + V_TextboxDeltaFlag_NavSelect = (1 << 9), }; -Struct(V_TextBoxDelta) +Struct(V_TextboxDelta) { - V_TextBoxDeltaFlag flags; + V_TextboxDeltaFlag flags; String text; i64 direct_start; i64 direct_end; }; -Struct(V_TextBoxDeltaNode) +Struct(V_TextboxDeltaNode) { - V_TextBoxDeltaNode *next; - V_TextBoxDelta delta; + V_TextboxDeltaNode *next; + V_TextboxDelta delta; }; -Struct(V_TextBoxDeltaList) +Struct(V_TextboxDeltaList) { - V_TextBoxDeltaNode *first; - V_TextBoxDeltaNode *last; + V_TextboxDeltaNode *first; + V_TextboxDeltaNode *last; }; -Struct(V_TextBoxState) +Struct(V_TextboxState) { i64 len; - u8 text[V_MaxTextBoxLen]; + u8 text[V_MaxTextboxLen]; i64 start; i64 end; @@ -210,7 +213,7 @@ Struct(V_Palette) b32 is_showing; f32 show; - V_TextBoxState search_state; + V_TextboxState search_state; }; //////////////////////////////////////////////////////////// @@ -325,6 +328,8 @@ Struct(V_Frame) Button held_buttons[Button_COUNT]; V_Palette palette; + UI_Key keyboard_focus_box; + String window_restore; // Vis commands @@ -350,7 +355,6 @@ Struct(V_Ctx) V_Panel *root_panel; V_Window *dragging_window; - UI_Key keyboard_focus_box; i64 text_input_ns; i64 connect_try_ns; @@ -402,10 +406,11 @@ void V_DrawPoint(Vec2 p, Vec4 srgb); //////////////////////////////////////////////////////////// //~ Text box -void V_ApplyTextBoxDelta(V_TextBoxState *tb, V_TextBoxDelta delta); -void V_ApplyTextBoxDeltas(V_TextBoxState *tb, V_TextBoxDeltaList deltas); +void V_ApplyTextboxDelta(V_TextboxState *tb, V_TextboxDelta delta); +void V_ApplyTextboxDeltas(V_TextboxState *tb, V_TextboxDeltaList deltas); -String V_StringFromTextBox(V_TextBoxState *tb); +String V_StringFromTextbox(V_TextboxState *tb); +String V_StringFromTextboxSelection(V_TextboxState *tb); //////////////////////////////////////////////////////////// //~ Timeline helpers diff --git a/src/window/window_win32/window_win32.c b/src/window/window_win32/window_win32.c index db6ed55f..fb95935e 100644 --- a/src/window/window_win32/window_win32.c +++ b/src/window/window_win32/window_win32.c @@ -331,6 +331,7 @@ LRESULT CALLBACK WND_W32_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM l Utf8EncodeResult encoded = EncodeUtf8(codepoint); ControllerEvent event = Zi; event.kind = ControllerEventKind_Text; + event.text_codepoint = codepoint; event.text_chars_count = MinU32(encoded.count8, countof(event.text_chars)); CopyBytes(event.text_chars, encoded.chars8, event.text_chars_count); WND_W32_PushEvent(window, event); @@ -348,10 +349,12 @@ LRESULT CALLBACK WND_W32_WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM l case WM_XBUTTONDOWN: { ControllerEvent event = Zi; - b32 is_down = msg == WM_LBUTTONDOWN || - msg == WM_MBUTTONDOWN || - msg == WM_RBUTTONDOWN || - msg == WM_XBUTTONDOWN; + b32 is_down = ( + msg == WM_LBUTTONDOWN || + msg == WM_MBUTTONDOWN || + msg == WM_RBUTTONDOWN || + msg == WM_XBUTTONDOWN + ); if (is_down) { event.kind = ControllerEventKind_ButtonDown;