Description
I did search online but could not find anything about it and so I wanted to propose my solution to the problem.
Wait a minute, what am I talking about (O.o")? Let's start from the beginning ...
... Hi! ... oops I think I have gone too far back XD ... excuse me ... Let me retry ... I was playing with InputTextMultiline when I noticed that there is not an official way to use a dynamic-allocated buffer (e.g. vector) for text typing and so you need to specify the size that may be a limit like in my case.
I apologize in advance if I am wrong was not my intention to disturb you.
Below my solution,
I wanted it compatible with the official version so I had not to modify anything other than InputTextMultiline and InputTextEx.
InputTextEx
I added a pointer to the vector, as optional parameter, that will be used only in case you have not a defined size while maintaining the function compatible for all other calls.
bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data, ImVector<char>* v)
I could not know how many characters I would have to add without first filtering them so I push them into a temporary vector that will be used immediately afterwards to reallocate the two vectors. Next, I call OnKeyPressed to append the characters.
if (io.InputCharacters[0])
{
// Process text input (before we check for Return because using some IME will effectively send a Return?)
// We ignore CTRL inputs, but need to allow CTRL+ALT as some keyboards (e.g. German) use AltGR - which is Alt+Ctrl - to input certain characters.
ImVector<int> filtered_input_characters;
if (!(io.KeyCtrl && !io.KeyAlt) && is_editable)
{
for (int n = 0; n < IM_ARRAYSIZE(io.InputCharacters) && io.InputCharacters[n]; n++)
if (unsigned int c = (unsigned int)io.InputCharacters[n])
{
if (!InputTextFilterCharacter(&c, flags, callback, user_data))
continue;
// Push the filtered character into a temporary vector for future use
filtered_input_characters.push_back((int)c);
}
}
// Check whether buf is referencing to v
// and make sure buf is the same as v->Data
if (v && buf == v->Data)
{
// Increase buf_size for future use
buf_size += filtered_input_characters.Size;
// Resize both vectors to have enough space to contain the filtered characters
edit_state.Text.resize(buf_size + 1);
v->resize(edit_state.Text.Size);
// Update BufSizeA
edit_state.BufSizeA = buf_size;
}
// Handle key press
for (int c : filtered_input_characters)
edit_state.OnKeyPressed(c);
memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters));
}
InputTextMultiline
I added a second definition of the InputTextMultiline function this time though using a vector. I check the vector size to make it safer to use by guaranteeing the validity of the pointer Data even if not initialized. I pass the vector address as last parameter.
bool ImGui::InputTextMultiline(const char* label, ImVector<char>& v, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data)
{
if (v.Size < 1) // Make sure Data is a valid pointer
v.push_back('\0'); // equivalent of v.resize(1); v.Data[0] = '\0';
return InputTextEx(label, v.Data, v.Size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data, &v);
}
ImVector
I had to make the ImVector class visible to the InputTextMultiline function.
template<typename T>
class ImVector; // Needed for InputTextMultiline
// ImGui end-user API
// In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types)
namespace ImGui
{
I hope to have been helpful and thank all those who have contributed to realize this masterpiece.
I apologize for my english and I look forward to your opinion on this.