-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib-unicode-names.c
130 lines (119 loc) · 2.86 KB
/
lib-unicode-names.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
/*
* Copyright Neil Brown ©2023 <[email protected]>
* May be distributed under terms of GPLv2 - see file:COPYING
*
* Parse the Unicode NamesList.txt file to find names for
* unicode characters.
*/
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include "core.h"
struct unicode_data {
struct command c;
char *names;
int len;
};
static void report_names(struct unicode_data *ud safe, const char *name safe,
int which,
struct pane *p safe, struct command *c safe)
{
/* name must be start of a word, as either primary or secondary
* name. Ignore case.
* If "which" is zero, return them all, else only return the
* nth one where which==n
*/
char *ptn = strconcat(p, "?i:^([0-9A-F]{4,5} | = ).*\\b", name);
int i;
if (!ud->names)
return;
for (i = 0; i < ud->len; ) {
int ch, s;
char *cp, *n, *eol;
s = call("text-search", p, 0, NULL, ptn,
ud->len - i, NULL, ud->names + i);
if (s <= 0)
break;
i += s-1;
/* i is now the start of the match */
cp = ud->names + i;
eol = strchr(cp, '\n');
if (!eol)
break;
i = (eol - ud->names) + 1;
if (eol[-1] == '\r')
eol -= 1;
if (*cp == '\t') {
/* secondary name "\t= "*/
n = strndup(cp+3, eol-cp-3);
/* find number */
while (cp > ud->names &&
(cp[-1] != '\n' || cp[0] == '\t'))
cp -= 1;
} else {
/* primary name "XXXXX?\t" */
if (cp[4] == '\t')
n = strndup(cp+5, eol-cp-5);
else
n = strndup(cp+6, eol-cp-6);
}
ch = strtoul(cp, &eol, 16);
if (eol == cp+4 || eol == cp+5) {
if (which == 0)
comm_call(c, "cb", p, ch, NULL, n);
else {
which -= 1;
if (which == 0) {
comm_call(c, "cb", p, ch, NULL, n);
i = ud->len;
}
}
}
free(n);
}
}
static void unicode_free(struct command *c safe)
{
struct unicode_data *ud = container_of(c, struct unicode_data, c);
if (ud->names)
munmap(ud->names, ud->len);
}
DEF_CMD(unicode_names)
{
struct unicode_data *ud;
if (ci->comm == &unicode_names) {
/* This is the first call - need to allocate storage,
* load the NamesList file, and register a new command.
*/
char *p;
int fd;
alloc(ud, pane);
ud->c = unicode_names;
ud->c.free = unicode_free;
call_comm("global-set-command", ci->home, &ud->c, 0, NULL,
"Unicode-names");
p = call_ret(str, "xdg-find-edlib-file", ci->focus, 0, NULL,
"NamesList.txt", 0, NULL, "data");
if (!p)
return Efail;
fd = open(p, O_RDONLY);
free(p);
if (fd < 0)
return Efail;
ud->len = lseek(fd, 0, 2);
ud->names = mmap(NULL, ud->len, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
} else {
ud = container_of(ci->comm, struct unicode_data, c);
}
if (!ud->names)
return Efail;
if (ci->str && ci->comm2)
report_names(ud, ci->str, ci->num, ci->focus, ci->comm2);
return 1;
}
void edlib_init(struct pane *ed safe)
{
call_comm("global-set-command", ed, &unicode_names,
0, NULL, "Unicode-names");
}