From 69345edd77b3ff98a99b36de8063f9e5febad3eb Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Sat, 7 Jul 2012 00:53:09 +0200 Subject: Add support for copy/paste registers This adds support for vim-style copy/paste registers which allows cutting and copying multiple items without having to overwrite the copy/paste buffer. Registers can be specified using the quote key ('"'). To access a register, type '"x' before a command where "x" is the name of a register. If you want to copy the currently selected item into register 1, type '"1c'. Valid registers are 0-9, a-z, "-" and "_". Note that the latter is the so-called black hole register, which works similar to the black hole register in vim. The register prefix key is currently hardcoded and cannot be configured. Signed-off-by: Lukas Fleischer --- src/calcurse.c | 10 +++++----- src/calcurse.h | 13 ++++++++----- src/custom.c | 8 ++++---- src/help.c | 2 +- src/interaction.c | 39 +++++++++++++++++++++------------------ src/keys.c | 24 ++++++++++++++++++++---- src/utils.c | 5 ++++- 7 files changed, 63 insertions(+), 38 deletions(-) diff --git a/src/calcurse.c b/src/calcurse.c index 8a5d261..770e967 100644 --- a/src/calcurse.c +++ b/src/calcurse.c @@ -64,7 +64,7 @@ int main(int argc, char **argv) { struct day_items_nb inday; int no_data_file = 1; - int count; + int count, reg; #if ENABLE_NLS setlocale(LC_ALL, ""); @@ -173,7 +173,7 @@ int main(int argc, char **argv) wins_reset(); } - key = keys_getch(win[STA].p, &count); + key = keys_getch(win[STA].p, &count, ®); switch (key) { case KEY_GENERIC_REDRAW: resize = 1; @@ -286,7 +286,7 @@ int main(int argc, char **argv) case KEY_GENERIC_CUT: if (wins_slctd() == APP && apoint_hilt() != 0) { - interact_day_item_cut(&inday.nb_events, &inday.nb_apoints); + interact_day_item_cut(&inday.nb_events, &inday.nb_apoints, reg); inday = do_storage(0); wins_update(FLAG_CAL | FLAG_APP); } @@ -294,7 +294,7 @@ int main(int argc, char **argv) case KEY_GENERIC_COPY: if (wins_slctd() == APP && apoint_hilt() != 0) { - interact_day_item_copy(&inday.nb_events, &inday.nb_apoints); + interact_day_item_copy(&inday.nb_events, &inday.nb_apoints, reg); inday = do_storage(0); wins_update(FLAG_CAL | FLAG_APP); } @@ -302,7 +302,7 @@ int main(int argc, char **argv) case KEY_GENERIC_PASTE: if (wins_slctd() == APP) { - interact_day_item_paste(&inday.nb_events, &inday.nb_apoints); + interact_day_item_paste(&inday.nb_events, &inday.nb_apoints, reg); inday = do_storage(0); wins_update(FLAG_CAL | FLAG_APP); } diff --git a/src/calcurse.h b/src/calcurse.h index 8674321..c9b0307 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -160,6 +160,9 @@ #define KEYS_LABELEN 8 /* length of command description */ #define KEYS_CMDS_PER_LINE 6 /* max number of commands per line */ +/* Register definitions. */ +#define REG_BLACK_HOLE 37 + /* Size of the hash table the note garbage collector uses. */ #define NOTE_GC_HSIZE 1024 @@ -722,10 +725,10 @@ void interact_day_item_delete(unsigned *, unsigned *); void interact_day_item_edit(void); void interact_day_item_pipe(void); void interact_day_item_repeat(void); -void interact_day_item_cut_free(); -void interact_day_item_cut(unsigned *, unsigned *); -void interact_day_item_copy(unsigned *, unsigned *); -void interact_day_item_paste(unsigned *, unsigned *); +void interact_day_item_cut_free(unsigned); +void interact_day_item_cut(unsigned *, unsigned *, unsigned); +void interact_day_item_copy(unsigned *, unsigned *, unsigned); +void interact_day_item_paste(unsigned *, unsigned *, unsigned); void interact_todo_add(void); void interact_todo_delete(void); void interact_todo_edit(void); @@ -768,7 +771,7 @@ void keys_free(void); void keys_dump_defaults(char *); const char *keys_get_label(enum key); enum key keys_get_action(int); -enum key keys_getch(WINDOW * win, int *); +enum key keys_getch(WINDOW * win, int *, int *); int keys_assign_binding(int, enum key); void keys_remove_binding(int, enum key); int keys_str2int(const char *); diff --git a/src/custom.c b/src/custom.c index 72c531b..185f65a 100644 --- a/src/custom.c +++ b/src/custom.c @@ -226,7 +226,7 @@ void custom_layout_config(void) display_layout_config(&conf_win, mark, cursor); clear(); - while ((ch = keys_getch(win[STA].p, NULL)) != KEY_GENERIC_QUIT) { + while ((ch = keys_getch(win[STA].p, NULL, NULL)) != KEY_GENERIC_QUIT) { need_reset = 0; switch (ch) { case KEY_GENERIC_HELP: @@ -310,7 +310,7 @@ void custom_sidebar_config(void) bindings_size, NULL); wins_doupdate(); - while ((ch = keys_getch(win[STA].p, NULL)) != KEY_GENERIC_QUIT) { + while ((ch = keys_getch(win[STA].p, NULL, NULL)) != KEY_GENERIC_QUIT) { switch (ch) { case KEY_MOVE_UP: wins_sbar_winc(); @@ -528,7 +528,7 @@ void custom_color_config(void) theme_changed); clear(); - while ((ch = keys_getch(win[STA].p, NULL)) != KEY_GENERIC_QUIT) { + while ((ch = keys_getch(win[STA].p, NULL, NULL)) != KEY_GENERIC_QUIT) { need_reset = 0; theme_changed = 0; @@ -921,7 +921,7 @@ void custom_keys_config(void) for (;;) { int ch; - ch = keys_getch(win[STA].p, NULL); + ch = keys_getch(win[STA].p, NULL, NULL); switch (ch) { case KEY_MOVE_UP: if (selrow > 0) { diff --git a/src/help.c b/src/help.c index 32704d3..9ad548f 100644 --- a/src/help.c +++ b/src/help.c @@ -800,7 +800,7 @@ void help_screen(void) } wins_scrollwin_display(&hwin); - ch = keys_getch(win[STA].p, NULL); + ch = keys_getch(win[STA].p, NULL, NULL); } wins_scrollwin_delete(&hwin); if (need_resize) diff --git a/src/interaction.c b/src/interaction.c index abe261d..b619992 100644 --- a/src/interaction.c +++ b/src/interaction.c @@ -36,7 +36,7 @@ #include "calcurse.h" -struct day_item day_cut = { 0, 0, { NULL } }; +struct day_item day_cut[37] = { { 0, 0, { NULL } } }; /* Request the user to enter a new time. */ static int day_edit_time(int time, unsigned *new_hour, unsigned *new_minute) @@ -870,29 +870,30 @@ void interact_day_item_repeat(void) } /* Free the current cut item, if any. */ -void interact_day_item_cut_free(void) +void interact_day_item_cut_free(unsigned reg) { - switch (day_cut.type) { + switch (day_cut[reg].type) { case 0: /* No previous item, don't free anything. */ break; case APPT: - apoint_free(day_cut.item.apt); + apoint_free(day_cut[reg].item.apt); break; case EVNT: - event_free(day_cut.item.ev); + event_free(day_cut[reg].item.ev); break; case RECUR_APPT: - recur_apoint_free(day_cut.item.rapt); + recur_apoint_free(day_cut[reg].item.rapt); break; case RECUR_EVNT: - recur_event_free(day_cut.item.rev); + recur_event_free(day_cut[reg].item.rev); break; } } /* Cut an item, so that it can be pasted somewhere else later. */ -void interact_day_item_cut(unsigned *nb_events, unsigned *nb_apoints) +void interact_day_item_cut(unsigned *nb_events, unsigned *nb_apoints, + unsigned reg) { const int NBITEMS = *nb_apoints + *nb_events; int to_be_removed; @@ -900,11 +901,11 @@ void interact_day_item_cut(unsigned *nb_events, unsigned *nb_apoints) if (NBITEMS == 0) return; - interact_day_item_cut_free(); + interact_day_item_cut_free(reg); struct day_item *p = day_cut_item(calendar_get_slctd_day_sec(), apoint_hilt()); - day_cut.type = p->type; - day_cut.item = p->item; + day_cut[reg].type = p->type; + day_cut[reg].item = p->item; calendar_monthly_view_cache_set_invalid(); @@ -927,27 +928,29 @@ void interact_day_item_cut(unsigned *nb_events, unsigned *nb_apoints) } /* Copy an item, so that it can be pasted somewhere else later. */ -void interact_day_item_copy(unsigned *nb_events, unsigned *nb_apoints) +void interact_day_item_copy(unsigned *nb_events, unsigned *nb_apoints, + unsigned reg) { const int NBITEMS = *nb_apoints + *nb_events; - if (NBITEMS == 0) + if (NBITEMS == 0 || reg == REG_BLACK_HOLE) return; - interact_day_item_cut_free(); - day_item_fork(day_get_item(apoint_hilt()), &day_cut); + interact_day_item_cut_free(reg); + day_item_fork(day_get_item(apoint_hilt()), &day_cut[reg]); } /* Paste a previously cut item. */ -void interact_day_item_paste(unsigned *nb_events, unsigned *nb_apoints) +void interact_day_item_paste(unsigned *nb_events, unsigned *nb_apoints, + unsigned reg) { int item_type; struct day_item day; - if (!day_cut.type) + if (reg == REG_BLACK_HOLE || !day_cut[reg].type) return; - day_item_fork(&day_cut, &day); + day_item_fork(&day_cut[reg], &day); item_type = day_paste_item(&day, calendar_get_slctd_day_sec()); calendar_monthly_view_cache_set_invalid(); diff --git a/src/keys.c b/src/keys.c index 579ddc8..38b6780 100644 --- a/src/keys.c +++ b/src/keys.c @@ -180,12 +180,13 @@ enum key keys_get_action(int pressed) return actions[pressed]; } -enum key keys_getch(WINDOW * win, int *count) +enum key keys_getch(WINDOW * win, int *count, int *reg) { int ch = '0'; - if (count) { + if (count && reg) { *count = 0; + *reg = 0; do { *count = *count * 10 + ch - '0'; ch = wgetch(win); @@ -194,8 +195,23 @@ enum key keys_getch(WINDOW * win, int *count) if (*count == 0) *count = 1; - } else + + if (ch == '"') { + ch = wgetch(win); + if (ch >= '1' && ch <= '9') { + *reg = ch - '1' + 1; + } + else if (ch >= 'a' && ch <= 'z') { + *reg = ch - 'a' + 10; + } + else if (ch == '_') { + *reg = REG_BLACK_HOLE; + } + ch = wgetch(win); + } + } else { ch = wgetch(win); + } switch (ch) { case KEY_RESIZE: @@ -524,7 +540,7 @@ void keys_popup_info(enum key key) #define WINCOL (col - 4) infowin = popup(WINROW, WINCOL, (row - WINROW) / 2, (col - WINCOL) / 2, keydef[key].label, info[key], 1); - keys_getch(infowin, NULL); + keys_getch(infowin, NULL, NULL); delwin(infowin); #undef WINROW #undef WINCOL diff --git a/src/utils.c b/src/utils.c index 1823321..3e86f17 100644 --- a/src/utils.c +++ b/src/utils.c @@ -97,12 +97,15 @@ void exit_calcurse(int status) void free_user_data(void) { + unsigned i; + day_free_list(); event_llist_free(); apoint_llist_free(); recur_apoint_llist_free(); recur_event_llist_free(); - interact_day_item_cut_free(); + for (i = 0; i <= 37; i++) + interact_day_item_cut_free(i); todo_free_list(); notify_free_app(); } -- cgit v1.2.3-54-g00ecf