diff options
Diffstat (limited to 'desktop')
-rw-r--r-- | desktop/local_history.c | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/desktop/local_history.c b/desktop/local_history.c index ddebbbe58..aa70ebb42 100644 --- a/desktop/local_history.c +++ b/desktop/local_history.c @@ -434,6 +434,36 @@ local_history_mouse_action(struct local_history_session *session, return NSERROR_OK; } +/** + * Determine the point on the parent line where this history line branches. + * + * If `branch_point` gets set then there is a guarantee that (a) `ent` is + * a transitive child (forward) of that point. and (b) `branch_point` has a + * parent. + * + * \param[in] ent The entry to work backward from + * \param[out] branch_point The entry to set to the branch point if one is found + */ +static void +_local_history_find_branch_point(struct history_entry *ent, + struct history_entry **branch_point) +{ + if (ent->back == NULL) { + /* We're at the root, nothing to do */ + return; + } + /* Start from our immediate parent */ + ent = ent->back; + while (ent->back != NULL) { + if (ent->back->forward != ent->back->forward_last) { + /* This point is a branch */ + *branch_point = ent; + break; + } + ent = ent->back; + } +} + /* exported interface documented in desktop/local_history.h */ bool local_history_keypress(struct local_history_session *session, uint32_t key) @@ -452,7 +482,7 @@ local_history_keypress(struct local_history_session *session, uint32_t key) return true; case NS_KEY_LEFT: /* Go to parent */ - if (session->cursor->back) { + if (session->cursor->back != NULL) { session->cursor = session->cursor->back; local_history_scroll_to_cursor(session); session->cw_t->invalidate(session->core_window_handle, NULL); @@ -461,7 +491,7 @@ local_history_keypress(struct local_history_session *session, uint32_t key) return true; case NS_KEY_RIGHT: /* Go to preferred child if there is one */ - if (session->cursor->forward_pref) { + if (session->cursor->forward_pref != NULL) { session->cursor = session->cursor->forward_pref; local_history_scroll_to_cursor(session); session->cw_t->invalidate(session->core_window_handle, NULL); @@ -470,25 +500,52 @@ local_history_keypress(struct local_history_session *session, uint32_t key) return true; case NS_KEY_DOWN: /* Go to next sibling down, if there is one */ - if (session->cursor->next) { + if (session->cursor->next != NULL) { session->cursor = session->cursor->next; - local_history_scroll_to_cursor(session); - session->cw_t->invalidate(session->core_window_handle, NULL); + } else { + struct history_entry *branch_point = NULL; + _local_history_find_branch_point( + session->cursor, + &branch_point); + if (branch_point != NULL) { + if (branch_point->next != NULL) { + branch_point = branch_point->next; + } + session->cursor = branch_point; + } } /* We have handled this keypress */ + local_history_scroll_to_cursor(session); + session->cw_t->invalidate(session->core_window_handle, NULL); return true; case NS_KEY_UP: /* Go to next sibling up, if there is one */ - if (session->cursor->back) { + if (session->cursor->back != NULL) { struct history_entry *ent = session->cursor->back->forward; - while (ent->next != NULL && ent->next != session->cursor) { + while (ent != session->cursor && + ent->next != NULL && + ent->next != session->cursor) { ent = ent->next; } - session->cursor = ent; - local_history_scroll_to_cursor(session); - session->cw_t->invalidate(session->core_window_handle, NULL); + if (session->cursor != ent) { + session->cursor = ent; + } else { + struct history_entry *branch_point = NULL; + _local_history_find_branch_point( + session->cursor, + &branch_point); + if (branch_point != NULL) { + struct history_entry *ent = branch_point->back->forward; + while (ent->next != NULL && ent->next != branch_point) { + ent = ent->next; + } + session->cursor = ent; + } + } } /* We have handled this keypress */ + local_history_scroll_to_cursor(session); + session->cw_t->invalidate(session->core_window_handle, NULL); return true; } return false; |