From 0c4f32fb1d04657916d7da9ef94f82bb435a1a5e Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Tue, 1 Oct 2013 18:29:22 +0100 Subject: Make undo and redo share common implementation. --- desktop/textarea.c | 100 +++++++++++++++-------------------------------------- 1 file changed, 28 insertions(+), 72 deletions(-) (limited to 'desktop') diff --git a/desktop/textarea.c b/desktop/textarea.c index a1ebe0ddc..b112a6bcb 100644 --- a/desktop/textarea.c +++ b/desktop/textarea.c @@ -1600,14 +1600,15 @@ static bool textarea_replace_text(struct textarea *ta, size_t b_start, /** - * Undo previous change. + * Undo or redo previous change. * * \param ta Textarea widget + * \param forward Iff true, redo, else undo * \param caret Updated to new caret pos in textarea (ta->show) * \param r Updated to area where redraw is required - * \return false if nothing to undo, true otherwise + * \return false if nothing to undo/redo, true otherwise */ -static bool textarea_undo(struct textarea *ta, +static bool textarea_undo(struct textarea *ta, bool forward, unsigned int *caret, struct rect *r) { unsigned int detail_n; @@ -1617,84 +1618,32 @@ static bool textarea_undo(struct textarea *ta, unsigned int b_text_len; int byte_delta; - if (ta->flags & TEXTAREA_PASSWORD) - /* No undo for password fields */ - return false; - - if (ta->undo.next_detail == 0) - /* Nothing to undo */ + if (ta->flags & TEXTAREA_PASSWORD || ta->flags & TEXTAREA_READONLY) + /* No undo/redo for password or readonly fields */ return false; - detail_n = ta->undo.next_detail - 1; - detail = &(ta->undo.details[detail_n]); - - b_len = detail->b_end - detail->b_start; - b_text_len = detail->b_text_end - detail->b_text_start; + if (forward) { + /* Redo */ + if (ta->undo.next_detail > ta->undo.last_detail) + /* Nothing to redo */ + return false; - /* Take copy of any current textarea text that undo will remove */ - if (detail->b_text_end > detail->b_text_start) { - temp = malloc(b_text_len); - if (temp == NULL) { - /* TODO */ + detail_n = ta->undo.next_detail; + } else { + /* Undo */ + if (ta->undo.next_detail == 0) + /* Nothing to undo */ return false; - } - memcpy(temp, ta->text.data + detail->b_text_start, b_text_len); + detail_n = ta->undo.next_detail - 1; } - /* Replace textarea text with undo buffer text */ - textarea_replace_text_internal(ta, - detail->b_text_start, detail->b_text_end, - ta->undo.text.data + detail->b_start, b_len, - false, &byte_delta, r); - - /* Update undo buffer for redo */ - memcpy(ta->undo.text.data + detail->b_start, temp, b_text_len); - detail->b_text_end = detail->b_text_start + b_len; - detail->b_end = detail->b_start + b_text_len; - - *caret = detail->b_text_end; - ta->undo.next_detail--; - - free(temp); - - return true; -} - - -/** - * Redo previous undo. - * - * \param ta Textarea widget - * \param caret Updated to new caret pos in textarea (ta->show) - * \param r Updated to area where redraw is required - * \return false if nothing to redo, true otherwise - */ -static bool textarea_redo(struct textarea *ta, - unsigned int *caret, struct rect *r) -{ - unsigned int detail_n; - struct textarea_undo_detail *detail; - char *temp = NULL; - unsigned int b_len; - unsigned int b_text_len; - int byte_delta; - - if (ta->flags & TEXTAREA_PASSWORD) - /* No redo for password fields */ - return false; - - if (ta->undo.next_detail > ta->undo.last_detail) - /* Nothing to redo */ - return false; - - detail_n = ta->undo.next_detail; detail = &(ta->undo.details[detail_n]); b_len = detail->b_end - detail->b_start; b_text_len = detail->b_text_end - detail->b_text_start; - /* Take copy of any current textarea text that redo will remove */ + /* Take copy of any current textarea text that undo/redo will remove */ if (detail->b_text_end > detail->b_text_start) { temp = malloc(b_text_len); if (temp == NULL) { @@ -1717,7 +1666,14 @@ static bool textarea_redo(struct textarea *ta, detail->b_end = detail->b_start + b_text_len; *caret = detail->b_text_end; - ta->undo.next_detail++; + + if (forward) { + /* Redo */ + ta->undo.next_detail++; + } else { + /* Undo */ + ta->undo.next_detail--; + } free(temp); @@ -2792,7 +2748,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key) caret += byte_delta; break; case KEY_UNDO: - if (!textarea_undo(ta, &caret, &r)) { + if (!textarea_undo(ta, false, &caret, &r)) { /* We consume the UNDO, even if we can't act * on it. */ return true; @@ -2803,7 +2759,7 @@ bool textarea_keypress(struct textarea *ta, uint32_t key) redraw = true; break; case KEY_REDO: - if (!textarea_redo(ta, &caret, &r)) { + if (!textarea_undo(ta, true, &caret, &r)) { /* We consume the REDO, even if we can't act * on it. */ return true; -- cgit v1.2.3