Introduction
Introduction Statistics Contact Development Disclaimer Help
search.c - ledit - Text editor (WIP)
git clone git://lumidify.org/ledit.git (fast, but not encrypted)
git clone https://lumidify.org/ledit.git (encrypted, but very slow)
git clone git://4kcetb7mo7hj6grozzybxtotsub5bempzo4lirzc3437amof2c2impyd.onion/…
Log
Files
Refs
README
LICENSE
---
search.c (5173B)
---
1 #include <string.h>
2
3 #include "view.h"
4 #include "buffer.h"
5 #include "search.h"
6 #include "memory.h"
7
8 /* FIXME: make sure only whole utf8 chars are matched
9 -> actually, isn't this always the case as long as the
10 pattern is valid utf8 because of the structure of utf8? */
11 static char *last_search = NULL;
12 static size_t last_search_len = 0;
13 enum {
14 FORWARD,
15 BACKWARD
16 } last_dir = FORWARD;
17
18 void
19 search_cleanup(void) {
20 free(last_search);
21 last_search = NULL;
22 last_search_len = 0;
23 }
24
25 void
26 set_search_forward(char *pattern) {
27 last_dir = FORWARD;
28 free(last_search);
29 last_search = ledit_strdup(pattern);
30 last_search_len = strlen(last_search);
31 }
32
33 void
34 set_search_backward(char *pattern) {
35 last_dir = BACKWARD;
36 free(last_search);
37 last_search = ledit_strdup(pattern);
38 last_search_len = strlen(last_search);
39 }
40
41 static search_state
42 search_forward(ledit_view *view, size_t *line_ret, size_t *byte_ret, siz…
43 *line_ret = view->cur_line;
44 *byte_ret = view->cur_index;
45 *len_ret = last_search_len;
46 /* if last_search is empty, strstr will find the ending '\0' */
47 if (last_search == NULL || last_search[0] == '\0')
48 return SEARCH_NO_PATTERN;
49 size_t line = view->cur_line;
50 /* start one byte later so it doesn't get stuck on a match
51 note: in certain cases, this may not be a valid index */
52 size_t byte = view->cur_index + 1;
53 char *res;
54 ledit_line *lline = buffer_get_line(view->buffer, line);
55 buffer_normalize_line(lline);
56 if (byte < lline->len && (res = strstr(lline->text + byte, last_…
57 *line_ret = line;
58 *byte_ret = (size_t)(res - lline->text);
59 return SEARCH_NORMAL;
60 }
61 for (size_t i = line + 1; i < view->lines_num; i++) {
62 lline = buffer_get_line(view->buffer, i);
63 buffer_normalize_line(lline);
64 if ((res = strstr(lline->text, last_search)) != NULL) {
65 *line_ret = i;
66 *byte_ret = (size_t)(res - lline->text);
67 return SEARCH_NORMAL;
68 }
69 }
70 for (size_t i = 0; i < line; i++) {
71 lline = buffer_get_line(view->buffer, i);
72 buffer_normalize_line(lline);
73 if ((res = strstr(lline->text, last_search)) != NULL) {
74 *line_ret = i;
75 *byte_ret = (size_t)(res - lline->text);
76 return SEARCH_WRAPPED;
77 }
78 }
79 lline = buffer_get_line(view->buffer, line);
80 buffer_normalize_line(lline);
81 if ((res = strstr(lline->text, last_search)) != NULL) {
82 *line_ret = line;
83 *byte_ret = (size_t)(res - lline->text);
84 return SEARCH_WRAPPED;
85 }
86 return SEARCH_NOT_FOUND;
87 }
88
89 /* FIXME: this is insanely inefficient */
90 /* FIXME: just go backwards char-by-char and compare or knuth-morris-pra…
91 static search_state
92 search_backward(ledit_view *view, size_t *line_ret, size_t *byte_ret, si…
93 *line_ret = view->cur_line;
94 *byte_ret = view->cur_index;
95 *len_ret = last_search_len;
96 if (last_search == NULL || last_search[0] == '\0')
97 return SEARCH_NO_PATTERN;
98 size_t line = view->cur_line;
99 size_t byte = view->cur_index;
100 ledit_line *lline = buffer_get_line(view->buffer, line);
101 buffer_normalize_line(lline);
102 char *last = NULL, *res = lline->text;
103 while ((res = strstr(res, last_search)) != NULL && res < lline->…
104 last = res;
105 res++;
106 }
107 if (last != NULL) {
108 *line_ret = line;
109 /* FIXME: check if this is safe */
110 *byte_ret = (size_t)(last - lline->text);
111 return SEARCH_NORMAL;
112 }
113 for (size_t i = line; i > 0; i--) {
114 lline = buffer_get_line(view->buffer, i-1);
115 buffer_normalize_line(lline);
116 res = lline->text;
117 while ((res = strstr(res, last_search)) != NULL) {
118 last = res;
119 res++;
120 }
121 if (last != NULL) {
122 *line_ret = i-1;
123 *byte_ret = (size_t)(last - lline->text);
124 return SEARCH_NORMAL;
125 }
126 }
127 for (size_t i = view->lines_num - 1; i > line; i--) {
128 lline = buffer_get_line(view->buffer, i);
129 buffer_normalize_line(lline);
130 res = lline->text;
131 while ((res = strstr(res, last_search)) != NULL) {
132 last = res;
133 res++;
134 }
135 if (last != NULL) {
136 *line_ret = i;
137 *byte_ret = (size_t)(last - lline->text);
138 return SEARCH_WRAPPED;
139 }
140 }
141 lline = buffer_get_line(view->buffer, line);
142 buffer_normalize_line(lline);
143 res = lline->text + byte;
144 while ((res = strstr(res, last_search)) != NULL) {
145 last = res;
146 res++;
147 }
148 if (last != NULL) {
149 *line_ret = line;
150 *byte_ret = (size_t)(last - lline->text);
151 return SEARCH_WRAPPED;
152 }
153 return SEARCH_NOT_FOUND;
154 }
155
156 search_state
157 ledit_search_next(ledit_view *view, size_t *line_ret, size_t *byte_ret, …
158 if (last_dir == FORWARD)
159 return search_forward(view, line_ret, byte_ret, len_ret);
160 else
161 return search_backward(view, line_ret, byte_ret, len_ret…
162 }
163
164 search_state
165 ledit_search_prev(ledit_view *view, size_t *line_ret, size_t *byte_ret, …
166 if (last_dir == FORWARD)
167 return search_backward(view, line_ret, byte_ret, len_ret…
168 else
169 return search_forward(view, line_ret, byte_ret, len_ret);
170 }
171
172 char *
173 search_state_to_str(search_state s) {
174 switch (s) {
175 case SEARCH_NORMAL:
176 return "Found match";
177 case SEARCH_WRAPPED:
178 return "Search wrapped";
179 case SEARCH_NOT_FOUND:
180 return "Pattern not found";
181 case SEARCH_NO_PATTERN:
182 return "No previous search pattern";
183 default:
184 return "This message should not be shown. "
185 "Please bug lumidify about it.";
186 }
187 }
You are viewing proxied material from lumidify.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.