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 <calcurse@cryptocrack.de>
This commit is contained in:
parent
dd059ca812
commit
69345edd77
@ -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);
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
24
src/keys.c
24
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
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user