-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib-copybuf.c
142 lines (127 loc) · 3.06 KB
/
lib-copybuf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
* Copyright Neil Brown ©2017-2022 <[email protected]>
* May be distributed under terms of GPLv2 - see file:COPYING
*
* copybuf
*
* A copy-buffer stores a number of texts that have been copied from
* elsewhere. It would be nice to store these in a text document, but
* as undo cannot be disabled, that would not be good for now.
* So lets just have a linked list of things.
*
* New texts can be added, old texts (indexed from most recent: 0 is latest, 1 is second
* latest) can be requested.
* Never store more than 10 texts.
*
* Register global commands "copy:save" and "copy:get" to access texts.
*/
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define PANE_DATA_TYPE struct copy_info
#include "core.h"
struct copy_info {
struct txt {
struct txt *next;
char *txt safe;
} *store;
int count;
struct command cmd;
struct pane *pane;
};
#include "core-pane.h"
static struct map *copy_map;
DEF_LOOKUP_CMD(copy_handle, copy_map);
static void free_txt(struct txt **tp safe)
{
struct txt *t = *tp;
if (!t)
return;
*tp = NULL;
free(t->txt);
free_txt(&t->next);
free(t);
}
DEF_CMD_CLOSED(copy_close)
{
struct copy_info *cyi = ci->home->data;
free_txt(&cyi->store);
return 1;
}
DEF_CB(copy_do)
{
struct copy_info *cyi = container_of(ci->comm, struct copy_info, cmd);
if (strcmp(ci->key, "copy:save") == 0 && ci->str && ci->num == 0) {
struct txt *t;
if (cyi->store && strcmp(ci->str, cyi->store->txt) == 0)
/* Identical to last save, don't bother */
return 1;
if (cyi->count >= 10) {
struct txt **tp = &cyi->store;
int cnt = 0;
while (*tp && cnt < 10) {
tp = &((*tp)->next);
cnt += 1;
}
if (*tp)
LOG("copy:save free %.20s", (*tp)->txt);
free_txt(tp);
}
LOG("copy:save add %.20s", ci->str);
t = calloc(1, sizeof(*t));
t->next = cyi->store;
t->txt = strdup(ci->str);
cyi->store = t;
return 1;
}
if (strcmp(ci->key, "copy:save") == 0 && ci->str && ci->num == 1) {
/* Append str to the latest copy */
struct txt *t;
char *txt;
LOG("copy:save append %.20s", ci->str);
t = cyi->store;
if (t) {
txt = t->txt;
t->txt = malloc(strlen(txt) + strlen(ci->str) + 1);
strcat(strcpy(t->txt, txt), ci->str);
free(txt);
} else {
t = calloc(1, sizeof(*t));
t->next = cyi->store;
t->txt = strdup(ci->str);
cyi->store = t;
}
return 1;
}
if (strcmp(ci->key, "copy:get") == 0) {
struct txt *t = cyi->store;
int idx = ci->num;
while (t && idx > 0) {
t = t->next;
idx -= 1;
}
if (t)
LOG("copy:get %d returns %.20s", ci->num, t->txt);
if (t)
comm_call(ci->comm2, "callback", ci->focus, 0, NULL, t->txt);
return 1;
}
return Efallthrough;
}
void edlib_init(struct pane *ed safe)
{
struct copy_info *cyi;
struct pane *p;
if (!copy_map) {
copy_map = key_alloc();
key_add(copy_map, "Close", ©_close);
}
p = pane_register(ed, 0, ©_handle.c);
if (!p)
return;
cyi = p->data;
cyi->cmd = copy_do;
cyi->pane = p;
call_comm("global-set-command", ed, &cyi->cmd, 0, NULL, "copy:save");
call_comm("global-set-command", ed, &cyi->cmd, 0, NULL, "copy:get");
}