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
|
#include "vis-core.h"
static int ranges_comparator(const void *a, const void *b) {
const Filerange *r1 = a, *r2 = b;
if (!text_range_valid(r1))
return text_range_valid(r2) ? 1 : 0;
if (!text_range_valid(r2))
return -1;
return (r1->start < r2->start || (r1->start == r2->start && r1->end < r2->end)) ? -1 : 1;
}
void vis_mark_normalize(Array *a) {
array_sort(a, ranges_comparator);
Filerange *prev = NULL, *r = array_get(a, 0);
for (size_t i = 0; r; r = array_get(a, i)) {
if (text_range_size(r) == 0) {
array_remove(a, i);
} else if (prev && text_range_overlap(prev, r)) {
*prev = text_range_union(prev, r);
array_remove(a, i);
} else {
prev = r;
i++;
}
}
}
void marks_init(Array *arr) {
array_init_sized(arr, sizeof(SelectionRegion));
}
void mark_release(Array *arr) {
if (!arr)
return;
array_release(arr);
}
static Array *mark_from(Vis *vis, enum VisMark id) {
if (id == VIS_MARK_SELECTION && vis->win)
return &vis->win->saved_selections;
File *file = vis->win->file;
if (id < LENGTH(file->marks))
return &file->marks[id];
return NULL;
}
enum VisMark vis_mark_used(Vis *vis) {
return vis->action.mark;
}
void vis_mark(Vis *vis, enum VisMark mark) {
if (mark < LENGTH(vis->win->file->marks))
vis->action.mark = mark;
}
Array vis_mark_get(Vis *vis, enum VisMark id) {
Array sel;
array_init_sized(&sel, sizeof(Filerange));
Array *mark = mark_from(vis, id);
if (!mark)
return sel;
View *view = vis->win->view;
size_t len = array_length(mark);
array_reserve(&sel, len);
for (size_t i = 0; i < len; i++) {
SelectionRegion *sr = array_get(mark, i);
Filerange r = view_regions_restore(view, sr);
if (text_range_valid(&r))
array_add(&sel, &r);
}
vis_mark_normalize(&sel);
return sel;
}
void vis_mark_set(Vis *vis, enum VisMark id, Array *sel) {
Array *mark = mark_from(vis, id);
if (!mark)
return;
array_clear(mark);
View *view = vis->win->view;
for (size_t i = 0, len = array_length(sel); i < len; i++) {
SelectionRegion ss;
Filerange *r = array_get(sel, i);
if (view_regions_save(view, r, &ss))
array_add(mark, &ss);
}
}
enum VisMark vis_mark_from(Vis *vis, char mark) {
if (mark >= 'a' && mark <= 'z')
return VIS_MARK_a + mark - 'a';
for (size_t i = 0; i < LENGTH(vis_marks); i++) {
if (vis_marks[i].name == mark)
return i;
}
return VIS_MARK_INVALID;
}
const MarkDef vis_marks[] = {
[VIS_MARK_DEFAULT] = { '\'', VIS_HELP("Default mark") },
[VIS_MARK_SELECTION] = { '^', VIS_HELP("Last selections") },
};
|