diff --git a/TODO.md b/TODO.md index 49e911e..41e534a 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,27 @@ # QEmacs TODO list +## Current work + +* S-TAB -> untabify +* TAB and S-TAB with selected block -> indent, unindent block +* `C-x (` should restart macro learning mode +* should implement a maximum macro length and abort macro learning mode if reached +* should keep modified status when undoing past a buffer save command +* should swap buffer names in `compare-files` +* check file time and length when selecting a different buffer or running any command on the current buffer: + - if a macro is running, stop it + - prompt the user for (r) read, (i) ignore, (k) keep, (c) compare + - if not modified since save, read in separate buffer and compare. + - if difference before window start, mark and/or point, try and resync + - if modified, modified version should be kept in a separate buffer. +* add commands: + - `enlarge-window` on `C-x ^` + - `enlarge-window-horizontally` on `C-x }` + - `shrink-window` on `C-x &` + - `shrink-window-horizontally` on `C-x {` + - `resize-window` on `C-x +` (interactive resizing using `up`, `down`, `left` and `right`.) + ## Documentation / Support * improve **README.md** diff --git a/qe.c b/qe.c index 37e66c7..be9ce83 100644 --- a/qe.c +++ b/qe.c @@ -8507,27 +8507,52 @@ void do_refresh_complete(EditState *s) } } -void do_other_window(EditState *s) +static EditState *get_next_window(EditState *s) +{ + QEmacsState *qs = s->qe_state; + + if (s->next_window) + return s->next_window; + else + return qs->first_window; +} + +static EditState *get_previous_window(EditState *s) { QEmacsState *qs = s->qe_state; EditState *e; - e = s->next_window; - if (!e) - e = qs->first_window; - qs->active_window = e; + for (e = qs->first_window; e->next_window; e = e->next_window) { + if (e->next_window == s) + break; + } + return e; +} + +static EditState **get_window_link(EditState *s) +{ + QEmacsState *qs = s->qe_state; + EditState **ep = &qs->first_window; + for (;;) { + if (*ep == s) + return ep; + if (*ep == NULL) + break; + ep = &(*ep)->next_window; + } + return NULL; +} + +void do_other_window(EditState *s) +{ + QEmacsState *qs = s->qe_state; + qs->active_window = get_next_window(s); } void do_previous_window(EditState *s) { QEmacsState *qs = s->qe_state; - EditState *e; - - for (e = qs->first_window; e->next_window != NULL; e = e->next_window) { - if (e->next_window == s) - break; - } - qs->active_window = e; + qs->active_window = get_previous_window(s); } /* Delete a window and try to resize other windows so that it gets @@ -8711,6 +8736,45 @@ void do_split_window(EditState *s, int prop, int side_by_side) qs->active_window = e; } +void do_window_swap_states(EditState *s) +{ + QEmacsState *qs = s->qe_state; + uint8_t buffer[offsetof(EditState, flags) - offsetof(EditState, xleft)]; + int mask = WF_POPUP | WF_MINIBUF | WF_HIDDEN | WF_POPLEFT | WF_FILELIST; + int flags; + EditState *e, *tmp, **elink, **slink; + + if (s->flags & mask) + return; + /* find another suitable window */ + for (e = s;;) { + e = get_previous_window(e); + if (e == s) + return; + if (!(e->flags & mask)) + break; + } + /* swapping window positions and focus */ + memcpy(buffer, &s->xleft, sizeof buffer); + memcpy(&s->xleft, &e->xleft, sizeof buffer); + memcpy(&e->xleft, buffer, sizeof buffer); + flags = (e->flags ^ s->flags) & (WF_RSEPARATOR | WF_MODELINE); + e->flags ^= flags; + s->flags ^= flags; + elink = get_window_link(e); + slink = get_window_link(s); + if (elink && slink) { + /* swap the windows in the list */ + *elink = s; + *slink = e; + tmp = e->next_window; + e->next_window = s->next_window; + s->next_window = tmp; + } + do_refresh(s); + qs->active_window = e; +} + #ifndef CONFIG_TINY void do_create_window(EditState *s, const char *filename, const char *layout) { diff --git a/qe.h b/qe.h index 6e7ba83..6c65f93 100644 --- a/qe.h +++ b/qe.h @@ -1395,6 +1395,7 @@ void do_refresh(EditState *s); // should take direction argument void do_other_window(EditState *s); void do_previous_window(EditState *s); +void do_window_swap_states(EditState *s); void do_delete_window(EditState *s, int force); #define SW_STACKED 0 #define SW_SIDE_BY_SIDE 1 diff --git a/qeconfig.h b/qeconfig.h index b311534..8051eea 100644 --- a/qeconfig.h +++ b/qeconfig.h @@ -332,6 +332,9 @@ static const CmdDef basic_commands[] = { CMD0( "previous-window", "C-x p", "Move the focus to the previous window", do_previous_window) + CMD0( "window-swap-states", "C-x /", + "Swap the states of the current and next windows", + do_window_swap_states) #ifndef CONFIG_TINY CMD1( "center-cursor", "M-C-l", "Center the window contents at point",