@ -4029,9 +4029,21 @@ static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* st
} // namespace ImStb
// We added an extra indirection where 'Stb' is heap-allocated, in order facilitate the work of bindings generators.
ImGuiInputTextState : : ImGuiInputTextState ( )
{
memset ( this , 0 , sizeof ( * this ) ) ;
Stb = IM_NEW ( ImStbTexteditState ) ;
}
ImGuiInputTextState : : ~ ImGuiInputTextState ( )
{
IM_DELETE ( Stb ) ;
}
void ImGuiInputTextState : : OnKeyPressed ( int key )
{
stb_textedit_key ( this , & Stb , key ) ;
stb_textedit_key ( this , Stb , key ) ;
CursorFollow = true ;
CursorAnimReset ( ) ;
}
@ -4229,7 +4241,7 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st
const int insert_len = new_last_diff - first_diff + 1 ;
const int delete_len = old_last_diff - first_diff + 1 ;
if ( insert_len > 0 | | delete_len > 0 )
if ( IMSTB_TEXTEDIT_CHARTYPE * p = stb_text_createundo ( & state - > Stb . undostate , first_diff , delete_len , insert_len ) )
if ( IMSTB_TEXTEDIT_CHARTYPE * p = stb_text_createundo ( & state - > Stb - > undostate , first_diff , delete_len , insert_len ) )
for ( int i = 0 ; i < delete_len ; i + + )
p [ i ] = ImStb : : STB_TEXTEDIT_GETCHAR ( state , first_diff + i ) ;
}
@ -4371,7 +4383,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
float scroll_y = is_multiline ? draw_window - > Scroll . y : FLT_MAX ;
const bool init_reload_from_user_buf = ( state ! = NULL & & state - > ReloadUserBuf ) ;
const bool init_changed_specs = ( state ! = NULL & & state - > Stb . single_line ! = ! is_multiline ) ; // state != NULL means its our state.
const bool init_changed_specs = ( state ! = NULL & & state - > Stb - > single_line ! = ! is_multiline ) ; // state != NULL means its our state.
const bool init_make_active = ( user_clicked | | user_scroll_finish | | input_requested_by_nav ) ;
const bool init_state = ( init_make_active | | user_scroll_active ) ;
if ( ( init_state & & g . ActiveId ! = id ) | | init_changed_specs | | init_reload_from_user_buf )
@ -4417,13 +4429,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
else
{
state - > Scroll = ImVec2 ( 0.0f , 0.0f ) ;
stb_textedit_initialize_state ( & state - > Stb , ! is_multiline ) ;
stb_textedit_initialize_state ( state - > Stb , ! is_multiline ) ;
}
if ( init_reload_from_user_buf )
{
state - > Stb . select_start = state - > ReloadSelectionStart ;
state - > Stb . cursor = state - > Stb . select_end = state - > ReloadSelectionEnd ;
state - > Stb - > select_start = state - > ReloadSelectionStart ;
state - > Stb - > cursor = state - > Stb - > select_end = state - > ReloadSelectionEnd ;
state - > CursorClamp ( ) ;
}
else if ( ! is_multiline )
@ -4437,7 +4449,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
if ( flags & ImGuiInputTextFlags_AlwaysOverwrite )
state - > Stb . insert_mode = 1 ; // stb field name is indeed incorrect (see #2863)
state - > Stb - > insert_mode = 1 ; // stb field name is indeed incorrect (see #2863)
}
const bool is_osx = io . ConfigMacOSXBehaviors ;
@ -4545,34 +4557,34 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
else if ( hovered & & io . MouseClickedCount [ 0 ] > = 2 & & ! io . KeyShift )
{
stb_textedit_click ( state , & state - > Stb , mouse_x , mouse_y ) ;
stb_textedit_click ( state , state - > Stb , mouse_x , mouse_y ) ;
const int multiclick_count = ( io . MouseClickedCount [ 0 ] - 2 ) ;
if ( ( multiclick_count % 2 ) = = 0 )
{
// Double-click: Select word
// We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant:
// FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS)
const bool is_bol = ( state - > Stb . cursor = = 0 ) | | ImStb : : STB_TEXTEDIT_GETCHAR ( state , state - > Stb . cursor - 1 ) = = ' \n ' ;
if ( STB_TEXT_HAS_SELECTION ( & state - > Stb ) | | ! is_bol )
const bool is_bol = ( state - > Stb - > cursor = = 0 ) | | ImStb : : STB_TEXTEDIT_GETCHAR ( state , state - > Stb - > cursor - 1 ) = = ' \n ' ;
if ( STB_TEXT_HAS_SELECTION ( state - > Stb ) | | ! is_bol )
state - > OnKeyPressed ( STB_TEXTEDIT_K_WORDLEFT ) ;
//state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
if ( ! STB_TEXT_HAS_SELECTION ( & state - > Stb ) )
ImStb : : stb_textedit_prep_selection_at_cursor ( & state - > Stb ) ;
state - > Stb . cursor = ImStb : : STB_TEXTEDIT_MOVEWORDRIGHT_MAC ( state , state - > Stb . cursor ) ;
state - > Stb . select_end = state - > Stb . cursor ;
ImStb : : stb_textedit_clamp ( state , & state - > Stb ) ;
if ( ! STB_TEXT_HAS_SELECTION ( state - > Stb ) )
ImStb : : stb_textedit_prep_selection_at_cursor ( state - > Stb ) ;
state - > Stb - > cursor = ImStb : : STB_TEXTEDIT_MOVEWORDRIGHT_MAC ( state , state - > Stb - > cursor ) ;
state - > Stb - > select_end = state - > Stb - > cursor ;
ImStb : : stb_textedit_clamp ( state , state - > Stb ) ;
}
else
{
// Triple-click: Select line
const bool is_eol = ImStb : : STB_TEXTEDIT_GETCHAR ( state , state - > Stb . cursor ) = = ' \n ' ;
const bool is_eol = ImStb : : STB_TEXTEDIT_GETCHAR ( state , state - > Stb - > cursor ) = = ' \n ' ;
state - > OnKeyPressed ( STB_TEXTEDIT_K_LINESTART ) ;
state - > OnKeyPressed ( STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT ) ;
state - > OnKeyPressed ( STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT ) ;
if ( ! is_eol & & is_multiline )
{
ImSwap ( state - > Stb . select_start , state - > Stb . select_end ) ;
state - > Stb . cursor = state - > Stb . select_end ;
ImSwap ( state - > Stb - > select_start , state - > Stb - > select_end ) ;
state - > Stb - > cursor = state - > Stb - > select_end ;
}
state - > CursorFollow = false ;
}
@ -4583,15 +4595,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if ( hovered )
{
if ( io . KeyShift )
stb_textedit_drag ( state , & state - > Stb , mouse_x , mouse_y ) ;
stb_textedit_drag ( state , state - > Stb , mouse_x , mouse_y ) ;
else
stb_textedit_click ( state , & state - > Stb , mouse_x , mouse_y ) ;
stb_textedit_click ( state , state - > Stb , mouse_x , mouse_y ) ;
state - > CursorAnimReset ( ) ;
}
}
else if ( io . MouseDown [ 0 ] & & ! state - > SelectedAllMouseLock & & ( io . MouseDelta . x ! = 0.0f | | io . MouseDelta . y ! = 0.0f ) )
{
stb_textedit_drag ( state , & state - > Stb , mouse_x , mouse_y ) ;
stb_textedit_drag ( state , state - > Stb , mouse_x , mouse_y ) ;
state - > CursorAnimReset ( ) ;
state - > CursorFollow = true ;
}
@ -4644,7 +4656,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
IM_ASSERT ( state ! = NULL ) ;
const int row_count_per_page = ImMax ( ( int ) ( ( inner_size . y - style . FramePadding . y ) / g . FontSize ) , 1 ) ;
state - > Stb . row_count_per_page = row_count_per_page ;
state - > Stb - > row_count_per_page = row_count_per_page ;
const int k_mask = ( io . KeyShift ? STB_TEXTEDIT_K_SHIFT : 0 ) ;
const bool is_wordmove_key_down = is_osx ? io . KeyAlt : io . KeyCtrl ; // OS X style: Text editing cursor movement using Alt instead of Ctrl
@ -4751,8 +4763,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Cut, Copy
if ( g . PlatformIO . Platform_SetClipboardTextFn ! = NULL )
{
const int ib = state - > HasSelection ( ) ? ImMin ( state - > Stb . select_start , state - > Stb . select_end ) : 0 ;
const int ie = state - > HasSelection ( ) ? ImMax ( state - > Stb . select_start , state - > Stb . select_end ) : state - > CurLenW ;
const int ib = state - > HasSelection ( ) ? ImMin ( state - > Stb - > select_start , state - > Stb - > select_end ) : 0 ;
const int ie = state - > HasSelection ( ) ? ImMax ( state - > Stb - > select_start , state - > Stb - > select_end ) : state - > CurLenW ;
const int clipboard_data_len = ImTextCountUtf8BytesFromStr ( state - > TextW . Data + ib , state - > TextW . Data + ie ) + 1 ;
char * clipboard_data = ( char * ) IM_ALLOC ( clipboard_data_len * sizeof ( char ) ) ;
ImTextStrToUtf8 ( clipboard_data , clipboard_data_len , state - > TextW . Data + ib , state - > TextW . Data + ie ) ;
@ -4764,7 +4776,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if ( ! state - > HasSelection ( ) )
state - > SelectAll ( ) ;
state - > CursorFollow = true ;
stb_textedit_cut ( state , & state - > Stb ) ;
stb_textedit_cut ( state , state - > Stb ) ;
}
}
else if ( is_paste )
@ -4786,7 +4798,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
clipboard_filtered [ clipboard_filtered_len ] = 0 ;
if ( clipboard_filtered_len > 0 ) // If everything was filtered, ignore the pasting operation
{
stb_textedit_paste ( state , & state - > Stb , clipboard_filtered , clipboard_filtered_len ) ;
stb_textedit_paste ( state , state - > Stb , clipboard_filtered , clipboard_filtered_len ) ;
state - > CursorFollow = true ;
}
MemFree ( clipboard_filtered ) ;
@ -4813,7 +4825,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
apply_new_text_length = 0 ;
value_changed = true ;
IMSTB_TEXTEDIT_CHARTYPE empty_string ;
stb_textedit_replace ( state , & state - > Stb , & empty_string , 0 ) ;
stb_textedit_replace ( state , state - > Stb , & empty_string , 0 ) ;
}
else if ( strcmp ( buf , state - > InitialTextA . Data ) ! = 0 )
{
@ -4828,7 +4840,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
w_text . resize ( ImTextCountCharsFromUtf8 ( apply_new_text , apply_new_text + apply_new_text_length ) + 1 ) ;
ImTextStrFromUtf8 ( w_text . Data , w_text . Size , apply_new_text , apply_new_text + apply_new_text_length ) ;
}
stb_textedit_replace ( state , & state - > Stb , w_text . Data , ( apply_new_text_length > 0 ) ? ( w_text . Size - 1 ) : 0 ) ;
stb_textedit_replace ( state , state - > Stb , w_text . Data , ( apply_new_text_length > 0 ) ? ( w_text . Size - 1 ) : 0 ) ;
}
}
@ -4903,9 +4915,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We have to convert from wchar-positions to UTF-8-positions, which can be pretty slow (an incentive to ditch the ImWchar buffer, see https://github.com/nothings/stb/issues/188)
ImWchar * text = state - > TextW . Data ;
const int utf8_cursor_pos = callback_data . CursorPos = ImTextCountUtf8BytesFromStr ( text , text + state - > Stb . cursor ) ;
const int utf8_selection_start = callback_data . SelectionStart = ImTextCountUtf8BytesFromStr ( text , text + state - > Stb . select_start ) ;
const int utf8_selection_end = callback_data . SelectionEnd = ImTextCountUtf8BytesFromStr ( text , text + state - > Stb . select_end ) ;
const int utf8_cursor_pos = callback_data . CursorPos = ImTextCountUtf8BytesFromStr ( text , text + state - > Stb - > cursor ) ;
const int utf8_selection_start = callback_data . SelectionStart = ImTextCountUtf8BytesFromStr ( text , text + state - > Stb - > select_start ) ;
const int utf8_selection_end = callback_data . SelectionEnd = ImTextCountUtf8BytesFromStr ( text , text + state - > Stb - > select_end ) ;
// Call user code
callback ( & callback_data ) ;
@ -4916,9 +4928,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
IM_ASSERT ( callback_data . BufSize = = state - > BufCapacityA ) ;
IM_ASSERT ( callback_data . Flags = = flags ) ;
const bool buf_dirty = callback_data . BufDirty ;
if ( callback_data . CursorPos ! = utf8_cursor_pos | | buf_dirty ) { state - > Stb . cursor = ImTextCountCharsFromUtf8 ( callback_data . Buf , callback_data . Buf + callback_data . CursorPos ) ; state - > CursorFollow = true ; }
if ( callback_data . SelectionStart ! = utf8_selection_start | | buf_dirty ) { state - > Stb . select_start = ( callback_data . SelectionStart = = callback_data . CursorPos ) ? state - > Stb . cursor : ImTextCountCharsFromUtf8 ( callback_data . Buf , callback_data . Buf + callback_data . SelectionStart ) ; }
if ( callback_data . SelectionEnd ! = utf8_selection_end | | buf_dirty ) { state - > Stb . select_end = ( callback_data . SelectionEnd = = callback_data . SelectionStart ) ? state - > Stb . select_start : ImTextCountCharsFromUtf8 ( callback_data . Buf , callback_data . Buf + callback_data . SelectionEnd ) ; }
if ( callback_data . CursorPos ! = utf8_cursor_pos | | buf_dirty ) { state - > Stb - > cursor = ImTextCountCharsFromUtf8 ( callback_data . Buf , callback_data . Buf + callback_data . CursorPos ) ; state - > CursorFollow = true ; }
if ( callback_data . SelectionStart ! = utf8_selection_start | | buf_dirty ) { state - > Stb - > select_start = ( callback_data . SelectionStart = = callback_data . CursorPos ) ? state - > Stb - > cursor : ImTextCountCharsFromUtf8 ( callback_data . Buf , callback_data . Buf + callback_data . SelectionStart ) ; }
if ( callback_data . SelectionEnd ! = utf8_selection_end | | buf_dirty ) { state - > Stb - > select_end = ( callback_data . SelectionEnd = = callback_data . SelectionStart ) ? state - > Stb - > select_start : ImTextCountCharsFromUtf8 ( callback_data . Buf , callback_data . Buf + callback_data . SelectionEnd ) ; }
if ( buf_dirty )
{
// Callback may update buffer and thus set buf_dirty even in read-only mode.
@ -5040,13 +5052,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
int searches_remaining = 0 ;
if ( render_cursor )
{
searches_input_ptr [ 0 ] = text_begin + state - > Stb . cursor ;
searches_input_ptr [ 0 ] = text_begin + state - > Stb - > cursor ;
searches_result_line_no [ 0 ] = - 1 ;
searches_remaining + + ;
}
if ( render_selection )
{
searches_input_ptr [ 1 ] = text_begin + ImMin ( state - > Stb . select_start , state - > Stb . select_end ) ;
searches_input_ptr [ 1 ] = text_begin + ImMin ( state - > Stb - > select_start , state - > Stb - > select_end ) ;
searches_result_line_no [ 1 ] = - 1 ;
searches_remaining + + ;
}
@ -5122,8 +5134,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const ImVec2 draw_scroll = ImVec2 ( state - > Scroll . x , 0.0f ) ;
if ( render_selection )
{
const ImWchar * text_selected_begin = text_begin + ImMin ( state - > Stb . select_start , state - > Stb . select_end ) ;
const ImWchar * text_selected_end = text_begin + ImMax ( state - > Stb . select_start , state - > Stb . select_end ) ;
const ImWchar * text_selected_begin = text_begin + ImMin ( state - > Stb - > select_start , state - > Stb - > select_end ) ;
const ImWchar * text_selected_end = text_begin + ImMax ( state - > Stb - > select_start , state - > Stb - > select_end ) ;
ImU32 bg_color = GetColorU32 ( ImGuiCol_TextSelectedBg , render_cursor ? 1.0f : 0.6f ) ; // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests.
float bg_offy_up = is_multiline ? 0.0f : - 1.0f ; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.
@ -5244,7 +5256,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
{
# ifndef IMGUI_DISABLE_DEBUG_TOOLS
ImGuiContext & g = * GImGui ;
ImStb : : STB_TexteditState * stb_state = & state - > Stb ;
ImStb : : STB_TexteditState * stb_state = state - > Stb ;
ImStb : : StbUndoState * undo_state = & stb_state - > undostate ;
Text ( " ID: 0x%08X, ActiveID: 0x%08X " , state - > ID , g . ActiveId ) ;
DebugLocateItemOnHover ( state - > ID ) ;