-
Notifications
You must be signed in to change notification settings - Fork 7.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
stb_textedit: Undo weirdness after failed paste #734
Comments
Hello, I'm looking at this now:
For maintainer: I can confirm this, ocornut/imgui#4038 has a repro which should be easy to replicate outside of Dear ImGui (by using same inputs sequence and same buffer size). Dear ImGui doesn't change the default value of
The wording in comment is a little ambiguous, but the code might have been aimed at undoing the work of the The failure conditions are: (A)
and (B)
Fix v1Exactly as suggested above, deleting that block is a simple fix. // remove the undo since we didn't actually insert the characters
if (state->undostate.undo_point)
--state->undostate.undo_point; On a paste failure it will however leave the selection deleted (which can be undone with a further ctrl+z). Fix v2If we want paste failure to leave the buffer untouched (no deletion of selection) we'd need to essentially undo the deletion. I first tried to compare value of
typedef struct
{
...
int unique_created_records;
} StbUndoState; 2 Increment: static StbUndoRecord *stb_text_create_undo_record(StbUndoState *state, int numchars)
{
...
state->unique_created_records++;
return &state->undo_rec[state->undo_point++];
}
static int stb_textedit_paste_internal(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
{
// if there's a selection, the paste should delete it
int unique_created_records_before_deletion;
int unique_created_records_after_deletion;
stb_textedit_clamp(str, state);
unique_created_records_before_deletion = state->undostate.unique_created_records;
stb_textedit_delete_selection(str,state);
unique_created_records_after_deletion = state->undostate.unique_created_records;
// try to insert the characters
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, len)) {
stb_text_makeundo_insert(state, state->cursor, len);
state->cursor += len;
state->has_preferred_x = 0;
return 1;
}
// remove the undo since we didn't actually insert the characters
if (unique_created_records_after_deletion > unique_created_records_before_deletion)
stb_text_undo(str, state);
return 0;
} With this a paste failure (no room for insertion) should leave buffer untouched IF there is room for deletion in the undo buffer in the first place. So in a way it is an improvement over V1.... or it is? Considering that CTRL+A followed by CTRL+V may be common sequence leading to paste failure, and that "storing old text in undo buffer" is as likely to fail as actual new text insertion (because undo buffer is fixed size and cannot be resized): one could argue that fix v1 (always leave old text deleted on paste failure, might still be in undo stack) has the merit to be more consistent than fix v2 (only leave old text deleted on paste failure if couldn't be stored in undo stack). Neither are perfectly right but if I have to be honest, in 6+ years no one complained of storage limitations in the undo buffer other than bugs so I'd say Fix v1 is fine and has the merit to be simpler. |
Could lead to freezes. Fixes issue #734.
Fix for this is merged into dev branch, will be in the next release. |
We've noticed some weirdness caused by the undo_point being erroneously adjusted after a failed paste.
We believe this is happening because
stb_textedit_paste_internal
decrementsstate->undostate.undo_point
if the paste fails, but the undo hadn't been created yet (contrary to the comment above the decrement). It looks like the undo it's trying to remove is the one created bystb_text_makeundo_insert
, which won't have happened if the insertion failed.This is the current version of
stb_textedit_paste_internal
:We've fixed this locally by removing the decrement, but I wanted to check your thoughts on this.
EDIT:
Forgot to mention that we've seen a soft-lock caused by this too in the case where the undo_char buffer has been filled up followed by a failed paste.
stb_text_create_undo_record
will lock-up in this while loop becausestb_textedit_discard_undo
does nothing ifundo_point==0
, which can happen due to the erroneous decrement.The text was updated successfully, but these errors were encountered: