Skip to content

Growing a vector from InputTextMultiline #1443

Closed
@ghost

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.

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions